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 <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.
(cherry picked from commit 6f8a8b30c9a0123d8c6f49c946084b94c580811b)
This commit is contained in:
Laine Stump 2012-10-20 04:39:18 -04:00 committed by Cole Robinson
parent 874a336108
commit 10f8762b4f
2 changed files with 38 additions and 9 deletions

View File

@ -2659,7 +2659,8 @@ virNetworkDefUpdatePortGroup(virNetworkDefPtr def,
/* virNetworkUpdateFlags */ /* virNetworkUpdateFlags */
unsigned int fflags ATTRIBUTE_UNUSED) unsigned int fflags ATTRIBUTE_UNUSED)
{ {
int ii, ret = -1; int ii, foundName = -1, foundDefault = -1;
int ret = -1;
virPortGroupDef portgroup; virPortGroupDef portgroup;
memset(&portgroup, 0, sizeof(portgroup)); memset(&portgroup, 0, sizeof(portgroup));
@ -2673,9 +2674,11 @@ virNetworkDefUpdatePortGroup(virNetworkDefPtr def,
/* check if a portgroup with same name already exists */ /* check if a portgroup with same name already exists */
for (ii = 0; ii < def->nPortGroups; ii++) { for (ii = 0; ii < def->nPortGroups; ii++) {
if (STREQ(portgroup.name, def->portGroups[ii].name)) 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_MODIFY) ||
(command == VIR_NETWORK_UPDATE_COMMAND_DELETE))) { (command == VIR_NETWORK_UPDATE_COMMAND_DELETE))) {
virReportError(VIR_ERR_OPERATION_INVALID, virReportError(VIR_ERR_OPERATION_INVALID,
@ -2683,7 +2686,7 @@ virNetworkDefUpdatePortGroup(virNetworkDefPtr def,
"in network '%s' matching <portgroup name='%s'>"), "in network '%s' matching <portgroup name='%s'>"),
def->name, portgroup.name); def->name, portgroup.name);
goto cleanup; goto cleanup;
} else if (ii < def->nPortGroups && } else if (foundName >= 0 &&
((command == VIR_NETWORK_UPDATE_COMMAND_ADD_FIRST) || ((command == VIR_NETWORK_UPDATE_COMMAND_ADD_FIRST) ||
(command == VIR_NETWORK_UPDATE_COMMAND_ADD_LAST))) { (command == VIR_NETWORK_UPDATE_COMMAND_ADD_LAST))) {
virReportError(VIR_ERR_OPERATION_INVALID, virReportError(VIR_ERR_OPERATION_INVALID,
@ -2694,11 +2697,25 @@ virNetworkDefUpdatePortGroup(virNetworkDefPtr def,
goto cleanup; 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) { if (command == VIR_NETWORK_UPDATE_COMMAND_MODIFY) {
/* replace existing entry */ /* replace existing entry */
virPortGroupDefClear(&def->portGroups[ii]); virPortGroupDefClear(&def->portGroups[foundName]);
def->portGroups[ii] = portgroup; def->portGroups[foundName] = portgroup;
memset(&portgroup, 0, sizeof(portgroup)); memset(&portgroup, 0, sizeof(portgroup));
} else if ((command == VIR_NETWORK_UPDATE_COMMAND_ADD_FIRST) || } else if ((command == VIR_NETWORK_UPDATE_COMMAND_ADD_FIRST) ||
@ -2723,9 +2740,9 @@ virNetworkDefUpdatePortGroup(virNetworkDefPtr def,
} else if (command == VIR_NETWORK_UPDATE_COMMAND_DELETE) { } else if (command == VIR_NETWORK_UPDATE_COMMAND_DELETE) {
/* remove it */ /* remove it */
virPortGroupDefClear(&def->portGroups[ii]); virPortGroupDefClear(&def->portGroups[foundName]);
memmove(def->portGroups + ii, def->portGroups + ii + 1, memmove(def->portGroups + foundName, def->portGroups + foundName + 1,
sizeof(*def->portGroups) * (def->nPortGroups - ii - 1)); sizeof(*def->portGroups) * (def->nPortGroups - foundName - 1));
def->nPortGroups--; def->nPortGroups--;
ignore_value(VIR_REALLOC_N(def->portGroups, def->nPortGroups)); ignore_value(VIR_REALLOC_N(def->portGroups, def->nPortGroups));
} else { } else {

View File

@ -2618,6 +2618,7 @@ networkValidate(virNetworkDefPtr def)
{ {
int ii; int ii;
bool vlanUsed, vlanAllowed; bool vlanUsed, vlanAllowed;
const char *defaultPortGroup = NULL;
/* The only type of networks that currently support transparent /* The only type of networks that currently support transparent
* vlan configuration are those using hostdev sr-iov devices from * vlan configuration are those using hostdev sr-iov devices from
@ -2638,6 +2639,17 @@ networkValidate(virNetworkDefPtr def)
== VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH)) { == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH)) {
vlanAllowed = true; 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) { if (vlanUsed && !vlanAllowed) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, virReportError(VIR_ERR_CONFIG_UNSUPPORTED,