summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaine Stump <laine@laine.org>2012-09-20 22:25:41 -0400
committerDaniel Veillard <veillard@redhat.com>2012-09-21 12:14:15 +0800
commit8b6f831c8eebaf04f5d6d10fe2cfc9e42da573c6 (patch)
tree8cc28404f462908a26c395580cc1f2fad832ba08
parentnetwork: backend for virNetworkUpdate of dhcp range (diff)
downloadlibvirt-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.c85
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: