From 58fab1b319adbb2204df5eca88109426ed867d8e Mon Sep 17 00:00:00 2001 Message-Id: <58fab1b319adbb2204df5eca88109426ed867d8e.1381871412.git.jdenemar@redhat.com> From: =?UTF-8?q?C=C3=A9dric=20Bosdonnat?= Date: Mon, 14 Oct 2013 16:45:16 +0100 Subject: [PATCH] LXC: workaround machined uncleaned data with containers running systemd. For https://bugzilla.redhat.com/show_bug.cgi?id=1018730 The problem is described by [0] but its effect on libvirt is that starting a container with a full distro running systemd after having stopped it simply fails. The container cleanup now calls the machined Terminate function to make sure that everything is in order for the next run. [0]: https://bugs.freedesktop.org/show_bug.cgi?id=68370 (cherry picked from commit bd773e74f0d1d1b9ebbfcaa645178316b4f2265c) Signed-off-by: Jiri Denemark --- src/libvirt_private.syms | 2 ++ src/lxc/lxc_process.c | 8 +++++ src/util/virsystemd.c | 80 +++++++++++++++++++++++++++++++++++++++++------- src/util/virsystemd.h | 8 +++++ tests/virsystemdtest.c | 28 +++++++++++++++++ 5 files changed, 115 insertions(+), 11 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 47e989c..d9561b8 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1938,8 +1938,10 @@ virSysinfoSetup; # util/virsystemd.h virSystemdCreateMachine; +virSystemdMakeMachineName; virSystemdMakeScopeName; virSystemdMakeSliceName; +virSystemdTerminateMachine; # util/virthread.h diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index 47e6dd7..724ffa9 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -50,6 +50,7 @@ #include "virstring.h" #include "viratomic.h" #include "virprocess.h" +#include "virsystemd.h" #define VIR_FROM_THIS VIR_FROM_LXC @@ -209,6 +210,13 @@ static void virLXCProcessCleanup(virLXCDriverPtr driver, virCgroupFree(&priv->cgroup); } + /* Get machined to terminate the machine as it may not have cleaned it + * properly. See https://bugs.freedesktop.org/show_bug.cgi?id=68370 for + * the bug we are working around here. + */ + virSystemdTerminateMachine(vm->def->name, "lxc", true); + + /* now that we know it's stopped call the hook if present */ if (virHookPresent(VIR_HOOK_DRIVER_LXC)) { char *xml = virDomainDefFormat(vm->def, 0); diff --git a/src/util/virsystemd.c b/src/util/virsystemd.c index e72b7f0..1ba37cc 100644 --- a/src/util/virsystemd.c +++ b/src/util/virsystemd.c @@ -116,6 +116,27 @@ char *virSystemdMakeSliceName(const char *partition) return virBufferContentAndReset(&buf); } +char *virSystemdMakeMachineName(const char *name, + const char *drivername, + bool privileged) +{ + char *machinename = NULL; + char *username = NULL; + if (privileged) { + if (virAsprintf(&machinename, "%s-%s", drivername, name) < 0) + goto cleanup; + } else { + if (!(username = virGetUserName(geteuid()))) + goto cleanup; + if (virAsprintf(&machinename, "%s-%s-%s", username, drivername, name) < 0) + goto cleanup; + } + +cleanup: + VIR_FREE(username); + + return machinename; +} /** * virSystemdCreateMachine: @@ -142,7 +163,6 @@ int virSystemdCreateMachine(const char *name, DBusConnection *conn; char *machinename = NULL; char *creatorname = NULL; - char *username = NULL; char *slicename = NULL; ret = virDBusIsServiceEnabled("org.freedesktop.machine1"); @@ -152,15 +172,8 @@ int virSystemdCreateMachine(const char *name, conn = virDBusGetSystemBus(); ret = -1; - if (privileged) { - if (virAsprintf(&machinename, "%s-%s", drivername, name) < 0) - goto cleanup; - } else { - if (!(username = virGetUserName(geteuid()))) - goto cleanup; - if (virAsprintf(&machinename, "%s-%s-%s", username, drivername, name) < 0) - goto cleanup; - } + if (!(machinename = virSystemdMakeMachineName(name, drivername, privileged))) + goto cleanup; if (virAsprintf(&creatorname, "libvirt-%s", drivername) < 0) goto cleanup; @@ -236,9 +249,54 @@ int virSystemdCreateMachine(const char *name, ret = 0; cleanup: - VIR_FREE(username); VIR_FREE(creatorname); VIR_FREE(machinename); VIR_FREE(slicename); return ret; } + +int virSystemdTerminateMachine(const char *name, + const char *drivername, + bool privileged) +{ + int ret; + DBusConnection *conn; + char *machinename = NULL; + + ret = virDBusIsServiceEnabled("org.freedesktop.machine1"); + if (ret < 0) + return ret; + + conn = virDBusGetSystemBus(); + + ret = -1; + if (!(machinename = virSystemdMakeMachineName(name, drivername, privileged))) + goto cleanup; + + /* + * The systemd DBus API we're invoking has the + * following signature + * + * TerminateMachine(in s name); + * + * @name a host unique name for the machine. shows up + * in 'ps' listing & similar + */ + + VIR_DEBUG("Attempting to terminate machine via systemd"); + if (virDBusCallMethod(conn, + NULL, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "TerminateMachine", + "s", + machinename) < 0) + goto cleanup; + + ret = 0; + +cleanup: + VIR_FREE(machinename); + return ret; +} diff --git a/src/util/virsystemd.h b/src/util/virsystemd.h index 414ae5a..d9845e1 100644 --- a/src/util/virsystemd.h +++ b/src/util/virsystemd.h @@ -29,6 +29,10 @@ char *virSystemdMakeScopeName(const char *name, const char *slicename); char *virSystemdMakeSliceName(const char *partition); +char *virSystemdMakeMachineName(const char *name, + const char *drivername, + bool privileged); + int virSystemdCreateMachine(const char *name, const char *drivername, bool privileged, @@ -38,4 +42,8 @@ int virSystemdCreateMachine(const char *name, bool iscontainer, const char *partition); +int virSystemdTerminateMachine(const char *name, + const char *drivername, + bool privileged); + #endif /* __VIR_SYSTEMD_H__ */ diff --git a/tests/virsystemdtest.c b/tests/virsystemdtest.c index 7dc7520..b314013 100644 --- a/tests/virsystemdtest.c +++ b/tests/virsystemdtest.c @@ -51,6 +51,18 @@ static int testCreateContainer(const void *opaque ATTRIBUTE_UNUSED) return 0; } +static int testTerminateContainer(const void *opaque ATTRIBUTE_UNUSED) +{ + if (virSystemdTerminateMachine("demo", + "lxc", + true) < 0) { + fprintf(stderr, "%s", "Failed to terminate LXC machine\n"); + return -1; + } + + return 0; +} + static int testCreateMachine(const void *opaque ATTRIBUTE_UNUSED) { unsigned char uuid[VIR_UUID_BUFLEN] = { @@ -74,6 +86,18 @@ static int testCreateMachine(const void *opaque ATTRIBUTE_UNUSED) return 0; } +static int testTerminateMachine(const void *opaque ATTRIBUTE_UNUSED) +{ + if (virSystemdTerminateMachine("demo", + "qemu", + false) < 0) { + fprintf(stderr, "%s", "Failed to terminate KVM machine\n"); + return -1; + } + + return 0; +} + static int testCreateNoSystemd(const void *opaque ATTRIBUTE_UNUSED) { unsigned char uuid[VIR_UUID_BUFLEN] = { @@ -181,8 +205,12 @@ mymain(void) if (virtTestRun("Test create container ", 1, testCreateContainer, NULL) < 0) ret = -1; + if (virtTestRun("Test terminate container ", 1, testTerminateContainer, NULL) < 0) + ret = -1; if (virtTestRun("Test create machine ", 1, testCreateMachine, NULL) < 0) ret = -1; + if (virtTestRun("Test terminate machine ", 1, testTerminateMachine, NULL) < 0) + ret = -1; if (virtTestRun("Test create no systemd ", 1, testCreateNoSystemd, NULL) < 0) ret = -1; if (virtTestRun("Test create bad systemd ", 1, testCreateBadSystemd, NULL) < 0) -- 1.8.3.2