[libvirt] [PATCH 1/2] lxc: add support for docker-json Memory and VCPU conversion

Venkat Datta N H nhvenkatdatta at gmail.com
Fri Jun 16 14:29:44 UTC 2017


Docker Memory and VCPU configuration is converted to fit for LXC container XML configuration
---
 po/POTFILES.in                                     |   1 +
 src/Makefile.am                                    |   1 +
 src/lxc/lxc_driver.c                               |  13 ++-
 src/lxc/lxc_native.h                               |   1 +
 src/lxc/lxc_native_docker.c                        | 112 ++++++++++++++++++
 src/lxc/lxc_native_docker.h                        |  30 +++++
 tests/Makefile.am                                  |   8 +-
 .../dockerjson2xmldata-simple.json                 |  36 ++++++
 .../dockerjson2xmldata-simple.xml                  |  15 +++
 tests/dockerjson2xmltest.c                         | 127 +++++++++++++++++++++
 10 files changed, 338 insertions(+), 6 deletions(-)
 create mode 100644 src/lxc/lxc_native_docker.c
 create mode 100644 src/lxc/lxc_native_docker.h
 create mode 100644 tests/dockerjson2xmldata/dockerjson2xmldata-simple.json
 create mode 100644 tests/dockerjson2xmldata/dockerjson2xmldata-simple.xml
 create mode 100644 tests/dockerjson2xmltest.c

diff --git a/po/POTFILES.in b/po/POTFILES.in
index 275df1f..098be9f 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -111,6 +111,7 @@ src/lxc/lxc_driver.c
 src/lxc/lxc_fuse.c
 src/lxc/lxc_hostdev.c
 src/lxc/lxc_native.c
+src/lxc/lxc_native_docker.c
 src/lxc/lxc_process.c
 src/network/bridge_driver.c
 src/network/bridge_driver_linux.c
diff --git a/src/Makefile.am b/src/Makefile.am
index eae32dc..53d1bca 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -839,6 +839,7 @@ LXC_DRIVER_SOURCES =						\
 		lxc/lxc_process.c lxc/lxc_process.h		\
 		lxc/lxc_fuse.c lxc/lxc_fuse.h			\
 		lxc/lxc_native.c lxc/lxc_native.h		\
+		lxc/lxc_native_docker.c lxc/lxc_native_docker.h \
 		lxc/lxc_driver.c lxc/lxc_driver.h
 
 LXC_CONTROLLER_SOURCES =					\
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index 22c8b58..0f5a7870 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -53,6 +53,7 @@
 #include "lxc_driver.h"
 #include "lxc_native.h"
 #include "lxc_process.h"
+#include "lxc_native_docker.h"
 #include "viralloc.h"
 #include "virnetdevbridge.h"
 #include "virnetdevveth.h"
@@ -1062,15 +1063,17 @@ static char *lxcConnectDomainXMLFromNative(virConnectPtr conn,
     if (virConnectDomainXMLFromNativeEnsureACL(conn) < 0)
         goto cleanup;
 
-    if (STRNEQ(nativeFormat, LXC_CONFIG_FORMAT)) {
+    if (STREQ(nativeFormat, DOCKER_CONFIG_FORMAT)) {
+        if (!(def = dockerParseJSONConfig(caps, driver->xmlopt, nativeConfig)))
+            goto cleanup;
+    } else if (STREQ(nativeFormat, LXC_CONFIG_FORMAT)) {
+        if (!(def = lxcParseConfigString(nativeConfig, caps, driver->xmlopt)))
+            goto cleanup;
+    } else {
         virReportError(VIR_ERR_INVALID_ARG,
                        _("unsupported config type %s"), nativeFormat);
         goto cleanup;
     }
-
-    if (!(def = lxcParseConfigString(nativeConfig, caps, driver->xmlopt)))
-        goto cleanup;
-
     xml = virDomainDefFormat(def, caps, 0);
 
  cleanup:
diff --git a/src/lxc/lxc_native.h b/src/lxc/lxc_native.h
index 15fa0d5..88263ae 100644
--- a/src/lxc/lxc_native.h
+++ b/src/lxc/lxc_native.h
@@ -26,6 +26,7 @@
 # include "domain_conf.h"
 
 # define LXC_CONFIG_FORMAT "lxc-tools"
+# define DOCKER_CONFIG_FORMAT "docker"
 
 virDomainDefPtr lxcParseConfigString(const char *config,
                                      virCapsPtr caps,
diff --git a/src/lxc/lxc_native_docker.c b/src/lxc/lxc_native_docker.c
new file mode 100644
index 0000000..a278309
--- /dev/null
+++ b/src/lxc/lxc_native_docker.c
@@ -0,0 +1,112 @@
+/*
+ * lxc_native_docker.c: LXC native docker configuration import
+ *
+ * Copyright (C) 2017 Venkat Datta N H
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Venkat Datta N H <nhvenkatdatta at gmail.com>
+ */
+#include <config.h>
+#include "util/viralloc.h"
+#include "util/virfile.h"
+#include "util/virstring.h"
+#include "util/virconf.h"
+#include "util/virjson.h"
+#include "util/virutil.h"
+#include "virerror.h"
+#include "virlog.h"
+#include "conf/domain_conf.h"
+#include "lxc_native_docker.h"
+#include "secret_conf.h"
+#define VIR_FROM_THIS VIR_FROM_LXC
+VIR_LOG_INIT("lxc.lxc_native_docker");
+
+static int dockerParseVCpus(virDomainDefPtr dom,
+                            virDomainXMLOptionPtr xmlopt,
+                            virJSONValuePtr prop)
+{
+    int vcpus;
+
+    if (virJSONValueObjectGetNumberInt(prop, "CpuShares", &vcpus)  != 0)
+        return -1;
+
+    if (virDomainDefSetVcpusMax(dom, vcpus, xmlopt) < 0)
+        return -1;
+
+    if (virDomainDefSetVcpus(dom, vcpus) < 0)
+        return -1;
+
+    return 0;
+}
+
+static int dockerParseMem(virDomainDefPtr dom,
+                   virJSONValuePtr prop)
+{
+    unsigned long long mem;
+
+    if (virJSONValueObjectGetNumberUlong(prop, "Memory", &mem) != 0)
+        return -1;
+
+    virDomainDefSetMemoryTotal(dom, mem / 1024);
+    dom->mem.cur_balloon = mem / 1024;
+
+    return 0;
+}
+
+virDomainDefPtr dockerParseJSONConfig(virCapsPtr caps ATTRIBUTE_UNUSED,
+                                      virDomainXMLOptionPtr xmlopt,
+                                      const char *config)
+{
+    virJSONValuePtr json_obj;
+    virJSONValuePtr host_config;
+
+    if (!(json_obj = virJSONValueFromString(config)))
+        return NULL;
+
+    virDomainDefPtr def;
+
+    if (!(def = virDomainDefNew()))
+        goto error;
+
+    def->id = -1;
+    def->mem.cur_balloon = 64*1024;
+    virDomainDefSetMemoryTotal(def, def->mem.cur_balloon);
+
+    if ((host_config = virJSONValueObjectGetObject(json_obj, "HostConfig")) != NULL) {
+        if (dockerParseVCpus(def, xmlopt, host_config) < 0) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("failed to parse VCpu"));
+            goto error;
+        }
+
+        if (dockerParseMem(def, host_config) < 0) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("failed to parse Memory"));
+            goto error;
+        }
+    }
+
+    def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_UTC;
+    def->onReboot = VIR_DOMAIN_LIFECYCLE_RESTART;
+    def->onCrash = VIR_DOMAIN_LIFECYCLE_CRASH_DESTROY;
+    def->onPoweroff = VIR_DOMAIN_LIFECYCLE_DESTROY;
+    def->virtType = VIR_DOMAIN_VIRT_LXC;
+    def->os.type = VIR_DOMAIN_OSTYPE_EXE;
+
+    return def;
+
+ error:
+    virDomainDefFree(def);
+    return NULL;
+}
diff --git a/src/lxc/lxc_native_docker.h b/src/lxc/lxc_native_docker.h
new file mode 100644
index 0000000..40285f9
--- /dev/null
+++ b/src/lxc/lxc_native_docker.h
@@ -0,0 +1,30 @@
+/*
+ * lxc_native_docker.h: header file for LXC native docker configuration
+ *
+ * Copyright (C) 2017 Venkat Datta N H
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Venkat Datta N H <nhvenkatdatta at gmail.com>
+ */
+#ifndef __LXC_NATIVE_DOCKER_H__
+# define __LXC_NATIVE_DOCKER_H__
+# include "domain_conf.h"
+
+virDomainDefPtr dockerParseJSONConfig(virCapsPtr caps,
+                                           virDomainXMLOptionPtr xmlopt,
+                                           const char *config);
+
+#endif
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 19986dc..3beb634 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -93,6 +93,7 @@ EXTRA_DIST =		\
 	capabilityschemadata \
 	commanddata \
 	cputestdata \
+	dockerjson2xmldata \
 	domaincapsschemadata \
 	domainconfdata \
 	domainschemadata \
@@ -295,7 +296,7 @@ test_libraries += libqemumonitortestutils.la \
 endif WITH_QEMU
 
 if WITH_LXC
-test_programs += lxcxml2xmltest lxcconf2xmltest
+test_programs += lxcxml2xmltest lxcconf2xmltest dockerjson2xmltest
 endif WITH_LXC
 
 if WITH_OPENVZ
@@ -693,6 +694,11 @@ lxcconf2xmltest_SOURCES = \
 	lxcconf2xmltest.c testutilslxc.c testutilslxc.h \
 	testutils.c testutils.h
 lxcconf2xmltest_LDADD = $(lxc_LDADDS)
+
+dockerjson2xmltest_SOURCES = \
+	dockerjson2xmltest.c testutilslxc.c testutilslxc.h \
+	testutils.c testutils.h
+dockerjson2xmltest_LDADD = $(lxc_LDADDS)
 else ! WITH_LXC
 EXTRA_DIST += lxcxml2xmltest.c testutilslxc.c testutilslxc.h
 endif ! WITH_LXC
diff --git a/tests/dockerjson2xmldata/dockerjson2xmldata-simple.json b/tests/dockerjson2xmldata/dockerjson2xmldata-simple.json
new file mode 100644
index 0000000..63470be
--- /dev/null
+++ b/tests/dockerjson2xmldata/dockerjson2xmldata-simple.json
@@ -0,0 +1,36 @@
+{
+	"Id": "dbb1ae21dac15973d66e6c2b8516d270b32ca766e0cf7551d8b7973513e5f079",
+        "Created": "2017-05-25T18:55:17.922934825Z",
+        "Path": "/bin/bash",
+        "Args": [],
+        "HostConfig": {
+            "Binds": null,
+            "ContainerIDFile": "",
+            "LogConfig": {
+                "Type": "json-file",
+                "Config": {}
+            },
+            "NetworkMode": "default",
+            "PortBindings": {},
+            "ShmSize": 67108864,
+            "Runtime": "runc",
+            "Isolation": "",
+            "CpuShares": 2,
+            "Memory": 1073741824,
+            "CgroupParent": "",
+            "CpuPeriod": 0,
+            "CpuQuota": 0,
+            "CpusetCpus": "",
+            "CpusetMems": "",
+            "KernelMemory": 0,
+            "MemoryReservation": 0,
+            "MemorySwap": -1,
+            "MemorySwappiness": -1,
+            "PidsLimit": 0,
+            "Ulimits": null,
+            "CpuCount": 0,
+            "CpuPercent": 0,
+            "IOMaximumIOps": 0,
+            "IOMaximumBandwidth": 0
+        }
+}
diff --git a/tests/dockerjson2xmldata/dockerjson2xmldata-simple.xml b/tests/dockerjson2xmldata/dockerjson2xmldata-simple.xml
new file mode 100644
index 0000000..8be1ace
--- /dev/null
+++ b/tests/dockerjson2xmldata/dockerjson2xmldata-simple.xml
@@ -0,0 +1,15 @@
+<domain type='lxc'>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>1048576</memory>
+  <currentMemory unit='KiB'>1048576</currentMemory>
+  <vcpu placement='static'>2</vcpu>
+  <os>
+    <type>exe</type>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+  </devices>
+</domain>
diff --git a/tests/dockerjson2xmltest.c b/tests/dockerjson2xmltest.c
new file mode 100644
index 0000000..41c46a1
--- /dev/null
+++ b/tests/dockerjson2xmltest.c
@@ -0,0 +1,127 @@
+#include <config.h>
+
+#include "testutils.h"
+
+#ifdef WITH_LXC
+
+# include "lxc/lxc_native_docker.h"
+# include "lxc/lxc_conf.h"
+# include "testutilslxc.h"
+
+# define VIR_FROM_THIS VIR_FROM_NONE
+
+static virCapsPtr caps;
+static virDomainXMLOptionPtr xmlopt;
+
+static int testSanitizeDef(virDomainDefPtr vmdef)
+{
+    /* Remove UUID randomness */
+    if (virUUIDParse("c7a5fdbd-edaf-9455-926a-d65c16db1809", vmdef->uuid) < 0)
+        return -1;
+    return 0;
+}
+
+static int
+testCompareXMLToConfigFiles(const char *xmlfile,
+                            const char *configfile,
+                            bool expectError)
+{
+    int ret = -1;
+    char *config = NULL;
+    char *actualxml = NULL;
+    virDomainDefPtr vmdef = NULL;
+
+    if (virTestLoadFile(configfile, &config) < 0)
+        goto fail;
+
+    vmdef = dockerParseJSONConfig(caps, xmlopt, config);
+
+    if (vmdef && expectError) {
+        if (testSanitizeDef(vmdef) < 0)
+            goto fail;
+
+        if (!(actualxml = virDomainDefFormat(vmdef, caps, 0)))
+            goto fail;
+
+        if (virTestCompareToFile(actualxml, xmlfile) < 0)
+            goto fail;
+    }
+
+    ret = 0;
+
+ fail:
+    VIR_FREE(actualxml);
+    VIR_FREE(config);
+    virDomainDefFree(vmdef);
+    return ret;
+}
+
+struct testInfo {
+    const char *name;
+    bool expectError;
+};
+
+static int
+testCompareXMLToConfigHelper(const void *data)
+{
+    int result = -1;
+    const struct testInfo *info = data;
+    char *xml = NULL;
+    char *config = NULL;
+
+    if (virAsprintf(&xml, "%s/dockerjson2xmldata/dockerjson2xmldata-%s.xml",
+                    abs_srcdir, info->name) < 0 ||
+        virAsprintf(&config, "%s/dockerjson2xmldata/dockerjson2xmldata-%s.json",
+                    abs_srcdir, info->name) < 0)
+        goto cleanup;
+
+    result = testCompareXMLToConfigFiles(xml, config, info->expectError);
+
+ cleanup:
+    VIR_FREE(xml);
+    VIR_FREE(config);
+    return result;
+}
+
+static int
+mymain(void)
+{
+    int ret = EXIT_SUCCESS;
+
+    if (!(caps = testLXCCapsInit()))
+        return EXIT_FAILURE;
+
+    if (!(xmlopt = lxcDomainXMLConfInit())) {
+        virObjectUnref(caps);
+        return EXIT_FAILURE;
+    }
+
+
+# define DO_TEST(name, expectError)                         \
+    do {                                                    \
+        const struct testInfo info = { name, expectError }; \
+        if (virTestRun("DOCKER JSON-2-XML " name,            \
+                       testCompareXMLToConfigHelper,        \
+                       &info) < 0)                          \
+            ret = EXIT_FAILURE;                             \
+    } while (0)
+
+    DO_TEST("simple", true);
+
+    virObjectUnref(xmlopt);
+    virObjectUnref(caps);
+
+    return ret;
+}
+
+VIR_TEST_MAIN(mymain)
+
+#else
+
+int
+main(void)
+{
+    return EXIT_AM_SKIP;
+}
+
+#endif /* WITH_LXC */
-- 
2.7.4




More information about the libvir-list mailing list