From 10f8762b4fc8d31050ce73f54e0ce92589f56007 Mon Sep 17 00:00:00 2001 From: Laine Stump Date: Sat, 20 Oct 2012 04:39:18 -0400 Subject: [PATCH] network: don't allow multiple default portgroups This resolves: https://bugzilla.redhat.com/show_bug.cgi?id=868483 virNetworkUpdate, virNetworkDefine, and virNetworkCreate all three allow network definitions to contain multiple 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. (cherry picked from commit 6f8a8b30c9a0123d8c6f49c946084b94c580811b) --- 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 82251184cb..9187de1660 100644 --- a/src/conf/network_conf.c +++ b/src/conf/network_conf.c @@ -2659,7 +2659,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)); @@ -2673,9 +2674,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, @@ -2683,7 +2686,7 @@ virNetworkDefUpdatePortGroup(virNetworkDefPtr def, "in network '%s' matching "), 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, @@ -2694,11 +2697,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) || @@ -2723,9 +2740,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 afeca22c26..03a74684bb 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 " + " 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,