When the container has the same '/dev' mount as host (no chroot),
calling domainShutdown(WithFlags) shouldn't shutdown the host it is
running on.
Signed-off-by: Martin Kletzander <mkletzan(a)redhat.com>
---
This is also valid for 1.0.[23]-maint branches, so in case this gets
ACK'd I'll either send a follow-up for those or push it there as well
(if the ACK says so).
src/lxc/lxc_driver.c | 45 ++++++++++++++++++++++++++++-----------------
1 file changed, 28 insertions(+), 17 deletions(-)
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index 8603078..ba14db7 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2012 Red Hat, Inc.
+ * Copyright (C) 2010-2013 Red Hat, Inc.
* Copyright IBM Corp. 2008
*
* lxc_driver.c: linux container driver functions
@@ -2778,13 +2778,19 @@ lxcDomainShutdownFlags(virDomainPtr dom,
virLXCDriverPtr driver = dom->conn->privateData;
virLXCDomainObjPrivatePtr priv;
virDomainObjPtr vm;
+ virDomainFSDefPtr root;
char *vroot = NULL;
int ret = -1;
- int rc;
+ int rc = 0;
+ bool methodSignal;
+ bool methodInitctl;
virCheckFlags(VIR_DOMAIN_SHUTDOWN_INITCTL |
VIR_DOMAIN_SHUTDOWN_SIGNAL, -1);
+ methodSignal = !!(flags & VIR_DOMAIN_SHUTDOWN_SIGNAL);
+ methodInitctl = !!(flags & VIR_DOMAIN_SHUTDOWN_INITCTL);
+
lxcDriverLock(driver);
vm = virDomainObjListFindByUUID(driver->domains, dom->uuid);
lxcDriverUnlock(driver);
@@ -2798,6 +2804,7 @@ lxcDomainShutdownFlags(virDomainPtr dom,
}
priv = vm->privateData;
+ root = virDomainGetRootFilesystem(vm->def);
if (!virDomainObjIsActive(vm)) {
virReportError(VIR_ERR_OPERATION_INVALID,
@@ -2817,27 +2824,31 @@ lxcDomainShutdownFlags(virDomainPtr dom,
goto cleanup;
}
- if (flags == 0 ||
- (flags & VIR_DOMAIN_SHUTDOWN_INITCTL)) {
- if ((rc = virInitctlSetRunLevel(VIR_INITCTL_RUNLEVEL_POWEROFF,
- vroot)) < 0) {
+ if (root && root->src) {
+ if (flags == 0)
+ methodSignal = methodInitctl = true;
+ } else if (methodInitctl) {
+ virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+ _("Cannot shutdown container using initctl "
+ "without separated namespace"));
+ goto cleanup;
+ } else {
+ methodSignal = true;
+ }
+
+ if (methodInitctl) {
+ rc = virInitctlSetRunLevel(VIR_INITCTL_RUNLEVEL_POWEROFF, vroot);
+ if (rc < 0)
goto cleanup;
- }
- if (rc == 0 && flags != 0 &&
- ((flags & ~VIR_DOMAIN_SHUTDOWN_INITCTL) == 0)) {
+ if (rc == 0 && !methodSignal) {
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
_("Container does not provide an initctl pipe"));
goto cleanup;
}
- } else {
- rc = 0;
}
-
- if (rc == 0 &&
- (flags == 0 ||
- (flags & VIR_DOMAIN_SHUTDOWN_SIGNAL))) {
- if (kill(priv->initpid, SIGTERM) < 0 &&
- errno != ESRCH) {
+ if (rc == 0 && methodSignal) {
+ ret = kill(priv->initpid, SIGTERM);
+ if (ret < 0 && errno != ESRCH) {
virReportSystemError(errno,
_("Unable to send SIGTERM to init pid %llu"),
(unsigned long long)priv->initpid);
--
1.8.1.5