aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaine Stump <laine@laine.org>2012-09-20 22:25:40 -0400
committerDaniel Veillard <veillard@redhat.com>2012-09-21 11:54:16 +0800
commit1100f61074b9024fbbc5fb548392fbc99e9e5ca4 (patch)
tree471bf2ba55c1fdb4c2f85a6b9ff0d172704b5a4e
parentvirsh: new net-update command (diff)
downloadlibvirt-1100f61074b9024fbbc5fb548392fbc99e9e5ca4.tar.gz
libvirt-1100f61074b9024fbbc5fb548392fbc99e9e5ca4.tar.bz2
libvirt-1100f61074b9024fbbc5fb548392fbc99e9e5ca4.zip
network: backend for virNetworkUpdate of dhcp range
The dhcp range element is contained in the <dhcp> element of one of a network's <ip> elements. There can be multiple <range> elements. Because there are only two attributes (start and end), and those are exactly what you would use to identify a particular range, it doesn't really make sense to modify an existing element, so VIR_NETWORK_UPDATE_COMMAND_MODIFY isn't supported for this section, only ADD_FIRST, ADD_LAST, and DELETE. Since virsh already has support for understanding all the defined sections, this new backend is automatically supported by virsh. You would use it like this: virsh net-update mynet add ip-dhcp-range \ "<range start='1.2.3.4' end='1.2.3.20'/>" --live --config The bridge driver also already supports all sections, so it's doing the correct thing in this case as well - since the dhcp range is placed on the dnsmasq commandline, the bridge driver recreates the dnsmasq commandline, and re-runs dnsmasq whenever a range is added/deleted (and AFFECT_LIVE is specified in the flags).
-rw-r--r--src/conf/network_conf.c92
1 files changed, 88 insertions, 4 deletions
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index f33834fb5..7fc559f8b 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -2494,14 +2494,98 @@ cleanup:
static int
virNetworkDefUpdateIPDHCPRange(virNetworkDefPtr def,
- unsigned int command ATTRIBUTE_UNUSED,
+ unsigned int command,
int parentIndex ATTRIBUTE_UNUSED,
- xmlXPathContextPtr ctxt ATTRIBUTE_UNUSED,
+ xmlXPathContextPtr ctxt,
/* virNetworkUpdateFlags */
unsigned int fflags ATTRIBUTE_UNUSED)
{
- virNetworkDefUpdateNoSupport(def, "ip dhcp range");
- return -1;
+ int ii, ret = -1;
+ virNetworkIpDefPtr ipdef = virNetworkIpDefByIndex(def, parentIndex);
+ virNetworkDHCPRangeDef range;
+
+ memset(&range, 0, sizeof(range));
+
+ if (virNetworkDefUpdateCheckElementName(def, ctxt->node, "range") < 0)
+ goto cleanup;
+
+ /* ipdef is the ip element that needs its range array updated */
+ if (!ipdef)
+ goto cleanup;
+
+ /* parse the xml into a virNetworkDHCPRangeDef */
+ if (command == VIR_NETWORK_UPDATE_COMMAND_MODIFY) {
+
+ virReportError(VIR_ERR_NO_SUPPORT, "%s",
+ _("dhcp ranges cannot be modified, "
+ "only added or deleted"));
+ goto cleanup;
+ }
+
+ if (virNetworkDHCPRangeDefParse(def->name, ctxt->node, &range) < 0)
+ goto cleanup;
+
+ /* check if an entry with same name/address/ip already exists */
+ for (ii = 0; ii < ipdef->nranges; ii++) {
+ if (virSocketAddrEqual(&range.start, &ipdef->ranges[ii].start) &&
+ virSocketAddrEqual(&range.end, &ipdef->ranges[ii].end)) {
+ break;
+ }
+ }
+
+ if ((command == VIR_NETWORK_UPDATE_COMMAND_ADD_FIRST) ||
+ (command == VIR_NETWORK_UPDATE_COMMAND_ADD_LAST)) {
+
+ if (ii < ipdef->nranges) {
+ char *startip = virSocketAddrFormat(&range.start);
+ char *endip = virSocketAddrFormat(&range.end);
+
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("there is an existing dhcp range entry in "
+ "network '%s' that matches "
+ "\"<range start='%s' end='%s'/>\""),
+ def->name,
+ startip ? startip : "unknown",
+ endip ? endip : "unknown");
+ goto cleanup;
+ }
+
+ /* add to beginning/end of list */
+ if (VIR_REALLOC_N(ipdef->ranges, ipdef->nranges +1) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (command == VIR_NETWORK_UPDATE_COMMAND_ADD_LAST) {
+ ipdef->ranges[ipdef->nranges] = range;
+ } else { /* implied (command == VIR_NETWORK_UPDATE_COMMAND_ADD_FIRST) */
+ memmove(ipdef->ranges + 1, ipdef->ranges,
+ sizeof(*ipdef->ranges) * ipdef->nranges);
+ ipdef->ranges[0] = range;
+ }
+ ipdef->nranges++;
+ memset(&range, 0, sizeof(range));
+
+ } else if (command == VIR_NETWORK_UPDATE_COMMAND_DELETE) {
+
+ if (ii == ipdef->nranges) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("couldn't locate a matching dhcp range entry "
+ "in network '%s'"), def->name);
+ goto cleanup;
+ }
+
+ /* remove it */
+ /* NB: nothing to clear from a RangeDef that's being freed */
+ memmove(ipdef->ranges + ii, ipdef->ranges + ii + 1,
+ sizeof(*ipdef->ranges) * (ipdef->nranges - ii - 1));
+ ipdef->nranges--;
+ ignore_value(VIR_REALLOC_N(ipdef->ranges, ipdef->nranges));
+ }
+
+ ret = 0;
+cleanup:
+ return ret;
}
static int