From 8b6f831c8eebaf04f5d6d10fe2cfc9e42da573c6 Mon Sep 17 00:00:00 2001 From: Laine Stump Date: Thu, 20 Sep 2012 22:25:41 -0400 Subject: [PATCH] network: backend for virNetworkUpdate of portgroups portgroup elements are located in the toplevel of objects. There can be multiple 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 7fc559f8b7..34487dd4cd 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 "), + 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 " + "\"\""), + 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: -- GitLab