From 12a75f371cf66393863b9c68b9696ce02db4736a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Bosdonnat?= Date: Wed, 23 Jul 2014 11:26:21 +0200 Subject: [PATCH] lxc conf2xml: convert IP addresses --- src/lxc/lxc_native.c | 194 +++++++++++------- .../lxcconf2xmldata/lxcconf2xml-simple.config | 2 + tests/lxcconf2xmldata/lxcconf2xml-simple.xml | 2 + 3 files changed, 122 insertions(+), 76 deletions(-) diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c index 41e069f10d..3c8f9288c9 100644 --- a/src/lxc/lxc_native.c +++ b/src/lxc/lxc_native.c @@ -413,66 +413,6 @@ lxcCreateHostdevDef(int mode, int type, const char *data) return hostdev; } -static int -lxcAddNetworkDefinition(virDomainDefPtr def, - const char *type, - const char *linkdev, - const char *mac, - const char *flag, - const char *macvlanmode, - const char *vlanid, - const char *name) -{ - virDomainNetDefPtr net = NULL; - virDomainHostdevDefPtr hostdev = NULL; - bool isPhys, isVlan = false; - - if ((type == NULL) || STREQ(type, "empty") || STREQ(type, "") || - STREQ(type, "none")) - return 0; - - isPhys = STREQ(type, "phys"); - isVlan = STREQ(type, "vlan"); - if (type != NULL && (isPhys || isVlan)) { - if (!linkdev) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("Missing 'link' attribute for NIC")); - goto error; - } - if (!(hostdev = lxcCreateHostdevDef(VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES, - VIR_DOMAIN_HOSTDEV_CAPS_TYPE_NET, - linkdev))) - goto error; - - /* This still requires the user to manually setup the vlan interface - * on the host */ - if (isVlan && vlanid) { - VIR_FREE(hostdev->source.caps.u.net.iface); - if (virAsprintf(&hostdev->source.caps.u.net.iface, - "%s.%s", linkdev, vlanid) < 0) - goto error; - } - - if (VIR_EXPAND_N(def->hostdevs, def->nhostdevs, 1) < 0) - goto error; - def->hostdevs[def->nhostdevs - 1] = hostdev; - } else { - if (!(net = lxcCreateNetDef(type, linkdev, mac, flag, macvlanmode, name))) - 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; -} - typedef struct { virDomainDefPtr def; char *type; @@ -482,10 +422,74 @@ typedef struct { char *macvlanmode; char *vlanid; char *name; + virDomainNetIpDefPtr *ips; + size_t nips; bool privnet; size_t networks; } lxcNetworkParseData; +static int +lxcAddNetworkDefinition(lxcNetworkParseData *data) +{ + virDomainNetDefPtr net = NULL; + virDomainHostdevDefPtr hostdev = NULL; + bool isPhys, isVlan = false; + size_t i; + + if ((data->type == NULL) || STREQ(data->type, "empty") || + STREQ(data->type, "") || STREQ(data->type, "none")) + return 0; + + isPhys = STREQ(data->type, "phys"); + isVlan = STREQ(data->type, "vlan"); + if (data->type != NULL && (isPhys || isVlan)) { + if (!data->link) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Missing 'link' attribute for NIC")); + goto error; + } + if (!(hostdev = lxcCreateHostdevDef(VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES, + VIR_DOMAIN_HOSTDEV_CAPS_TYPE_NET, + data->link))) + goto error; + + /* This still requires the user to manually setup the vlan interface + * on the host */ + if (isVlan && data->vlanid) { + VIR_FREE(hostdev->source.caps.u.net.iface); + if (virAsprintf(&hostdev->source.caps.u.net.iface, + "%s.%s", data->link, data->vlanid) < 0) + goto error; + } + + if (VIR_EXPAND_N(data->def->hostdevs, data->def->nhostdevs, 1) < 0) + goto error; + data->def->hostdevs[data->def->nhostdevs - 1] = hostdev; + } else { + if (!(net = lxcCreateNetDef(data->type, data->link, data->mac, + data->flag, data->macvlanmode, + data->name))) + goto error; + + net->ips = data->ips; + net->nips = data->nips; + + if (VIR_EXPAND_N(data->def->nets, data->def->nnets, 1) < 0) + goto error; + data->def->nets[data->def->nnets - 1] = net; + } + + return 1; + + error: + for (i = 0; i < data->nips; i++) + VIR_FREE(data->ips[i]); + VIR_FREE(data->ips); + virDomainNetDefFree(net); + virDomainHostdevDefFree(hostdev); + return -1; +} + static int lxcNetworkWalkCallback(const char *name, virConfValuePtr value, void *data) { @@ -494,12 +498,7 @@ lxcNetworkWalkCallback(const char *name, virConfValuePtr value, void *data) if (STREQ(name, "lxc.network.type")) { /* Store the previous NIC */ - status = lxcAddNetworkDefinition(parseData->def, parseData->type, - parseData->link, parseData->mac, - parseData->flag, - parseData->macvlanmode, - parseData->vlanid, - parseData->name); + status = lxcAddNetworkDefinition(parseData); if (status < 0) return -1; @@ -517,6 +516,9 @@ lxcNetworkWalkCallback(const char *name, virConfValuePtr value, void *data) parseData->vlanid = NULL; parseData->name = NULL; + parseData->ips = NULL; + parseData->nips = 0; + /* Keep the new value */ parseData->type = value->str; } @@ -532,10 +534,42 @@ lxcNetworkWalkCallback(const char *name, virConfValuePtr value, void *data) parseData->vlanid = value->str; else if (STREQ(name, "lxc.network.name")) parseData->name = value->str; - else if (STRPREFIX(name, "lxc.network")) + else if (STREQ(name, "lxc.network.ipv4") || + STREQ(name, "lxc.network.ipv6")) { + int family = AF_INET; + char **ipparts = NULL; + virDomainNetIpDefPtr ip = NULL; + + if (VIR_ALLOC(ip) < 0) + return -1; + + if (STREQ(name, "lxc.network.ipv6")) + family = AF_INET6; + + ipparts = virStringSplit(value->str, "/", 2); + if (virStringListLength(ipparts) != 2 || + virSocketAddrParse(&ip->address, ipparts[0], family) < 0 || + virStrToLong_ui(ipparts[1], NULL, 10, &ip->prefix) < 0) { + + virReportError(VIR_ERR_INVALID_ARG, + _("Invalid CIDR address: '%s'"), value->str); + + virStringFreeList(ipparts); + VIR_FREE(ip); + return -1; + } + + virStringFreeList(ipparts); + + if (VIR_APPEND_ELEMENT(parseData->ips, parseData->nips, ip) < 0) { + VIR_FREE(ip); + return -1; + } + } else if (STRPREFIX(name, "lxc.network")) { VIR_WARN("Unhandled network property: %s = %s", name, value->str); + } return 0; } @@ -544,19 +578,20 @@ static int lxcConvertNetworkSettings(virDomainDefPtr def, virConfPtr properties) { int status; + int result = -1; + size_t i; lxcNetworkParseData data = {def, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, true, 0}; + NULL, NULL, NULL, NULL, 0, true, 0}; + + if (virConfWalk(properties, lxcNetworkWalkCallback, &data) < 0) + goto error; - virConfWalk(properties, lxcNetworkWalkCallback, &data); /* Add the last network definition found */ - status = lxcAddNetworkDefinition(def, data.type, data.link, - data.mac, data.flag, - data.macvlanmode, - data.vlanid, - data.name); + status = lxcAddNetworkDefinition(&data); + if (status < 0) - return -1; + goto error; else if (status > 0) data.networks++; else if (data.type != NULL && STREQ(data.type, "none")) @@ -566,8 +601,15 @@ lxcConvertNetworkSettings(virDomainDefPtr def, virConfPtr properties) /* When no network type is provided LXC only adds loopback */ def->features[VIR_DOMAIN_FEATURE_PRIVNET] = VIR_TRISTATE_SWITCH_ON; } + result = 0; - return 0; + return result; + + error: + for (i = 0; i < data.nips; i++) + VIR_FREE(data.ips[i]); + VIR_FREE(data.ips); + return -1; } static int diff --git a/tests/lxcconf2xmldata/lxcconf2xml-simple.config b/tests/lxcconf2xmldata/lxcconf2xml-simple.config index b90abc11a0..d417ba0492 100644 --- a/tests/lxcconf2xmldata/lxcconf2xml-simple.config +++ b/tests/lxcconf2xmldata/lxcconf2xml-simple.config @@ -6,6 +6,8 @@ lxc.network.flags = up lxc.network.link = virbr0 lxc.network.hwaddr = 02:00:15:8f:05:c1 lxc.network.name = eth0 +lxc.network.ipv4 = 192.168.122.2/24 +lxc.network.ipv6 = 2003:db8:1:0:214:1234:fe0b:3596/64 #remove next line if host DNS configuration should not be available to container lxc.mount.entry = proc proc proc nodev,noexec,nosuid 0 0 diff --git a/tests/lxcconf2xmldata/lxcconf2xml-simple.xml b/tests/lxcconf2xmldata/lxcconf2xml-simple.xml index 10428ec615..0dbbc71d14 100644 --- a/tests/lxcconf2xmldata/lxcconf2xml-simple.xml +++ b/tests/lxcconf2xmldata/lxcconf2xml-simple.xml @@ -37,6 +37,8 @@ + +