diff options
author | 2012-09-20 22:25:41 -0400 | |
---|---|---|
committer | 2012-09-21 12:14:15 +0800 | |
commit | 8b6f831c8eebaf04f5d6d10fe2cfc9e42da573c6 (patch) | |
tree | 8cc28404f462908a26c395580cc1f2fad832ba08 | |
parent | network: backend for virNetworkUpdate of dhcp range (diff) | |
download | libvirt-8b6f831c8eebaf04f5d6d10fe2cfc9e42da573c6.tar.gz libvirt-8b6f831c8eebaf04f5d6d10fe2cfc9e42da573c6.tar.bz2 libvirt-8b6f831c8eebaf04f5d6d10fe2cfc9e42da573c6.zip |
network: backend for virNetworkUpdate of portgroups
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).
-rw-r--r-- | src/conf/network_conf.c | 85 |
1 files changed, 79 insertions, 6 deletions
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c index 7fc559f8b..34487dd4c 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: |