]> xenbits.xensource.com Git - people/dariof/libvirt.git/commitdiff
Add APIs for formatting systemd slice/scope names
authorDaniel P. Berrange <berrange@redhat.com>
Fri, 26 Jul 2013 14:18:55 +0000 (15:18 +0100)
committerDaniel P. Berrange <berrange@redhat.com>
Wed, 31 Jul 2013 18:24:53 +0000 (19:24 +0100)
There are some interesting escaping rules to consider when dealing
with systemd slice/scope names. Thus it is helpful to have APIs
for formatting names

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
src/libvirt_private.syms
src/util/virsystemd.c
src/util/virsystemd.h
tests/virsystemdtest.c

index aaec1f9467694683c87ecf1bdb86fdc1e0f51e22..6e6e280f8c46b1ae3ed0ceb1687301e2b8efb673 100644 (file)
@@ -1936,6 +1936,8 @@ virSysinfoSetup;
 
 # util/virsystemd.h
 virSystemdCreateMachine;
+virSystemdMakeScopeName;
+virSystemdMakeSliceName;
 
 
 # util/virthread.h
index 11d1153045173a36e3ffcf9bb4507008dbf7b083..251b8463ffd5d4a0e7e00df4a1c08ff1ee4fc527 100644 (file)
 #include "viralloc.h"
 #include "virutil.h"
 #include "virlog.h"
+#include "virerror.h"
 
 #define VIR_FROM_THIS VIR_FROM_SYSTEMD
 
+
+static void virSystemdEscapeName(virBufferPtr buf,
+                                 const char *name)
+{
+    static const char hextable[16] = "0123456789abcdef";
+
+#define ESCAPE(c)                                                       \
+    do {                                                                \
+        virBufferAddChar(buf, '\\');                                    \
+        virBufferAddChar(buf, 'x');                                     \
+        virBufferAddChar(buf, hextable[(c >> 4) & 15]);                 \
+        virBufferAddChar(buf, hextable[c & 15]);                        \
+    } while (0)
+
+#define VALID_CHARS                             \
+        "0123456789"                            \
+        "abcdefghijklmnopqrstuvwxyz"            \
+        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"            \
+        ":-_.\\"
+
+    if (*name == '.') {
+        ESCAPE(*name);
+        name++;
+    }
+
+    while (*name) {
+        if (*name == '/')
+            virBufferAddChar(buf, '-');
+        else if (*name == '-' ||
+                 *name == '\\' ||
+                 !strchr(VALID_CHARS, *name))
+            ESCAPE(*name);
+        else
+            virBufferAddChar(buf, *name);
+        name++;
+    }
+
+#undef ESCAPE
+#undef VALID_CHARS
+}
+
+
+char *virSystemdMakeScopeName(const char *name,
+                              const char *drivername,
+                              const char *partition)
+{
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+    if (*partition == '/')
+        partition++;
+
+    virSystemdEscapeName(&buf, partition);
+    virBufferAddChar(&buf, '-');
+    virSystemdEscapeName(&buf, drivername);
+    virBufferAddLit(&buf, "\\x2d");
+    virSystemdEscapeName(&buf, name);
+    virBufferAddLit(&buf, ".scope");
+
+    if (virBufferError(&buf)) {
+        virReportOOMError();
+        return NULL;
+    }
+
+    return virBufferContentAndReset(&buf);
+}
+
+
+char *virSystemdMakeSliceName(const char *partition)
+{
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+    if (*partition == '/')
+        partition++;
+
+    virSystemdEscapeName(&buf, partition);
+    virBufferAddLit(&buf, ".slice");
+
+    if (virBufferError(&buf)) {
+        virReportOOMError();
+        return NULL;
+    }
+
+    return virBufferContentAndReset(&buf);
+}
+
+
 /**
  * virSystemdCreateMachine:
  * @name: driver unique name of the machine
@@ -75,8 +162,8 @@ int virSystemdCreateMachine(const char *name,
         goto cleanup;
 
     if (partition) {
-        if (virAsprintf(&slicename, "%s.slice", partition) < 0)
-            goto cleanup;
+        if (!(slicename = virSystemdMakeSliceName(partition)))
+             goto cleanup;
     } else {
         if (VIR_STRDUP(slicename, "") < 0)
             goto cleanup;
index 9ca4e0b206ea2dd99791c62dced34c01f7df2ad2..414ae5ac9fea2793e501f080b76b4721546280f4 100644 (file)
 
 # include "internal.h"
 
+char *virSystemdMakeScopeName(const char *name,
+                              const char *drivername,
+                              const char *slicename);
+char *virSystemdMakeSliceName(const char *partition);
+
 int virSystemdCreateMachine(const char *name,
                             const char *drivername,
                             bool privileged,
index bcf3ad32f8180b1980a227c8396870117f9d3082..a9c6d32eca2659ac6ed6cdbd8e0472dcd917d841 100644 (file)
@@ -138,6 +138,38 @@ static int testCreateBadSystemd(const void *opaque ATTRIBUTE_UNUSED)
     return 0;
 }
 
+
+struct testScopeData {
+    const char *name;
+    const char *partition;
+    const char *expected;
+};
+
+static int
+testScopeName(const void *opaque)
+{
+    const struct testScopeData *data = opaque;
+    int ret = -1;
+    char *actual = NULL;
+
+    if (!(actual = virSystemdMakeScopeName(data->name,
+                                           "lxc",
+                                           data->partition)))
+        goto cleanup;
+
+    if (STRNEQ(actual, data->expected)) {
+        fprintf(stderr, "Expected '%s' but got '%s'\n",
+                data->expected, actual);
+        goto cleanup;
+    }
+
+    ret = 0;
+
+ cleanup:
+    VIR_FREE(actual);
+    return ret;
+}
+
 static int
 mymain(void)
 {
@@ -152,6 +184,23 @@ mymain(void)
     if (virtTestRun("Test create bad systemd ", 1, testCreateBadSystemd, NULL) < 0)
         ret = -1;
 
+#define TEST_SCOPE(name, partition, unitname)                           \
+    do {                                                                \
+        struct testScopeData data = {                                   \
+            name, partition, unitname                                   \
+        };                                                              \
+        if (virtTestRun("Test scopename", 1, testScopeName, &data) < 0) \
+            ret = -1;                                                   \
+    } while (0)
+
+    TEST_SCOPE("demo", "/machine", "machine-lxc\\x2ddemo.scope");
+    TEST_SCOPE("demo-name", "/machine", "machine-lxc\\x2ddemo\\x2dname.scope");
+    TEST_SCOPE("demo!name", "/machine", "machine-lxc\\x2ddemo\\x21name.scope");
+    TEST_SCOPE(".demo", "/machine", "machine-lxc\\x2d\\x2edemo.scope");
+    TEST_SCOPE("demo", "/machine/eng-dept", "machine-eng\\x2ddept-lxc\\x2ddemo.scope");
+    TEST_SCOPE("demo", "/machine/eng-dept/testing!stuff",
+               "machine-eng\\x2ddept-testing\\x21stuff-lxc\\x2ddemo.scope");
+
     return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
 }