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 | 35 ++++++++++++++++++++++++++--------- src/network/bridge_driver.c | 12 ++++++++++++ 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c index 2f9ad2e..8976f2a 100644 --- a/src/conf/network_conf.c +++ b/src/conf/network_conf.c @@ -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 { diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 1c97f29..8837843 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -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, -- 1.7.11.7 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list