[libvirt] [PATCH 5/5] lxc: Don't reboot host on virDomainReboot

Michal Privoznik mprivozn at redhat.com
Fri Jan 25 13:31:49 UTC 2019


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 at redhat.com>
---
 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




More information about the libvir-list mailing list