]> xenbits.xensource.com Git - libvirt.git/commitdiff
network: don't allow multiple default portgroups
authorLaine Stump <laine@laine.org>
Sat, 20 Oct 2012 08:39:18 +0000 (04:39 -0400)
committerLaine Stump <laine@laine.org>
Sun, 21 Oct 2012 01:29:19 +0000 (21:29 -0400)
This resolves: https://bugzilla.redhat.com/show_bug.cgi?id=868483

virNetworkUpdate, virNetworkDefine, and virNetworkCreate all three
allow network definitions to contain multiple <portgroup> elements
with default='yes'. Only a single default portgroup should be allowed
for each network.

This patch updates networkValidate() (called by both
virNetworkCreate() and virNetworkDefine()) and
virNetworkDefUpdatePortGroup (called by virNetworkUpdate() to not
allow multiple default portgroups.

src/conf/network_conf.c
src/network/bridge_driver.c

index 2f9ad2edc55dd788a6f14c2986d86407d420c55a..8976f2a122fb7d4b8a9a8433c8eb6cec87a7bc54 100644 (file)
@@ -2752,7 +2752,8 @@ virNetworkDefUpdatePortGroup(virNetworkDefPtr def,
                              /* virNetworkUpdateFlags */
                              unsigned int fflags ATTRIBUTE_UNUSED)
 {
-    int ii, ret = -1;
+    int ii, foundName = -1, foundDefault = -1;
+    int ret = -1;
     virPortGroupDef portgroup;
 
     memset(&portgroup, 0, sizeof(portgroup));
@@ -2766,9 +2767,11 @@ virNetworkDefUpdatePortGroup(virNetworkDefPtr def,
     /* 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;
+            foundName = ii;
+        if (def->portGroups[ii].isDefault)
+            foundDefault = ii;
     }
-    if (ii == def->nPortGroups &&
+    if (foundName == -1 &&
         ((command == VIR_NETWORK_UPDATE_COMMAND_MODIFY) ||
          (command == VIR_NETWORK_UPDATE_COMMAND_DELETE))) {
         virReportError(VIR_ERR_OPERATION_INVALID,
@@ -2776,7 +2779,7 @@ virNetworkDefUpdatePortGroup(virNetworkDefPtr def,
                          "in network '%s' matching <portgroup name='%s'>"),
                        def->name, portgroup.name);
         goto cleanup;
-    } else if (ii < def->nPortGroups &&
+    } else if (foundName >= 0 &&
                ((command == VIR_NETWORK_UPDATE_COMMAND_ADD_FIRST) ||
                 (command == VIR_NETWORK_UPDATE_COMMAND_ADD_LAST))) {
         virReportError(VIR_ERR_OPERATION_INVALID,
@@ -2787,11 +2790,25 @@ virNetworkDefUpdatePortGroup(virNetworkDefPtr def,
         goto cleanup;
     }
 
+    /* if there is already a different default, we can't make this
+     * one the default.
+     */
+    if (command != VIR_NETWORK_UPDATE_COMMAND_DELETE &&
+        portgroup.isDefault &&
+        foundDefault >= 0 && foundDefault != foundName) {
+        virReportError(VIR_ERR_OPERATION_INVALID,
+                       _("a different portgroup entry in "
+                         "network '%s' is already set as the default. "
+                         "Only one default is allowed."),
+                       def->name);
+        goto cleanup;
+    }
+
     if (command == VIR_NETWORK_UPDATE_COMMAND_MODIFY) {
 
         /* replace existing entry */
-        virPortGroupDefClear(&def->portGroups[ii]);
-        def->portGroups[ii] = portgroup;
+        virPortGroupDefClear(&def->portGroups[foundName]);
+        def->portGroups[foundName] = portgroup;
         memset(&portgroup, 0, sizeof(portgroup));
 
     } else if ((command == VIR_NETWORK_UPDATE_COMMAND_ADD_FIRST) ||
@@ -2816,9 +2833,9 @@ virNetworkDefUpdatePortGroup(virNetworkDefPtr def,
     } 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));
+        virPortGroupDefClear(&def->portGroups[foundName]);
+        memmove(def->portGroups + foundName, def->portGroups + foundName + 1,
+                sizeof(*def->portGroups) * (def->nPortGroups - foundName - 1));
         def->nPortGroups--;
         ignore_value(VIR_REALLOC_N(def->portGroups, def->nPortGroups));
     } else {
index 1c97f290cbf74865cef46da2ed9abc4d20e62c95..88378439264119161ce4234203228743bb205d6a 100644 (file)
@@ -2618,6 +2618,7 @@ networkValidate(virNetworkDefPtr def)
 {
     int ii;
     bool vlanUsed, vlanAllowed;
+    const char *defaultPortGroup = NULL;
 
     /* The only type of networks that currently support transparent
      * vlan configuration are those using hostdev sr-iov devices from
@@ -2638,6 +2639,17 @@ networkValidate(virNetworkDefPtr def)
              == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH)) {
             vlanAllowed = true;
         }
+        if (def->portGroups[ii].isDefault) {
+            if (defaultPortGroup) {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                               _("network '%s' has multiple default "
+                                 "<portgroup> elements (%s and %s), "
+                                 "but only one default is allowed"),
+                               def->name, defaultPortGroup,
+                               def->portGroups[ii].name);
+            }
+            defaultPortGroup = def->portGroups[ii].name;
+        }
     }
     if (vlanUsed && !vlanAllowed) {
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,