From 318df5a05f35ceda70822c5f56ac93e21bbfe691 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Tue, 11 Nov 2014 17:38:43 +0000 Subject: [PATCH] Add support for systemd-machined CreateMachineWithNetwork systemd-machined introduced a new method CreateMachineWithNetwork that obsoletes CreateMachine. It expects to be given a list of VETH/TAP device indexes for the host side device(s) associated with a container/machine. This falls back to the old CreateMachine method when the new one is not supported. --- po/POTFILES.in | 1 + src/lxc/lxc_cgroup.c | 1 + src/qemu/qemu_cgroup.c | 1 + src/util/vircgroup.c | 8 +++ src/util/vircgroup.h | 2 + src/util/virsystemd.c | 122 ++++++++++++++++++++++++++++++++--------- src/util/virsystemd.h | 2 + tests/virsystemdtest.c | 36 ++++++++++++ 8 files changed, 147 insertions(+), 26 deletions(-) diff --git a/po/POTFILES.in b/po/POTFILES.in index 094c8e3704..2db87862ce 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -216,6 +216,7 @@ src/util/virstorageencryption.c src/util/virstoragefile.c src/util/virstring.c src/util/virsysinfo.c +src/util/virsystemd.c src/util/virerror.c src/util/virerror.h src/util/virtime.c diff --git a/src/lxc/lxc_cgroup.c b/src/lxc/lxc_cgroup.c index eb67191304..728e8e500d 100644 --- a/src/lxc/lxc_cgroup.c +++ b/src/lxc/lxc_cgroup.c @@ -486,6 +486,7 @@ virCgroupPtr virLXCCgroupCreate(virDomainDefPtr def) NULL, getpid(), true, + 0, NULL, def->resource->partition, -1, &cgroup) < 0) diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c index 1acb77d253..d71ffbcf20 100644 --- a/src/qemu/qemu_cgroup.c +++ b/src/qemu/qemu_cgroup.c @@ -769,6 +769,7 @@ qemuInitCgroup(virQEMUDriverPtr driver, NULL, vm->pid, false, + 0, NULL, vm->def->resource->partition, cfg->cgroupControllers, &priv->cgroup) < 0) { diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c index 64bc647db8..f5f617ed67 100644 --- a/src/util/vircgroup.c +++ b/src/util/vircgroup.c @@ -1584,6 +1584,8 @@ virCgroupNewMachineSystemd(const char *name, const char *rootdir, pid_t pidleader, bool isContainer, + size_t nnicindexes, + int *nicindexes, const char *partition, int controllers, virCgroupPtr *group) @@ -1602,6 +1604,8 @@ virCgroupNewMachineSystemd(const char *name, rootdir, pidleader, isContainer, + nnicindexes, + nicindexes, partition)) < 0) return rv; @@ -1747,6 +1751,8 @@ virCgroupNewMachine(const char *name, const char *rootdir, pid_t pidleader, bool isContainer, + size_t nnicindexes, + int *nicindexes, const char *partition, int controllers, virCgroupPtr *group) @@ -1762,6 +1768,8 @@ virCgroupNewMachine(const char *name, rootdir, pidleader, isContainer, + nnicindexes, + nicindexes, partition, controllers, group)) == 0) diff --git a/src/util/vircgroup.h b/src/util/vircgroup.h index f07c1a74ee..9f984e787d 100644 --- a/src/util/vircgroup.h +++ b/src/util/vircgroup.h @@ -100,6 +100,8 @@ int virCgroupNewMachine(const char *name, const char *rootdir, pid_t pidleader, bool isContainer, + size_t nnicindexes, + int *nicindexes, const char *partition, int controllers, virCgroupPtr *group) diff --git a/src/util/virsystemd.c b/src/util/virsystemd.c index ddfc0474a7..3eea5c2700 100644 --- a/src/util/virsystemd.c +++ b/src/util/virsystemd.c @@ -26,6 +26,7 @@ #endif #include "virsystemd.h" +#include "viratomic.h" #include "virdbus.h" #include "virstring.h" #include "viralloc.h" @@ -147,7 +148,10 @@ char *virSystemdMakeMachineName(const char *name, * @uuid: globally unique UUID of the machine * @rootdir: root directory of machine filesystem * @pidleader: PID of the leader process - * @slice: name of the slice to place the machine in + * @iscontainer: true if a container, false if a VM + * @nnicindexes: number of network interface indexes in list + * @nicindexes: list of network interface indexes + * @partition: name of the slice to place the machine in * * Returns 0 on success, -1 on fatal error, or -2 if systemd-machine is not available */ @@ -158,6 +162,8 @@ int virSystemdCreateMachine(const char *name, const char *rootdir, pid_t pidleader, bool iscontainer, + size_t nnicindexes, + int *nicindexes, const char *partition) { int ret; @@ -165,6 +171,7 @@ int virSystemdCreateMachine(const char *name, char *machinename = NULL; char *creatorname = NULL; char *slicename = NULL; + static int hasCreateWithNetwork = 1; ret = virDBusIsServiceEnabled("org.freedesktop.machine1"); if (ret < 0) @@ -192,8 +199,18 @@ int virSystemdCreateMachine(const char *name, } /* - * The systemd DBus API we're invoking has the - * following signature + * The systemd DBus APIs we're invoking have the + * following signature(s) + * + * CreateMachineWithNetwork(in s name, + * in ay id, + * in s service, + * in s class, + * in u leader, + * in s root_directory, + * in ai nicindexes + * in a(sv) scope_properties, + * out o path); * * CreateMachine(in s name, * in ay id, @@ -221,38 +238,91 @@ int virSystemdCreateMachine(const char *name, * @root_directory: the root directory of the container, if * this is known & visible in the host filesystem, or empty string * + * @nicindexes: list of network interface indexes for the + * host end of the VETH device pairs. + * * @scope_properties:an array (not a dict!) of properties that are * passed on to PID 1 when creating a scope unit for your machine. * Will allow initial settings for the cgroup & similar. * * @path: a bus path returned for the machine object created, to * allow further API calls to be made against the object. + * */ VIR_DEBUG("Attempting to create machine via systemd"); - if (virDBusCallMethod(conn, - NULL, - NULL, - "org.freedesktop.machine1", - "/org/freedesktop/machine1", - "org.freedesktop.machine1.Manager", - "CreateMachine", - "sayssusa(sv)", - machinename, - 16, - uuid[0], uuid[1], uuid[2], uuid[3], - uuid[4], uuid[5], uuid[6], uuid[7], - uuid[8], uuid[9], uuid[10], uuid[11], - uuid[12], uuid[13], uuid[14], uuid[15], - creatorname, - iscontainer ? "container" : "vm", - (unsigned int)pidleader, - rootdir ? rootdir : "", - 3, - "Slice", "s", slicename, - "After", "as", 1, "libvirtd.service", - "Before", "as", 1, "libvirt-guests.service") < 0) - goto cleanup; + if (virAtomicIntGet(&hasCreateWithNetwork)) { + DBusError error; + dbus_error_init(&error); + + if (virDBusCallMethod(conn, + NULL, + &error, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "CreateMachineWithNetwork", + "sayssusa&ia(sv)", + machinename, + 16, + uuid[0], uuid[1], uuid[2], uuid[3], + uuid[4], uuid[5], uuid[6], uuid[7], + uuid[8], uuid[9], uuid[10], uuid[11], + uuid[12], uuid[13], uuid[14], uuid[15], + creatorname, + iscontainer ? "container" : "vm", + (unsigned int)pidleader, + rootdir ? rootdir : "", + nnicindexes, nicindexes, + 3, + "Slice", "s", slicename, + "After", "as", 1, "libvirtd.service", + "Before", "as", 1, "libvirt-guests.service") < 0) + goto cleanup; + + if (dbus_error_is_set(&error)) { + if (STREQ_NULLABLE("org.freedesktop.DBus.Error.UnknownMethod", + error.name)) { + VIR_INFO("CreateMachineWithNetwork isn't supported, switching " + "to legacy CreateMachine method for systemd-machined"); + dbus_error_free(&error); + virAtomicIntSet(&hasCreateWithNetwork, 0); + /* Could re-structure without Using goto, but this + * avoids another atomic read which would trigger + * another memory barrier */ + goto fallback; + } + virReportError(VIR_ERR_DBUS_SERVICE, + _("CreateMachineWithNetwork: %s"), + error.message ? error.message : _("unknown error")); + goto cleanup; + } + } else { + fallback: + if (virDBusCallMethod(conn, + NULL, + NULL, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "CreateMachine", + "sayssusa(sv)", + machinename, + 16, + uuid[0], uuid[1], uuid[2], uuid[3], + uuid[4], uuid[5], uuid[6], uuid[7], + uuid[8], uuid[9], uuid[10], uuid[11], + uuid[12], uuid[13], uuid[14], uuid[15], + creatorname, + iscontainer ? "container" : "vm", + (unsigned int)pidleader, + rootdir ? rootdir : "", + 3, + "Slice", "s", slicename, + "After", "as", 1, "libvirtd.service", + "Before", "as", 1, "libvirt-guests.service") < 0) + goto cleanup; + } ret = 0; diff --git a/src/util/virsystemd.h b/src/util/virsystemd.h index 491c9b7de3..7a29dbafff 100644 --- a/src/util/virsystemd.h +++ b/src/util/virsystemd.h @@ -40,6 +40,8 @@ int virSystemdCreateMachine(const char *name, const char *rootdir, pid_t pidleader, bool iscontainer, + size_t nnicindexes, + int *nicindexes, const char *partition); int virSystemdTerminateMachine(const char *name, diff --git a/tests/virsystemdtest.c b/tests/virsystemdtest.c index 0d57a6aae1..261c4cc345 100644 --- a/tests/virsystemdtest.c +++ b/tests/virsystemdtest.c @@ -146,6 +146,7 @@ static int testCreateContainer(const void *opaque ATTRIBUTE_UNUSED) "/proc/123/root", 123, true, + 0, NULL, "highpriority.slice") < 0) { fprintf(stderr, "%s", "Failed to create LXC machine\n"); return -1; @@ -181,6 +182,7 @@ static int testCreateMachine(const void *opaque ATTRIBUTE_UNUSED) NULL, 123, false, + 0, NULL, NULL) < 0) { fprintf(stderr, "%s", "Failed to create KVM machine\n"); return -1; @@ -220,6 +222,7 @@ static int testCreateNoSystemd(const void *opaque ATTRIBUTE_UNUSED) NULL, 123, false, + 0, NULL, NULL)) == 0) { unsetenv("FAIL_NO_SERVICE"); fprintf(stderr, "%s", "Unexpected create machine success\n"); @@ -254,6 +257,7 @@ static int testCreateSystemdNotRunning(const void *opaque ATTRIBUTE_UNUSED) NULL, 123, false, + 0, NULL, NULL)) == 0) { unsetenv("FAIL_NOT_REGISTERED"); fprintf(stderr, "%s", "Unexpected create machine success\n"); @@ -288,6 +292,7 @@ static int testCreateBadSystemd(const void *opaque ATTRIBUTE_UNUSED) NULL, 123, false, + 0, NULL, NULL)) == 0) { unsetenv("FAIL_BAD_SERVICE"); fprintf(stderr, "%s", "Unexpected create machine success\n"); @@ -304,6 +309,35 @@ static int testCreateBadSystemd(const void *opaque ATTRIBUTE_UNUSED) } +static int testCreateNetwork(const void *opaque ATTRIBUTE_UNUSED) +{ + unsigned char uuid[VIR_UUID_BUFLEN] = { + 1, 1, 1, 1, + 2, 2, 2, 2, + 3, 3, 3, 3, + 4, 4, 4, 4 + }; + int nicindexes[] = { + 2, 1729, 87539319, + }; + size_t nnicindexes = ARRAY_CARDINALITY(nicindexes); + if (virSystemdCreateMachine("demo", + "lxc", + true, + uuid, + "/proc/123/root", + 123, + true, + nnicindexes, nicindexes, + "highpriority.slice") < 0) { + fprintf(stderr, "%s", "Failed to create LXC machine\n"); + return -1; + } + + return 0; +} + + struct testScopeData { const char *name; const char *partition; @@ -435,6 +469,8 @@ mymain(void) ret = -1; if (virtTestRun("Test create bad systemd ", testCreateBadSystemd, NULL) < 0) ret = -1; + if (virtTestRun("Test create with network ", testCreateNetwork, NULL) < 0) + ret = -1; # define TEST_SCOPE(name, partition, unitname) \ do { \