---
 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 41e069f..f695a00 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 = NULL;
+    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

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Reply via email to