Allow changing network interfaces in domain configuration.

ifname is used as iterface identifier: if there is interface
with some ifname in old config and there are no interfaces with
such name in the new config - issue prlctl command to delete
the network interface. And vice versa - if interface with
some ifname exists only in new config - issue prlctl command
to create it.

Signed-off-by: Dmitry Guryanov <dgurya...@parallels.com>
---
 src/parallels/parallels_driver.c |  169 +++++++++++++++++++++++++++++++++++++-
 1 files changed, 168 insertions(+), 1 deletions(-)

diff --git a/src/parallels/parallels_driver.c b/src/parallels/parallels_driver.c
index 755816e..f29b6ca 100644
--- a/src/parallels/parallels_driver.c
+++ b/src/parallels/parallels_driver.c
@@ -1776,6 +1776,170 @@ parallelsApplyDisksParams(virConnectPtr conn, 
parallelsDomObjPtr pdom,
     return 0;
 }
 
+static int parallelsApplyIfaceParams(parallelsDomObjPtr pdom,
+                                     virDomainNetDefPtr oldnet,
+                                     virDomainNetDefPtr newnet)
+{
+    bool create = false;
+    bool is_changed = false;
+    virCommandPtr cmd;
+    char strmac[VIR_MAC_STRING_BUFLEN];
+    int i;
+
+    if (!oldnet) {
+        create = true;
+        if (VIR_ALLOC(oldnet) < 0) {
+            virReportOOMError();
+            return -1;
+        }
+    }
+
+    if (!create && oldnet->type != newnet->type) {
+        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
+                       _("Changing network type is not supported"));
+        return -1;
+    }
+
+    if (!STREQ_NULLABLE(oldnet->model, newnet->model)) {
+        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
+                       _("Changing network device model is not supported"));
+        return -1;
+    }
+
+    if (!STREQ_NULLABLE(oldnet->data.network.portgroup,
+                        newnet->data.network.portgroup)) {
+        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
+                       _("Changing network portgroup is not supported"));
+        return -1;
+    }
+
+    if (!virNetDevVPortProfileEqual(oldnet->virtPortProfile,
+                                    newnet->virtPortProfile)) {
+        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
+                       _("Changing virtual port profile is not supported"));
+        return -1;
+    }
+
+    if (newnet->tune.sndbuf_specified) {
+        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
+                       _("Setting send buffer size is not supported"));
+        return -1;
+    }
+
+    if (!STREQ_NULLABLE(oldnet->script, newnet->script)) {
+        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
+                       _("Setting startup script is not supported"));
+        return -1;
+    }
+
+    if (!STREQ_NULLABLE(oldnet->filter, newnet->filter)) {
+        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
+                       _("Changing filter params is not supported"));
+        return -1;
+    }
+
+    if (newnet->bandwidth != NULL) {
+        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
+                       _("Setting bandwidth params is not supported"));
+        return -1;
+    }
+
+    for (i = 0; i < sizeof(newnet->vlan); i++) {
+        if (((char *)&newnet->vlan)[i] != 0) {
+            virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
+                           _("Setting vlan params is not supported"));
+            return -1;
+        }
+    }
+
+    /* Here we know, that there are no differences, that are forbidden.
+     * Check is something changed, if no - do nothing */
+
+    if (create) {
+        cmd = virCommandNewArgList(PRLCTL, "set", pdom->uuid,
+                                   "--device-add", "net", NULL);
+    } else {
+        cmd = virCommandNewArgList(PRLCTL, "set", pdom->uuid,
+                                   "--device-set", newnet->ifname, NULL);
+    }
+
+    if (virMacAddrCmp(&oldnet->mac, &newnet->mac)) {
+        virMacAddrFormat(&newnet->mac, strmac);
+        virCommandAddArgFormat(cmd, "--mac=%s", strmac);
+        is_changed = true;
+    }
+
+    if (!STREQ_NULLABLE(oldnet->data.network.name, newnet->data.network.name)) 
{
+        virCommandAddArgFormat(cmd, "--network=%s", newnet->data.network.name);
+        is_changed = true;
+    }
+
+    if (oldnet->linkstate != newnet->linkstate) {
+        if (newnet->linkstate == VIR_DOMAIN_NET_INTERFACE_LINK_STATE_UP) {
+            virCommandAddArgFormat(cmd, "--connect");
+        } else if (newnet->linkstate == 
VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DOWN) {
+            virCommandAddArgFormat(cmd, "--disconnect");
+        }
+        is_changed = true;
+    }
+
+    if (!create && !is_changed) {
+        /* nothing changed - no need to run prlctl */
+        return 0;
+    }
+
+    if (virCommandRun(cmd, NULL))
+        return -1;
+
+    return 0;
+}
+
+static int
+parallelsApplyIfacesParams(parallelsDomObjPtr pdom,
+                            virDomainNetDefPtr *oldnets, int nold,
+                            virDomainNetDefPtr *newnets, int nnew)
+{
+    int i, j;
+
+    for (i = 0; i < nold; i++) {
+        virDomainNetDefPtr newnet = NULL;
+        virDomainNetDefPtr oldnet = oldnets[i];
+        for (j = 0; j < nnew; j++) {
+            if (STREQ_NULLABLE(newnets[j]->ifname, oldnet->ifname)) {
+                newnet = newnets[j];
+                break;
+            }
+        }
+
+        if (!newnet) {
+            if (parallelsCmdRun(PRLCTL, "set", pdom->uuid,
+                                "--device-del", oldnet->ifname, NULL) < 0)
+                return -1;
+
+            continue;
+        }
+
+        if (parallelsApplyIfaceParams(pdom, oldnet, newnet) < 0)
+            return -1;
+    }
+
+    for (i = 0; i < nnew; i++) {
+        virDomainNetDefPtr newnet = newnets[i];
+        bool found = false;
+
+        for (j = 0; j < nold; j++)
+            if (STREQ_NULLABLE(oldnets[j]->ifname, newnet->ifname))
+                found = true;
+        if (found)
+            continue;
+
+        if (parallelsApplyIfaceParams(pdom, NULL, newnet))
+            return -1;
+    }
+
+    return 0;
+}
+
 static int
 parallelsApplyChanges(virConnectPtr conn, virDomainObjPtr dom, virDomainDefPtr 
new)
 {
@@ -1975,7 +2139,7 @@ parallelsApplyChanges(virConnectPtr conn, virDomainObjPtr 
dom, virDomainDefPtr n
                                    new->graphics, new->ngraphics) < 0)
         return -1;
 
-    if (new->nfss != 0 || new->nnets != 0 ||
+    if (new->nfss != 0 ||
         new->nsounds != 0 || new->nhostdevs != 0 ||
         new->nredirdevs != 0 || new->nsmartcards != 0 ||
         new->nparallels || new->nchannels != 0 ||
@@ -2013,6 +2177,9 @@ parallelsApplyChanges(virConnectPtr conn, virDomainObjPtr 
dom, virDomainDefPtr n
     if (parallelsApplyDisksParams(conn, pdom, old->disks, old->ndisks,
                                   new->disks, new->ndisks) < 0)
         return -1;
+    if (parallelsApplyIfacesParams(pdom, old->nets, old->nnets,
+                                  new->nets, new->nnets) < 0)
+        return -1;
 
     return 0;
 }
-- 
1.7.7.6

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

Reply via email to