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

Cedric Bosdonnat cbosdonnat at suse.com
Fri Jun 16 15:49:54 UTC 2017


Quick note: next time you send a patch series, add a cover letter to it.
You can get git to automatically ask you about one by running
 
    git config add format.coverletter auto

Having reviewed them off-list first, ACK from me to those changes.
Daniel, do you want to double-review them?

--
Cedric

On Fri, 2017-06-16 at 19:59 +0530, Venkat Datta N H wrote:
> 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 */




More information about the libvir-list mailing list