[libvirt] [PATCH 1/4] Add support for systemd-machined CreateMachineWithNetwork

Daniel P. Berrange berrange at redhat.com
Wed Jan 14 14:05:44 UTC 2015


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 CreateeMachine 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 094c8e3..2db8786 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 eb67191..728e8e5 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 1acb77d..d71ffbc 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 64bc647..f5f617e 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 f07c1a7..9f984e7 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 ddfc047..3eea5c2 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 491c9b7..7a29dba 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 0d57a6a..261c4cc 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 {                                                                \
-- 
2.1.0




More information about the libvir-list mailing list