]> xenbits.xensource.com Git - libvirt.git/commitdiff
lxc: Don't reboot host on virDomainReboot
authorMichal Privoznik <mprivozn@redhat.com>
Fri, 25 Jan 2019 11:42:54 +0000 (12:42 +0100)
committerMichal Privoznik <mprivozn@redhat.com>
Thu, 7 Feb 2019 10:36:41 +0000 (11:36 +0100)
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@redhat.com>
Reviewed-by: Erik Skultety <eskultet@redhat.com>
src/lxc/lxc_domain.c
src/lxc/lxc_domain.h
src/lxc/lxc_driver.c

index a1cdbdca2c83cf382a94e890a08962f803b89f69..e5029971185cada852b42601d1b748640408a9ba 100644 (file)
@@ -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"
@@ -418,3 +419,92 @@ virLXCDomainGetMachineName(virDomainDefPtr def, pid_t pid)
 
     return ret;
 }
+
+
+typedef struct _lxcDomainInitctlCallbackData lxcDomainInitctlCallbackData;
+struct _lxcDomainInitctlCallbackData {
+    int runlevel;
+    bool *st_valid;
+    struct stat *st;
+};
+
+
+static int
+lxcDomainInitctlCallback(pid_t pid ATTRIBUTE_UNUSED,
+                         void *opaque)
+{
+    lxcDomainInitctlCallbackData *data = opaque;
+    size_t i;
+
+    for (i = 0; virInitctlFifos[i]; 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 nfifos = 0;
+    size_t i;
+    int ret = -1;
+
+    memset(&data, 0, sizeof(data));
+
+    data.runlevel = runlevel;
+
+    for (nfifos = 0; virInitctlFifos[nfifos]; nfifos++)
+        ;
+
+    if (VIR_ALLOC_N(data.st, nfifos) < 0 ||
+        VIR_ALLOC_N(data.st_valid, nfifos) < 0)
+        goto cleanup;
+
+    for (i = 0; virInitctlFifos[i]; i++) {
+        const char *fifo = virInitctlFifos[i];
+
+        if (stat(fifo, &(data.st[i])) < 0) {
+            if (errno == ENOENT)
+                continue;
+
+            virReportSystemError(errno, _("Unable to stat %s"), fifo);
+            goto cleanup;
+        }
+
+        data.st_valid[i] = true;
+    }
+
+    ret = virProcessRunInMountNamespace(priv->initpid,
+                                        lxcDomainInitctlCallback,
+                                        &data);
+ cleanup:
+    VIR_FREE(data.st);
+    VIR_FREE(data.st_valid);
+    return ret;
+}
index 07b850f8a12096f470312a8e40d1658b24f1a44c..f4e9c378a901e90a614feaca7b3c86d5d36db315 100644 (file)
@@ -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 */
index d6be9e87574832e3784b69b12765887b9f89e6b3..c48f6d9067ce7038faa5395542f852cf4d5b5cdd 100644 (file)
@@ -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)) {