portgroup elements are located in the toplevel of <network> objects. There can be multiple <portgroup> 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 7fc559f..34487dd 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 <portgroup name='%s'>"), + 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 " + "\"<portgroup name='%s'>\""), + 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: -- 1.7.11.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list