--- src/lxc/lxc_native.c | 145 +++++++++++++++--------- tests/lxcconf2xmldata/lxcconf2xml-simple.config | 2 + tests/lxcconf2xmldata/lxcconf2xml-simple.xml | 2 + 3 files changed, 98 insertions(+), 51 deletions(-) diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c index 41e069f..6ab093d 100644 --- a/src/lxc/lxc_native.c +++ b/src/lxc/lxc_native.c @@ -413,79 +413,84 @@ lxcCreateHostdevDef(int mode, int type, const char *data) return hostdev; } +typedef struct { + virDomainDefPtr def; + char *type; + char *link; + char *mac; + char *flag; + char *macvlanmode; + char *vlanid; + char *name; + virDomainNetIpDefPtr *ips; + size_t nips; + bool privnet; + size_t networks; +} lxcNetworkParseData; + 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) +lxcAddNetworkDefinition(lxcNetworkParseData *data) { virDomainNetDefPtr net = NULL; virDomainHostdevDefPtr hostdev = NULL; bool isPhys, isVlan = false; + size_t i; - if ((type == NULL) || STREQ(type, "empty") || STREQ(type, "") || - STREQ(type, "none")) + if ((data->type == NULL) || STREQ(data->type, "empty") || + STREQ(data->type, "") || STREQ(data->type, "none")) return 0; - isPhys = STREQ(type, "phys"); - isVlan = STREQ(type, "vlan"); - if (type != NULL && (isPhys || isVlan)) { - if (!linkdev) { + 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, - linkdev))) + data->link))) goto error; /* This still requires the user to manually setup the vlan interface * on the host */ - if (isVlan && vlanid) { + if (isVlan && data->vlanid) { VIR_FREE(hostdev->source.caps.u.net.iface); if (virAsprintf(&hostdev->source.caps.u.net.iface, - "%s.%s", linkdev, vlanid) < 0) + "%s.%s", data->link, data->vlanid) < 0) goto error; } - if (VIR_EXPAND_N(def->hostdevs, def->nhostdevs, 1) < 0) + if (VIR_EXPAND_N(data->def->hostdevs, data->def->nhostdevs, 1) < 0) goto error; - def->hostdevs[def->nhostdevs - 1] = hostdev; + data->def->hostdevs[data->def->nhostdevs - 1] = hostdev; } else { - if (!(net = lxcCreateNetDef(type, linkdev, mac, flag, macvlanmode, name))) + if (!(net = lxcCreateNetDef(data->type, data->link, data->mac, + data->flag, data->macvlanmode, + data->name))) goto error; - if (VIR_EXPAND_N(def->nets, def->nnets, 1) < 0) + net->ips = data->ips; + net->nips = data->nips; + + if (VIR_EXPAND_N(data->def->nets, data->def->nnets, 1) < 0) goto error; - def->nets[def->nnets - 1] = net; + 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; } -typedef struct { - virDomainDefPtr def; - char *type; - char *link; - char *mac; - char *flag; - char *macvlanmode; - char *vlanid; - char *name; - bool privnet; - size_t networks; -} lxcNetworkParseData; - static int lxcNetworkWalkCallback(const char *name, virConfValuePtr value, void *data) { @@ -494,12 +499,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 +517,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 +535,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 +579,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 +602,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 b90abc1..d417ba0 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 10428ec..0dbbc71 100644 --- a/tests/lxcconf2xmldata/lxcconf2xml-simple.xml +++ b/tests/lxcconf2xmldata/lxcconf2xml-simple.xml @@ -37,6 +37,8 @@ <interface type='bridge'> <mac address='02:00:15:8f:05:c1'/> <source bridge='virbr0'/> + <ip address='192.168.122.2' family='ipv4' prefix='24'/> + <ip address='2003:db8:1:0:214:1234:fe0b:3596' family='ipv6' prefix='64'/> <guest dev='eth0'/> <link state='up'/> </interface> -- 2.1.2 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list