If the container is really a simple one (init is just bash and the whole root is passed through) then virDomainReboot and virDomainShutdown will talk to the actual init within the host. Therefore, 'virsh shutdown $dom' will result in shutting down the host. True, at that point the container is shut down too but looks a bit harsh to me. The solution is to check if the init inside the container is or is not the same as the init running on the host. Signed-off-by: Michal Privoznik <mprivozn@xxxxxxxxxx> --- src/lxc/lxc_domain.c | 77 ++++++++++++++++++++++++++++++++++++++++++++ src/lxc/lxc_domain.h | 4 +++ src/lxc/lxc_driver.c | 17 ++-------- 3 files changed, 83 insertions(+), 15 deletions(-) diff --git a/src/lxc/lxc_domain.c b/src/lxc/lxc_domain.c index b197f9dfc2..73023c0a57 100644 --- a/src/lxc/lxc_domain.c +++ b/src/lxc/lxc_domain.c @@ -32,6 +32,7 @@ #include "virfile.h" #include "virtime.h" #include "virsystemd.h" +#include "virinitctl.h" #define VIR_FROM_THIS VIR_FROM_LXC #define LXC_NAMESPACE_HREF "http://libvirt.org/schemas/domain/lxc/1.0" @@ -416,3 +417,79 @@ virLXCDomainGetMachineName(virDomainDefPtr def, pid_t pid) return ret; } + + +typedef struct _lxcDomainInitctlCallbackData lxcDomainInitctlCallbackData; +struct _lxcDomainInitctlCallbackData { + int runlevel; + bool st_valid[ARRAY_CARDINALITY(virInitctlFifos)]; + struct stat st[ARRAY_CARDINALITY(virInitctlFifos)]; +}; + + +static int +lxcDomainInitctlCallback(pid_t pid ATTRIBUTE_UNUSED, + void *opaque) +{ + lxcDomainInitctlCallbackData *data = opaque; + size_t i; + + for (i = 0; i < ARRAY_CARDINALITY(virInitctlFifos); i++) { + const char *fifo = virInitctlFifos[i]; + struct stat cont_sb; + + if (stat(fifo, &cont_sb) < 0) { + if (errno == ENOENT) + continue; + + virReportSystemError(errno, _("Unable to stat %s"), fifo); + return -1; + } + + /* Check if the init fifo is not the very one that's on + * the host. We don't want to change the host's runlevel. + */ + if (data->st_valid[i] && + data->st[i].st_dev == cont_sb.st_dev && + data->st[i].st_ino == cont_sb.st_ino) + continue; + + return virInitctlSetRunLevel(fifo, data->runlevel); + } + + /* If no usable fifo was found then declare success. Caller + * will try killing the domain with signal. */ + return 0; +} + + +int +virLXCDomainSetRunlevel(virDomainObjPtr vm, + int runlevel) +{ + virLXCDomainObjPrivatePtr priv = vm->privateData; + lxcDomainInitctlCallbackData data; + size_t i; + + memset(&data, 0, sizeof(data)); + + data.runlevel = runlevel; + + for (i = 0; i < ARRAY_CARDINALITY(virInitctlFifos); i++) { + const char *fifo = virInitctlFifos[i]; + + if (stat(fifo, &(data.st[i])) < 0) { + if (errno == ENOENT) + continue; + + virReportSystemError(errno, _("Unable to stat %s"), fifo); + return -1; + } + + data.st_valid[i] = true; + } + + return virProcessRunInMountNamespace(priv->initpid, + lxcDomainInitctlCallback, + &data); +} diff --git a/src/lxc/lxc_domain.h b/src/lxc/lxc_domain.h index 364b8e5a44..c62d6d1362 100644 --- a/src/lxc/lxc_domain.h +++ b/src/lxc/lxc_domain.h @@ -109,4 +109,8 @@ virLXCDomainObjEndJob(virLXCDriverPtr driver, char * virLXCDomainGetMachineName(virDomainDefPtr def, pid_t pid); +int +virLXCDomainSetRunlevel(virDomainObjPtr vm, + int runlevel); + #endif /* LIBVIRT_LXC_DOMAIN_H */ diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 943d199616..f0d72aa569 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -3272,15 +3272,6 @@ lxcConnectListAllDomains(virConnectPtr conn, } -static int -lxcDomainInitctlCallback(pid_t pid ATTRIBUTE_UNUSED, - void *opaque) -{ - int *command = opaque; - return virInitctlSetRunLevel(NULL, *command); -} - - static int lxcDomainShutdownFlags(virDomainPtr dom, unsigned int flags) @@ -3318,9 +3309,7 @@ lxcDomainShutdownFlags(virDomainPtr dom, (flags & VIR_DOMAIN_SHUTDOWN_INITCTL)) { int command = VIR_INITCTL_RUNLEVEL_POWEROFF; - if ((rc = virProcessRunInMountNamespace(priv->initpid, - lxcDomainInitctlCallback, - &command)) < 0) + if ((rc = virLXCDomainSetRunlevel(vm, command)) < 0) goto endjob; if (rc == 0 && flags != 0 && ((flags & ~VIR_DOMAIN_SHUTDOWN_INITCTL) == 0)) { @@ -3398,9 +3387,7 @@ lxcDomainReboot(virDomainPtr dom, (flags & VIR_DOMAIN_REBOOT_INITCTL)) { int command = VIR_INITCTL_RUNLEVEL_REBOOT; - if ((rc = virProcessRunInMountNamespace(priv->initpid, - lxcDomainInitctlCallback, - &command)) < 0) + if ((rc = virLXCDomainSetRunlevel(vm, command)) < 0) goto endjob; if (rc == 0 && flags != 0 && ((flags & ~VIR_DOMAIN_SHUTDOWN_INITCTL) == 0)) { -- 2.19.2 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list