Discussion:
[libvirt] [PATCH v3 03/21] LXC from native: import rootfs
(too old to reply)
Cédric Bosdonnat
2014-02-05 14:10:01 UTC
Permalink
LXC rootfs can be either a directory or a block device or an image
file. The first two types have been implemented, but the image file is
still to be done since LXC auto-guesses the file format at mount time
and the LXC driver doesn't support the 'auto' format.
---
src/lxc/lxc_native.c | 69 ++++++++++++++++++++++++++++
tests/lxcconf2xmldata/lxcconf2xml-simple.xml | 4 ++
2 files changed, 73 insertions(+)

diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c
index 723ebcf..86d0dd3 100644
--- a/src/lxc/lxc_native.c
+++ b/src/lxc/lxc_native.c
@@ -31,6 +31,72 @@

#define VIR_FROM_THIS VIR_FROM_LXC

+
+static virDomainFSDefPtr
+lxcCreateFSDef(int type, char *src, char* dst)
+{
+ virDomainFSDefPtr def;
+
+ if (VIR_ALLOC(def) < 0)
+ return NULL;
+
+ def->type = type;
+ def->accessmode = VIR_DOMAIN_FS_ACCESSMODE_PASSTHROUGH;
+ def->src = src;
+ def->dst = dst;
+
+ return def;
+}
+
+static int
+lxcAddFSDef(virDomainDefPtr def, int type, char *src, char *dst)
+{
+ virDomainFSDefPtr fsDef = NULL;
+
+ if (!(fsDef = lxcCreateFSDef(type, src, dst)))
+ goto error;
+
+ if (VIR_EXPAND_N(def->fss, def->nfss, 1) < 0)
+ goto error;
+ def->fss[def->nfss - 1] = fsDef;
+
+ return 0;
+
+error:
+ virDomainFSDefFree(fsDef);
+ return -1;
+}
+
+static int
+lxcSetRootfs(virDomainDefPtr def,
+ virConfPtr properties)
+{
+ char *fssrc = NULL;
+ char *fsdst = NULL;
+ int type = VIR_DOMAIN_FS_TYPE_MOUNT;
+ virConfValuePtr value;
+
+ if (!(value = virConfGetValue(properties, "lxc.rootfs")) ||
+ !value->str ||
+ (VIR_STRDUP(fssrc, value->str) < 0) ||
+ VIR_STRDUP(fsdst, "/") < 0)
+ goto error;
+
+ if (STRPREFIX(fssrc, "/dev/"))
+ type = VIR_DOMAIN_FS_TYPE_BLOCK;
+
+
+ if (lxcAddFSDef(def, type, fssrc, fsdst) < 0)
+ goto error;
+
+ return 0;
+
+error:
+ VIR_FREE(fssrc);
+ VIR_FREE(fsdst);
+ return -1;
+}
+
virDomainDefPtr
lxcParseConfigString(const char *config)
{
@@ -73,6 +139,9 @@ lxcParseConfigString(const char *config)
if (!vmdef->name && (VIR_STRDUP(vmdef->name, "unnamed") < 0))
goto error;

+ if (lxcSetRootfs(vmdef, properties) < 0)
+ goto error;
+
goto cleanup;

error:
diff --git a/tests/lxcconf2xmldata/lxcconf2xml-simple.xml b/tests/lxcconf2xmldata/lxcconf2xml-simple.xml
index 641e624..eebcb4e 100644
--- a/tests/lxcconf2xmldata/lxcconf2xml-simple.xml
+++ b/tests/lxcconf2xmldata/lxcconf2xml-simple.xml
@@ -13,5 +13,9 @@
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
+ <filesystem type='mount' accessmode='passthrough'>
+ <source dir='/var/lib/lxc/migrate_test/rootfs'/>
+ <target dir='/'/>
+ </filesystem>
</devices>
</domain>
--
1.8.5.2
Cédric Bosdonnat
2014-02-05 14:10:08 UTC
Permalink
---
src/lxc/lxc_native.c | 44 ++++++++++++++++++++++++++
tests/lxcconf2xmldata/lxcconf2xml-idmap.config | 5 +++
tests/lxcconf2xmldata/lxcconf2xml-idmap.xml | 28 ++++++++++++++++
tests/lxcconf2xmltest.c | 1 +
4 files changed, 78 insertions(+)
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-idmap.config
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-idmap.xml

diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c
index b413e42..dd706f8 100644
--- a/src/lxc/lxc_native.c
+++ b/src/lxc/lxc_native.c
@@ -567,6 +567,46 @@ error:
return -1;
}

+static int
+lxcIdmapWalkCallback(const char *name, virConfValuePtr value, void *data)
+{
+ virDomainDefPtr def = data;
+ virDomainIdMapEntryPtr idmap = NULL;
+ char type;
+ unsigned long start, target, count;
+
+ if (STRNEQ(name, "lxc.id_map") || !value->str)
+ return 0;
+
+ if (sscanf(value->str, "%c %lu %lu %lu", &type,
+ &target, &start, &count) != 4) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, _("invalid lxc.id_map: '%s'"),
+ value->str);
+ return -1;
+ }
+
+ if (VIR_ALLOC(idmap) < 0)
+ return -1;
+
+ if (type == 'u') {
+ if (VIR_EXPAND_N(def->idmap.uidmap, def->idmap.nuidmap, 1) < 0)
+ return -1;
+ idmap = &def->idmap.uidmap[def->idmap.nuidmap - 1];
+ } else if (type == 'g') {
+ if (VIR_EXPAND_N(def->idmap.gidmap, def->idmap.ngidmap, 1) < 0)
+ return -1;
+ idmap = &def->idmap.gidmap[def->idmap.ngidmap - 1];
+ } else {
+ return -1;
+ }
+
+ idmap->start = start;
+ idmap->target = target;
+ idmap->count = count;
+
+ return 0;
+}
+
virDomainDefPtr
lxcParseConfigString(const char *config)
{
@@ -635,6 +675,10 @@ lxcParseConfigString(const char *config)
if (lxcCreateConsoles(vmdef, properties) < 0)
goto error;

+ /* lxc.id_map */
+ if (virConfWalk(properties, lxcIdmapWalkCallback, vmdef) < 0)
+ goto error;
+
goto cleanup;

error:
diff --git a/tests/lxcconf2xmldata/lxcconf2xml-idmap.config b/tests/lxcconf2xmldata/lxcconf2xml-idmap.config
new file mode 100644
index 0000000..4c3657a
--- /dev/null
+++ b/tests/lxcconf2xmldata/lxcconf2xml-idmap.config
@@ -0,0 +1,5 @@
+lxc.rootfs = /var/lib/lxc/migrate_test/rootfs
+lxc.utsname = migrate_test
+
+lxc.id_map = u 10000 0 2000
+lxc.id_map = g 10000 0 1000
diff --git a/tests/lxcconf2xmldata/lxcconf2xml-idmap.xml b/tests/lxcconf2xmldata/lxcconf2xml-idmap.xml
new file mode 100644
index 0000000..576c903
--- /dev/null
+++ b/tests/lxcconf2xmldata/lxcconf2xml-idmap.xml
@@ -0,0 +1,28 @@
+<domain type='lxc'>
+ <name>migrate_test</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>65536</memory>
+ <currentMemory unit='KiB'>0</currentMemory>
+ <vcpu placement='static' current='0'>1</vcpu>
+ <os>
+ <type>exe</type>
+ <init>/sbin/init</init>
+ </os>
+ <idmap>
+ <uid start='0' target='10000' count='2000'/>
+ <gid start='0' target='10000' count='1000'/>
+ </idmap>
+ <features>
+ <privnet/>
+ </features>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <filesystem type='mount' accessmode='passthrough'>
+ <source dir='/var/lib/lxc/migrate_test/rootfs'/>
+ <target dir='/'/>
+ </filesystem>
+ </devices>
+</domain>
diff --git a/tests/lxcconf2xmltest.c b/tests/lxcconf2xmltest.c
index 4e7dd58..7042bdf 100644
--- a/tests/lxcconf2xmltest.c
+++ b/tests/lxcconf2xmltest.c
@@ -108,6 +108,7 @@ mymain(void)
DO_TEST("nonenetwork", false);
DO_TEST("physnetwork", false);
DO_TEST("macvlannetwork", false);
+ DO_TEST("idmap", false);

return ret;
}
--
1.8.5.2
Daniel P. Berrange
2014-02-12 17:44:35 UTC
Permalink
Post by Cédric Bosdonnat
---
src/lxc/lxc_native.c | 44 ++++++++++++++++++++++++++
tests/lxcconf2xmldata/lxcconf2xml-idmap.config | 5 +++
tests/lxcconf2xmldata/lxcconf2xml-idmap.xml | 28 ++++++++++++++++
tests/lxcconf2xmltest.c | 1 +
4 files changed, 78 insertions(+)
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-idmap.config
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-idmap.xml
ACK

Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
Daniel P. Berrange
2014-02-12 17:50:54 UTC
Permalink
Post by Cédric Bosdonnat
---
src/lxc/lxc_native.c | 44 ++++++++++++++++++++++++++
tests/lxcconf2xmldata/lxcconf2xml-idmap.config | 5 +++
tests/lxcconf2xmldata/lxcconf2xml-idmap.xml | 28 ++++++++++++++++
tests/lxcconf2xmltest.c | 1 +
4 files changed, 78 insertions(+)
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-idmap.config
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-idmap.xml
diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c
index b413e42..dd706f8 100644
--- a/src/lxc/lxc_native.c
+++ b/src/lxc/lxc_native.c
+static int
+lxcIdmapWalkCallback(const char *name, virConfValuePtr value, void *data)
+{
+ virDomainDefPtr def = data;
+ virDomainIdMapEntryPtr idmap = NULL;
+ char type;
+ unsigned long start, target, count;
+
+ if (STRNEQ(name, "lxc.id_map") || !value->str)
+ return 0;
+
+ if (sscanf(value->str, "%c %lu %lu %lu", &type,
+ &target, &start, &count) != 4) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, _("invalid lxc.id_map: '%s'"),
+ value->str);
+ return -1;
+ }
+
+ if (VIR_ALLOC(idmap) < 0)
+ return -1;
This alloc is bogus since we assign to 'idmap' a few lines later.
I'm removing it when i push.
Post by Cédric Bosdonnat
+
+ if (type == 'u') {
+ if (VIR_EXPAND_N(def->idmap.uidmap, def->idmap.nuidmap, 1) < 0)
+ return -1;
+ idmap = &def->idmap.uidmap[def->idmap.nuidmap - 1];
+ } else if (type == 'g') {
+ if (VIR_EXPAND_N(def->idmap.gidmap, def->idmap.ngidmap, 1) < 0)
+ return -1;
+ idmap = &def->idmap.gidmap[def->idmap.ngidmap - 1];
+ } else {
+ return -1;
+ }
+
+ idmap->start = start;
+ idmap->target = target;
+ idmap->count = count;
+
+ return 0;
+}
Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
Cédric Bosdonnat
2014-02-05 14:10:02 UTC
Permalink
Tmpfs relative size and default 50% size values aren't supported as
we have no idea of the available memory at the conversion time.
---
src/lxc/lxc_container.c | 2 +-
src/lxc/lxc_container.h | 2 +
src/lxc/lxc_native.c | 251 +++++++++++++++++++++++-
tests/lxcconf2xmldata/lxcconf2xml-fstab.config | 37 ++++
tests/lxcconf2xmldata/lxcconf2xml-simple.config | 4 +-
tests/lxcconf2xmldata/lxcconf2xml-simple.xml | 9 +
tests/lxcconf2xmltest.c | 60 +++---
7 files changed, 336 insertions(+), 29 deletions(-)
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-fstab.config

diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index c6bdc8c..f08dbc2 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -744,7 +744,7 @@ static const virLXCBasicMountInfo lxcBasicMounts[] = {
};


-static bool lxcIsBasicMountLocation(const char *path)
+bool lxcIsBasicMountLocation(const char *path)
{
size_t i;

diff --git a/src/lxc/lxc_container.h b/src/lxc/lxc_container.h
index e74a7d7..67292ab 100644
--- a/src/lxc/lxc_container.h
+++ b/src/lxc/lxc_container.h
@@ -71,4 +71,6 @@ virArch lxcContainerGetAlt32bitArch(virArch arch);

int lxcContainerChown(virDomainDefPtr def, const char *path);

+bool lxcIsBasicMountLocation(const char *path);
+
#endif /* LXC_CONTAINER_H */
diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c
index 86d0dd3..acd68db 100644
--- a/src/lxc/lxc_native.c
+++ b/src/lxc/lxc_native.c
@@ -21,10 +21,13 @@
*/

#include <config.h>
+#include <stdio.h>

#include "internal.h"
+#include "lxc_container.h"
#include "lxc_native.h"
#include "util/viralloc.h"
+#include "util/virfile.h"
#include "util/virlog.h"
#include "util/virstring.h"
#include "util/virconf.h"
@@ -33,7 +36,11 @@


static virDomainFSDefPtr
-lxcCreateFSDef(int type, char *src, char* dst)
+lxcCreateFSDef(int type,
+ char *src,
+ char* dst,
+ bool readonly,
+ unsigned long long usage)
{
virDomainFSDefPtr def;

@@ -44,16 +51,124 @@ lxcCreateFSDef(int type, char *src, char* dst)
def->accessmode = VIR_DOMAIN_FS_ACCESSMODE_PASSTHROUGH;
def->src = src;
def->dst = dst;
+ def->readonly = readonly;
+ def->usage = usage;

return def;
}

+typedef struct _lxcFstab lxcFstab;
+typedef lxcFstab *lxcFstabPtr;
+struct _lxcFstab {
+ lxcFstabPtr next;
+ char *src;
+ char *dst;
+ char *type;
+ char *options;
+};
+
+static void
+lxcFstabFree(lxcFstabPtr fstab)
+{
+ while (fstab) {
+ lxcFstabPtr next = NULL;
+ next = fstab->next;
+
+ VIR_FREE(fstab->src);
+ VIR_FREE(fstab->dst);
+ VIR_FREE(fstab->type);
+ VIR_FREE(fstab->options);
+ VIR_FREE(fstab);
+
+ fstab = next;
+ }
+}
+
+static char ** lxcStringSplit(const char *string)
+{
+ char *tmp;
+ size_t i;
+ size_t ntokens = 0;
+ char **parts;
+ char **result = NULL;
+
+ if (VIR_STRDUP(tmp, string) < 0)
+ return NULL;
+
+ /* Replace potential \t by a space */
+ for (i = 0; tmp[i]; i++) {
+ if (tmp[i] == '\t')
+ tmp[i] = ' ';
+ }
+
+ parts = virStringSplit(tmp, " ", 0);
+ for (i = 0; parts[i]; i++) {
+ if (STREQ(parts[i], ""))
+ continue;
+
+ if (VIR_EXPAND_N(result, ntokens, 1) < 0)
+ goto error;
+
+ if (VIR_STRDUP(result[ntokens-1], parts[i]) < 0)
+ goto error;
+ }
+
+ /* Append NULL element */
+ if (VIR_EXPAND_N(result, ntokens, 1) < 0)
+ goto error;
+
+ VIR_FREE(tmp);
+ virStringFreeList(parts);
+ return result;
+
+error:
+ VIR_FREE(tmp);
+ virStringFreeList(parts);
+ virStringFreeList(result);
+ return NULL;
+}
+
+static lxcFstabPtr
+lxcParseFstabLine(char *fstabLine)
+{
+ lxcFstabPtr fstab = NULL;
+ char **parts;
+
+ if (!fstabLine || VIR_ALLOC(fstab) < 0)
+ return NULL;
+
+ parts = lxcStringSplit(fstabLine);
+
+ if (!parts[0] || !parts[1] || !parts[2] || !parts[3])
+ goto error;
+
+ if (VIR_STRDUP(fstab->src, parts[0]) < 0 ||
+ VIR_STRDUP(fstab->dst, parts[1]) < 0 ||
+ VIR_STRDUP(fstab->type, parts[2]) < 0 ||
+ VIR_STRDUP(fstab->options, parts[3]) < 0)
+ goto error;
+
+ virStringFreeList(parts);
+
+ return fstab;
+
+error:
+ lxcFstabFree(fstab);
+ virStringFreeList(parts);
+ return NULL;
+}
+
static int
-lxcAddFSDef(virDomainDefPtr def, int type, char *src, char *dst)
+lxcAddFSDef(virDomainDefPtr def,
+ int type,
+ char *src,
+ char *dst,
+ bool readonly,
+ unsigned long long usage)
{
virDomainFSDefPtr fsDef = NULL;

- if (!(fsDef = lxcCreateFSDef(type, src, dst)))
+ if (!(fsDef = lxcCreateFSDef(type, src, dst, readonly, usage)))
goto error;

if (VIR_EXPAND_N(def->fss, def->nfss, 1) < 0)
@@ -86,7 +201,7 @@ lxcSetRootfs(virDomainDefPtr def,
type = VIR_DOMAIN_FS_TYPE_BLOCK;


- if (lxcAddFSDef(def, type, fssrc, fsdst) < 0)
+ if (lxcAddFSDef(def, type, fssrc, fsdst, false, 0) < 0)
goto error;

return 0;
@@ -97,6 +212,119 @@ error:
return -1;
}

+static int
+lxcConvertSize(const char *size, unsigned long long *value)
+{
+ char *unit = NULL;
+
+ /* Split the string into value and unit */
+ if (virStrToLong_ull(size, &unit, 10, value) < 0)
+ goto error;
+
+ if (STREQ(unit, "%")) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("can't convert relative size: '%s'"),
+ size);
+ return -1;
+ } else {
+ if (virScaleInteger(value, unit, 1, ULLONG_MAX) < 0)
+ goto error;
+ }
+
+ return 0;
+
+error:
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("failed to convert size: '%s'"),
+ size);
+ return -1;
+}
+
+static int
+lxcAddFstabLine(virDomainDefPtr def, lxcFstabPtr fstab)
+{
+ char *src = NULL;
+ char *dst = NULL;
+ char **options = virStringSplit(fstab->options, ",", 0);
+ bool readonly;
+ int type = VIR_DOMAIN_FS_TYPE_MOUNT;
+ unsigned long long usage = 0;
+
+ if (fstab->dst[0] != '/') {
+ if (virAsprintf(&dst, "/%s", fstab->dst) < 0)
+ goto error;
+ } else {
+ if (VIR_STRDUP(dst, fstab->dst) < 0)
+ goto error;
+ }
+
+ /* Check that we don't add basic mounts */
+ if (lxcIsBasicMountLocation(dst)) {
+ VIR_FREE(dst);
+ return 0;
+ }
+
+ if (STREQ(fstab->type, "tmpfs")) {
+ char *sizeStr = NULL;
+ size_t i;
+ type = VIR_DOMAIN_FS_TYPE_RAM;
+
+ for (i = 0; options[i]; i++) {
+ if ((sizeStr = STRSKIP(options[i], "size="))) {
+ if (lxcConvertSize(sizeStr, &usage) < 0)
+ goto error;
+ break;
+ }
+ }
+ if (!sizeStr) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("missing tmpfs size, set the size option"));
+ goto error;
+ }
+ } else {
+ if (VIR_STRDUP(src, fstab->src) < 0)
+ goto error;
+ }
+
+ /* Do we have ro in options? */
+ readonly = virStringArrayHasString(options, "ro");
+
+ if (lxcAddFSDef(def, type, src, dst, readonly, usage) < 0)
+ goto error;
+
+
+ return 1;
+
+error:
+ VIR_FREE(dst);
+ VIR_FREE(src);
+ virStringFreeList(options);
+ return -1;
+}
+
+static int
+lxcFstabWalkCallback(const char* name, virConfValuePtr value, void * data)
+{
+ int ret = 0;
+ lxcFstabPtr fstabLine;
+ virDomainDefPtr def = data;
+
+ /* We only care about lxc.mount.entry lines */
+ if (STRNEQ(name, "lxc.mount.entry"))
+ return 0;
+
+ fstabLine = lxcParseFstabLine(value->str);
+
+ if (!fstabLine)
+ return -1;
+
+ if (lxcAddFstabLine(def, fstabLine) < 0)
+ ret = -1;
+
+ lxcFstabFree(fstabLine);
+ return ret;
+}
+
virDomainDefPtr
lxcParseConfigString(const char *config)
{
@@ -115,6 +343,7 @@ lxcParseConfigString(const char *config)
_("failed to generate uuid"));
goto error;
}
+
vmdef->id = -1;
vmdef->mem.max_balloon = 64 * 1024;

@@ -127,6 +356,8 @@ lxcParseConfigString(const char *config)
* minimum required to make XML parsing pass */
vmdef->maxvcpus = 1;

+ vmdef->nfss = 0;
+
if (VIR_STRDUP(vmdef->os.type, "exe") < 0)
goto error;

@@ -142,6 +373,18 @@ lxcParseConfigString(const char *config)
if (lxcSetRootfs(vmdef, properties) < 0)
goto error;

+ /* Look for fstab: we shouldn't have it */
+ if (virConfGetValue(properties, "lxc.mount")) {
+ virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
+ _("lxc.mount found, use lxc.mount.entry lines instead"));
+ goto error;
+ }
+
+ /* Loop over lxc.mount.entry to add filesystem devices for them */
+ value = virConfGetValue(properties, "lxc.mount.entry");
+ if (virConfWalk(properties, lxcFstabWalkCallback, vmdef) < 0)
+ goto error;
+
goto cleanup;

error:
diff --git a/tests/lxcconf2xmldata/lxcconf2xml-fstab.config b/tests/lxcconf2xmldata/lxcconf2xml-fstab.config
new file mode 100644
index 0000000..8c03c22
--- /dev/null
+++ b/tests/lxcconf2xmldata/lxcconf2xml-fstab.config
@@ -0,0 +1,37 @@
+# Template used to create this container: opensuse
+# Template script checksum (SHA-1): 27307e0a95bd81b2c0bd82d6f87fdbe83be075ef
+
+lxc.network.type = veth
+lxc.network.flags = up
+lxc.network.link = virbr0
+lxc.network.hwaddr = 02:00:15:8f:05:c1
+lxc.network.name = eth0
+
+#remove next line if host DNS configuration should not be available to container
+lxc.mount = /var/lib/lxc/migrate_test/fstab
+lxc.rootfs = /var/lib/lxc/migrate_test/rootfs
+lxc.utsname = migrate_test
+lxc.autodev=1
+lxc.tty = 2
+lxc.pts = 1024
+lxc.cap.drop = sys_module mac_admin mac_override mknod
+
+# When using LXC with apparmor, uncomment the next line to run unconfined:
+#lxc.aa_profile = unconfined
+
+lxc.cgroup.devices.deny = a
+# /dev/null and zero
+lxc.cgroup.devices.allow = c 1:3 rwm
+lxc.cgroup.devices.allow = c 1:5 rwm
+# consoles
+lxc.cgroup.devices.allow = c 5:1 rwm
+lxc.cgroup.devices.allow = c 5:0 rwm
+lxc.cgroup.devices.allow = c 4:0 rwm
+lxc.cgroup.devices.allow = c 4:1 rwm
+# /dev/{,u}random
+lxc.cgroup.devices.allow = c 1:9 rwm
+lxc.cgroup.devices.allow = c 1:8 rwm
+lxc.cgroup.devices.allow = c 136:* rwm
+lxc.cgroup.devices.allow = c 5:2 rwm
+# rtc
+lxc.cgroup.devices.allow = c 254:0 rwm
diff --git a/tests/lxcconf2xmldata/lxcconf2xml-simple.config b/tests/lxcconf2xmldata/lxcconf2xml-simple.config
index 12428bb..f75e8fc 100644
--- a/tests/lxcconf2xmldata/lxcconf2xml-simple.config
+++ b/tests/lxcconf2xmldata/lxcconf2xml-simple.config
@@ -8,13 +8,15 @@ lxc.network.hwaddr = 02:00:15:8f:05:c1
lxc.network.name = eth0

#remove next line if host DNS configuration should not be available to container
+lxc.mount.entry = proc proc proc nodev,noexec,nosuid 0 0
+lxc.mount.entry = sysfs sys sysfs defaults 0 0
+lxc.mount.entry = tmpfs run tmpfs size=8m,mode=0755,nodev,nosuid 0 0
lxc.mount.entry = /etc/resolv.conf etc/resolv.conf none bind,ro 0 0
lxc.rootfs = /var/lib/lxc/migrate_test/rootfs
lxc.utsname = migrate_test
lxc.autodev=1
lxc.tty = 2
lxc.pts = 1024
-lxc.mount = /var/lib/lxc/migrate_test/fstab
lxc.cap.drop = sys_module mac_admin mac_override mknod

# When using LXC with apparmor, uncomment the next line to run unconfined:
diff --git a/tests/lxcconf2xmldata/lxcconf2xml-simple.xml b/tests/lxcconf2xmldata/lxcconf2xml-simple.xml
index eebcb4e..fadbdca 100644
--- a/tests/lxcconf2xmldata/lxcconf2xml-simple.xml
+++ b/tests/lxcconf2xmldata/lxcconf2xml-simple.xml
@@ -17,5 +17,14 @@
<source dir='/var/lib/lxc/migrate_test/rootfs'/>
<target dir='/'/>
</filesystem>
+ <filesystem type='ram' accessmode='passthrough'>
+ <source usage='8192' units='KiB'/>
+ <target dir='/run'/>
+ </filesystem>
+ <filesystem type='mount' accessmode='passthrough'>
+ <source dir='/etc/resolv.conf'/>
+ <target dir='/etc/resolv.conf'/>
+ <readonly/>
+ </filesystem>
</devices>
</domain>
diff --git a/tests/lxcconf2xmltest.c b/tests/lxcconf2xmltest.c
index 9a840f9..c4b21ec 100644
--- a/tests/lxcconf2xmltest.c
+++ b/tests/lxcconf2xmltest.c
@@ -18,7 +18,8 @@ blankProblemElements(char *data)

static int
testCompareXMLToConfigFiles(const char *xml,
- const char *configfile)
+ const char *configfile,
+ bool expectError)
{
int ret = -1;
char *config = NULL;
@@ -28,22 +29,26 @@ testCompareXMLToConfigFiles(const char *xml,

if (virtTestLoadFile(configfile, &config) < 0)
goto fail;
- if (virtTestLoadFile(xml, &expectxml) < 0)
- goto fail;

- if (!(vmdef = lxcParseConfigString(config)))
+ vmdef = lxcParseConfigString(config);
+ if ((vmdef && expectError) || (!vmdef && !expectError))
goto fail;

- if (!(actualxml = virDomainDefFormat(vmdef, 0)))
- goto fail;
+ if (vmdef) {
+ if (!(actualxml = virDomainDefFormat(vmdef, 0)))
+ goto fail;

- if (blankProblemElements(expectxml) < 0 ||
- blankProblemElements(actualxml) < 0)
- goto fail;
+ if (virtTestLoadFile(xml, &expectxml) < 0)
+ goto fail;

- if (STRNEQ(expectxml, actualxml)) {
- virtTestDifference(stderr, expectxml, actualxml);
- goto fail;
+ if (blankProblemElements(expectxml) < 0 ||
+ blankProblemElements(actualxml) < 0)
+ goto fail;
+
+ if (STRNEQ(expectxml, actualxml)) {
+ virtTestDifference(stderr, expectxml, actualxml);
+ goto fail;
+ }
}

ret = 0;
@@ -56,21 +61,26 @@ fail:
return ret;
}

+struct testInfo {
+ const char *name;
+ bool expectError;
+};
+
static int
testCompareXMLToConfigHelper(const void *data)
{
int result = -1;
- const char *name = data;
+ const struct testInfo *info = data;
char *xml = NULL;
char *config = NULL;

if (virAsprintf(&xml, "%s/lxcconf2xmldata/lxcconf2xml-%s.xml",
- abs_srcdir, name) < 0 ||
+ abs_srcdir, info->name) < 0 ||
virAsprintf(&config, "%s/lxcconf2xmldata/lxcconf2xml-%s.config",
- abs_srcdir, name) < 0)
+ abs_srcdir, info->name) < 0)
goto cleanup;

- result = testCompareXMLToConfigFiles(xml, config);
+ result = testCompareXMLToConfigFiles(xml, config, info->expectError);

cleanup:
VIR_FREE(xml);
@@ -83,13 +93,17 @@ mymain(void)
{
int ret = EXIT_SUCCESS;

-# define DO_TEST(name) \
- if (virtTestRun("LXC Native-2-XML " name, \
- testCompareXMLToConfigHelper, \
- name) < 0) \
- ret = EXIT_FAILURE
-
- DO_TEST("simple");
+# define DO_TEST(name, expectError) \
+ do { \
+ const struct testInfo info = { name, expectError }; \
+ if (virtTestRun("LXC Native-2-XML " name, \
+ testCompareXMLToConfigHelper, \
+ &info) < 0) \
+ ret = EXIT_FAILURE; \
+ } while (0)
+
+ DO_TEST("simple", false);
+ DO_TEST("fstab", true);

return ret;
}
--
1.8.5.2
Daniel P. Berrange
2014-02-12 17:40:25 UTC
Permalink
Post by Cédric Bosdonnat
Tmpfs relative size and default 50% size values aren't supported as
we have no idea of the available memory at the conversion time.
---
src/lxc/lxc_container.c | 2 +-
src/lxc/lxc_container.h | 2 +
src/lxc/lxc_native.c | 251 +++++++++++++++++++++++-
tests/lxcconf2xmldata/lxcconf2xml-fstab.config | 37 ++++
tests/lxcconf2xmldata/lxcconf2xml-simple.config | 4 +-
tests/lxcconf2xmldata/lxcconf2xml-simple.xml | 9 +
tests/lxcconf2xmltest.c | 60 +++---
7 files changed, 336 insertions(+), 29 deletions(-)
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-fstab.config
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index c6bdc8c..f08dbc2 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -744,7 +744,7 @@ static const virLXCBasicMountInfo lxcBasicMounts[] = {
};
-static bool lxcIsBasicMountLocation(const char *path)
+bool lxcIsBasicMountLocation(const char *path)
{
size_t i;
diff --git a/src/lxc/lxc_container.h b/src/lxc/lxc_container.h
index e74a7d7..67292ab 100644
--- a/src/lxc/lxc_container.h
+++ b/src/lxc/lxc_container.h
@@ -71,4 +71,6 @@ virArch lxcContainerGetAlt32bitArch(virArch arch);
int lxcContainerChown(virDomainDefPtr def, const char *path);
+bool lxcIsBasicMountLocation(const char *path);
+
#endif /* LXC_CONTAINER_H */
diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c
index 86d0dd3..acd68db 100644
--- a/src/lxc/lxc_native.c
+++ b/src/lxc/lxc_native.c
@@ -21,10 +21,13 @@
*/
#include <config.h>
+#include <stdio.h>
#include "internal.h"
+#include "lxc_container.h"
#include "lxc_native.h"
#include "util/viralloc.h"
+#include "util/virfile.h"
#include "util/virlog.h"
#include "util/virstring.h"
#include "util/virconf.h"
@@ -33,7 +36,11 @@
static virDomainFSDefPtr
-lxcCreateFSDef(int type, char *src, char* dst)
+lxcCreateFSDef(int type,
+ char *src,
+ char* dst,
+ bool readonly,
+ unsigned long long usage)
{
virDomainFSDefPtr def;
@@ -44,16 +51,124 @@ lxcCreateFSDef(int type, char *src, char* dst)
def->accessmode = VIR_DOMAIN_FS_ACCESSMODE_PASSTHROUGH;
def->src = src;
def->dst = dst;
+ def->readonly = readonly;
+ def->usage = usage;
return def;
}
+typedef struct _lxcFstab lxcFstab;
+typedef lxcFstab *lxcFstabPtr;
+struct _lxcFstab {
+ lxcFstabPtr next;
+ char *src;
+ char *dst;
+ char *type;
+ char *options;
+};
+
+static void
+lxcFstabFree(lxcFstabPtr fstab)
+{
+ while (fstab) {
+ lxcFstabPtr next = NULL;
+ next = fstab->next;
+
+ VIR_FREE(fstab->src);
+ VIR_FREE(fstab->dst);
+ VIR_FREE(fstab->type);
+ VIR_FREE(fstab->options);
+ VIR_FREE(fstab);
+
+ fstab = next;
+ }
+}
+
+static char ** lxcStringSplit(const char *string)
+{
+ char *tmp;
+ size_t i;
+ size_t ntokens = 0;
+ char **parts;
+ char **result = NULL;
+
+ if (VIR_STRDUP(tmp, string) < 0)
+ return NULL;
+
+ /* Replace potential \t by a space */
+ for (i = 0; tmp[i]; i++) {
+ if (tmp[i] == '\t')
+ tmp[i] = ' ';
+ }
+
+ parts = virStringSplit(tmp, " ", 0);
Not checking parts for NULL
Post by Cédric Bosdonnat
+ for (i = 0; parts[i]; i++) {
+ if (STREQ(parts[i], ""))
+ continue;
+
+ if (VIR_EXPAND_N(result, ntokens, 1) < 0)
+ goto error;
+
+ if (VIR_STRDUP(result[ntokens-1], parts[i]) < 0)
+ goto error;
+ }
+
+ /* Append NULL element */
+ if (VIR_EXPAND_N(result, ntokens, 1) < 0)
+ goto error;
A really subtle problem here - we need results to be
NULL terminated at all times, not only when the loop
is finished. If the VIR_EXPAND_N or VIR_STRDUP calls
in the loop body fail, we jump to error where we
call virStringFreeList which expects NULL termination.
As it stands we have array out of bounds access on OOM.
Post by Cédric Bosdonnat
+
+ VIR_FREE(tmp);
+ virStringFreeList(parts);
+ return result;
+
+ VIR_FREE(tmp);
+ virStringFreeList(parts);
+ virStringFreeList(result);
+ return NULL;
+}
+
+static lxcFstabPtr
+lxcParseFstabLine(char *fstabLine)
+{
+ lxcFstabPtr fstab = NULL;
+ char **parts;
+
+ if (!fstabLine || VIR_ALLOC(fstab) < 0)
+ return NULL;
+
+ parts = lxcStringSplit(fstabLine);
Not checking for NULL
Post by Cédric Bosdonnat
+
+ if (!parts[0] || !parts[1] || !parts[2] || !parts[3])
+ goto error;
+
+ if (VIR_STRDUP(fstab->src, parts[0]) < 0 ||
+ VIR_STRDUP(fstab->dst, parts[1]) < 0 ||
+ VIR_STRDUP(fstab->type, parts[2]) < 0 ||
+ VIR_STRDUP(fstab->options, parts[3]) < 0)
+ goto error;
+
+ virStringFreeList(parts);
+
+ return fstab;
+
+ lxcFstabFree(fstab);
+ virStringFreeList(parts);
+ return NULL;
+}
+
static int
-lxcAddFSDef(virDomainDefPtr def, int type, char *src, char *dst)
+lxcAddFSDef(virDomainDefPtr def,
+ int type,
+ char *src,
+ char *dst,
+ bool readonly,
+ unsigned long long usage)
{
virDomainFSDefPtr fsDef = NULL;
- if (!(fsDef = lxcCreateFSDef(type, src, dst)))
+ if (!(fsDef = lxcCreateFSDef(type, src, dst, readonly, usage)))
goto error;
if (VIR_EXPAND_N(def->fss, def->nfss, 1) < 0)
@@ -86,7 +201,7 @@ lxcSetRootfs(virDomainDefPtr def,
type = VIR_DOMAIN_FS_TYPE_BLOCK;
- if (lxcAddFSDef(def, type, fssrc, fsdst) < 0)
+ if (lxcAddFSDef(def, type, fssrc, fsdst, false, 0) < 0)
goto error;
return 0;
+static int
+lxcAddFstabLine(virDomainDefPtr def, lxcFstabPtr fstab)
+{
+ char *src = NULL;
+ char *dst = NULL;
+ char **options = virStringSplit(fstab->options, ",", 0);
+ bool readonly;
+ int type = VIR_DOMAIN_FS_TYPE_MOUNT;
+ unsigned long long usage = 0;
This method leaks 'options' array.
Post by Cédric Bosdonnat
+
+ if (fstab->dst[0] != '/') {
+ if (virAsprintf(&dst, "/%s", fstab->dst) < 0)
+ goto error;
+ } else {
+ if (VIR_STRDUP(dst, fstab->dst) < 0)
+ goto error;
+ }
+
+ /* Check that we don't add basic mounts */
+ if (lxcIsBasicMountLocation(dst)) {
+ VIR_FREE(dst);
+ return 0;
+ }
+
+ if (STREQ(fstab->type, "tmpfs")) {
+ char *sizeStr = NULL;
+ size_t i;
+ type = VIR_DOMAIN_FS_TYPE_RAM;
+
+ for (i = 0; options[i]; i++) {
+ if ((sizeStr = STRSKIP(options[i], "size="))) {
+ if (lxcConvertSize(sizeStr, &usage) < 0)
+ goto error;
+ break;
+ }
+ }
+ if (!sizeStr) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("missing tmpfs size, set the size option"));
+ goto error;
+ }
+ } else {
+ if (VIR_STRDUP(src, fstab->src) < 0)
+ goto error;
+ }
+
+ /* Do we have ro in options? */
+ readonly = virStringArrayHasString(options, "ro");
+
+ if (lxcAddFSDef(def, type, src, dst, readonly, usage) < 0)
+ goto error;
+
+
+ return 1;
+
+ VIR_FREE(dst);
+ VIR_FREE(src);
+ virStringFreeList(options);
+ return -1;
+}
ACK, I'm going to push and squash in 2 fixes

For the memory leaks:

diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c
index acd68db..c740e9f 100644
--- a/src/lxc/lxc_native.c
+++ b/src/lxc/lxc_native.c
@@ -249,19 +249,20 @@ lxcAddFstabLine(virDomainDefPtr def, lxcFstabPtr fstab)
bool readonly;
int type = VIR_DOMAIN_FS_TYPE_MOUNT;
unsigned long long usage = 0;
+ int ret = -1;

if (fstab->dst[0] != '/') {
if (virAsprintf(&dst, "/%s", fstab->dst) < 0)
- goto error;
+ goto cleanup;
} else {
if (VIR_STRDUP(dst, fstab->dst) < 0)
- goto error;
+ goto cleanup;
}

/* Check that we don't add basic mounts */
if (lxcIsBasicMountLocation(dst)) {
- VIR_FREE(dst);
- return 0;
+ ret = 0;
+ goto cleanup;
}

if (STREQ(fstab->type, "tmpfs")) {
@@ -272,34 +273,34 @@ lxcAddFstabLine(virDomainDefPtr def, lxcFstabPtr fstab)
for (i = 0; options[i]; i++) {
if ((sizeStr = STRSKIP(options[i], "size="))) {
if (lxcConvertSize(sizeStr, &usage) < 0)
- goto error;
+ goto cleanup;
break;
}
}
if (!sizeStr) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("missing tmpfs size, set the size option"));
- goto error;
+ goto cleanup;
}
} else {
if (VIR_STRDUP(src, fstab->src) < 0)
- goto error;
+ goto cleanup;
}

/* Do we have ro in options? */
readonly = virStringArrayHasString(options, "ro");

if (lxcAddFSDef(def, type, src, dst, readonly, usage) < 0)
- goto error;
-
+ goto cleanup;

- return 1;
+ src = dst = NULL;
+ ret = 1;

-error:
+ cleanup:
VIR_FREE(dst);
VIR_FREE(src);
virStringFreeList(options);
- return -1;
+ return ret;
}

static int



And then for the OOM fixes

diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c
index 3e6c2bc..66be361 100644
--- a/src/lxc/lxc_native.c
+++ b/src/lxc/lxc_native.c
@@ -107,7 +107,13 @@ static char ** lxcStringSplit(const char *string)
tmp[i] = ' ';
}

- parts = virStringSplit(tmp, " ", 0);
+ if (!(parts = virStringSplit(tmp, " ", 0)))
+ goto error;
+
+ /* Append NULL element */
+ if (VIR_EXPAND_N(result, ntokens, 1) < 0)
+ goto error;
+
for (i = 0; parts[i]; i++) {
if (STREQ(parts[i], ""))
continue;
@@ -115,14 +121,10 @@ static char ** lxcStringSplit(const char *string)
if (VIR_EXPAND_N(result, ntokens, 1) < 0)
goto error;

- if (VIR_STRDUP(result[ntokens-1], parts[i]) < 0)
+ if (VIR_STRDUP(result[ntokens-2], parts[i]) < 0)
goto error;
}

- /* Append NULL element */
- if (VIR_EXPAND_N(result, ntokens, 1) < 0)
- goto error;
-
VIR_FREE(tmp);
virStringFreeList(parts);
return result;
@@ -143,7 +145,8 @@ lxcParseFstabLine(char *fstabLine)
if (!fstabLine || VIR_ALLOC(fstab) < 0)
return NULL;

- parts = lxcStringSplit(fstabLine);
+ if (!(parts = lxcStringSplit(fstabLine)))
+ goto error;

if (!parts[0] || !parts[1] || !parts[2] || !parts[3])
goto error;
@@ -250,6 +253,9 @@ lxcAddFstabLine(virDomainDefPtr def, lxcFstabPtr fstab)
unsigned long long usage = 0;
int ret = -1;

+ if (!options)
+ return -1;
+
if (fstab->dst[0] != '/') {
if (virAsprintf(&dst, "/%s", fstab->dst) < 0)
goto cleanup;
@@ -291,7 +297,6 @@ lxcAddFstabLine(virDomainDefPtr def, lxcFstabPtr fstab)
if (lxcAddFSDef(def, type, src, dst, readonly, usage) < 0)
goto cleanup;

- dst = NULL;
ret = 1;

cleanup:
--
|: Http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
John Ferlan
2014-02-13 11:34:52 UTC
Permalink
New Coverity complaint regarding this change ...

<...snip...>
Post by Cédric Bosdonnat
virDomainDefPtr
lxcParseConfigString(const char *config)
{
@@ -115,6 +343,7 @@ lxcParseConfigString(const char *config)
_("failed to generate uuid"));
goto error;
}
+
vmdef->id = -1;
vmdef->mem.max_balloon = 64 * 1024;
@@ -127,6 +356,8 @@ lxcParseConfigString(const char *config)
* minimum required to make XML parsing pass */
vmdef->maxvcpus = 1;
+ vmdef->nfss = 0;
+
if (VIR_STRDUP(vmdef->os.type, "exe") < 0)
goto error;
@@ -142,6 +373,18 @@ lxcParseConfigString(const char *config)
if (lxcSetRootfs(vmdef, properties) < 0)
goto error;
+ /* Look for fstab: we shouldn't have it */
+ if (virConfGetValue(properties, "lxc.mount")) {
+ virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
+ _("lxc.mount found, use lxc.mount.entry lines instead"));
+ goto error;
+ }
+
+ /* Loop over lxc.mount.entry to add filesystem devices for them */
+ value = virConfGetValue(properties, "lxc.mount.entry");
(1) Event returned_pointer: Pointer "value" returned by
"virConfGetValue(properties, "lxc.mount.entry")" is never used.


'value' is set, but never used.


John
Post by Cédric Bosdonnat
+ if (virConfWalk(properties, lxcFstabWalkCallback, vmdef) < 0)
+ goto error;
+
goto cleanup;
Cedric Bosdonnat
2014-02-13 12:45:12 UTC
Permalink
Post by John Ferlan
New Coverity complaint regarding this change ...
<...snip...>
Post by Cédric Bosdonnat
virDomainDefPtr
lxcParseConfigString(const char *config)
{
@@ -115,6 +343,7 @@ lxcParseConfigString(const char *config)
_("failed to generate uuid"));
goto error;
}
+
vmdef->id = -1;
vmdef->mem.max_balloon = 64 * 1024;
@@ -127,6 +356,8 @@ lxcParseConfigString(const char *config)
* minimum required to make XML parsing pass */
vmdef->maxvcpus = 1;
+ vmdef->nfss = 0;
+
if (VIR_STRDUP(vmdef->os.type, "exe") < 0)
goto error;
@@ -142,6 +373,18 @@ lxcParseConfigString(const char *config)
if (lxcSetRootfs(vmdef, properties) < 0)
goto error;
+ /* Look for fstab: we shouldn't have it */
+ if (virConfGetValue(properties, "lxc.mount")) {
+ virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
+ _("lxc.mount found, use lxc.mount.entry lines instead"));
+ goto error;
+ }
+
+ /* Loop over lxc.mount.entry to add filesystem devices for them */
+ value = virConfGetValue(properties, "lxc.mount.entry");
(1) Event returned_pointer: Pointer "value" returned by
"virConfGetValue(properties, "lxc.mount.entry")" is never used.
'value' is set, but never used.
Oops, that one line is the remaining of a refactoring I made between 2
versions of the patchset. I'll submit a patch to fix that.

--
Cedric
Cédric Bosdonnat
2014-02-05 14:10:00 UTC
Permalink
This function aims at converting LXC configuration into a libvirt
domain XML description to help users migrate from LXC to libvirt.

Here is an example of how the lxc configuration works:
virsh -c lxc:/// domxml-from-native lxc-tools /var/lib/lxc/migrate_test/config

It is possible that some parts couldn't be properly mapped into a
domain XML fragment, so users should carefully review the result
before creating the domain.

fstab files in lxc.mount lines will need to be merged into the
configuration file as lxc.mount.entry.

As we can't know the amount of memory of the host, we have to set a
default value for max_balloon that users will probably want to adjust.
---
.gitignore | 1 +
po/POTFILES.in | 1 +
src/Makefile.am | 1 +
src/lxc/lxc_driver.c | 31 +++++++
src/lxc/lxc_native.c | 86 +++++++++++++++++++
src/lxc/lxc_native.h | 32 +++++++
tests/Makefile.am | 7 +-
tests/lxcconf2xmldata/lxcconf2xml-simple.config | 38 +++++++++
tests/lxcconf2xmldata/lxcconf2xml-simple.xml | 17 ++++
tests/lxcconf2xmltest.c | 107 ++++++++++++++++++++++++
10 files changed, 320 insertions(+), 1 deletion(-)
create mode 100644 src/lxc/lxc_native.c
create mode 100644 src/lxc/lxc_native.h
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-simple.config
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-simple.xml
create mode 100644 tests/lxcconf2xmltest.c

diff --git a/.gitignore b/.gitignore
index 757dfed..65b6763 100644
--- a/.gitignore
+++ b/.gitignore
@@ -157,6 +157,7 @@
/tests/hashtest
/tests/jsontest
/tests/libvirtdconftest
+/tests/lxcconf2xmltest
/tests/metadatatest
/tests/networkxml2argvtest
/tests/nodeinfotest
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 0359b2f..fd36bc5 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -62,6 +62,7 @@ src/locking/sanlock_helper.c
src/lxc/lxc_cgroup.c
src/lxc/lxc_fuse.c
src/lxc/lxc_hostdev.c
+src/lxc/lxc_native.c
src/lxc/lxc_container.c
src/lxc/lxc_conf.c
src/lxc/lxc_controller.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 3f8d22f..4ac31e2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -619,6 +619,7 @@ LXC_DRIVER_SOURCES = \
lxc/lxc_monitor.c lxc/lxc_monitor.h \
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_driver.c lxc/lxc_driver.h

LXC_CONTROLLER_SOURCES = \
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index 138c706..dc0e8e0 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -44,6 +44,7 @@
#include "lxc_container.h"
#include "lxc_domain.h"
#include "lxc_driver.h"
+#include "lxc_native.h"
#include "lxc_process.h"
#include "viralloc.h"
#include "virnetdevbridge.h"
@@ -988,6 +989,35 @@ cleanup:
return ret;
}

+static char *lxcConnectDomainXMLFromNative(virConnectPtr conn,
+ const char *nativeFormat,
+ const char *nativeConfig,
+ unsigned int flags)
+{
+ char *xml = NULL;
+ virDomainDefPtr def = NULL;
+
+ virCheckFlags(0, NULL);
+
+ if (virConnectDomainXMLFromNativeEnsureACL(conn) < 0)
+ goto cleanup;
+
+ if (STRNEQ(nativeFormat, LXC_CONFIG_FORMAT)) {
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("unsupported config type %s"), nativeFormat);
+ goto cleanup;
+ }
+
+ if (!(def = lxcParseConfigString(nativeConfig)))
+ goto cleanup;
+
+ xml = virDomainDefFormat(def, 0);
+
+cleanup:
+ virDomainDefFree(def);
+ return xml;
+}
+
/**
* lxcDomainCreateWithFiles:
* @dom: domain to start
@@ -5376,6 +5406,7 @@ static virDriver lxcDriver = {
.domainGetSecurityLabel = lxcDomainGetSecurityLabel, /* 0.9.10 */
.nodeGetSecurityModel = lxcNodeGetSecurityModel, /* 0.9.10 */
.domainGetXMLDesc = lxcDomainGetXMLDesc, /* 0.4.2 */
+ .connectDomainXMLFromNative = lxcConnectDomainXMLFromNative, /* 1.2.2 */
.connectListDefinedDomains = lxcConnectListDefinedDomains, /* 0.4.2 */
.connectNumOfDefinedDomains = lxcConnectNumOfDefinedDomains, /* 0.4.2 */
.domainCreate = lxcDomainCreate, /* 0.4.4 */
diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c
new file mode 100644
index 0000000..723ebcf
--- /dev/null
+++ b/src/lxc/lxc_native.c
@@ -0,0 +1,86 @@
+/*
+ * lxc_native.c: LXC native configuration import
+ *
+ * Copyright (c) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany.
+ *
+ * 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: Cedric Bosdonnat <***@suse.com>
+ */
+
+#include <config.h>
+
+#include "internal.h"
+#include "lxc_native.h"
+#include "util/viralloc.h"
+#include "util/virlog.h"
+#include "util/virstring.h"
+#include "util/virconf.h"
+
+#define VIR_FROM_THIS VIR_FROM_LXC
+
+virDomainDefPtr
+lxcParseConfigString(const char *config)
+{
+ virDomainDefPtr vmdef = NULL;
+ virConfPtr properties = NULL;
+ virConfValuePtr value;
+
+ if (!(properties = virConfReadMem(config, 0, VIR_CONF_FLAG_LXC_FORMAT)))
+ return NULL;
+
+ if (VIR_ALLOC(vmdef) < 0)
+ goto error;
+
+ if (virUUIDGenerate(vmdef->uuid) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("failed to generate uuid"));
+ goto error;
+ }
+ vmdef->id = -1;
+ vmdef->mem.max_balloon = 64 * 1024;
+
+ vmdef->onReboot = VIR_DOMAIN_LIFECYCLE_RESTART;
+ vmdef->onCrash = VIR_DOMAIN_LIFECYCLE_DESTROY;
+ vmdef->onPoweroff = VIR_DOMAIN_LIFECYCLE_DESTROY;
+ vmdef->virtType = VIR_DOMAIN_VIRT_LXC;
+
+ /* Value not handled by the LXC driver, setting to
+ * minimum required to make XML parsing pass */
+ vmdef->maxvcpus = 1;
+
+ if (VIR_STRDUP(vmdef->os.type, "exe") < 0)
+ goto error;
+
+ if (VIR_STRDUP(vmdef->os.init, "/sbin/init") < 0)
+ goto error;
+
+ if (!(value = virConfGetValue(properties, "lxc.utsname")) ||
+ !value->str || (VIR_STRDUP(vmdef->name, value->str) < 0))
+ goto error;
+ if (!vmdef->name && (VIR_STRDUP(vmdef->name, "unnamed") < 0))
+ goto error;
+
+ goto cleanup;
+
+error:
+ virDomainDefFree(vmdef);
+ vmdef = NULL;
+
+cleanup:
+ virConfFree(properties);
+
+ return vmdef;
+}
diff --git a/src/lxc/lxc_native.h b/src/lxc/lxc_native.h
new file mode 100644
index 0000000..a80f2b1
--- /dev/null
+++ b/src/lxc/lxc_native.h
@@ -0,0 +1,32 @@
+/*
+ * lxc_native.h: LXC native configuration import
+ *
+ * Copyright (c) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany.
+ *
+ * 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: Cedric Bosdonnat <***@suse.com>
+ */
+
+#ifndef __LXC_NATIVE_H__
+# define __LXC_NATIVE_H__
+
+# include "domain_conf.h"
+
+# define LXC_CONFIG_FORMAT "lxc-tools"
+
+virDomainDefPtr lxcParseConfigString(const char *config);
+
+#endif /* __LXC_NATIVE_H__ */
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 30cdd1d..734c9d9 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -199,7 +199,7 @@ test_programs += qemuxml2argvtest qemuxml2xmltest qemuxmlnstest \
endif WITH_QEMU

if WITH_LXC
-test_programs += lxcxml2xmltest
+test_programs += lxcxml2xmltest lxcconf2xmltest
endif WITH_LXC

if WITH_OPENVZ
@@ -515,6 +515,11 @@ lxcxml2xmltest_SOURCES = \
lxcxml2xmltest.c testutilslxc.c testutilslxc.h \
testutils.c testutils.h
lxcxml2xmltest_LDADD = $(lxc_LDADDS)
+
+lxcconf2xmltest_SOURCES = \
+ lxcconf2xmltest.c \
+ testutils.c testutils.h
+lxcconf2xmltest_LDADD = $(lxc_LDADDS)
else ! WITH_LXC
EXTRA_DIST += lxcxml2xmltest.c testutilslxc.c testutilslxc.h
endif ! WITH_LXC
diff --git a/tests/lxcconf2xmldata/lxcconf2xml-simple.config b/tests/lxcconf2xmldata/lxcconf2xml-simple.config
new file mode 100644
index 0000000..12428bb
--- /dev/null
+++ b/tests/lxcconf2xmldata/lxcconf2xml-simple.config
@@ -0,0 +1,38 @@
+# Template used to create this container: opensuse
+# Template script checksum (SHA-1): 27307e0a95bd81b2c0bd82d6f87fdbe83be075ef
+
+lxc.network.type = veth
+lxc.network.flags = up
+lxc.network.link = virbr0
+lxc.network.hwaddr = 02:00:15:8f:05:c1
+lxc.network.name = eth0
+
+#remove next line if host DNS configuration should not be available to container
+lxc.mount.entry = /etc/resolv.conf etc/resolv.conf none bind,ro 0 0
+lxc.rootfs = /var/lib/lxc/migrate_test/rootfs
+lxc.utsname = migrate_test
+lxc.autodev=1
+lxc.tty = 2
+lxc.pts = 1024
+lxc.mount = /var/lib/lxc/migrate_test/fstab
+lxc.cap.drop = sys_module mac_admin mac_override mknod
+
+# When using LXC with apparmor, uncomment the next line to run unconfined:
+#lxc.aa_profile = unconfined
+
+lxc.cgroup.devices.deny = a
+# /dev/null and zero
+lxc.cgroup.devices.allow = c 1:3 rwm
+lxc.cgroup.devices.allow = c 1:5 rwm
+# consoles
+lxc.cgroup.devices.allow = c 5:1 rwm
+lxc.cgroup.devices.allow = c 5:0 rwm
+lxc.cgroup.devices.allow = c 4:0 rwm
+lxc.cgroup.devices.allow = c 4:1 rwm
+# /dev/{,u}random
+lxc.cgroup.devices.allow = c 1:9 rwm
+lxc.cgroup.devices.allow = c 1:8 rwm
+lxc.cgroup.devices.allow = c 136:* rwm
+lxc.cgroup.devices.allow = c 5:2 rwm
+# rtc
+lxc.cgroup.devices.allow = c 254:0 rwm
diff --git a/tests/lxcconf2xmldata/lxcconf2xml-simple.xml b/tests/lxcconf2xmldata/lxcconf2xml-simple.xml
new file mode 100644
index 0000000..641e624
--- /dev/null
+++ b/tests/lxcconf2xmldata/lxcconf2xml-simple.xml
@@ -0,0 +1,17 @@
+<domain type='lxc'>
+ <name>migrate_test</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>65536</memory>
+ <currentMemory unit='KiB'>0</currentMemory>
+ <vcpu placement='static' current='0'>1</vcpu>
+ <os>
+ <type>exe</type>
+ <init>/sbin/init</init>
+ </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/lxcconf2xmltest.c b/tests/lxcconf2xmltest.c
new file mode 100644
index 0000000..9a840f9
--- /dev/null
+++ b/tests/lxcconf2xmltest.c
@@ -0,0 +1,107 @@
+#include <config.h>
+
+#include "testutils.h"
+
+#ifdef WITH_LXC
+
+# include "lxc/lxc_native.h"
+
+# define VIR_FROM_THIS VIR_FROM_NONE
+
+static int
+blankProblemElements(char *data)
+{
+ if (virtTestClearLineRegex("<uuid>([[:alnum:]]|-)+</uuid>", data) < 0)
+ return -1;
+ return 0;
+}
+
+static int
+testCompareXMLToConfigFiles(const char *xml,
+ const char *configfile)
+{
+ int ret = -1;
+ char *config = NULL;
+ char *expectxml = NULL;
+ char *actualxml = NULL;
+ virDomainDefPtr vmdef = NULL;
+
+ if (virtTestLoadFile(configfile, &config) < 0)
+ goto fail;
+ if (virtTestLoadFile(xml, &expectxml) < 0)
+ goto fail;
+
+ if (!(vmdef = lxcParseConfigString(config)))
+ goto fail;
+
+ if (!(actualxml = virDomainDefFormat(vmdef, 0)))
+ goto fail;
+
+ if (blankProblemElements(expectxml) < 0 ||
+ blankProblemElements(actualxml) < 0)
+ goto fail;
+
+ if (STRNEQ(expectxml, actualxml)) {
+ virtTestDifference(stderr, expectxml, actualxml);
+ goto fail;
+ }
+
+ ret = 0;
+
+fail:
+ VIR_FREE(expectxml);
+ VIR_FREE(actualxml);
+ VIR_FREE(config);
+ virDomainDefFree(vmdef);
+ return ret;
+}
+
+static int
+testCompareXMLToConfigHelper(const void *data)
+{
+ int result = -1;
+ const char *name = data;
+ char *xml = NULL;
+ char *config = NULL;
+
+ if (virAsprintf(&xml, "%s/lxcconf2xmldata/lxcconf2xml-%s.xml",
+ abs_srcdir, name) < 0 ||
+ virAsprintf(&config, "%s/lxcconf2xmldata/lxcconf2xml-%s.config",
+ abs_srcdir, name) < 0)
+ goto cleanup;
+
+ result = testCompareXMLToConfigFiles(xml, config);
+
+cleanup:
+ VIR_FREE(xml);
+ VIR_FREE(config);
+ return result;
+}
+
+static int
+mymain(void)
+{
+ int ret = EXIT_SUCCESS;
+
+# define DO_TEST(name) \
+ if (virtTestRun("LXC Native-2-XML " name, \
+ testCompareXMLToConfigHelper, \
+ name) < 0) \
+ ret = EXIT_FAILURE
+
+ DO_TEST("simple");
+
+ return ret;
+}
+
+VIRT_TEST_MAIN(mymain)
+
+#else
+
+int
+main(void)
+{
+ return EXIT_AM_SKIP;
+}
+
+#endif /* WITH_LXC */
--
1.8.5.2
Daniel P. Berrange
2014-02-12 17:23:24 UTC
Permalink
Post by Cédric Bosdonnat
This function aims at converting LXC configuration into a libvirt
domain XML description to help users migrate from LXC to libvirt.
virsh -c lxc:/// domxml-from-native lxc-tools /var/lib/lxc/migrate_test/config
It is possible that some parts couldn't be properly mapped into a
domain XML fragment, so users should carefully review the result
before creating the domain.
fstab files in lxc.mount lines will need to be merged into the
configuration file as lxc.mount.entry.
As we can't know the amount of memory of the host, we have to set a
default value for max_balloon that users will probably want to adjust.
---
.gitignore | 1 +
po/POTFILES.in | 1 +
src/Makefile.am | 1 +
src/lxc/lxc_driver.c | 31 +++++++
src/lxc/lxc_native.c | 86 +++++++++++++++++++
src/lxc/lxc_native.h | 32 +++++++
tests/Makefile.am | 7 +-
tests/lxcconf2xmldata/lxcconf2xml-simple.config | 38 +++++++++
tests/lxcconf2xmldata/lxcconf2xml-simple.xml | 17 ++++
tests/lxcconf2xmltest.c | 107 ++++++++++++++++++++++++
10 files changed, 320 insertions(+), 1 deletion(-)
create mode 100644 src/lxc/lxc_native.c
create mode 100644 src/lxc/lxc_native.h
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-simple.config
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-simple.xml
create mode 100644 tests/lxcconf2xmltest.c
ACK

Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
Cédric Bosdonnat
2014-02-05 14:10:11 UTC
Permalink
---
src/lxc/lxc_native.c | 30 ++++++++++++++++++++++
.../lxcconf2xmldata/lxcconf2xml-cpusettune.config | 6 +++++
tests/lxcconf2xmldata/lxcconf2xml-cpusettune.xml | 27 +++++++++++++++++++
tests/lxcconf2xmltest.c | 1 +
4 files changed, 64 insertions(+)
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-cpusettune.config
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-cpusettune.xml

diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c
index 65a1d0d..ee8fa75 100644
--- a/src/lxc/lxc_native.c
+++ b/src/lxc/lxc_native.c
@@ -673,6 +673,32 @@ error:
return -1;
}

+static int
+lxcSetCpusetTune(virDomainDefPtr def, virConfPtr properties)
+{
+ virConfValuePtr value;
+
+ if ((value = virConfGetValue(properties, "lxc.cgroup.cpuset.cpus")) &&
+ value->str) {
+ if (virBitmapParse(value->str, 0, &def->cpumask,
+ VIR_DOMAIN_CPUMASK_LEN) < 0)
+ return -1;
+
+ def->placement_mode = VIR_DOMAIN_CPU_PLACEMENT_MODE_STATIC;
+ }
+
+ if ((value = virConfGetValue(properties, "lxc.cgroup.cpuset.mems")) &&
+ value->str) {
+ def->numatune.memory.placement_mode = VIR_NUMA_TUNE_MEM_PLACEMENT_MODE_STATIC;
+ def->numatune.memory.mode = VIR_DOMAIN_NUMATUNE_MEM_STRICT;
+ if (virBitmapParse(value->str, 0, &def->numatune.memory.nodemask,
+ VIR_DOMAIN_CPUMASK_LEN) < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
virDomainDefPtr
lxcParseConfigString(const char *config)
{
@@ -753,6 +779,10 @@ lxcParseConfigString(const char *config)
if (lxcSetCpuTune(vmdef, properties) < 0)
goto error;

+ /* lxc.cgroup.cpuset.* */
+ if (lxcSetCpusetTune(vmdef, properties) < 0)
+ goto error;
+
goto cleanup;

error:
diff --git a/tests/lxcconf2xmldata/lxcconf2xml-cpusettune.config b/tests/lxcconf2xmldata/lxcconf2xml-cpusettune.config
new file mode 100644
index 0000000..a550f57
--- /dev/null
+++ b/tests/lxcconf2xmldata/lxcconf2xml-cpusettune.config
@@ -0,0 +1,6 @@
+lxc.rootfs = /var/lib/lxc/migrate_test/rootfs
+lxc.utsname = migrate_test
+lxc.autodev=1
+
+lxc.cgroup.cpuset.cpus = 1,2,5-7
+lxc.cgroup.cpuset.mems = 1-4
diff --git a/tests/lxcconf2xmldata/lxcconf2xml-cpusettune.xml b/tests/lxcconf2xmldata/lxcconf2xml-cpusettune.xml
new file mode 100644
index 0000000..1b8fb0c
--- /dev/null
+++ b/tests/lxcconf2xmldata/lxcconf2xml-cpusettune.xml
@@ -0,0 +1,27 @@
+<domain type='lxc'>
+ <name>migrate_test</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>65536</memory>
+ <currentMemory unit='KiB'>0</currentMemory>
+ <vcpu placement='static' cpuset='1-2,5-7' current='0'>1</vcpu>
+ <numatune>
+ <memory mode='strict' nodeset='1-4'/>
+ </numatune>
+ <os>
+ <type>exe</type>
+ <init>/sbin/init</init>
+ </os>
+ <features>
+ <privnet/>
+ </features>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <filesystem type='mount' accessmode='passthrough'>
+ <source dir='/var/lib/lxc/migrate_test/rootfs'/>
+ <target dir='/'/>
+ </filesystem>
+ </devices>
+</domain>
diff --git a/tests/lxcconf2xmltest.c b/tests/lxcconf2xmltest.c
index 1148cd3..6bee5c5 100644
--- a/tests/lxcconf2xmltest.c
+++ b/tests/lxcconf2xmltest.c
@@ -111,6 +111,7 @@ mymain(void)
DO_TEST("idmap", false);
DO_TEST("memtune", false);
DO_TEST("cputune", false);
+ DO_TEST("cpusettune", false);

return ret;
}
--
1.8.5.2
Daniel P. Berrange
2014-02-12 17:47:01 UTC
Permalink
Post by Cédric Bosdonnat
---
src/lxc/lxc_native.c | 30 ++++++++++++++++++++++
.../lxcconf2xmldata/lxcconf2xml-cpusettune.config | 6 +++++
tests/lxcconf2xmldata/lxcconf2xml-cpusettune.xml | 27 +++++++++++++++++++
tests/lxcconf2xmltest.c | 1 +
4 files changed, 64 insertions(+)
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-cpusettune.config
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-cpusettune.xml
ACK

Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
Cédric Bosdonnat
2014-02-05 14:10:05 UTC
Permalink
---
src/lxc/lxc_native.c | 44 +++++++++++++++++++---
.../lxcconf2xmldata/lxcconf2xml-physnetwork.config | 6 +++
tests/lxcconf2xmldata/lxcconf2xml-physnetwork.xml | 26 +++++++++++++
tests/lxcconf2xmltest.c | 1 +
4 files changed, 72 insertions(+), 5 deletions(-)
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-physnetwork.config
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-physnetwork.xml

diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c
index 42eccfc..7997fda 100644
--- a/src/lxc/lxc_native.c
+++ b/src/lxc/lxc_native.c
@@ -366,6 +366,26 @@ error:
return NULL;
}

+static virDomainHostdevDefPtr
+lxcCreateHostdevDef(int mode, int type, const char *data)
+{
+ virDomainHostdevDefPtr hostdev = virDomainHostdevDefAlloc();
+
+ if (!hostdev)
+ return NULL;
+
+ hostdev->mode = mode;
+ hostdev->source.caps.type = type;
+
+ if (type == VIR_DOMAIN_HOSTDEV_CAPS_TYPE_NET &&
+ VIR_STRDUP(hostdev->source.caps.u.net.iface, data) < 0) {
+ virDomainHostdevDefFree(hostdev);
+ hostdev = NULL;
+ }
+
+ return hostdev;
+}
+
static int
lxcAddNetworkDefinition(virDomainDefPtr def,
const char *type,
@@ -374,22 +394,36 @@ lxcAddNetworkDefinition(virDomainDefPtr def,
const char *flag)
{
virDomainNetDefPtr net = NULL;
+ virDomainHostdevDefPtr hostdev = NULL;

if ((type == NULL) || STREQ(type, "empty") || STREQ(type, "") ||
STREQ(type, "none"))
return 0;

- if (!(net = lxcCreateNetDef(type, link, mac, flag)))
- goto error;
+ if (type != NULL && STREQ(type, "phys")) {
+ if (!link ||
+ !(hostdev = lxcCreateHostdevDef(VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES,
+ VIR_DOMAIN_HOSTDEV_CAPS_TYPE_NET,
+ link)))
+ goto error;

- if (VIR_EXPAND_N(def->nets, def->nnets, 1) < 0)
- goto error;
- def->nets[def->nnets - 1] = net;
+ if (VIR_EXPAND_N(def->hostdevs, def->nhostdevs, 1) < 0)
+ goto error;
+ def->hostdevs[def->nhostdevs - 1] = hostdev;
+ } else {
+ if (!(net = lxcCreateNetDef(type, link, mac, flag)))
+ goto error;
+
+ if (VIR_EXPAND_N(def->nets, def->nnets, 1) < 0)
+ goto error;
+ def->nets[def->nnets - 1] = net;
+ }

return 1;

error:
virDomainNetDefFree(net);
+ virDomainHostdevDefFree(hostdev);
return -1;
}

diff --git a/tests/lxcconf2xmldata/lxcconf2xml-physnetwork.config b/tests/lxcconf2xmldata/lxcconf2xml-physnetwork.config
new file mode 100644
index 0000000..63a4aa1
--- /dev/null
+++ b/tests/lxcconf2xmldata/lxcconf2xml-physnetwork.config
@@ -0,0 +1,6 @@
+lxc.network.type = phys
+lxc.network.link = eth0
+
+lxc.rootfs = /var/lib/lxc/migrate_test/rootfs
+lxc.utsname = migrate_test
+lxc.autodev=1
diff --git a/tests/lxcconf2xmldata/lxcconf2xml-physnetwork.xml b/tests/lxcconf2xmldata/lxcconf2xml-physnetwork.xml
new file mode 100644
index 0000000..35a2a96
--- /dev/null
+++ b/tests/lxcconf2xmldata/lxcconf2xml-physnetwork.xml
@@ -0,0 +1,26 @@
+<domain type='lxc'>
+ <name>migrate_test</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>65536</memory>
+ <currentMemory unit='KiB'>0</currentMemory>
+ <vcpu placement='static' current='0'>1</vcpu>
+ <os>
+ <type>exe</type>
+ <init>/sbin/init</init>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <filesystem type='mount' accessmode='passthrough'>
+ <source dir='/var/lib/lxc/migrate_test/rootfs'/>
+ <target dir='/'/>
+ </filesystem>
+ <hostdev mode='capabilities' type='net'>
+ <source>
+ <interface>eth0</interface>
+ </source>
+ </hostdev>
+ </devices>
+</domain>
diff --git a/tests/lxcconf2xmltest.c b/tests/lxcconf2xmltest.c
index 50041a5..c888b42 100644
--- a/tests/lxcconf2xmltest.c
+++ b/tests/lxcconf2xmltest.c
@@ -106,6 +106,7 @@ mymain(void)
DO_TEST("fstab", true);
DO_TEST("nonetwork", false);
DO_TEST("nonenetwork", false);
+ DO_TEST("physnetwork", false);

return ret;
}
--
1.8.5.2
Daniel P. Berrange
2014-02-12 17:43:45 UTC
Permalink
Post by Cédric Bosdonnat
---
src/lxc/lxc_native.c | 44 +++++++++++++++++++---
.../lxcconf2xmldata/lxcconf2xml-physnetwork.config | 6 +++
tests/lxcconf2xmldata/lxcconf2xml-physnetwork.xml | 26 +++++++++++++
tests/lxcconf2xmltest.c | 1 +
4 files changed, 72 insertions(+), 5 deletions(-)
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-physnetwork.config
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-physnetwork.xml
ACK

Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
Cédric Bosdonnat
2014-02-05 14:10:09 UTC
Permalink
---
src/lxc/lxc_native.c | 40 ++++++++++++++++++++++++
tests/lxcconf2xmldata/lxcconf2xml-memtune.config | 10 ++++++
tests/lxcconf2xmldata/lxcconf2xml-memtune.xml | 29 +++++++++++++++++
tests/lxcconf2xmltest.c | 1 +
4 files changed, 80 insertions(+)
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-memtune.config
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-memtune.xml

diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c
index dd706f8..d430abc 100644
--- a/src/lxc/lxc_native.c
+++ b/src/lxc/lxc_native.c
@@ -607,6 +607,42 @@ lxcIdmapWalkCallback(const char *name, virConfValuePtr value, void *data)
return 0;
}

+static int
+lxcSetMemTune(virDomainDefPtr def, virConfPtr properties)
+{
+ virConfValuePtr value;
+ unsigned long long size = 0;
+
+ if ((value = virConfGetValue(properties,
+ "lxc.cgroup.memory.limit_in_bytes")) &&
+ value->str && STRNEQ(value->str, "-1")) {
+ if (lxcConvertSize(value->str, &size) < 0)
+ return -1;
+ size = size / 1024;
+ def->mem.max_balloon = size;
+ def->mem.hard_limit = size;
+ }
+
+ if ((value = virConfGetValue(properties,
+ "lxc.cgroup.memory.soft_limit_in_bytes")) &&
+ value->str && STRNEQ(value->str, "-1")) {
+ if (lxcConvertSize(value->str, &size) < 0)
+ return -1;
+
+ def->mem.soft_limit = size / 1024;
+ }
+
+ if ((value = virConfGetValue(properties,
+ "lxc.cgroup.memory.memsw.limit_in_bytes")) &&
+ value->str && STRNEQ(value->str, "-1")) {
+ if (lxcConvertSize(value->str, &size) < 0)
+ return -1;
+
+ def->mem.swap_hard_limit = size / 1024;
+ }
+ return 0;
+}
+
virDomainDefPtr
lxcParseConfigString(const char *config)
{
@@ -679,6 +715,10 @@ lxcParseConfigString(const char *config)
if (virConfWalk(properties, lxcIdmapWalkCallback, vmdef) < 0)
goto error;

+ /* lxc.cgroup.memory.* */
+ if (lxcSetMemTune(vmdef, properties) < 0)
+ goto error;
+
goto cleanup;

error:
diff --git a/tests/lxcconf2xmldata/lxcconf2xml-memtune.config b/tests/lxcconf2xmldata/lxcconf2xml-memtune.config
new file mode 100644
index 0000000..ef07a51
--- /dev/null
+++ b/tests/lxcconf2xmldata/lxcconf2xml-memtune.config
@@ -0,0 +1,10 @@
+lxc.rootfs = /var/lib/lxc/migrate_test/rootfs
+lxc.utsname = migrate_test
+lxc.autodev=1
+
+# 1GiB
+lxc.cgroup.memory.limit_in_bytes = 1073741824
+# 128MiB
+lxc.cgroup.memory.soft_limit_in_bytes = 134217728
+# 2GiB
+lxc.cgroup.memory.memsw.limit_in_bytes = 2147483648
diff --git a/tests/lxcconf2xmldata/lxcconf2xml-memtune.xml b/tests/lxcconf2xmldata/lxcconf2xml-memtune.xml
new file mode 100644
index 0000000..0264356
--- /dev/null
+++ b/tests/lxcconf2xmldata/lxcconf2xml-memtune.xml
@@ -0,0 +1,29 @@
+<domain type='lxc'>
+ <name>migrate_test</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>1048576</memory>
+ <currentMemory unit='KiB'>0</currentMemory>
+ <memtune>
+ <hard_limit unit='KiB'>1048576</hard_limit>
+ <soft_limit unit='KiB'>131072</soft_limit>
+ <swap_hard_limit unit='KiB'>2097152</swap_hard_limit>
+ </memtune>
+ <vcpu placement='static' current='0'>1</vcpu>
+ <os>
+ <type>exe</type>
+ <init>/sbin/init</init>
+ </os>
+ <features>
+ <privnet/>
+ </features>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <filesystem type='mount' accessmode='passthrough'>
+ <source dir='/var/lib/lxc/migrate_test/rootfs'/>
+ <target dir='/'/>
+ </filesystem>
+ </devices>
+</domain>
diff --git a/tests/lxcconf2xmltest.c b/tests/lxcconf2xmltest.c
index 7042bdf..3dd0a0b 100644
--- a/tests/lxcconf2xmltest.c
+++ b/tests/lxcconf2xmltest.c
@@ -109,6 +109,7 @@ mymain(void)
DO_TEST("physnetwork", false);
DO_TEST("macvlannetwork", false);
DO_TEST("idmap", false);
+ DO_TEST("memtune", false);

return ret;
}
--
1.8.5.2
Daniel P. Berrange
2014-02-12 17:46:27 UTC
Permalink
Post by Cédric Bosdonnat
---
src/lxc/lxc_native.c | 40 ++++++++++++++++++++++++
tests/lxcconf2xmldata/lxcconf2xml-memtune.config | 10 ++++++
tests/lxcconf2xmldata/lxcconf2xml-memtune.xml | 29 +++++++++++++++++
tests/lxcconf2xmltest.c | 1 +
4 files changed, 80 insertions(+)
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-memtune.config
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-memtune.xml
ACK

Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
Cédric Bosdonnat
2014-02-05 14:10:06 UTC
Permalink
---
src/lxc/lxc_native.c | 44 ++++++++++++++++++++++++++++
tests/lxcconf2xmldata/lxcconf2xml-simple.xml | 6 ++++
2 files changed, 50 insertions(+)

diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c
index 7997fda..96523c4 100644
--- a/src/lxc/lxc_native.c
+++ b/src/lxc/lxc_native.c
@@ -500,6 +500,46 @@ lxcConvertNetworkSettings(virDomainDefPtr def, virConfPtr properties)
return 0;
}

+static int
+lxcCreateConsoles(virDomainDefPtr def, virConfPtr properties)
+{
+ virConfValuePtr value;
+ int nbttys = 0;
+ virDomainChrDefPtr console;
+ size_t i;
+
+ if (!(value = virConfGetValue(properties, "lxc.tty")) || !value->str)
+ return 0;
+
+ if (virStrToLong_i(value->str, NULL, 10, &nbttys) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, _("failed to parse int: '%s'"),
+ value->str);
+ return -1;
+ }
+
+ if (VIR_ALLOC_N(def->consoles, nbttys) < 0)
+ return -1;
+
+ def->nconsoles = nbttys;
+ for (i = 0; i < nbttys; i++) {
+ if (!(console = virDomainChrDefNew()))
+ goto error;
+
+ console->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE;
+ console->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_LXC;
+ console->target.port = i;
+ console->source.type = VIR_DOMAIN_CHR_TYPE_PTY;
+
+ def->consoles[i] = console;
+ }
+
+ return 0;
+
+error:
+ virDomainChrDefFree(console);
+ return -1;
+}
+
virDomainDefPtr
lxcParseConfigString(const char *config)
{
@@ -564,6 +604,10 @@ lxcParseConfigString(const char *config)
if (lxcConvertNetworkSettings(vmdef, properties) < 0)
goto error;

+ /* Consoles */
+ if (lxcCreateConsoles(vmdef, properties) < 0)
+ goto error;
+
goto cleanup;

error:
diff --git a/tests/lxcconf2xmldata/lxcconf2xml-simple.xml b/tests/lxcconf2xmldata/lxcconf2xml-simple.xml
index 75c3b28..711e0d9 100644
--- a/tests/lxcconf2xmldata/lxcconf2xml-simple.xml
+++ b/tests/lxcconf2xmldata/lxcconf2xml-simple.xml
@@ -31,5 +31,11 @@
<source bridge='virbr0'/>
<link state='up'/>
</interface>
+ <console type='pty'>
+ <target type='lxc' port='0'/>
+ </console>
+ <console type='pty'>
+ <target type='lxc' port='1'/>
+ </console>
</devices>
</domain>
--
1.8.5.2
Daniel P. Berrange
2014-02-12 17:44:02 UTC
Permalink
Post by Cédric Bosdonnat
---
src/lxc/lxc_native.c | 44 ++++++++++++++++++++++++++++
tests/lxcconf2xmldata/lxcconf2xml-simple.xml | 6 ++++
2 files changed, 50 insertions(+)
ACK

Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
Cédric Bosdonnat
2014-02-05 14:10:04 UTC
Permalink
Some of the LXC configuration properties aren't migrated since they
would only cause problems in libvirt-lxc:
* lxc.network.ipv[46]: LXC driver doesn't setup IP address of guests,
see rhbz#1059624
* lxc.network.name, see rhbz#1059630
---
src/lxc/lxc_native.c | 114 ++++++++++++++++++++++++---
tests/lxcconf2xmldata/lxcconf2xml-simple.xml | 5 ++
2 files changed, 107 insertions(+), 12 deletions(-)

diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c
index bc14d69..42eccfc 100644
--- a/src/lxc/lxc_native.c
+++ b/src/lxc/lxc_native.c
@@ -325,8 +325,80 @@ lxcFstabWalkCallback(const char* name, virConfValuePtr value, void * data)
return ret;
}

+static virDomainNetDefPtr
+lxcCreateNetDef(const char *type,
+ const char *link,
+ const char *mac,
+ const char *flag)
+{
+ virDomainNetDefPtr net = NULL;
+
+ if (VIR_ALLOC(net) < 0)
+ goto error;
+
+ if (flag) {
+ if (STREQ(flag, "up"))
+ net->linkstate = VIR_DOMAIN_NET_INTERFACE_LINK_STATE_UP;
+ else
+ net->linkstate = VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DOWN;
+ }
+
+ if (STREQ(type, "veth")) {
+ virMacAddr macAddr;
+
+ if (!link)
+ goto error;
+
+ net->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
+
+ if (VIR_STRDUP(net->data.bridge.brname, link) < 0)
+ goto error;
+
+ if (mac && virMacAddrParse(mac, &macAddr) == 0)
+ net->mac = macAddr;
+
+ }
+
+ return net;
+
+error:
+ virDomainNetDefFree(net);
+ return NULL;
+}
+
+static int
+lxcAddNetworkDefinition(virDomainDefPtr def,
+ const char *type,
+ const char *link,
+ const char *mac,
+ const char *flag)
+{
+ virDomainNetDefPtr net = NULL;
+
+ if ((type == NULL) || STREQ(type, "empty") || STREQ(type, "") ||
+ STREQ(type, "none"))
+ return 0;
+
+ if (!(net = lxcCreateNetDef(type, link, mac, flag)))
+ goto error;
+
+ if (VIR_EXPAND_N(def->nets, def->nnets, 1) < 0)
+ goto error;
+ def->nets[def->nnets - 1] = net;
+
+ return 1;
+
+error:
+ virDomainNetDefFree(net);
+ return -1;
+}
+
typedef struct {
+ virDomainDefPtr def;
char *type;
+ char *link;
+ char *mac;
+ char *flag;
bool privnet;
size_t networks;
} lxcNetworkParseData;
@@ -335,38 +407,56 @@ static int
lxcNetworkWalkCallback(const char *name, virConfValuePtr value, void *data)
{
lxcNetworkParseData *parseData = data;
+ int status;

if (STREQ(name, "lxc.network.type")) {
- if (parseData->type != NULL && STREQ(parseData->type, "none"))
- parseData->privnet = false;
- else if ((parseData->type != NULL) &&
- STRNEQ(parseData->type, "empty") &&
- STRNEQ(parseData->type, "")) {
+ /* Store the previous NIC */
+ status = lxcAddNetworkDefinition(parseData->def, parseData->type,
+ parseData->link, parseData->mac,
+ parseData->flag);
+ if (status < 0)
+ return -1;
+ else if (status > 0)
parseData->networks++;
- }
+ else if (parseData->type != NULL && STREQ(parseData->type, "none"))
+ parseData->privnet = false;

/* Start a new network interface config */
parseData->type = NULL;
+ parseData->link = NULL;
+ parseData->mac = NULL;
+ parseData->flag = NULL;

/* Keep the new value */
parseData->type = value->str;
}
+ else if (STREQ(name, "lxc.network.link"))
+ parseData->link = value->str;
+ else if (STREQ(name, "lxc.network.hwaddr"))
+ parseData->mac = value->str;
+ else if (STREQ(name, "lxc.network.flags"))
+ parseData->flag = value->str;
+
return 0;
}

static int
lxcConvertNetworkSettings(virDomainDefPtr def, virConfPtr properties)
{
- lxcNetworkParseData data = {NULL, true, 0};
+ int status;
+ lxcNetworkParseData data = {def, NULL, NULL, NULL, NULL, true, 0};

virConfWalk(properties, lxcNetworkWalkCallback, &data);

- if ((data.type != NULL) && STREQ(data.type, "none"))
- data.privnet = false;
- else if ((data.type != NULL) && STRNEQ(data.type, "empty") &&
- STRNEQ(data.type, "")) {
+ /* Add the last network definition found */
+ status = lxcAddNetworkDefinition(def, data.type, data.link,
+ data.mac, data.flag);
+ if (status < 0)
+ return -1;
+ else if (status > 0)
data.networks++;
- }
+ else if (data.type != NULL && STREQ(data.type, "none"))
+ data.privnet = false;

if (data.networks == 0 && data.privnet) {
/* When no network type is provided LXC only adds loopback */
diff --git a/tests/lxcconf2xmldata/lxcconf2xml-simple.xml b/tests/lxcconf2xmldata/lxcconf2xml-simple.xml
index fadbdca..75c3b28 100644
--- a/tests/lxcconf2xmldata/lxcconf2xml-simple.xml
+++ b/tests/lxcconf2xmldata/lxcconf2xml-simple.xml
@@ -26,5 +26,10 @@
<target dir='/etc/resolv.conf'/>
<readonly/>
</filesystem>
+ <interface type='bridge'>
+ <mac address='02:00:15:8f:05:c1'/>
+ <source bridge='virbr0'/>
+ <link state='up'/>
+ </interface>
</devices>
</domain>
--
1.8.5.2
Daniel P. Berrange
2014-02-12 17:43:24 UTC
Permalink
Post by Cédric Bosdonnat
Some of the LXC configuration properties aren't migrated since they
* lxc.network.ipv[46]: LXC driver doesn't setup IP address of guests,
see rhbz#1059624
* lxc.network.name, see rhbz#1059630
---
src/lxc/lxc_native.c | 114 ++++++++++++++++++++++++---
tests/lxcconf2xmldata/lxcconf2xml-simple.xml | 5 ++
2 files changed, 107 insertions(+), 12 deletions(-)
ACK

Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
Cédric Bosdonnat
2014-02-05 14:09:59 UTC
Permalink
virConf now honours a VIR_CONF_FLAG_LXC_FORMAT flag to handle LXC
configuration files. The differences are that property names can
contain '.' character and values are all strings without any bounding
quotes.

Provide a new virConfWalk function calling a handler on all non-comment
values. This function will be used by the LXC conversion code to loop
over LXC configuration lines.
---
src/libvirt_private.syms | 1 +
src/util/virconf.c | 46 ++++++++++++++++++++++++++++++++++++++++++++--
src/util/virconf.h | 10 ++++++++++
3 files changed, 55 insertions(+), 2 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index c5a7637..ba10b4e 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1128,6 +1128,7 @@ virConfNew;
virConfReadFile;
virConfReadMem;
virConfSetValue;
+virConfWalk;
virConfWriteFile;
virConfWriteMem;

diff --git a/src/util/virconf.c b/src/util/virconf.c
index e882d15..63aa569 100644
--- a/src/util/virconf.c
+++ b/src/util/virconf.c
@@ -429,6 +429,16 @@ virConfParseString(virConfParserCtxtPtr ctxt)
if (VIR_STRNDUP(ret, base, ctxt->cur - base) < 0)
return NULL;
NEXT;
+ } else if (ctxt->conf->flags & VIR_CONF_FLAG_LXC_FORMAT) {
+ base = ctxt->cur;
+ /* LXC config format doesn't support comments after the value */
+ while ((ctxt->cur < ctxt->end) && (!IS_EOL(CUR)))
+ NEXT;
+ /* Reverse to exclude the trailing blanks from the value */
+ while ((ctxt->cur > base) && (c_isblank(CUR)))
+ ctxt->cur--;
+ if (VIR_STRNDUP(ret, base, ctxt->cur - base) < 0)
+ return NULL;
}
return ret;
}
@@ -454,7 +464,8 @@ virConfParseValue(virConfParserCtxtPtr ctxt)
virConfError(ctxt, VIR_ERR_CONF_SYNTAX, _("expecting a value"));
return NULL;
}
- if ((CUR == '"') || (CUR == '\'')) {
+ if ((CUR == '"') || (CUR == '\'') ||
+ (ctxt->conf->flags & VIR_CONF_FLAG_LXC_FORMAT)) {
type = VIR_CONF_STRING;
str = virConfParseString(ctxt);
if (str == NULL)
@@ -561,7 +572,9 @@ virConfParseName(virConfParserCtxtPtr ctxt)
while ((ctxt->cur < ctxt->end) &&
(c_isalnum(CUR) || (CUR == '_') ||
((ctxt->conf->flags & VIR_CONF_FLAG_VMX_FORMAT) &&
- ((CUR == ':') || (CUR == '.') || (CUR == '-')))))
+ ((CUR == ':') || (CUR == '.') || (CUR == '-'))) ||
+ ((ctxt->conf->flags & VIR_CONF_FLAG_LXC_FORMAT) &&
+ (CUR == '.'))))
NEXT;
if (VIR_STRNDUP(ret, base, ctxt->cur - base) < 0)
return NULL;
@@ -905,6 +918,35 @@ virConfSetValue(virConfPtr conf,
return 0;
}

+/**
+ * virConfWalk:
+ * @conf: a configuration file handle
+ * @callback: the function to call to process each entry
+ * @data: obscure data passed to callback
+ *
+ * Walk over all entries of the configuration file and run the callback
+ * for each with entry name, value and the obscure data.
+ *
+ * Returns 0 on success, or -1 on failure.
+ */
+int virConfWalk(virConfPtr conf,
+ virConfWalkCallback callback,
+ void *opaque)
+{
+ virConfEntryPtr cur;
+
+ if (!conf)
+ return 0;
+
+ cur = conf->entries;
+ while (cur != NULL) {
+ if (cur->name && cur->value &&
+ callback(cur->name, cur->value, opaque) < 0)
+ return -1;
+ cur = cur->next;
+ }
+ return 0;
+}

/**
* virConfWriteFile:
diff --git a/src/util/virconf.h b/src/util/virconf.h
index 577af8c..2a6b050 100644
--- a/src/util/virconf.h
+++ b/src/util/virconf.h
@@ -40,6 +40,9 @@ typedef enum {
VIR_CONF_FLAG_VMX_FORMAT = 1, /* allow ':', '.' and '-' in names for compatibility
with VMware VMX configuration file, but restrict
allowed value types to string only */
+ VIR_CONF_FLAG_LXC_FORMAT = 2, /* allow '.' in names for compatibility with LXC
+ configuration file, restricts allowed value types
+ to string only and don't expect quotes for values */
} virConfFlags;

static inline const char *
@@ -79,6 +82,10 @@ struct _virConfValue {
typedef struct _virConf virConf;
typedef virConf *virConfPtr;

+typedef int (*virConfWalkCallback)(const char* name,
+ virConfValuePtr value,
+ void *opaque);
+
virConfPtr virConfNew (void);
virConfPtr virConfReadFile (const char *filename, unsigned int flags);
virConfPtr virConfReadMem (const char *memory,
@@ -91,6 +98,9 @@ virConfValuePtr virConfGetValue (virConfPtr conf,
int virConfSetValue (virConfPtr conf,
const char *setting,
virConfValuePtr value);
+int virConfWalk(virConfPtr conf,
+ virConfWalkCallback callback,
+ void *opaque);
int virConfWriteFile (const char *filename,
virConfPtr conf);
int virConfWriteMem (char *memory,
--
1.8.5.2
Daniel P. Berrange
2014-02-12 17:23:05 UTC
Permalink
Post by Cédric Bosdonnat
virConf now honours a VIR_CONF_FLAG_LXC_FORMAT flag to handle LXC
configuration files. The differences are that property names can
contain '.' character and values are all strings without any bounding
quotes.
Provide a new virConfWalk function calling a handler on all non-comment
values. This function will be used by the LXC conversion code to loop
over LXC configuration lines.
---
src/libvirt_private.syms | 1 +
src/util/virconf.c | 46 ++++++++++++++++++++++++++++++++++++++++++++--
src/util/virconf.h | 10 ++++++++++
3 files changed, 55 insertions(+), 2 deletions(-)
ACK

Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
Cédric Bosdonnat
2014-02-05 14:10:19 UTC
Permalink
To ease LXC configuration conversion, allow blkiotune device XML
fragments to define the device using its major:minor numbers.
---
docs/formatdomain.html.in | 10 +-
src/conf/domain_conf.c | 45 ++++++++-
src/conf/domain_conf.h | 2 +
src/lxc/lxc_cgroup.c | 5 +
src/lxc/lxc_driver.c | 10 ++
src/lxc/lxc_native.c | 24 ++++-
src/qemu/qemu_cgroup.c | 5 +
src/qemu/qemu_driver.c | 10 ++
src/util/vircgroup.c | 126 ++++++++++--------------
src/util/vircgroup.h | 10 ++
tests/lxcconf2xmldata/lxcconf2xml-blkiotune.xml | 4 +-
11 files changed, 165 insertions(+), 86 deletions(-)

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index fd02864..2ab7d39 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -761,6 +761,10 @@
&lt;path&gt;/dev/sdb&lt;/path&gt;
&lt;weight&gt;500&lt;/weight&gt;
&lt;/device&gt;
+ &lt;device&gt;
+ &lt;node major='8' minor='0'/&gt;
+ &lt;weight&gt;500&lt;/weight&gt;
+ &lt;/device&gt;
&lt;/blkiotune&gt;
...
&lt;/domain&gt;
@@ -794,7 +798,11 @@
absolute path of the device, and <code>weight</code> giving
the relative weight of that device, in the range [100,
1000]. After kernel 2.6.39, the value could be in the
- range [10, 1000].<span class="since">Since 0.9.8</span></dd>
+ range [10, 1000].<span class="since">Since 0.9.8</span>.
+ <span class="since">Since 1.2.2</span> each <code>device</code>
+ element can replace the mandatory <code>path</code> sub-element
+ by a <code>node</code> one. <code>node</code> has two mandatory
+ attributes <code>major</code> and <code>minor</code>.</dd>
</dl>


diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 28e24f9..65192df 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -905,6 +905,7 @@ virBlkioDeviceArrayClear(virBlkioDevicePtr devices,
*
* <device>
* <path>/fully/qualified/device/path</path>
+ * <node major='8' minor='0/>
* <weight>weight</weight>
* <read_bytes_sec>bps</read_bytes_sec>
* <write_bytes_sec>bps</write_bytes_sec>
@@ -920,12 +921,38 @@ virDomainBlkioDeviceParseXML(xmlNodePtr root,
{
char *c = NULL;
xmlNodePtr node;
+ char *major = NULL;
+ char *minor = NULL;
+ bool hasNumbers = false;

node = root->children;
while (node) {
if (node->type == XML_ELEMENT_NODE) {
if (xmlStrEqual(node->name, BAD_CAST "path") && !dev->path) {
dev->path = (char *)xmlNodeGetContent(node);
+ } else if (xmlStrEqual(node->name, BAD_CAST "node") &&
+ !hasNumbers){
+ if (!(major = virXMLPropString(node, "major")) ||
+ (!(minor = virXMLPropString(node, "minor")))) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("node missing major or minor attribute"));
+ goto error;
+ }
+ if (virStrToLong_ui(major, NULL, 10, &dev->major) < 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("could not parse major %s"),
+ major);
+ goto error;
+ }
+ if (virStrToLong_ui(major, NULL, 10, &dev->minor) < 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("could not parse minor %s"),
+ minor);
+ goto error;
+ }
+ hasNumbers = true;
+ VIR_FREE(major);
+ VIR_FREE(minor);
} else if (xmlStrEqual(node->name, BAD_CAST "weight")) {
c = (char *)xmlNodeGetContent(node);
if (virStrToLong_ui(c, NULL, 10, &dev->weight) < 0) {
@@ -975,9 +1002,13 @@ virDomainBlkioDeviceParseXML(xmlNodePtr root,
}
node = node->next;
}
- if (!dev->path) {
+ if (!dev->path && !hasNumbers) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("missing per-device path"));
+ _("missing per-device path or major/minor"));
+ return -1;
+ } else if (dev->path && hasNumbers) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("cannot have both per-device path and major/minor"));
return -1;
}

@@ -985,6 +1016,8 @@ virDomainBlkioDeviceParseXML(xmlNodePtr root,

error:
VIR_FREE(c);
+ VIR_FREE(major);
+ VIR_FREE(minor);
VIR_FREE(dev->path);
return -1;
}
@@ -16855,8 +16888,12 @@ virDomainDefFormatInternal(virDomainDefPtr def,
!dev->rbps && !dev->wbps)
continue;
virBufferAddLit(buf, " <device>\n");
- virBufferEscapeString(buf, " <path>%s</path>\n",
- dev->path);
+ if (dev->path)
+ virBufferEscapeString(buf, " <path>%s</path>\n",
+ dev->path);
+ else
+ virBufferAsprintf(buf, " <node major='%u' minor='%u'/>\n",
+ dev->major, dev->minor);
if (dev->weight)
virBufferAsprintf(buf, " <weight>%u</weight>\n",
dev->weight);
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index d8f2e49..24cc00c 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1890,6 +1890,8 @@ struct _virBlkioDevice {
unsigned int wiops;
unsigned long long rbps;
unsigned long long wbps;
+ unsigned int major;
+ unsigned int minor;
};

enum virDomainRNGModel {
diff --git a/src/lxc/lxc_cgroup.c b/src/lxc/lxc_cgroup.c
index cc0d5e8..aabd4f8 100644
--- a/src/lxc/lxc_cgroup.c
+++ b/src/lxc/lxc_cgroup.c
@@ -116,26 +116,31 @@ static int virLXCCgroupSetupBlkioTune(virDomainDefPtr def,

if (dev->weight &&
(virCgroupSetBlkioDeviceWeight(cgroup, dev->path,
+ dev->major, dev->minor,
dev->weight) < 0))
return -1;

if (dev->riops &&
(virCgroupSetBlkioDeviceReadIops(cgroup, dev->path,
+ dev->major, dev->minor,
dev->riops) < 0))
return -1;

if (dev->wiops &&
(virCgroupSetBlkioDeviceWriteIops(cgroup, dev->path,
+ dev->major, dev->minor,
dev->wiops) < 0))
return -1;

if (dev->rbps &&
(virCgroupSetBlkioDeviceReadBps(cgroup, dev->path,
+ dev->major, dev->minor,
dev->rbps) < 0))
return -1;

if (dev->wbps &&
(virCgroupSetBlkioDeviceWriteBps(cgroup, dev->path,
+ dev->major, dev->minor,
dev->wbps) < 0))
return -1;
}
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index dc0e8e0..057214a 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -2323,6 +2323,8 @@ lxcDomainSetBlkioParameters(virDomainPtr dom,
for (j = 0; j < ndevices; j++) {
if (virCgroupSetBlkioDeviceWeight(priv->cgroup,
devices[j].path,
+ devices[j].major,
+ devices[j].minor,
devices[j].weight) < 0) {
ret = -1;
break;
@@ -2332,6 +2334,8 @@ lxcDomainSetBlkioParameters(virDomainPtr dom,
for (j = 0; j < ndevices; j++) {
if (virCgroupSetBlkioDeviceReadIops(priv->cgroup,
devices[j].path,
+ devices[j].major,
+ devices[j].minor,
devices[j].riops) < 0) {
ret = -1;
break;
@@ -2341,6 +2345,8 @@ lxcDomainSetBlkioParameters(virDomainPtr dom,
for (j = 0; j < ndevices; j++) {
if (virCgroupSetBlkioDeviceWriteIops(priv->cgroup,
devices[j].path,
+ devices[j].major,
+ devices[j].minor,
devices[j].wiops) < 0) {
ret = -1;
break;
@@ -2350,6 +2356,8 @@ lxcDomainSetBlkioParameters(virDomainPtr dom,
for (j = 0; j < ndevices; j++) {
if (virCgroupSetBlkioDeviceReadBps(priv->cgroup,
devices[j].path,
+ devices[j].major,
+ devices[j].minor,
devices[j].rbps) < 0) {
ret = -1;
break;
@@ -2359,6 +2367,8 @@ lxcDomainSetBlkioParameters(virDomainPtr dom,
for (j = 0; j < ndevices; j++) {
if (virCgroupSetBlkioDeviceWriteBps(priv->cgroup,
devices[j].path,
+ devices[j].major,
+ devices[j].minor,
devices[j].wbps) < 0) {
ret = -1;
break;
diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c
index 675883c..c7ebfb2 100644
--- a/src/lxc/lxc_native.c
+++ b/src/lxc/lxc_native.c
@@ -725,36 +725,52 @@ static int
lxcBlkioDeviceWalkCallback(const char *name, virConfValuePtr value, void *data)
{
char **parts = NULL;
+ char **numbers = NULL;
virBlkioDevicePtr device = NULL;
virDomainDefPtr def = data;
size_t i = 0;
char *path = NULL;
+ unsigned int major, minor = 0;

if (!STRPREFIX(name, "lxc.cgroup.blkio.") ||
STREQ(name, "lxc.cgroup.blkio.weight")|| !value->str)
return 0;

- if ((!(parts = lxcStringSplit(value->str)) && (!parts[0] || !parts[1]))) {
+ if ((!(parts = lxcStringSplit(value->str))) || virStringListLength(parts) != 2 ||
+ (!(numbers = virStringSplit(parts[0], ":", 2))) ||
+ virStringListLength(numbers) != 2) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("invalid %s value: '%s'"),
name, value->str);
goto error;
}

- if (virAsprintf(&path, "/dev/block/%s", parts[0]) < 0)
+ /* *Get the major:minor numbers */
+ if (virStrToLong_ui(numbers[0], NULL, 10, &major) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("failed to parse major: '%s'"), numbers[0]);
goto error;
+ }
+ if (virStrToLong_ui(numbers[1], NULL, 10, &minor) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("failed to parse minor: '%s'"), numbers[1]);
+ goto error;
+ }

/* Do we already have a device definition for this path?
* Get that device or create a new one */
for (i = 0; !device && i < def->blkio.ndevices; i++) {
- if (STREQ(def->blkio.devices[i].path, path))
+ if (def->blkio.devices[i].major == major &&
+ def->blkio.devices[i].minor == minor)
device = &def->blkio.devices[i];
}
if (!device) {
if (VIR_EXPAND_N(def->blkio.devices, def->blkio.ndevices, 1) < 0)
goto error;
device = &def->blkio.devices[def->blkio.ndevices - 1];
- device->path = path;
+ device->major = major;
+ device->minor = minor;
+ device->path = NULL;
}

/* Set the value */
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index a97f184..2808749 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -404,26 +404,31 @@ qemuSetupBlkioCgroup(virDomainObjPtr vm)
virBlkioDevicePtr dev = &vm->def->blkio.devices[i];
if (dev->weight &&
(virCgroupSetBlkioDeviceWeight(priv->cgroup, dev->path,
+ dev->major, dev->minor,
dev->weight) < 0))
return -1;

if (dev->riops &&
(virCgroupSetBlkioDeviceReadIops(priv->cgroup, dev->path,
+ dev->major, dev->minor,
dev->riops) < 0))
return -1;

if (dev->wiops &&
(virCgroupSetBlkioDeviceWriteIops(priv->cgroup, dev->path,
+ dev->major, dev->minor,
dev->wiops) < 0))
return -1;

if (dev->rbps &&
(virCgroupSetBlkioDeviceReadBps(priv->cgroup, dev->path,
+ dev->major, dev->minor,
dev->rbps) < 0))
return -1;

if (dev->wbps &&
(virCgroupSetBlkioDeviceWriteBps(priv->cgroup, dev->path,
+ dev->major, dev->minor,
dev->wbps) < 0))
return -1;
}
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 0128356..f73d942 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -7691,6 +7691,8 @@ qemuDomainSetBlkioParameters(virDomainPtr dom,
for (j = 0; j < ndevices; j++) {
if (virCgroupSetBlkioDeviceWeight(priv->cgroup,
devices[j].path,
+ devices[j].major,
+ devices[j].minor,
devices[j].weight) < 0) {
ret = -1;
break;
@@ -7700,6 +7702,8 @@ qemuDomainSetBlkioParameters(virDomainPtr dom,
for (j = 0; j < ndevices; j++) {
if (virCgroupSetBlkioDeviceReadIops(priv->cgroup,
devices[j].path,
+ devices[j].major,
+ devices[j].minor,
devices[j].riops) < 0) {
ret = -1;
break;
@@ -7709,6 +7713,8 @@ qemuDomainSetBlkioParameters(virDomainPtr dom,
for (j = 0; j < ndevices; j++) {
if (virCgroupSetBlkioDeviceWriteIops(priv->cgroup,
devices[j].path,
+ devices[j].major,
+ devices[j].minor,
devices[j].wiops) < 0) {
ret = -1;
break;
@@ -7718,6 +7724,8 @@ qemuDomainSetBlkioParameters(virDomainPtr dom,
for (j = 0; j < ndevices; j++) {
if (virCgroupSetBlkioDeviceReadBps(priv->cgroup,
devices[j].path,
+ devices[j].major,
+ devices[j].minor,
devices[j].rbps) < 0) {
ret = -1;
break;
@@ -7727,6 +7735,8 @@ qemuDomainSetBlkioParameters(virDomainPtr dom,
for (j = 0; j < ndevices; j++) {
if (virCgroupSetBlkioDeviceWriteBps(priv->cgroup,
devices[j].path,
+ devices[j].major,
+ devices[j].minor,
devices[j].wbps) < 0) {
ret = -1;
break;
diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
index a6d60c5..e29d7c3 100644
--- a/src/util/vircgroup.c
+++ b/src/util/vircgroup.c
@@ -1824,6 +1824,37 @@ virCgroupGetBlkioWeight(virCgroupPtr group, unsigned int *weight)
return ret;
}

+static int
+virCgroupGetBlkioDeviceNumbers(const char *path,
+ unsigned int *major,
+ unsigned int *minor)
+{
+ struct stat sb;
+
+ if (!major || !minor)
+ return -1;
+
+ if (path) {
+ if (stat(path, &sb) < 0) {
+ virReportSystemError(errno,
+ _("Path '%s' is not accessible"),
+ path);
+ return -1;
+ }
+
+ if (!S_ISBLK(sb.st_mode)) {
+ virReportSystemError(EINVAL,
+ _("Path '%s' must be a block device"),
+ path);
+ return -1;
+ }
+
+ *major = major(sb.st_rdev);
+ *minor = minor(sb.st_rdev);
+ }
+ return 0;
+}
+
/**
* virCgroupSetBlkioDeviceReadIops:
* @group: The cgroup to change block io setting for
@@ -1835,28 +1866,17 @@ virCgroupGetBlkioWeight(virCgroupPtr group, unsigned int *weight)
int
virCgroupSetBlkioDeviceReadIops(virCgroupPtr group,
const char *path,
+ unsigned int major,
+ unsigned int minor,
unsigned int riops)
{
char *str;
- struct stat sb;
int ret;

- if (stat(path, &sb) < 0) {
- virReportSystemError(errno,
- _("Path '%s' is not accessible"),
- path);
+ if (virCgroupGetBlkioDeviceNumbers(path, &major, &minor) < 0)
return -1;
- }

- if (!S_ISBLK(sb.st_mode)) {
- virReportSystemError(EINVAL,
- _("Path '%s' must be a block device"),
- path);
- return -1;
- }
-
- if (virAsprintf(&str, "%d:%d %u", major(sb.st_rdev),
- minor(sb.st_rdev), riops) < 0)
+ if (virAsprintf(&str, "%u:%u %u", major, minor, riops) < 0)
return -1;

ret = virCgroupSetValueStr(group,
@@ -1880,28 +1900,17 @@ virCgroupSetBlkioDeviceReadIops(virCgroupPtr group,
int
virCgroupSetBlkioDeviceWriteIops(virCgroupPtr group,
const char *path,
+ unsigned int major,
+ unsigned int minor,
unsigned int wiops)
{
char *str;
- struct stat sb;
int ret;

- if (stat(path, &sb) < 0) {
- virReportSystemError(errno,
- _("Path '%s' is not accessible"),
- path);
+ if (virCgroupGetBlkioDeviceNumbers(path, &major, &minor) < 0)
return -1;
- }

- if (!S_ISBLK(sb.st_mode)) {
- virReportSystemError(EINVAL,
- _("Path '%s' must be a block device"),
- path);
- return -1;
- }
-
- if (virAsprintf(&str, "%d:%d %u", major(sb.st_rdev),
- minor(sb.st_rdev), wiops) < 0)
+ if (virAsprintf(&str, "%u:%u %u", major, minor, wiops) < 0)
return -1;

ret = virCgroupSetValueStr(group,
@@ -1925,28 +1934,17 @@ virCgroupSetBlkioDeviceWriteIops(virCgroupPtr group,
int
virCgroupSetBlkioDeviceReadBps(virCgroupPtr group,
const char *path,
+ unsigned int major,
+ unsigned int minor,
unsigned long long rbps)
{
char *str;
- struct stat sb;
int ret;

- if (stat(path, &sb) < 0) {
- virReportSystemError(errno,
- _("Path '%s' is not accessible"),
- path);
+ if (virCgroupGetBlkioDeviceNumbers(path, &major, &minor) < 0)
return -1;
- }

- if (!S_ISBLK(sb.st_mode)) {
- virReportSystemError(EINVAL,
- _("Path '%s' must be a block device"),
- path);
- return -1;
- }
-
- if (virAsprintf(&str, "%d:%d %llu", major(sb.st_rdev),
- minor(sb.st_rdev), rbps) < 0)
+ if (virAsprintf(&str, "%u:%u %llu", major, minor, rbps) < 0)
return -1;

ret = virCgroupSetValueStr(group,
@@ -1969,28 +1967,17 @@ virCgroupSetBlkioDeviceReadBps(virCgroupPtr group,
int
virCgroupSetBlkioDeviceWriteBps(virCgroupPtr group,
const char *path,
+ unsigned int major,
+ unsigned int minor,
unsigned long long wbps)
{
char *str;
- struct stat sb;
int ret;

- if (stat(path, &sb) < 0) {
- virReportSystemError(errno,
- _("Path '%s' is not accessible"),
- path);
- return -1;
- }
-
- if (!S_ISBLK(sb.st_mode)) {
- virReportSystemError(EINVAL,
- _("Path '%s' must be a block device"),
- path);
+ if (virCgroupGetBlkioDeviceNumbers(path, &major, &minor) < 0)
return -1;
- }

- if (virAsprintf(&str, "%d:%d %llu", major(sb.st_rdev),
- minor(sb.st_rdev), wbps) < 0)
+ if (virAsprintf(&str, "%u:%u %llu", major, minor, wbps) < 0)
return -1;

ret = virCgroupSetValueStr(group,
@@ -2018,28 +2005,17 @@ virCgroupSetBlkioDeviceWriteBps(virCgroupPtr group,
int
virCgroupSetBlkioDeviceWeight(virCgroupPtr group,
const char *path,
+ unsigned int major,
+ unsigned int minor,
unsigned int weight)
{
char *str;
- struct stat sb;
int ret;

- if (stat(path, &sb) < 0) {
- virReportSystemError(errno,
- _("Path '%s' is not accessible"),
- path);
- return -1;
- }
-
- if (!S_ISBLK(sb.st_mode)) {
- virReportSystemError(EINVAL,
- _("Path '%s' must be a block device"),
- path);
+ if (virCgroupGetBlkioDeviceNumbers(path, &major, &minor) < 0)
return -1;
- }

- if (virAsprintf(&str, "%d:%d %d", major(sb.st_rdev), minor(sb.st_rdev),
- weight) < 0)
+ if (virAsprintf(&str, "%u:%u %d", major, minor, weight) < 0)
return -1;

ret = virCgroupSetValueStr(group,
diff --git a/src/util/vircgroup.h b/src/util/vircgroup.h
index a70eb18..2258b36 100644
--- a/src/util/vircgroup.h
+++ b/src/util/vircgroup.h
@@ -124,22 +124,32 @@ int virCgroupGetBlkioWeight(virCgroupPtr group, unsigned int *weight);

int virCgroupSetBlkioDeviceWeight(virCgroupPtr group,
const char *path,
+ unsigned int major,
+ unsigned int minor,
unsigned int weight);

int virCgroupSetBlkioDeviceReadIops(virCgroupPtr group,
const char *path,
+ unsigned int major,
+ unsigned int minor,
unsigned int riops);

int virCgroupSetBlkioDeviceWriteIops(virCgroupPtr group,
const char *path,
+ unsigned int major,
+ unsigned int minor,
unsigned int wiops);

int virCgroupSetBlkioDeviceReadBps(virCgroupPtr group,
const char *path,
+ unsigned int major,
+ unsigned int minor,
unsigned long long rbps);

int virCgroupSetBlkioDeviceWriteBps(virCgroupPtr group,
const char *path,
+ unsigned int major,
+ unsigned int minor,
unsigned long long wbps);

int virCgroupSetMemory(virCgroupPtr group, unsigned long long kb);
diff --git a/tests/lxcconf2xmldata/lxcconf2xml-blkiotune.xml b/tests/lxcconf2xmldata/lxcconf2xml-blkiotune.xml
index 628798d..73f90ef 100644
--- a/tests/lxcconf2xmldata/lxcconf2xml-blkiotune.xml
+++ b/tests/lxcconf2xmldata/lxcconf2xml-blkiotune.xml
@@ -6,7 +6,7 @@
<blkiotune>
<weight>500</weight>
<device>
- <path>/dev/block/8:16</path>
+ <node major='8' minor='16'/>
<weight>1000</weight>
<read_iops_sec>4321</read_iops_sec>
<write_iops_sec>8765</write_iops_sec>
@@ -14,7 +14,7 @@
<write_bytes_sec>5678</write_bytes_sec>
</device>
<device>
- <path>/dev/block/8:0</path>
+ <node major='8' minor='0'/>
<weight>300</weight>
</device>
</blkiotune>
--
1.8.5.2
Daniel P. Berrange
2014-02-11 14:55:06 UTC
Permalink
Post by Cédric Bosdonnat
To ease LXC configuration conversion, allow blkiotune device XML
fragments to define the device using its major:minor numbers.
---
docs/formatdomain.html.in | 10 +-
src/conf/domain_conf.c | 45 ++++++++-
src/conf/domain_conf.h | 2 +
src/lxc/lxc_cgroup.c | 5 +
src/lxc/lxc_driver.c | 10 ++
src/lxc/lxc_native.c | 24 ++++-
src/qemu/qemu_cgroup.c | 5 +
src/qemu/qemu_driver.c | 10 ++
src/util/vircgroup.c | 126 ++++++++++--------------
src/util/vircgroup.h | 10 ++
tests/lxcconf2xmldata/lxcconf2xml-blkiotune.xml | 4 +-
11 files changed, 165 insertions(+), 86 deletions(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index fd02864..2ab7d39 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -761,6 +761,10 @@
I realize this is helping the conversion of existing configs, but
personally I'm pretty loathe to add this syntax. With device paths
it is possible to have stable paths ie using /dev/disk/by*. With
major/minor the XML configuration is not portable across hosts or
even stable within a host since major numbers are fairly arbitrarily
assigned with hotpluggable SCSI or networked iSCSI.

Personally I'd list this as one of the things an admin has to fixup
manually post conversion.

Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
Cedric Bosdonnat
2014-02-11 16:40:21 UTC
Permalink
Hi Daniel,
Post by Daniel P. Berrange
I realize this is helping the conversion of existing configs, but
personally I'm pretty loathe to add this syntax. With device paths
it is possible to have stable paths ie using /dev/disk/by*. With
major/minor the XML configuration is not portable across hosts or
even stable within a host since major numbers are fairly arbitrarily
assigned with hotpluggable SCSI or networked iSCSI.
Personally I'd list this as one of the things an admin has to fixup
manually post conversion.
Ok, then let's drop that patch from the serie: it was just a way to
communicate on that topic ;)

--
Cedric
Cédric Bosdonnat
2014-02-05 14:10:18 UTC
Permalink
direct interfaces are already brought up when creating them.
---
src/lxc/lxc_process.c | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c
index ed729f6..6f7ff74 100644
--- a/src/lxc/lxc_process.c
+++ b/src/lxc/lxc_process.c
@@ -245,6 +245,7 @@ char *virLXCProcessSetupInterfaceBridged(virConnectPtr conn,
char *parentVeth;
char *containerVeth = NULL;
virNetDevVPortProfilePtr vport = virDomainNetGetActualVirtPortProfile(net);
+ bool vethUp = false;

VIR_DEBUG("calling vethCreate()");
parentVeth = net->ifname;
@@ -283,6 +284,10 @@ char *virLXCProcessSetupInterfaceBridged(virConnectPtr conn,
virDomainConfNWFilterInstantiate(conn, vm->uuid, net) < 0)
goto cleanup;

+ vethUp = net->linkstate == VIR_DOMAIN_NET_INTERFACE_LINK_STATE_UP;
+ if (virNetDevSetOnline(containerVeth, vethUp) < 0)
+ goto cleanup;
+
ret = containerVeth;

cleanup:
--
1.8.5.2
Cedric Bosdonnat
2014-02-06 13:00:56 UTC
Permalink
Post by Cédric Bosdonnat
direct interfaces are already brought up when creating them.
Just ignore (and drop) this patch, veth interfaces are already up when
starting the container... even thought I couldn't ifdown it ;)

--
Cedric
Post by Cédric Bosdonnat
---
src/lxc/lxc_process.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c
index ed729f6..6f7ff74 100644
--- a/src/lxc/lxc_process.c
+++ b/src/lxc/lxc_process.c
@@ -245,6 +245,7 @@ char *virLXCProcessSetupInterfaceBridged(virConnectPtr conn,
char *parentVeth;
char *containerVeth = NULL;
virNetDevVPortProfilePtr vport = virDomainNetGetActualVirtPortProfile(net);
+ bool vethUp = false;
VIR_DEBUG("calling vethCreate()");
parentVeth = net->ifname;
@@ -283,6 +284,10 @@ char *virLXCProcessSetupInterfaceBridged(virConnectPtr conn,
virDomainConfNWFilterInstantiate(conn, vm->uuid, net) < 0)
goto cleanup;
+ vethUp = net->linkstate == VIR_DOMAIN_NET_INTERFACE_LINK_STATE_UP;
+ if (virNetDevSetOnline(containerVeth, vethUp) < 0)
+ goto cleanup;
+
ret = containerVeth;
Cédric Bosdonnat
2014-02-05 14:10:14 UTC
Permalink
---
src/lxc/lxc_native.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c
index 1997370..9a16523 100644
--- a/src/lxc/lxc_native.c
+++ b/src/lxc/lxc_native.c
@@ -286,6 +286,10 @@ lxcAddFstabLine(virDomainDefPtr def, lxcFstabPtr fstab)
goto error;
}

+ /* Is it a block device that needs special favor? */
+ if (STRPREFIX(fstab->src, "/dev/"))
+ type = VIR_DOMAIN_FS_TYPE_BLOCK;
+
/* Do we have ro in options? */
readonly = virStringArrayHasString(options, "ro");
--
1.8.5.2
Daniel P. Berrange
2014-02-12 17:48:47 UTC
Permalink
Post by Cédric Bosdonnat
---
src/lxc/lxc_native.c | 4 ++++
1 file changed, 4 insertions(+)
ACK

Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
Cédric Bosdonnat
2014-02-05 14:10:10 UTC
Permalink
---
src/lxc/lxc_native.c | 34 ++++++++++++++++++++++++
tests/lxcconf2xmldata/lxcconf2xml-cputune.config | 7 +++++
tests/lxcconf2xmldata/lxcconf2xml-cputune.xml | 29 ++++++++++++++++++++
tests/lxcconf2xmltest.c | 1 +
4 files changed, 71 insertions(+)
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-cputune.config
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-cputune.xml

diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c
index d430abc..65a1d0d 100644
--- a/src/lxc/lxc_native.c
+++ b/src/lxc/lxc_native.c
@@ -643,6 +643,36 @@ lxcSetMemTune(virDomainDefPtr def, virConfPtr properties)
return 0;
}

+static int
+lxcSetCpuTune(virDomainDefPtr def, virConfPtr properties)
+{
+ virConfValuePtr value;
+
+ if ((value = virConfGetValue(properties, "lxc.cgroup.cpu.shares")) &&
+ value->str && virStrToLong_ul(value->str, NULL, 10,
+ &def->cputune.shares) < 0)
+ goto error;
+
+ if ((value = virConfGetValue(properties,
+ "lxc.cgroup.cpu.cfs_quota_us")) &&
+ value->str && virStrToLong_ll(value->str, NULL, 10,
+ &def->cputune.quota) < 0)
+ goto error;
+
+ if ((value = virConfGetValue(properties,
+ "lxc.cgroup.cpu.cfs_period_us")) &&
+ value->str && virStrToLong_ull(value->str, NULL, 10,
+ &def->cputune.period) < 0)
+ goto error;
+
+ return 0;
+
+error:
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("failed to parse integer: '%s'"), value->str);
+ return -1;
+}
+
virDomainDefPtr
lxcParseConfigString(const char *config)
{
@@ -719,6 +749,10 @@ lxcParseConfigString(const char *config)
if (lxcSetMemTune(vmdef, properties) < 0)
goto error;

+ /* lxc.cgroup.cpu.* */
+ if (lxcSetCpuTune(vmdef, properties) < 0)
+ goto error;
+
goto cleanup;

error:
diff --git a/tests/lxcconf2xmldata/lxcconf2xml-cputune.config b/tests/lxcconf2xmldata/lxcconf2xml-cputune.config
new file mode 100644
index 0000000..9797dec
--- /dev/null
+++ b/tests/lxcconf2xmldata/lxcconf2xml-cputune.config
@@ -0,0 +1,7 @@
+lxc.rootfs = /var/lib/lxc/migrate_test/rootfs
+lxc.utsname = migrate_test
+lxc.autodev=1
+
+lxc.cgroup.cpu.shares = 1024
+lxc.cgroup.cpu.cfs_quota_us = -1
+lxc.cgroup.cpu.cfs_period_us = 500000
diff --git a/tests/lxcconf2xmldata/lxcconf2xml-cputune.xml b/tests/lxcconf2xmldata/lxcconf2xml-cputune.xml
new file mode 100644
index 0000000..a511dcf
--- /dev/null
+++ b/tests/lxcconf2xmldata/lxcconf2xml-cputune.xml
@@ -0,0 +1,29 @@
+<domain type='lxc'>
+ <name>migrate_test</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>65536</memory>
+ <currentMemory unit='KiB'>0</currentMemory>
+ <vcpu placement='static' current='0'>1</vcpu>
+ <cputune>
+ <shares>1024</shares>
+ <period>500000</period>
+ <quota>-1</quota>
+ </cputune>
+ <os>
+ <type>exe</type>
+ <init>/sbin/init</init>
+ </os>
+ <features>
+ <privnet/>
+ </features>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <filesystem type='mount' accessmode='passthrough'>
+ <source dir='/var/lib/lxc/migrate_test/rootfs'/>
+ <target dir='/'/>
+ </filesystem>
+ </devices>
+</domain>
diff --git a/tests/lxcconf2xmltest.c b/tests/lxcconf2xmltest.c
index 3dd0a0b..1148cd3 100644
--- a/tests/lxcconf2xmltest.c
+++ b/tests/lxcconf2xmltest.c
@@ -110,6 +110,7 @@ mymain(void)
DO_TEST("macvlannetwork", false);
DO_TEST("idmap", false);
DO_TEST("memtune", false);
+ DO_TEST("cputune", false);

return ret;
}
--
1.8.5.2
Daniel P. Berrange
2014-02-12 17:46:47 UTC
Permalink
Post by Cédric Bosdonnat
---
src/lxc/lxc_native.c | 34 ++++++++++++++++++++++++
tests/lxcconf2xmldata/lxcconf2xml-cputune.config | 7 +++++
tests/lxcconf2xmldata/lxcconf2xml-cputune.xml | 29 ++++++++++++++++++++
tests/lxcconf2xmltest.c | 1 +
4 files changed, 71 insertions(+)
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-cputune.config
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-cputune.xml
ACK

Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
Cédric Bosdonnat
2014-02-05 14:10:13 UTC
Permalink
---
src/lxc/lxc_native.c | 9 +++++++++
tests/lxcconf2xmldata/lxcconf2xml-simple.config | 1 +
tests/lxcconf2xmldata/lxcconf2xml-simple.xml | 2 +-
3 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c
index 15c03f2..1997370 100644
--- a/src/lxc/lxc_native.c
+++ b/src/lxc/lxc_native.c
@@ -794,6 +794,15 @@ lxcParseConfigString(const char *config)
if (VIR_STRDUP(vmdef->os.type, "exe") < 0)
goto error;

+ if ((value = virConfGetValue(properties, "lxc.arch")) && value->str) {
+ virArch arch = virArchFromString(value->str);
+ if (arch == VIR_ARCH_NONE && STREQ(value->str, "x86"))
+ arch = VIR_ARCH_I686;
+ else if (arch == VIR_ARCH_NONE && STREQ(value->str, "amd64"))
+ arch = VIR_ARCH_X86_64;
+ vmdef->os.arch = arch;
+ }
+
if (VIR_STRDUP(vmdef->os.init, "/sbin/init") < 0)
goto error;

diff --git a/tests/lxcconf2xmldata/lxcconf2xml-simple.config b/tests/lxcconf2xmldata/lxcconf2xml-simple.config
index f75e8fc..b90abc1 100644
--- a/tests/lxcconf2xmldata/lxcconf2xml-simple.config
+++ b/tests/lxcconf2xmldata/lxcconf2xml-simple.config
@@ -14,6 +14,7 @@ lxc.mount.entry = tmpfs run tmpfs size=8m,mode=0755,nodev,nosuid 0 0
lxc.mount.entry = /etc/resolv.conf etc/resolv.conf none bind,ro 0 0
lxc.rootfs = /var/lib/lxc/migrate_test/rootfs
lxc.utsname = migrate_test
+lxc.arch = x86
lxc.autodev=1
lxc.tty = 2
lxc.pts = 1024
diff --git a/tests/lxcconf2xmldata/lxcconf2xml-simple.xml b/tests/lxcconf2xmldata/lxcconf2xml-simple.xml
index 711e0d9..6ec0f17 100644
--- a/tests/lxcconf2xmldata/lxcconf2xml-simple.xml
+++ b/tests/lxcconf2xmldata/lxcconf2xml-simple.xml
@@ -5,7 +5,7 @@
<currentMemory unit='KiB'>0</currentMemory>
<vcpu placement='static' current='0'>1</vcpu>
<os>
- <type>exe</type>
+ <type arch='i686'>exe</type>
<init>/sbin/init</init>
</os>
<clock offset='utc'/>
--
1.8.5.2
Daniel P. Berrange
2014-02-12 17:48:25 UTC
Permalink
Post by Cédric Bosdonnat
---
src/lxc/lxc_native.c | 9 +++++++++
tests/lxcconf2xmldata/lxcconf2xml-simple.config | 1 +
tests/lxcconf2xmldata/lxcconf2xml-simple.xml | 2 +-
3 files changed, 11 insertions(+), 1 deletion(-)
ACK

Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
Cédric Bosdonnat
2014-02-05 14:10:16 UTC
Permalink
---
docs/drvlxc.html.in | 34 +++++++++++++++++++++++++++++++++-
1 file changed, 33 insertions(+), 1 deletion(-)

diff --git a/docs/drvlxc.html.in b/docs/drvlxc.html.in
index 0f3efb0..fc4bc20 100644
--- a/docs/drvlxc.html.in
+++ b/docs/drvlxc.html.in
@@ -555,7 +555,7 @@ and LXC. For further details about usage of virsh consult its
manual page.
</p>

-<h3><a name="usageSave">Defining (saving) container configuration></a></h3>
+<h3><a name="usageSave">Defining (saving) container configuration</a></h3>

<p>
The <code>virsh define</code> command takes an XML configuration
@@ -702,5 +702,37 @@ host
# virt-top -c lxc:///
</pre>

+<h3><a name="usageConvert">Converting LXC container configuration</a></h3>
+
+<p>
+The <code>virsh domxml-from-native</code> command can be used to convert
+most of the LXC container configuration into a domain XML fragment
+</p>
+
+<pre>
+# virsh -c lxc:/// domxml-from-native lxc-tools /var/lib/lxc/myguest/config
+</pre>
+
+<p>
+This conversion has some limitations due to the fact that the
+domxml-from-native command output has to be independent of the host. Here
+are a few things to take care of before converting:
+</p>
+
+<ul>
+<li>
+Replace the fstab file referenced by <tt>lxc.mount</tt> by the corresponding
+lxc.mount.entry lines.
+</li>
+<li>
+Replace all relative sizes of tmpfs mount entries to absolute sizes. Also
+make sure that tmpfs entries all have a size option (default is 50%).
+</li>
+<li>
+Define <tt>lxc.cgroup.memory.limit_in_bytes</tt> to properly limit the memory
+available to the container. The conversion will use 64MiB as the default.
+</li>
+</ul>
+
</body>
</html>
--
1.8.5.2
Daniel P. Berrange
2014-02-12 17:49:13 UTC
Permalink
Post by Cédric Bosdonnat
---
docs/drvlxc.html.in | 34 +++++++++++++++++++++++++++++++++-
1 file changed, 33 insertions(+), 1 deletion(-)
ACK

Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
Cédric Bosdonnat
2014-02-05 14:10:03 UTC
Permalink
If no network configuration is provided, LXC only provides the loopback
interface. To match this, we need to use the privnet feature. LXC will
also define a 'none' network type in its 1.0.0 version that fits
libvirt LXC driver's default.
---
src/lxc/lxc_native.c | 55 ++++++++++++++++++++++
.../lxcconf2xmldata/lxcconf2xml-nonenetwork.config | 4 ++
tests/lxcconf2xmldata/lxcconf2xml-nonenetwork.xml | 21 +++++++++
tests/lxcconf2xmldata/lxcconf2xml-nonetwork.config | 3 ++
tests/lxcconf2xmldata/lxcconf2xml-nonetwork.xml | 24 ++++++++++
tests/lxcconf2xmltest.c | 2 +
6 files changed, 109 insertions(+)
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-nonenetwork.config
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-nonenetwork.xml
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-nonetwork.config
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-nonetwork.xml

diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c
index acd68db..bc14d69 100644
--- a/src/lxc/lxc_native.c
+++ b/src/lxc/lxc_native.c
@@ -325,6 +325,57 @@ lxcFstabWalkCallback(const char* name, virConfValuePtr value, void * data)
return ret;
}

+typedef struct {
+ char *type;
+ bool privnet;
+ size_t networks;
+} lxcNetworkParseData;
+
+static int
+lxcNetworkWalkCallback(const char *name, virConfValuePtr value, void *data)
+{
+ lxcNetworkParseData *parseData = data;
+
+ if (STREQ(name, "lxc.network.type")) {
+ if (parseData->type != NULL && STREQ(parseData->type, "none"))
+ parseData->privnet = false;
+ else if ((parseData->type != NULL) &&
+ STRNEQ(parseData->type, "empty") &&
+ STRNEQ(parseData->type, "")) {
+ parseData->networks++;
+ }
+
+ /* Start a new network interface config */
+ parseData->type = NULL;
+
+ /* Keep the new value */
+ parseData->type = value->str;
+ }
+ return 0;
+}
+
+static int
+lxcConvertNetworkSettings(virDomainDefPtr def, virConfPtr properties)
+{
+ lxcNetworkParseData data = {NULL, true, 0};
+
+ virConfWalk(properties, lxcNetworkWalkCallback, &data);
+
+ if ((data.type != NULL) && STREQ(data.type, "none"))
+ data.privnet = false;
+ else if ((data.type != NULL) && STRNEQ(data.type, "empty") &&
+ STRNEQ(data.type, "")) {
+ data.networks++;
+ }
+
+ if (data.networks == 0 && data.privnet) {
+ /* When no network type is provided LXC only adds loopback */
+ def->features[VIR_DOMAIN_FEATURE_PRIVNET] = VIR_DOMAIN_FEATURE_STATE_ON;
+ }
+
+ return 0;
+}
+
virDomainDefPtr
lxcParseConfigString(const char *config)
{
@@ -385,6 +436,10 @@ lxcParseConfigString(const char *config)
if (virConfWalk(properties, lxcFstabWalkCallback, vmdef) < 0)
goto error;

+ /* Network configuration */
+ if (lxcConvertNetworkSettings(vmdef, properties) < 0)
+ goto error;
+
goto cleanup;

error:
diff --git a/tests/lxcconf2xmldata/lxcconf2xml-nonenetwork.config b/tests/lxcconf2xmldata/lxcconf2xml-nonenetwork.config
new file mode 100644
index 0000000..c1bb9a6
--- /dev/null
+++ b/tests/lxcconf2xmldata/lxcconf2xml-nonenetwork.config
@@ -0,0 +1,4 @@
+lxc.rootfs = /var/lib/lxc/migrate_test/rootfs
+lxc.utsname = migrate_test
+lxc.autodev=1
+lxc.network.type = none
diff --git a/tests/lxcconf2xmldata/lxcconf2xml-nonenetwork.xml b/tests/lxcconf2xmldata/lxcconf2xml-nonenetwork.xml
new file mode 100644
index 0000000..eebcb4e
--- /dev/null
+++ b/tests/lxcconf2xmldata/lxcconf2xml-nonenetwork.xml
@@ -0,0 +1,21 @@
+<domain type='lxc'>
+ <name>migrate_test</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>65536</memory>
+ <currentMemory unit='KiB'>0</currentMemory>
+ <vcpu placement='static' current='0'>1</vcpu>
+ <os>
+ <type>exe</type>
+ <init>/sbin/init</init>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <filesystem type='mount' accessmode='passthrough'>
+ <source dir='/var/lib/lxc/migrate_test/rootfs'/>
+ <target dir='/'/>
+ </filesystem>
+ </devices>
+</domain>
diff --git a/tests/lxcconf2xmldata/lxcconf2xml-nonetwork.config b/tests/lxcconf2xmldata/lxcconf2xml-nonetwork.config
new file mode 100644
index 0000000..b6fbe1d
--- /dev/null
+++ b/tests/lxcconf2xmldata/lxcconf2xml-nonetwork.config
@@ -0,0 +1,3 @@
+lxc.rootfs = /var/lib/lxc/migrate_test/rootfs
+lxc.utsname = migrate_test
+lxc.autodev=1
diff --git a/tests/lxcconf2xmldata/lxcconf2xml-nonetwork.xml b/tests/lxcconf2xmldata/lxcconf2xml-nonetwork.xml
new file mode 100644
index 0000000..511e3dd
--- /dev/null
+++ b/tests/lxcconf2xmldata/lxcconf2xml-nonetwork.xml
@@ -0,0 +1,24 @@
+<domain type='lxc'>
+ <name>migrate_test</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>65536</memory>
+ <currentMemory unit='KiB'>0</currentMemory>
+ <vcpu placement='static' current='0'>1</vcpu>
+ <os>
+ <type>exe</type>
+ <init>/sbin/init</init>
+ </os>
+ <features>
+ <privnet/>
+ </features>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <filesystem type='mount' accessmode='passthrough'>
+ <source dir='/var/lib/lxc/migrate_test/rootfs'/>
+ <target dir='/'/>
+ </filesystem>
+ </devices>
+</domain>
diff --git a/tests/lxcconf2xmltest.c b/tests/lxcconf2xmltest.c
index c4b21ec..50041a5 100644
--- a/tests/lxcconf2xmltest.c
+++ b/tests/lxcconf2xmltest.c
@@ -104,6 +104,8 @@ mymain(void)

DO_TEST("simple", false);
DO_TEST("fstab", true);
+ DO_TEST("nonetwork", false);
+ DO_TEST("nonenetwork", false);

return ret;
}
--
1.8.5.2
Daniel P. Berrange
2014-02-12 17:43:10 UTC
Permalink
Post by Cédric Bosdonnat
If no network configuration is provided, LXC only provides the loopback
interface. To match this, we need to use the privnet feature. LXC will
also define a 'none' network type in its 1.0.0 version that fits
libvirt LXC driver's default.
---
src/lxc/lxc_native.c | 55 ++++++++++++++++++++++
.../lxcconf2xmldata/lxcconf2xml-nonenetwork.config | 4 ++
tests/lxcconf2xmldata/lxcconf2xml-nonenetwork.xml | 21 +++++++++
tests/lxcconf2xmldata/lxcconf2xml-nonetwork.config | 3 ++
tests/lxcconf2xmldata/lxcconf2xml-nonetwork.xml | 24 ++++++++++
tests/lxcconf2xmltest.c | 2 +
6 files changed, 109 insertions(+)
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-nonenetwork.config
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-nonenetwork.xml
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-nonetwork.config
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-nonetwork.xml
ACK

Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
Cédric Bosdonnat
2014-02-05 14:10:15 UTC
Permalink
The problem with VLAN is that the user still has to manually create the
vlan interface on the host. Then the generated configuration will use
it as a nerwork hostdev device. So the generated configurations of the
following two fragments are equivalent (see rhbz#1059637).

lxc.network.type = phys
lxc.network.link = eth0.5

lxc.network.type = vlan
lxc.network.link = eth0
lxc.network.vlan.id = 5
---
src/lxc/lxc_native.c | 28 ++++++++++++++++++----
.../lxcconf2xmldata/lxcconf2xml-vlannetwork.config | 12 ++++++++++
tests/lxcconf2xmldata/lxcconf2xml-vlannetwork.xml | 26 ++++++++++++++++++++
tests/lxcconf2xmltest.c | 1 +
4 files changed, 62 insertions(+), 5 deletions(-)
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-vlannetwork.config
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-vlannetwork.xml

diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c
index 9a16523..8d8c50a 100644
--- a/src/lxc/lxc_native.c
+++ b/src/lxc/lxc_native.c
@@ -411,22 +411,33 @@ lxcAddNetworkDefinition(virDomainDefPtr def,
const char *link,
const char *mac,
const char *flag,
- const char *macvlanmode)
+ const char *macvlanmode,
+ const char *vlanid)
{
virDomainNetDefPtr net = NULL;
virDomainHostdevDefPtr hostdev = NULL;
+ bool isPhys, isVlan = false;

if ((type == NULL) || STREQ(type, "empty") || STREQ(type, "") ||
STREQ(type, "none"))
return 0;

- if (type != NULL && STREQ(type, "phys")) {
+ isPhys = STREQ(type, "phys");
+ isVlan = STREQ(type, "vlan");
+ if (type != NULL && (isPhys || isVlan)) {
if (!link ||
!(hostdev = lxcCreateHostdevDef(VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES,
VIR_DOMAIN_HOSTDEV_CAPS_TYPE_NET,
link)))
goto error;

+ /* This still requires the user to manually setup the vlan interface
+ * on the host */
+ if (isVlan && !(link && vlanid &&
+ virAsprintf(&hostdev->source.caps.u.net.iface,
+ "%s.%s", link, vlanid) >= 0))
+ goto error;
+
if (VIR_EXPAND_N(def->hostdevs, def->nhostdevs, 1) < 0)
goto error;
def->hostdevs[def->nhostdevs - 1] = hostdev;
@@ -454,6 +465,7 @@ typedef struct {
char *mac;
char *flag;
char *macvlanmode;
+ char *vlanid;
bool privnet;
size_t networks;
} lxcNetworkParseData;
@@ -469,7 +481,8 @@ lxcNetworkWalkCallback(const char *name, virConfValuePtr value, void *data)
status = lxcAddNetworkDefinition(parseData->def, parseData->type,
parseData->link, parseData->mac,
parseData->flag,
- parseData->macvlanmode);
+ parseData->macvlanmode,
+ parseData->vlanid);

if (status < 0)
return -1;
@@ -484,6 +497,7 @@ lxcNetworkWalkCallback(const char *name, virConfValuePtr value, void *data)
parseData->mac = NULL;
parseData->flag = NULL;
parseData->macvlanmode = NULL;
+ parseData->vlanid = NULL;

/* Keep the new value */
parseData->type = value->str;
@@ -496,6 +510,8 @@ lxcNetworkWalkCallback(const char *name, virConfValuePtr value, void *data)
parseData->flag = value->str;
else if (STREQ(name, "lxc.network.macvlan.mode"))
parseData->macvlanmode = value->str;
+ else if (STREQ(name, "lxc.network.vlan.id"))
+ parseData->vlanid = value->str;
else if (STRPREFIX(name, "lxc.network"))
VIR_WARN("Unhandled network property: %s = %s",
name,
@@ -508,14 +524,16 @@ static int
lxcConvertNetworkSettings(virDomainDefPtr def, virConfPtr properties)
{
int status;
- lxcNetworkParseData data = {def, NULL, NULL, NULL, NULL, NULL, true, 0};
+ lxcNetworkParseData data = {def, NULL, NULL, NULL, NULL,
+ NULL, NULL, true, 0};

virConfWalk(properties, lxcNetworkWalkCallback, &data);

/* Add the last network definition found */
status = lxcAddNetworkDefinition(def, data.type, data.link,
data.mac, data.flag,
- data.macvlanmode);
+ data.macvlanmode,
+ data.vlanid);
if (status < 0)
return -1;
else if (status > 0)
diff --git a/tests/lxcconf2xmldata/lxcconf2xml-vlannetwork.config b/tests/lxcconf2xmldata/lxcconf2xml-vlannetwork.config
new file mode 100644
index 0000000..327202c
--- /dev/null
+++ b/tests/lxcconf2xmldata/lxcconf2xml-vlannetwork.config
@@ -0,0 +1,12 @@
+# Template used to create this container: opensuse
+# Template script checksum (SHA-1): 27307e0a95bd81b2c0bd82d6f87fdbe83be075ef
+
+lxc.network.type = vlan
+lxc.network.flags = up
+lxc.network.link = eth0
+lxc.network.hwaddr = 02:00:15:8f:05:c1
+lxc.network.vlan.id = 2
+
+lxc.rootfs = /var/lib/lxc/migrate_test/rootfs
+lxc.utsname = migrate_test
+lxc.autodev=1
diff --git a/tests/lxcconf2xmldata/lxcconf2xml-vlannetwork.xml b/tests/lxcconf2xmldata/lxcconf2xml-vlannetwork.xml
new file mode 100644
index 0000000..7d6d51b
--- /dev/null
+++ b/tests/lxcconf2xmldata/lxcconf2xml-vlannetwork.xml
@@ -0,0 +1,26 @@
+<domain type='lxc'>
+ <name>migrate_test</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>65536</memory>
+ <currentMemory unit='KiB'>0</currentMemory>
+ <vcpu placement='static' current='0'>1</vcpu>
+ <os>
+ <type>exe</type>
+ <init>/sbin/init</init>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <filesystem type='mount' accessmode='passthrough'>
+ <source dir='/var/lib/lxc/migrate_test/rootfs'/>
+ <target dir='/'/>
+ </filesystem>
+ <hostdev mode='capabilities' type='net'>
+ <source>
+ <interface>eth0.2</interface>
+ </source>
+ </hostdev>
+ </devices>
+</domain>
diff --git a/tests/lxcconf2xmltest.c b/tests/lxcconf2xmltest.c
index 77baf20..e799893 100644
--- a/tests/lxcconf2xmltest.c
+++ b/tests/lxcconf2xmltest.c
@@ -108,6 +108,7 @@ mymain(void)
DO_TEST("nonenetwork", false);
DO_TEST("physnetwork", false);
DO_TEST("macvlannetwork", false);
+ DO_TEST("vlannetwork", false);
DO_TEST("idmap", false);
DO_TEST("memtune", false);
DO_TEST("cputune", false);
--
1.8.5.2
Daniel P. Berrange
2014-02-12 17:49:00 UTC
Permalink
Post by Cédric Bosdonnat
The problem with VLAN is that the user still has to manually create the
vlan interface on the host. Then the generated configuration will use
it as a nerwork hostdev device. So the generated configurations of the
following two fragments are equivalent (see rhbz#1059637).
lxc.network.type = phys
lxc.network.link = eth0.5
lxc.network.type = vlan
lxc.network.link = eth0
lxc.network.vlan.id = 5
---
src/lxc/lxc_native.c | 28 ++++++++++++++++++----
.../lxcconf2xmldata/lxcconf2xml-vlannetwork.config | 12 ++++++++++
tests/lxcconf2xmldata/lxcconf2xml-vlannetwork.xml | 26 ++++++++++++++++++++
tests/lxcconf2xmltest.c | 1 +
4 files changed, 62 insertions(+), 5 deletions(-)
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-vlannetwork.config
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-vlannetwork.xml
ACK

Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
Daniel P. Berrange
2014-02-12 17:51:47 UTC
Permalink
Post by Cédric Bosdonnat
The problem with VLAN is that the user still has to manually create the
vlan interface on the host. Then the generated configuration will use
it as a nerwork hostdev device. So the generated configurations of the
following two fragments are equivalent (see rhbz#1059637).
lxc.network.type = phys
lxc.network.link = eth0.5
lxc.network.type = vlan
lxc.network.link = eth0
lxc.network.vlan.id = 5
---
src/lxc/lxc_native.c | 28 ++++++++++++++++++----
.../lxcconf2xmldata/lxcconf2xml-vlannetwork.config | 12 ++++++++++
tests/lxcconf2xmldata/lxcconf2xml-vlannetwork.xml | 26 ++++++++++++++++++++
tests/lxcconf2xmltest.c | 1 +
4 files changed, 62 insertions(+), 5 deletions(-)
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-vlannetwork.config
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-vlannetwork.xml
diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c
index 9a16523..8d8c50a 100644
--- a/src/lxc/lxc_native.c
+++ b/src/lxc/lxc_native.c
@@ -411,22 +411,33 @@ lxcAddNetworkDefinition(virDomainDefPtr def,
const char *link,
const char *mac,
const char *flag,
- const char *macvlanmode)
+ const char *macvlanmode,
+ const char *vlanid)
{
virDomainNetDefPtr net = NULL;
virDomainHostdevDefPtr hostdev = NULL;
+ bool isPhys, isVlan = false;
if ((type == NULL) || STREQ(type, "empty") || STREQ(type, "") ||
STREQ(type, "none"))
return 0;
- if (type != NULL && STREQ(type, "phys")) {
+ isPhys = STREQ(type, "phys");
+ isVlan = STREQ(type, "vlan");
+ if (type != NULL && (isPhys || isVlan)) {
if (!link ||
!(hostdev = lxcCreateHostdevDef(VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES,
VIR_DOMAIN_HOSTDEV_CAPS_TYPE_NET,
link)))
goto error;
+ /* This still requires the user to manually setup the vlan interface
+ * on the host */
+ if (isVlan && !(link && vlanid &&
+ virAsprintf(&hostdev->source.caps.u.net.iface,
+ "%s.%s", link, vlanid) >= 0))
+ goto error;
Small memory leak as this virAsprintf overwrites memory allocated
by lxcCreateHostdevDef. Will fx that when pushing

Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
Cédric Bosdonnat
2014-02-05 14:10:17 UTC
Permalink
---
src/lxc/lxc_native.c | 68 ++++++++++++++++++----
tests/lxcconf2xmldata/lxcconf2xml-blkiotune.config | 4 ++
tests/lxcconf2xmldata/lxcconf2xml-blkiotune.xml | 4 ++
3 files changed, 65 insertions(+), 11 deletions(-)

diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c
index 8d8c50a..675883c 100644
--- a/src/lxc/lxc_native.c
+++ b/src/lxc/lxc_native.c
@@ -727,28 +727,73 @@ lxcBlkioDeviceWalkCallback(const char *name, virConfValuePtr value, void *data)
char **parts = NULL;
virBlkioDevicePtr device = NULL;
virDomainDefPtr def = data;
+ size_t i = 0;
+ char *path = NULL;

- if (STRNEQ(name, "lxc.cgroup.blkio.device_weight") || !value->str)
+ if (!STRPREFIX(name, "lxc.cgroup.blkio.") ||
+ STREQ(name, "lxc.cgroup.blkio.weight")|| !value->str)
return 0;

if ((!(parts = lxcStringSplit(value->str)) && (!parts[0] || !parts[1]))) {
virReportError(VIR_ERR_INTERNAL_ERROR,
- _("invalid blkio.device_weight value: '%s'"),
- value->str);
+ _("invalid %s value: '%s'"),
+ name, value->str);
goto error;
}

- if (VIR_EXPAND_N(def->blkio.devices, def->blkio.ndevices, 1) < 0)
+ if (virAsprintf(&path, "/dev/block/%s", parts[0]) < 0)
goto error;
- device = &def->blkio.devices[def->blkio.ndevices - 1];

- if (virAsprintf(&device->path, "/dev/block/%s", parts[0]) < 0)
- goto error;
+ /* Do we already have a device definition for this path?
+ * Get that device or create a new one */
+ for (i = 0; !device && i < def->blkio.ndevices; i++) {
+ if (STREQ(def->blkio.devices[i].path, path))
+ device = &def->blkio.devices[i];
+ }
+ if (!device) {
+ if (VIR_EXPAND_N(def->blkio.devices, def->blkio.ndevices, 1) < 0)
+ goto error;
+ device = &def->blkio.devices[def->blkio.ndevices - 1];
+ device->path = path;
+ }

- if (virStrToLong_ui(parts[1], NULL, 10, &device->weight) < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("failed to parse integer: '%s'"), parts[1]);
- goto error;
+ /* Set the value */
+ if (STREQ(name, "lxc.cgroup.blkio.device_weight")) {
+ if (virStrToLong_ui(parts[1], NULL, 10, &device->weight) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("failed to parse device weight: '%s'"), parts[1]);
+ goto error;
+ }
+ } else if (STREQ(name, "lxc.cgroup.blkio.throttle.read_bps_device")) {
+ if (virStrToLong_ull(parts[1], NULL, 10, &device->rbps) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("failed to parse read_bps_device: '%s'"),
+ parts[1]);
+ goto error;
+ }
+ } else if (STREQ(name, "lxc.cgroup.blkio.throttle.write_bps_device")) {
+ if (virStrToLong_ull(parts[1], NULL, 10, &device->wbps) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("failed to parse write_bps_device: '%s'"),
+ parts[1]);
+ goto error;
+ }
+ } else if (STREQ(name, "lxc.cgroup.blkio.throttle.read_iops_device")) {
+ if (virStrToLong_ui(parts[1], NULL, 10, &device->riops) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("failed to parse read_iops_device: '%s'"),
+ parts[1]);
+ goto error;
+ }
+ } else if (STREQ(name, "lxc.cgroup.blkio.throttle.write_iops_device")) {
+ if (virStrToLong_ui(parts[1], NULL, 10, &device->wiops) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("failed to parse write_iops_device: '%s'"),
+ parts[1]);
+ goto error;
+ }
+ } else {
+ VIR_WARN("Unhandled blkio tune config: %s", name);
}

virStringFreeList(parts);
@@ -758,6 +803,7 @@ lxcBlkioDeviceWalkCallback(const char *name, virConfValuePtr value, void *data)
error:
if (parts)
virStringFreeList(parts);
+ VIR_FREE(path);
return -1;
}

diff --git a/tests/lxcconf2xmldata/lxcconf2xml-blkiotune.config b/tests/lxcconf2xmldata/lxcconf2xml-blkiotune.config
index 8083c71..b19d9a5 100644
--- a/tests/lxcconf2xmldata/lxcconf2xml-blkiotune.config
+++ b/tests/lxcconf2xmldata/lxcconf2xml-blkiotune.config
@@ -5,3 +5,7 @@ lxc.autodev=1
lxc.cgroup.blkio.weight = 500
lxc.cgroup.blkio.device_weight = 8:16 1000
lxc.cgroup.blkio.device_weight = 8:0 300
+lxc.cgroup.blkio.throttle.read_bps_device = 8:16 1234
+lxc.cgroup.blkio.throttle.write_bps_device = 8:16 5678
+lxc.cgroup.blkio.throttle.read_iops_device = 8:16 4321
+lxc.cgroup.blkio.throttle.write_iops_device = 8:16 8765
diff --git a/tests/lxcconf2xmldata/lxcconf2xml-blkiotune.xml b/tests/lxcconf2xmldata/lxcconf2xml-blkiotune.xml
index d2408f4..628798d 100644
--- a/tests/lxcconf2xmldata/lxcconf2xml-blkiotune.xml
+++ b/tests/lxcconf2xmldata/lxcconf2xml-blkiotune.xml
@@ -8,6 +8,10 @@
<device>
<path>/dev/block/8:16</path>
<weight>1000</weight>
+ <read_iops_sec>4321</read_iops_sec>
+ <write_iops_sec>8765</write_iops_sec>
+ <read_bytes_sec>1234</read_bytes_sec>
+ <write_bytes_sec>5678</write_bytes_sec>
</device>
<device>
<path>/dev/block/8:0</path>
--
1.8.5.2
Daniel P. Berrange
2014-02-12 17:49:55 UTC
Permalink
Post by Cédric Bosdonnat
---
src/lxc/lxc_native.c | 68 ++++++++++++++++++----
tests/lxcconf2xmldata/lxcconf2xml-blkiotune.config | 4 ++
tests/lxcconf2xmldata/lxcconf2xml-blkiotune.xml | 4 ++
3 files changed, 65 insertions(+), 11 deletions(-)
ACK

Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
Cédric Bosdonnat
2014-02-05 14:10:12 UTC
Permalink
---
src/lxc/lxc_native.c | 63 ++++++++++++++++++++++
tests/lxcconf2xmldata/lxcconf2xml-blkiotune.config | 7 +++
tests/lxcconf2xmldata/lxcconf2xml-blkiotune.xml | 35 ++++++++++++
tests/lxcconf2xmltest.c | 1 +
4 files changed, 106 insertions(+)
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-blkiotune.config
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-blkiotune.xml

diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c
index ee8fa75..15c03f2 100644
--- a/src/lxc/lxc_native.c
+++ b/src/lxc/lxc_native.c
@@ -699,6 +699,65 @@ lxcSetCpusetTune(virDomainDefPtr def, virConfPtr properties)
return 0;
}

+static int
+lxcBlkioDeviceWalkCallback(const char *name, virConfValuePtr value, void *data)
+{
+ char **parts = NULL;
+ virBlkioDevicePtr device = NULL;
+ virDomainDefPtr def = data;
+
+ if (STRNEQ(name, "lxc.cgroup.blkio.device_weight") || !value->str)
+ return 0;
+
+ if ((!(parts = lxcStringSplit(value->str)) && (!parts[0] || !parts[1]))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("invalid blkio.device_weight value: '%s'"),
+ value->str);
+ goto error;
+ }
+
+ if (VIR_EXPAND_N(def->blkio.devices, def->blkio.ndevices, 1) < 0)
+ goto error;
+ device = &def->blkio.devices[def->blkio.ndevices - 1];
+
+ if (virAsprintf(&device->path, "/dev/block/%s", parts[0]) < 0)
+ goto error;
+
+ if (virStrToLong_ui(parts[1], NULL, 10, &device->weight) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("failed to parse integer: '%s'"), parts[1]);
+ goto error;
+ }
+
+ virStringFreeList(parts);
+
+ return 0;
+
+error:
+ if (parts)
+ virStringFreeList(parts);
+ return -1;
+}
+
+static int
+lxcSetBlkioTune(virDomainDefPtr def, virConfPtr properties)
+{
+ virConfValuePtr value;
+
+ if ((value = virConfGetValue(properties, "lxc.cgroup.blkio.weight")) &&
+ value->str && virStrToLong_ui(value->str, NULL, 10,
+ &def->blkio.weight) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("failed to parse integer: '%s'"), value->str);
+ return -1;
+ }
+
+ if (virConfWalk(properties, lxcBlkioDeviceWalkCallback, def) < 0)
+ return -1;
+
+ return 0;
+}
+
virDomainDefPtr
lxcParseConfigString(const char *config)
{
@@ -783,6 +842,10 @@ lxcParseConfigString(const char *config)
if (lxcSetCpusetTune(vmdef, properties) < 0)
goto error;

+ /* lxc.cgroup.blkio.* */
+ if (lxcSetBlkioTune(vmdef, properties) < 0)
+ goto error;
+
goto cleanup;

error:
diff --git a/tests/lxcconf2xmldata/lxcconf2xml-blkiotune.config b/tests/lxcconf2xmldata/lxcconf2xml-blkiotune.config
new file mode 100644
index 0000000..8083c71
--- /dev/null
+++ b/tests/lxcconf2xmldata/lxcconf2xml-blkiotune.config
@@ -0,0 +1,7 @@
+lxc.rootfs = /var/lib/lxc/migrate_test/rootfs
+lxc.utsname = migrate_test
+lxc.autodev=1
+
+lxc.cgroup.blkio.weight = 500
+lxc.cgroup.blkio.device_weight = 8:16 1000
+lxc.cgroup.blkio.device_weight = 8:0 300
diff --git a/tests/lxcconf2xmldata/lxcconf2xml-blkiotune.xml b/tests/lxcconf2xmldata/lxcconf2xml-blkiotune.xml
new file mode 100644
index 0000000..d2408f4
--- /dev/null
+++ b/tests/lxcconf2xmldata/lxcconf2xml-blkiotune.xml
@@ -0,0 +1,35 @@
+<domain type='lxc'>
+ <name>migrate_test</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>65536</memory>
+ <currentMemory unit='KiB'>0</currentMemory>
+ <blkiotune>
+ <weight>500</weight>
+ <device>
+ <path>/dev/block/8:16</path>
+ <weight>1000</weight>
+ </device>
+ <device>
+ <path>/dev/block/8:0</path>
+ <weight>300</weight>
+ </device>
+ </blkiotune>
+ <vcpu placement='static' current='0'>1</vcpu>
+ <os>
+ <type>exe</type>
+ <init>/sbin/init</init>
+ </os>
+ <features>
+ <privnet/>
+ </features>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <filesystem type='mount' accessmode='passthrough'>
+ <source dir='/var/lib/lxc/migrate_test/rootfs'/>
+ <target dir='/'/>
+ </filesystem>
+ </devices>
+</domain>
diff --git a/tests/lxcconf2xmltest.c b/tests/lxcconf2xmltest.c
index 6bee5c5..77baf20 100644
--- a/tests/lxcconf2xmltest.c
+++ b/tests/lxcconf2xmltest.c
@@ -112,6 +112,7 @@ mymain(void)
DO_TEST("memtune", false);
DO_TEST("cputune", false);
DO_TEST("cpusettune", false);
+ DO_TEST("blkiotune", false);

return ret;
}
--
1.8.5.2
Daniel P. Berrange
2014-02-12 17:47:56 UTC
Permalink
Post by Cédric Bosdonnat
---
src/lxc/lxc_native.c | 63 ++++++++++++++++++++++
tests/lxcconf2xmldata/lxcconf2xml-blkiotune.config | 7 +++
tests/lxcconf2xmldata/lxcconf2xml-blkiotune.xml | 35 ++++++++++++
tests/lxcconf2xmltest.c | 1 +
4 files changed, 106 insertions(+)
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-blkiotune.config
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-blkiotune.xml
+ if ((!(parts = lxcStringSplit(value->str)) && (!parts[0] || !parts[1]))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("invalid blkio.device_weight value: '%s'"),
+ value->str);
+ goto error;
+ }
The conditional here is wrong and crashes if lxcStringSplit returns
NULL.


ACK and will add the following

@@ -709,7 +709,10 @@ lxcBlkioDeviceWalkCallback(const char *name, virConfValuePtr value, void *data)
if (STRNEQ(name, "lxc.cgroup.blkio.device_weight") || !value->str)
return 0;

- if ((!(parts = lxcStringSplit(value->str)) && (!parts[0] || !parts[1]))) {
+ if (!(parts = lxcStringSplit(value->str)))
+ return -1;
+
+ if (!parts[0] || !parts[1]) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("invalid blkio.device_weight value: '%s'"),
value->str);
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
Cédric Bosdonnat
2014-02-05 14:10:07 UTC
Permalink
---
src/lxc/lxc_native.c | 47 +++++++++++++++++-----
.../lxcconf2xml-macvlannetwork.config | 13 ++++++
.../lxcconf2xmldata/lxcconf2xml-macvlannetwork.xml | 26 ++++++++++++
tests/lxcconf2xmltest.c | 1 +
4 files changed, 77 insertions(+), 10 deletions(-)
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-macvlannetwork.config
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-macvlannetwork.xml

diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c
index 96523c4..b413e42 100644
--- a/src/lxc/lxc_native.c
+++ b/src/lxc/lxc_native.c
@@ -329,9 +329,11 @@ static virDomainNetDefPtr
lxcCreateNetDef(const char *type,
const char *link,
const char *mac,
- const char *flag)
+ const char *flag,
+ const char *macvlanmode)
{
virDomainNetDefPtr net = NULL;
+ virMacAddr macAddr;

if (VIR_ALLOC(net) < 0)
goto error;
@@ -343,9 +345,11 @@ lxcCreateNetDef(const char *type,
net->linkstate = VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DOWN;
}

- if (STREQ(type, "veth")) {
- virMacAddr macAddr;

+ if (mac && virMacAddrParse(mac, &macAddr) == 0)
+ net->mac = macAddr;
+
+ if (STREQ(type, "veth")) {
if (!link)
goto error;

@@ -354,9 +358,20 @@ lxcCreateNetDef(const char *type,
if (VIR_STRDUP(net->data.bridge.brname, link) < 0)
goto error;

- if (mac && virMacAddrParse(mac, &macAddr) == 0)
- net->mac = macAddr;
+ } else if (STREQ(type, "macvlan")) {
+ net->type = VIR_DOMAIN_NET_TYPE_DIRECT;

+ if (!link || VIR_STRDUP(net->data.direct.linkdev, link) < 0)
+ goto error;
+
+ if (!macvlanmode || STREQ(macvlanmode, "private"))
+ net->data.direct.mode = VIR_NETDEV_MACVLAN_MODE_PRIVATE;
+ else if (STREQ(macvlanmode, "vepa"))
+ net->data.direct.mode = VIR_NETDEV_MACVLAN_MODE_VEPA;
+ else if (STREQ(macvlanmode, "bridge"))
+ net->data.direct.mode = VIR_NETDEV_MACVLAN_MODE_BRIDGE;
+ else
+ VIR_WARN("Unknown macvlan type: %s", macvlanmode);
}

return net;
@@ -391,7 +406,8 @@ lxcAddNetworkDefinition(virDomainDefPtr def,
const char *type,
const char *link,
const char *mac,
- const char *flag)
+ const char *flag,
+ const char *macvlanmode)
{
virDomainNetDefPtr net = NULL;
virDomainHostdevDefPtr hostdev = NULL;
@@ -411,7 +427,7 @@ lxcAddNetworkDefinition(virDomainDefPtr def,
goto error;
def->hostdevs[def->nhostdevs - 1] = hostdev;
} else {
- if (!(net = lxcCreateNetDef(type, link, mac, flag)))
+ if (!(net = lxcCreateNetDef(type, link, mac, flag, macvlanmode)))
goto error;

if (VIR_EXPAND_N(def->nets, def->nnets, 1) < 0)
@@ -433,6 +449,7 @@ typedef struct {
char *link;
char *mac;
char *flag;
+ char *macvlanmode;
bool privnet;
size_t networks;
} lxcNetworkParseData;
@@ -447,7 +464,9 @@ lxcNetworkWalkCallback(const char *name, virConfValuePtr value, void *data)
/* Store the previous NIC */
status = lxcAddNetworkDefinition(parseData->def, parseData->type,
parseData->link, parseData->mac,
- parseData->flag);
+ parseData->flag,
+ parseData->macvlanmode);
+
if (status < 0)
return -1;
else if (status > 0)
@@ -460,6 +479,7 @@ lxcNetworkWalkCallback(const char *name, virConfValuePtr value, void *data)
parseData->link = NULL;
parseData->mac = NULL;
parseData->flag = NULL;
+ parseData->macvlanmode = NULL;

/* Keep the new value */
parseData->type = value->str;
@@ -470,6 +490,12 @@ lxcNetworkWalkCallback(const char *name, virConfValuePtr value, void *data)
parseData->mac = value->str;
else if (STREQ(name, "lxc.network.flags"))
parseData->flag = value->str;
+ else if (STREQ(name, "lxc.network.macvlan.mode"))
+ parseData->macvlanmode = value->str;
+ else if (STRPREFIX(name, "lxc.network"))
+ VIR_WARN("Unhandled network property: %s = %s",
+ name,
+ value->str);

return 0;
}
@@ -478,13 +504,14 @@ static int
lxcConvertNetworkSettings(virDomainDefPtr def, virConfPtr properties)
{
int status;
- lxcNetworkParseData data = {def, NULL, NULL, NULL, NULL, true, 0};
+ lxcNetworkParseData data = {def, NULL, NULL, NULL, NULL, NULL, true, 0};

virConfWalk(properties, lxcNetworkWalkCallback, &data);

/* Add the last network definition found */
status = lxcAddNetworkDefinition(def, data.type, data.link,
- data.mac, data.flag);
+ data.mac, data.flag,
+ data.macvlanmode);
if (status < 0)
return -1;
else if (status > 0)
diff --git a/tests/lxcconf2xmldata/lxcconf2xml-macvlannetwork.config b/tests/lxcconf2xmldata/lxcconf2xml-macvlannetwork.config
new file mode 100644
index 0000000..7c96bfa
--- /dev/null
+++ b/tests/lxcconf2xmldata/lxcconf2xml-macvlannetwork.config
@@ -0,0 +1,13 @@
+# Template used to create this container: opensuse
+# Template script checksum (SHA-1): 27307e0a95bd81b2c0bd82d6f87fdbe83be075ef
+
+lxc.network.type = macvlan
+lxc.network.flags = up
+lxc.network.link = eth0
+lxc.network.hwaddr = 02:00:15:8f:05:c1
+lxc.network.macvlan.mode = vepa
+
+#remove next line if host DNS configuration should not be available to container
+lxc.rootfs = /var/lib/lxc/migrate_test/rootfs
+lxc.utsname = migrate_test
+lxc.autodev=1
diff --git a/tests/lxcconf2xmldata/lxcconf2xml-macvlannetwork.xml b/tests/lxcconf2xmldata/lxcconf2xml-macvlannetwork.xml
new file mode 100644
index 0000000..aa0683a
--- /dev/null
+++ b/tests/lxcconf2xmldata/lxcconf2xml-macvlannetwork.xml
@@ -0,0 +1,26 @@
+<domain type='lxc'>
+ <name>migrate_test</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>65536</memory>
+ <currentMemory unit='KiB'>0</currentMemory>
+ <vcpu placement='static' current='0'>1</vcpu>
+ <os>
+ <type>exe</type>
+ <init>/sbin/init</init>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <filesystem type='mount' accessmode='passthrough'>
+ <source dir='/var/lib/lxc/migrate_test/rootfs'/>
+ <target dir='/'/>
+ </filesystem>
+ <interface type='direct'>
+ <mac address='02:00:15:8f:05:c1'/>
+ <source dev='eth0' mode='vepa'/>
+ <link state='up'/>
+ </interface>
+ </devices>
+</domain>
diff --git a/tests/lxcconf2xmltest.c b/tests/lxcconf2xmltest.c
index c888b42..4e7dd58 100644
--- a/tests/lxcconf2xmltest.c
+++ b/tests/lxcconf2xmltest.c
@@ -107,6 +107,7 @@ mymain(void)
DO_TEST("nonetwork", false);
DO_TEST("nonenetwork", false);
DO_TEST("physnetwork", false);
+ DO_TEST("macvlannetwork", false);

return ret;
}
--
1.8.5.2
Daniel P. Berrange
2014-02-12 17:44:20 UTC
Permalink
Post by Cédric Bosdonnat
---
src/lxc/lxc_native.c | 47 +++++++++++++++++-----
.../lxcconf2xml-macvlannetwork.config | 13 ++++++
.../lxcconf2xmldata/lxcconf2xml-macvlannetwork.xml | 26 ++++++++++++
tests/lxcconf2xmltest.c | 1 +
4 files changed, 77 insertions(+), 10 deletions(-)
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-macvlannetwork.config
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-macvlannetwork.xml
ACK

Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
Daniel P. Berrange
2014-02-12 17:23:39 UTC
Permalink
Post by Cédric Bosdonnat
LXC rootfs can be either a directory or a block device or an image
file. The first two types have been implemented, but the image file is
still to be done since LXC auto-guesses the file format at mount time
and the LXC driver doesn't support the 'auto' format.
---
src/lxc/lxc_native.c | 69 ++++++++++++++++++++++++++++
tests/lxcconf2xmldata/lxcconf2xml-simple.xml | 4 ++
2 files changed, 73 insertions(+)
ACK

Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
Daniel P. Berrange
2014-02-12 17:31:52 UTC
Permalink
Post by Cédric Bosdonnat
LXC rootfs can be either a directory or a block device or an image
file. The first two types have been implemented, but the image file is
still to be done since LXC auto-guesses the file format at mount time
and the LXC driver doesn't support the 'auto' format.
---
src/lxc/lxc_native.c | 69 ++++++++++++++++++++++++++++
tests/lxcconf2xmldata/lxcconf2xml-simple.xml | 4 ++
2 files changed, 73 insertions(+)
ACK
Actually there's a crash on OOM in this patch due to a double-free
of the 'src' and 'dst' strings. I'm going to squash the following
change in before pushing it

Daniel

diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c
index 86d0dd3..af9d34e 100644
--- a/src/lxc/lxc_native.c
+++ b/src/lxc/lxc_native.c
@@ -33,7 +33,9 @@


static virDomainFSDefPtr
-lxcCreateFSDef(int type, char *src, char* dst)
+lxcCreateFSDef(int type,
+ const char *src,
+ const char* dst)
{
virDomainFSDefPtr def;

@@ -42,14 +44,23 @@ lxcCreateFSDef(int type, char *src, char* dst)

def->type = type;
def->accessmode = VIR_DOMAIN_FS_ACCESSMODE_PASSTHROUGH;
- def->src = src;
- def->dst = dst;
+ if (src && VIR_STRDUP(def->src, src) < 0)
+ goto error;
+ if (VIR_STRDUP(def->dst, dst) < 0)
+ goto error;

return def;
+
+ error:
+ virDomainFSDefFree(def);
+ return NULL;
}

static int
-lxcAddFSDef(virDomainDefPtr def, int type, char *src, char *dst)
+lxcAddFSDef(virDomainDefPtr def,
+ int type,
+ const char *src,
+ const char *dst)
{
virDomainFSDefPtr fsDef = NULL;

@@ -71,30 +82,23 @@ static int
lxcSetRootfs(virDomainDefPtr def,
virConfPtr properties)
{
- char *fssrc = NULL;
- char *fsdst = NULL;
int type = VIR_DOMAIN_FS_TYPE_MOUNT;
virConfValuePtr value;

if (!(value = virConfGetValue(properties, "lxc.rootfs")) ||
- !value->str ||
- (VIR_STRDUP(fssrc, value->str) < 0) ||
- VIR_STRDUP(fsdst, "/") < 0)
- goto error;
+ !value->str) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Missing lxc.rootfs configuration"));
+ return -1;
+ }

- if (STRPREFIX(fssrc, "/dev/"))
+ if (STRPREFIX(value->str, "/dev/"))
type = VIR_DOMAIN_FS_TYPE_BLOCK;

-
- if (lxcAddFSDef(def, type, fssrc, fsdst) < 0)
- goto error;
+ if (lxcAddFSDef(def, type, value->str, "/") < 0)
+ return -1;

return 0;
-
-error:
- VIR_FREE(fssrc);
- VIR_FREE(fsdst);
- return -1;
}

virDomainDefPtr
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
Daniel P. Berrange
2014-02-12 17:55:17 UTC
Permalink
Here is an updated version of the patch set fixing comments from Daniel.
* One adding conversion for the newly supported blkio throttle tune
in lxc driver.
* One actually using the state of the veth network device in lxc
driver.
* One adding the ability to give major:minor numbers instead of a path
for blkio tune devices.
The last one is a way to address Daniel's comment on the /dev/block/...
paths.
Improve virConf parse to handle LXC config format
LXC driver: started implementing connectDomainXMLFromNative
LXC from native: import rootfs
LXC from native: migrate fstab and lxc.mount.entry
LXC from native: implement no network conversion
LXC from native: migrate veth network configuration
LXC from native: convert phys network types to net hostdev devices
LXC from native: convert lxc.tty to console devices
LXC from native: convert macvlan network configuration
LXC from native: convert lxc.id_map into <idmap>
LXC from native: migrate memory tuning
LXC from native: map lxc.cgroup.cpu.*
LXC from native: map lxc.cgroup.cpuset.*
LXC from native: add lxc.cgroup.blkio.* mapping
LXC from native: map block filesystems
LXC from native: map vlan network type
LXC: added some doc on domxml-from-native with mention of limitations
LXC from native: convert blkio throttle config
lxc: honor link state=up for veth interfaces
blkiotune: allow <node major='' minor=''/> in place of <path>
.gitignore | 1 +
docs/drvlxc.html.in | 34 +-
docs/formatdomain.html.in | 10 +-
po/POTFILES.in | 1 +
src/Makefile.am | 1 +
src/conf/domain_conf.c | 45 +-
src/conf/domain_conf.h | 2 +
src/libvirt_private.syms | 1 +
src/lxc/lxc_cgroup.c | 5 +
src/lxc/lxc_container.c | 2 +-
src/lxc/lxc_container.h | 2 +
src/lxc/lxc_driver.c | 41 +
src/lxc/lxc_native.c | 952 +++++++++++++++++++++
src/lxc/lxc_native.h | 32 +
src/lxc/lxc_process.c | 5 +
src/qemu/qemu_cgroup.c | 5 +
src/qemu/qemu_driver.c | 10 +
src/util/vircgroup.c | 126 ++-
src/util/vircgroup.h | 10 +
src/util/virconf.c | 46 +-
src/util/virconf.h | 10 +
tests/Makefile.am | 7 +-
tests/lxcconf2xmldata/lxcconf2xml-blkiotune.config | 11 +
tests/lxcconf2xmldata/lxcconf2xml-blkiotune.xml | 39 +
.../lxcconf2xmldata/lxcconf2xml-cpusettune.config | 6 +
tests/lxcconf2xmldata/lxcconf2xml-cpusettune.xml | 27 +
tests/lxcconf2xmldata/lxcconf2xml-cputune.config | 7 +
tests/lxcconf2xmldata/lxcconf2xml-cputune.xml | 29 +
tests/lxcconf2xmldata/lxcconf2xml-fstab.config | 37 +
tests/lxcconf2xmldata/lxcconf2xml-idmap.config | 5 +
tests/lxcconf2xmldata/lxcconf2xml-idmap.xml | 28 +
.../lxcconf2xml-macvlannetwork.config | 13 +
.../lxcconf2xmldata/lxcconf2xml-macvlannetwork.xml | 26 +
tests/lxcconf2xmldata/lxcconf2xml-memtune.config | 10 +
tests/lxcconf2xmldata/lxcconf2xml-memtune.xml | 29 +
.../lxcconf2xmldata/lxcconf2xml-nonenetwork.config | 4 +
tests/lxcconf2xmldata/lxcconf2xml-nonenetwork.xml | 21 +
tests/lxcconf2xmldata/lxcconf2xml-nonetwork.config | 3 +
tests/lxcconf2xmldata/lxcconf2xml-nonetwork.xml | 24 +
.../lxcconf2xmldata/lxcconf2xml-physnetwork.config | 6 +
tests/lxcconf2xmldata/lxcconf2xml-physnetwork.xml | 26 +
tests/lxcconf2xmldata/lxcconf2xml-simple.config | 41 +
tests/lxcconf2xmldata/lxcconf2xml-simple.xml | 41 +
.../lxcconf2xmldata/lxcconf2xml-vlannetwork.config | 12 +
tests/lxcconf2xmldata/lxcconf2xml-vlannetwork.xml | 26 +
tests/lxcconf2xmltest.c | 131 +++
46 files changed, 1865 insertions(+), 85 deletions(-)
create mode 100644 src/lxc/lxc_native.c
create mode 100644 src/lxc/lxc_native.h
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-blkiotune.config
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-blkiotune.xml
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-cpusettune.config
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-cpusettune.xml
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-cputune.config
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-cputune.xml
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-fstab.config
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-idmap.config
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-idmap.xml
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-macvlannetwork.config
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-macvlannetwork.xml
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-memtune.config
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-memtune.xml
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-nonenetwork.config
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-nonenetwork.xml
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-nonetwork.config
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-nonetwork.xml
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-physnetwork.config
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-physnetwork.xml
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-simple.config
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-simple.xml
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-vlannetwork.config
create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-vlannetwork.xml
create mode 100644 tests/lxcconf2xmltest.c
This series is now pushed, except patches 20/21, with the various OOM
crash and memory leak bugs I discovered during testing.

Thanks for this great new feature!

Regards,
Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
Ján Tomko
2014-02-14 08:29:21 UTC
Permalink
Here is an updated version of the patch set fixing comments from Daniel.
* One adding conversion for the newly supported blkio throttle tune
in lxc driver.
* One actually using the state of the veth network device in lxc
driver.
* One adding the ability to give major:minor numbers instead of a path
for blkio tune devices.
The last one is a way to address Daniel's comment on the /dev/block/...
paths.
Improve virConf parse to handle LXC config format
LXC driver: started implementing connectDomainXMLFromNative
LXC from native: import rootfs
LXC from native: migrate fstab and lxc.mount.entry
LXC from native: implement no network conversion
LXC from native: migrate veth network configuration
LXC from native: convert phys network types to net hostdev devices
LXC from native: convert lxc.tty to console devices
LXC from native: convert macvlan network configuration
LXC from native: convert lxc.id_map into <idmap>
LXC from native: migrate memory tuning
LXC from native: map lxc.cgroup.cpu.*
LXC from native: map lxc.cgroup.cpuset.*
LXC from native: add lxc.cgroup.blkio.* mapping
LXC from native: map block filesystems
LXC from native: map vlan network type
LXC: added some doc on domxml-from-native with mention of limitations
LXC from native: convert blkio throttle config
lxc: honor link state=up for veth interfaces
blkiotune: allow <node major='' minor=''/> in place of <path>
...
src/lxc/lxc_native.c | 952 +++++++++++++++++++++
Hi,

The use of 'link' as a function parameter breaks the build on RHEL-6.4:

cc1: warnings being treated as errors
../../src/lxc/lxc_native.c: In function 'lxcCreateNetDef':
../../src/lxc/lxc_native.c:337: error: declaration of 'link' shadows a global
declaration [-Wshadow]
/usr/include/unistd.h:809: error: shadowed declaration is here [-Wshadow]
../../src/lxc/lxc_native.c: In function 'lxcAddNetworkDefinition':
../../src/lxc/lxc_native.c:414: error: declaration of 'link' shadows a global
declaration [-Wshadow]
/usr/include/unistd.h:809: error: shadowed declaration is here [-Wshadow]
make[3]: *** [lxc/libvirt_driver_lxc_impl_la-lxc_native.lo] Error 1

Jan

Loading...