43fe83
From ba776c58abac13bd5a539cd128c002284a363f58 Mon Sep 17 00:00:00 2001
43fe83
Message-Id: <ba776c58abac13bd5a539cd128c002284a363f58.1375465853.git.jdenemar@redhat.com>
43fe83
From: "Daniel P. Berrange" <berrange@redhat.com>
43fe83
Date: Wed, 31 Jul 2013 19:48:20 +0100
43fe83
Subject: [PATCH] Enable support for systemd-machined in cgroups creation
43fe83
43fe83
https://bugzilla.redhat.com/show_bug.cgi?id=980929
43fe83
43fe83
Make the virCgroupNewMachine method try to use systemd-machined
43fe83
first. If that fails, then fallback to using the traditional
43fe83
cgroup setup code path.
43fe83
43fe83
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
43fe83
43fe83
(cherry picked from commit 2fe2470181ce3722788fd7125d3f1f9be87e6278)
43fe83
---
43fe83
 src/lxc/lxc_process.c  |  10 +--
43fe83
 src/qemu/qemu_cgroup.c |   1 +
43fe83
 src/util/vircgroup.c   | 187 ++++++++++++++++++++++++++++++++++++++++++++-----
43fe83
 src/util/vircgroup.h   |   1 +
43fe83
 4 files changed, 179 insertions(+), 20 deletions(-)
43fe83
43fe83
diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c
43fe83
index 247e516..0a28305 100644
43fe83
--- a/src/lxc/lxc_process.c
43fe83
+++ b/src/lxc/lxc_process.c
43fe83
@@ -1203,8 +1203,9 @@ int virLXCProcessStart(virConnectPtr conn,
43fe83
         goto cleanup;
43fe83
     }
43fe83
 
43fe83
-    if (virCgroupNewDetectMachine(vm->def->name, "lxc",
43fe83
-                                  vm->pid, -1, &priv->cgroup) < 0)
43fe83
+    if (virCgroupNewDetectMachine(vm->def->name, "lxc", vm->pid,
43fe83
+                                  vm->def->resource->partition,
43fe83
+                                  -1, &priv->cgroup) < 0)
43fe83
         goto error;
43fe83
 
43fe83
     if (!priv->cgroup) {
43fe83
@@ -1411,8 +1412,9 @@ virLXCProcessReconnectDomain(virDomainObjPtr vm,
43fe83
         if (!(priv->monitor = virLXCProcessConnectMonitor(driver, vm)))
43fe83
             goto error;
43fe83
 
43fe83
-        if (virCgroupNewDetectMachine(vm->def->name, "lxc",
43fe83
-                                      vm->pid, -1, &priv->cgroup) < 0)
43fe83
+        if (virCgroupNewDetectMachine(vm->def->name, "lxc", vm->pid,
43fe83
+                                      vm->def->resource->partition,
43fe83
+                                      -1, &priv->cgroup) < 0)
43fe83
             goto error;
43fe83
 
43fe83
         if (!priv->cgroup) {
43fe83
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
43fe83
index 9f6b251..787ddeb 100644
43fe83
--- a/src/qemu/qemu_cgroup.c
43fe83
+++ b/src/qemu/qemu_cgroup.c
43fe83
@@ -707,6 +707,7 @@ qemuConnectCgroup(virQEMUDriverPtr driver,
43fe83
     if (virCgroupNewDetectMachine(vm->def->name,
43fe83
                                   "qemu",
43fe83
                                   vm->pid,
43fe83
+                                  vm->def->resource->partition,
43fe83
                                   cfg->cgroupControllers,
43fe83
                                   &priv->cgroup) < 0)
43fe83
         goto cleanup;
43fe83
diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
43fe83
index a70bb98..cfb4b3f 100644
43fe83
--- a/src/util/vircgroup.c
43fe83
+++ b/src/util/vircgroup.c
43fe83
@@ -50,6 +50,7 @@
43fe83
 #include "virhash.h"
43fe83
 #include "virhashcode.h"
43fe83
 #include "virstring.h"
43fe83
+#include "virsystemd.h"
43fe83
 
43fe83
 #define CGROUP_MAX_VAL 512
43fe83
 
43fe83
@@ -102,11 +103,13 @@ static bool
43fe83
 virCgroupValidateMachineGroup(virCgroupPtr group,
43fe83
                               const char *name,
43fe83
                               const char *drivername,
43fe83
+                              const char *partition,
43fe83
                               bool stripEmulatorSuffix)
43fe83
 {
43fe83
     size_t i;
43fe83
     bool valid = false;
43fe83
     char *partname;
43fe83
+    char *scopename;
43fe83
 
43fe83
     if (virAsprintf(&partname, "%s.libvirt-%s",
43fe83
                     name, drivername) < 0)
43fe83
@@ -115,6 +118,15 @@ virCgroupValidateMachineGroup(virCgroupPtr group,
43fe83
     if (virCgroupPartitionEscape(&partname) < 0)
43fe83
         goto cleanup;
43fe83
 
43fe83
+    if (!partition)
43fe83
+        partition = "/machine";
43fe83
+
43fe83
+    if (!(scopename = virSystemdMakeScopeName(name, drivername, partition)))
43fe83
+        goto cleanup;
43fe83
+
43fe83
+    if (virCgroupPartitionEscape(&scopename) < 0)
43fe83
+        goto cleanup;
43fe83
+
43fe83
     for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
43fe83
         char *tmp;
43fe83
 
43fe83
@@ -142,9 +154,10 @@ virCgroupValidateMachineGroup(virCgroupPtr group,
43fe83
         tmp++;
43fe83
 
43fe83
         if (STRNEQ(tmp, name) &&
43fe83
-            STRNEQ(tmp, partname)) {
43fe83
-            VIR_DEBUG("Name '%s' for controller '%s' does not match '%s' or '%s'",
43fe83
-                      tmp, virCgroupControllerTypeToString(i), name, partname);
43fe83
+            STRNEQ(tmp, partname) &&
43fe83
+            STRNEQ(tmp, scopename)) {
43fe83
+            VIR_DEBUG("Name '%s' for controller '%s' does not match '%s', '%s' or '%s'",
43fe83
+                      tmp, virCgroupControllerTypeToString(i), name, partname, scopename);
43fe83
             goto cleanup;
43fe83
         }
43fe83
     }
43fe83
@@ -153,6 +166,7 @@ virCgroupValidateMachineGroup(virCgroupPtr group,
43fe83
 
43fe83
  cleanup:
43fe83
     VIR_FREE(partname);
43fe83
+    VIR_FREE(scopename);
43fe83
     return valid;
43fe83
 }
43fe83
 #else
43fe83
@@ -1649,6 +1663,7 @@ int virCgroupNewDetect(pid_t pid ATTRIBUTE_UNUSED,
43fe83
 int virCgroupNewDetectMachine(const char *name,
43fe83
                               const char *drivername,
43fe83
                               pid_t pid,
43fe83
+                              const char *partition,
43fe83
                               int controllers,
43fe83
                               virCgroupPtr *group)
43fe83
 {
43fe83
@@ -1658,7 +1673,7 @@ int virCgroupNewDetectMachine(const char *name,
43fe83
         return -1;
43fe83
     }
43fe83
 
43fe83
-    if (!virCgroupValidateMachineGroup(*group, name, drivername, true)) {
43fe83
+    if (!virCgroupValidateMachineGroup(*group, name, drivername, partition, true)) {
43fe83
         VIR_DEBUG("Failed to validate machine name for '%s' driver '%s'",
43fe83
                   name, drivername);
43fe83
         virCgroupFree(group);
43fe83
@@ -1668,22 +1683,124 @@ int virCgroupNewDetectMachine(const char *name,
43fe83
     return 0;
43fe83
 }
43fe83
 
43fe83
-int virCgroupNewMachine(const char *name,
43fe83
-                        const char *drivername,
43fe83
-                        bool privileged ATTRIBUTE_UNUSED,
43fe83
-                        const unsigned char *uuid ATTRIBUTE_UNUSED,
43fe83
-                        const char *rootdir ATTRIBUTE_UNUSED,
43fe83
-                        pid_t pidleader ATTRIBUTE_UNUSED,
43fe83
-                        bool isContainer ATTRIBUTE_UNUSED,
43fe83
-                        const char *partition,
43fe83
-                        int controllers,
43fe83
-                        virCgroupPtr *group)
43fe83
+/*
43fe83
+ * Returns 0 on success, -1 on fatal error, -2 on systemd not available
43fe83
+ */
43fe83
+static int
43fe83
+virCgroupNewMachineSystemd(const char *name,
43fe83
+                           const char *drivername,
43fe83
+                           bool privileged,
43fe83
+                           const unsigned char *uuid,
43fe83
+                           const char *rootdir,
43fe83
+                           pid_t pidleader,
43fe83
+                           bool isContainer,
43fe83
+                           const char *partition,
43fe83
+                           int controllers,
43fe83
+                           virCgroupPtr *group)
43fe83
 {
43fe83
-    virCgroupPtr parent = NULL;
43fe83
     int ret = -1;
43fe83
+    int rv;
43fe83
+    virCgroupPtr init, parent = NULL;
43fe83
+    char *path = NULL;
43fe83
+    char *offset;
43fe83
+
43fe83
+    VIR_DEBUG("Trying to setup machine '%s' via systemd", name);
43fe83
+    if ((rv = virSystemdCreateMachine(name,
43fe83
+                                      drivername,
43fe83
+                                      privileged,
43fe83
+                                      uuid,
43fe83
+                                      rootdir,
43fe83
+                                      pidleader,
43fe83
+                                      isContainer,
43fe83
+                                      partition)) < 0)
43fe83
+        return rv;
43fe83
+
43fe83
+    if (controllers != -1)
43fe83
+        controllers |= (1 << VIR_CGROUP_CONTROLLER_SYSTEMD);
43fe83
+
43fe83
+    VIR_DEBUG("Detecting systemd placement");
43fe83
+    if (virCgroupNewDetect(pidleader,
43fe83
+                           controllers,
43fe83
+                           &init) < 0)
43fe83
+        return -1;
43fe83
 
43fe83
-    *group = NULL;
43fe83
+    path = init->controllers[VIR_CGROUP_CONTROLLER_SYSTEMD].placement;
43fe83
+    init->controllers[VIR_CGROUP_CONTROLLER_SYSTEMD].placement = NULL;
43fe83
+    virCgroupFree(&init);
43fe83
+
43fe83
+    if (!path || STREQ(path, "/") || path[0] != '/') {
43fe83
+        VIR_DEBUG("Systemd didn't setup its controller");
43fe83
+        ret = -2;
43fe83
+        goto cleanup;
43fe83
+    }
43fe83
+
43fe83
+    offset = path;
43fe83
+
43fe83
+    if (virCgroupNew(pidleader,
43fe83
+                     "",
43fe83
+                     NULL,
43fe83
+                     controllers,
43fe83
+                     &parent) < 0)
43fe83
+        goto cleanup;
43fe83
+
43fe83
+
43fe83
+    for (;;) {
43fe83
+        virCgroupPtr tmp;
43fe83
+        char *t = strchr(offset + 1, '/');
43fe83
+        if (t)
43fe83
+            *t = '\0';
43fe83
+
43fe83
+        if (virCgroupNew(pidleader,
43fe83
+                         path,
43fe83
+                         parent,
43fe83
+                         controllers,
43fe83
+                         &tmp) < 0)
43fe83
+            goto cleanup;
43fe83
+
43fe83
+        if (virCgroupMakeGroup(parent, tmp, true, VIR_CGROUP_NONE) < 0) {
43fe83
+            virCgroupFree(&tmp);
43fe83
+            goto cleanup;
43fe83
+        }
43fe83
+        if (t) {
43fe83
+            *t = '/';
43fe83
+            offset = t;
43fe83
+            virCgroupFree(&parent);
43fe83
+            parent = tmp;
43fe83
+        } else {
43fe83
+            *group = tmp;
43fe83
+            break;
43fe83
+        }
43fe83
+    }
43fe83
+
43fe83
+    if (virCgroupAddTask(*group, pidleader) < 0) {
43fe83
+        virErrorPtr saved = virSaveLastError();
43fe83
+        virCgroupRemove(*group);
43fe83
+        virCgroupFree(group);
43fe83
+        if (saved) {
43fe83
+            virSetError(saved);
43fe83
+            virFreeError(saved);
43fe83
+        }
43fe83
+    }
43fe83
+
43fe83
+    ret = 0;
43fe83
+ cleanup:
43fe83
+    virCgroupFree(&parent);
43fe83
+    VIR_FREE(path);
43fe83
+    return ret;
43fe83
+}
43fe83
 
43fe83
+static int
43fe83
+virCgroupNewMachineManual(const char *name,
43fe83
+                          const char *drivername,
43fe83
+                          pid_t pidleader,
43fe83
+                          const char *partition,
43fe83
+                          int controllers,
43fe83
+                          virCgroupPtr *group)
43fe83
+{
43fe83
+    virCgroupPtr parent = NULL;
43fe83
+    int ret = -1;
43fe83
+
43fe83
+    VIR_DEBUG("Fallback to non-systemd setup");
43fe83
     if (virCgroupNewPartition(partition,
43fe83
                               STREQ(partition, "/machine"),
43fe83
                               controllers,
43fe83
@@ -1719,6 +1836,44 @@ cleanup:
43fe83
     return ret;
43fe83
 }
43fe83
 
43fe83
+int virCgroupNewMachine(const char *name,
43fe83
+                        const char *drivername,
43fe83
+                        bool privileged,
43fe83
+                        const unsigned char *uuid,
43fe83
+                        const char *rootdir,
43fe83
+                        pid_t pidleader,
43fe83
+                        bool isContainer,
43fe83
+                        const char *partition,
43fe83
+                        int controllers,
43fe83
+                        virCgroupPtr *group)
43fe83
+{
43fe83
+    int rv;
43fe83
+
43fe83
+    *group = NULL;
43fe83
+
43fe83
+    if ((rv = virCgroupNewMachineSystemd(name,
43fe83
+                                         drivername,
43fe83
+                                         privileged,
43fe83
+                                         uuid,
43fe83
+                                         rootdir,
43fe83
+                                         pidleader,
43fe83
+                                         isContainer,
43fe83
+                                         partition,
43fe83
+                                         controllers,
43fe83
+                                         group)) == 0)
43fe83
+        return 0;
43fe83
+
43fe83
+    if (rv == -1)
43fe83
+        return -1;
43fe83
+
43fe83
+    return virCgroupNewMachineManual(name,
43fe83
+                                     drivername,
43fe83
+                                     pidleader,
43fe83
+                                     partition,
43fe83
+                                     controllers,
43fe83
+                                     group);
43fe83
+}
43fe83
+
43fe83
 bool virCgroupNewIgnoreError(void)
43fe83
 {
43fe83
     if (virLastErrorIsSystemErrno(ENXIO) ||
43fe83
diff --git a/src/util/vircgroup.h b/src/util/vircgroup.h
43fe83
index e579f41..d7ce892 100644
43fe83
--- a/src/util/vircgroup.h
43fe83
+++ b/src/util/vircgroup.h
43fe83
@@ -83,6 +83,7 @@ int virCgroupNewDetect(pid_t pid,
43fe83
 int virCgroupNewDetectMachine(const char *name,
43fe83
                               const char *drivername,
43fe83
                               pid_t pid,
43fe83
+                              const char *partition,
43fe83
                               int controllers,
43fe83
                               virCgroupPtr *group);
43fe83
 
43fe83
-- 
43fe83
1.8.3.2
43fe83