[libvirt] [PATCH 2/2] network: backend for virNetworkUpdate of portgroups

Laine Stump laine at laine.org
Fri Sep 21 02:25:41 UTC 2012


portgroup elements are located in the toplevel of <network>
objects. There can be multiple <portgroup> elements, and they each
have a unique name attribute.

Add, delete, and modify are all supported for portgroup. When deleting
a portgroup, only the name must be specified in the provided xml - all
other attributes and subelements are ignored for the purposes of
matching and existing portgroup.

The bridge driver and virsh already know about the portgroup element,
so providing this backend should cause the entire stack to work. Note
that in the case of portgroup, there is no external daemon based on
the portgroup config, so nothing must be restarted.

It is important to note that guests make a copy of the appropriate
network's portgroup data when they are started, so although an updated
portgroup's configuration will have an affect on new guests started
after the cahange, existing guests won't magically have their
bandwidth changed, for example. If something like that is desired, it
will take a lot of redesign work in the way network devices are setup
(there is currently no link from the network back to the individual
interfaces using it, much less from a portgroup within a network back
to the individual interfaces).
---
 src/conf/network_conf.c | 85 +++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 79 insertions(+), 6 deletions(-)

diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index 7fc559f..34487dd 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -2625,15 +2625,88 @@ virNetworkDefUpdateForwardPF(virNetworkDefPtr def,
 }
 
 static int
-virNetworkDefUpdatePortgroup(virNetworkDefPtr def,
-                             unsigned int command ATTRIBUTE_UNUSED,
+virNetworkDefUpdatePortGroup(virNetworkDefPtr def,
+                             unsigned int command,
                              int parentIndex ATTRIBUTE_UNUSED,
-                             xmlXPathContextPtr ctxt ATTRIBUTE_UNUSED,
+                             xmlXPathContextPtr ctxt,
                              /* virNetworkUpdateFlags */
                              unsigned int fflags ATTRIBUTE_UNUSED)
 {
-    virNetworkDefUpdateNoSupport(def, "portgroup");
-    return -1;
+    int ii, ret = -1;
+    virPortGroupDef portgroup;
+
+    memset(&portgroup, 0, sizeof(portgroup));
+
+    if (virNetworkDefUpdateCheckElementName(def, ctxt->node, "portgroup") < 0)
+        goto cleanup;
+
+    if (virNetworkPortGroupParseXML(&portgroup, ctxt->node, ctxt) < 0)
+        goto cleanup;
+
+    /* check if a portgroup with same name already exists */
+    for (ii = 0; ii < def->nPortGroups; ii++) {
+        if (STREQ(portgroup.name, def->portGroups[ii].name))
+            break;
+    }
+    if (ii == def->nPortGroups &&
+        ((command == VIR_NETWORK_UPDATE_COMMAND_MODIFY) ||
+         (command == VIR_NETWORK_UPDATE_COMMAND_DELETE))) {
+        virReportError(VIR_ERR_OPERATION_INVALID,
+                       _("couldn't find a portgroup entry "
+                         "in network '%s' matching <portgroup name='%s'>"),
+                       def->name, portgroup.name);
+        goto cleanup;
+    } else if (ii < def->nPortGroups &&
+               ((command == VIR_NETWORK_UPDATE_COMMAND_ADD_FIRST) ||
+                (command == VIR_NETWORK_UPDATE_COMMAND_ADD_LAST))) {
+        virReportError(VIR_ERR_OPERATION_INVALID,
+                       _("there is an existing portgroup entry in "
+                         "network '%s' that matches "
+                         "\"<portgroup name='%s'>\""),
+                       def->name, portgroup.name);
+        goto cleanup;
+    }
+
+    if (command == VIR_NETWORK_UPDATE_COMMAND_MODIFY) {
+
+        /* replace existing entry */
+        virPortGroupDefClear(&def->portGroups[ii]);
+        def->portGroups[ii] = portgroup;
+        memset(&portgroup, 0, sizeof(portgroup));
+
+    } else if ((command == VIR_NETWORK_UPDATE_COMMAND_ADD_FIRST) ||
+        (command == VIR_NETWORK_UPDATE_COMMAND_ADD_LAST)) {
+
+        /* add to beginning/end of list */
+        if (VIR_REALLOC_N(def->portGroups, def->nPortGroups +1) < 0) {
+            virReportOOMError();
+            goto cleanup;
+        }
+
+        if (command == VIR_NETWORK_UPDATE_COMMAND_ADD_LAST) {
+            def->portGroups[def->nPortGroups] = portgroup;
+        } else { /* implied (command == VIR_NETWORK_UPDATE_COMMAND_ADD_FIRST) */
+            memmove(def->portGroups + 1, def->portGroups,
+                    sizeof(*def->portGroups) * def->nPortGroups);
+            def->portGroups[0] = portgroup;
+        }
+        def->nPortGroups++;
+        memset(&portgroup, 0, sizeof(portgroup));
+
+    } else if (command == VIR_NETWORK_UPDATE_COMMAND_DELETE) {
+
+        /* remove it */
+        virPortGroupDefClear(&def->portGroups[ii]);
+        memmove(def->portGroups + ii, def->portGroups + ii + 1,
+                sizeof(*def->portGroups) * (def->nPortGroups - ii - 1));
+        def->nPortGroups--;
+        ignore_value(VIR_REALLOC_N(def->portGroups, def->nPortGroups));
+    }
+
+    ret = 0;
+cleanup:
+    virPortGroupDefClear(&portgroup);
+    return ret;
 }
 
 static int
@@ -2719,7 +2792,7 @@ virNetworkDefUpdateSection(virNetworkDefPtr def,
                                            parentIndex, ctxt, flags);
         break;
     case VIR_NETWORK_SECTION_PORTGROUP:
-        ret = virNetworkDefUpdatePortgroup(def, command,
+        ret = virNetworkDefUpdatePortGroup(def, command,
                                            parentIndex, ctxt, flags);
         break;
     case VIR_NETWORK_SECTION_DNS_HOST:
-- 
1.7.11.4




More information about the libvir-list mailing list