---
src/lxc/lxc_native.c | 153 ++++++++++++++++--------
tests/lxcconf2xmldata/lxcconf2xml-simple.config | 2 +
tests/lxcconf2xmldata/lxcconf2xml-simple.xml | 2 +
3 files changed, 106 insertions(+), 51 deletions(-)
diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c
index d3fde07..bc13d89 100644
--- a/src/lxc/lxc_native.c
+++ b/src/lxc/lxc_native.c
@@ -413,93 +413,124 @@ 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;
+ char **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 nips = 0;
+ virDomainNetIpDefPtr *ips = NULL;
+ virDomainNetIpDefPtr ip = NULL;
+ char **ipparts;
+ 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) {
+ /* Add the IP addresses */
+ for (i = 0; i < data->nips; i++) {
+ if (VIR_ALLOC(ip) < 0)
+ goto error;
+
+ ipparts = virStringSplit(data->ips[i], "/", 2);
+ if (virStringListLength(ipparts) != 2 ||
+ strlen(ipparts[0]) == 0 ||
+ virStrToLong_ui(ipparts[1], NULL, 10, &ip->prefix) < 0) {
+
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("Invalid CIDR address: '%s'"),
data->ips[i]);
+ goto error;
+ }
+
+ if (VIR_STRDUP(ip->address, ipparts[0]) < 0)
+ goto error;
+
+ if (VIR_APPEND_ELEMENT(ips, nips, ip) < 0)
+ goto error;
+
+ virStringFreeList(ipparts);
+ }
+
+ 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 = ips;
+ net->nips = 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 < nips; i++) {
+ virDomainNetIpDefFree(ips[i]);
+ }
+ VIR_FREE(ips);
+ virStringFreeList(ipparts);
+ virDomainNetIpDefFree(ip);
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)
{
lxcNetworkParseData *parseData = data;
int status;
+ size_t i;
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 +548,12 @@ lxcNetworkWalkCallback(const char *name, virConfValuePtr value, void
*data)
parseData->vlanid = NULL;
parseData->name = NULL;
+ /* IPs array needs to be free'd as all IPs are dup'ed there */
+ for (i = 0; i < parseData->nips; i++)
+ VIR_FREE(parseData->ips[i]);
+ VIR_FREE(parseData->ips);
+ parseData->nips = 0;
+
/* Keep the new value */
parseData->type = value->str;
}
@@ -532,7 +569,14 @@ 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")) {
+
+ if (VIR_EXPAND_N(parseData->ips, parseData->nips, 1) < 0)
+ return -1;
+ if (VIR_STRDUP(parseData->ips[parseData->nips - 1], value->str) < 0)
+ return -1;
+ } else if (STRPREFIX(name, "lxc.network"))
VIR_WARN("Unhandled network property: %s = %s",
name,
value->str);
@@ -544,19 +588,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 cleanup;
- 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 cleanup;
else if (status > 0)
data.networks++;
else if (data.type != NULL && STREQ(data.type, "none"))
@@ -566,8 +611,14 @@ 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;
+ cleanup:
+ for (i = 0; i < data.nips; i++)
+ VIR_FREE(data.ips[i]);
+ VIR_FREE(data.ips);
+
+ return result;
}
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..a73d05c 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' prefix='24'/>
+ <ip address='2003:db8:1:0:214:1234:fe0b:3596' prefix='64'/>
<guest dev='eth0'/>
<link state='up'/>
</interface>
--
1.8.4.5