diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 48e4b047c8..4bc4d69977 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1947,8 +1947,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 4835bd5003..f92c613293 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 @@ -210,6 +211,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 e72b7f0276..1ba37ccdfe 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 414ae5ac9f..d9845e14c2 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 e68b3ac664..e6efebf3a8 100644 --- a/tests/virsystemdtest.c +++ b/tests/virsystemdtest.c @@ -54,6 +54,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] = { @@ -77,6 +89,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] = { @@ -184,8 +208,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)