virNetworkObjUpdate takes care of all virNetworkUpdate-related changes
to the data stored in the in-memory virNetworkObj list. It should be
called by network drivers that use this in-memory list.
virNetworkObjUpdate *does not* take care of updating any disk-based
copies of the config, nor does it perform any other operations
necessary to have the new config data take effect (e.g. it won't
re-write dnsmasq host files, nor will it send a SIGHUP to dnsmasq) -
those things should all be taken care of in the network driver
function that calls virNetworkObjUpdate (assuming that it returns
success).
---
I'm resending this patch because, while implementing the backend for a
specific section (IP_DHCP_HOST), I realized that it will be much more
useful for virNetworkObjUpdate() to create an xmlDoc and
xmlXPathContext, and send that down to the section-specific functions
rather than the character string - they're all going to need an xmlDoc
anyway, so I may as well write the code once.
src/conf/network_conf.c | 287 +++++++++++++++++++++++++++++++++++++++++++++++
src/conf/network_conf.h | 7 ++
src/libvirt_private.syms | 1 +
3 files changed, 295 insertions(+)
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index a48eb9e..d991b2a 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -2251,6 +2251,293 @@ void virNetworkSetBridgeMacAddr(virNetworkDefPtr def)
}
}
+/* NetworkObj backend of the virNetworkUpdate API */
+
+static void
+virNetworkDefUpdateNoSupport(virNetworkDefPtr def, const char *section)
+{
+ virReportError(VIR_ERR_NO_SUPPORT,
+ _("can't update '%s' section of network
'%s'"),
+ section, def->name);
+}
+
+#if 0
+static int
+virNetworkDefUpdateCheckElementName(virNetworkDefPtr def,
+ xmlNodePtr node,
+ const char *section)
+{
+ if (!xmlStrEqual(node->name, BAD_CAST section)) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("unexpected element <%s>, expecting <%s>,
"
+ "while updating network '%s'"),
+ node->name, section, def->name);
+ return -1;
+ }
+ return 0;
+}
+#endif
+
+static int
+virNetworkDefUpdateBridge(virNetworkDefPtr def,
+ int parentIndex ATTRIBUTE_UNUSED,
+ xmlXPathContextPtr ctxt ATTRIBUTE_UNUSED,
+ /* virNetworkUpdateFlags */
+ unsigned int fflags ATTRIBUTE_UNUSED)
+{
+ virNetworkDefUpdateNoSupport(def, "bridge");
+ return -1;
+}
+
+static int
+virNetworkDefUpdateDomain(virNetworkDefPtr def,
+ int parentIndex ATTRIBUTE_UNUSED,
+ xmlXPathContextPtr ctxt ATTRIBUTE_UNUSED,
+ /* virNetworkUpdateFlags */
+ unsigned int fflags ATTRIBUTE_UNUSED)
+{
+ virNetworkDefUpdateNoSupport(def, "domain");
+ return -1;
+}
+
+static int
+virNetworkDefUpdateIP(virNetworkDefPtr def,
+ int parentIndex ATTRIBUTE_UNUSED,
+ xmlXPathContextPtr ctxt ATTRIBUTE_UNUSED,
+ /* virNetworkUpdateFlags */
+ unsigned int fflags ATTRIBUTE_UNUSED)
+{
+ virNetworkDefUpdateNoSupport(def, "ip");
+ return -1;
+}
+
+static int
+virNetworkDefUpdateIPDHCPHost(virNetworkDefPtr def,
+ int parentIndex ATTRIBUTE_UNUSED,
+ xmlXPathContextPtr ctxt ATTRIBUTE_UNUSED,
+ /* virNetworkUpdateFlags */
+ unsigned int fflags ATTRIBUTE_UNUSED)
+{
+ virNetworkDefUpdateNoSupport(def, "ip dhcp host");
+ return -1;
+}
+
+static int
+virNetworkDefUpdateIPDHCPRange(virNetworkDefPtr def,
+ int parentIndex ATTRIBUTE_UNUSED,
+ xmlXPathContextPtr ctxt ATTRIBUTE_UNUSED,
+ /* virNetworkUpdateFlags */
+ unsigned int fflags ATTRIBUTE_UNUSED)
+{
+ virNetworkDefUpdateNoSupport(def, "ip dhcp range");
+ return -1;
+}
+
+static int
+virNetworkDefUpdateForward(virNetworkDefPtr def,
+ int parentIndex ATTRIBUTE_UNUSED,
+ xmlXPathContextPtr ctxt ATTRIBUTE_UNUSED,
+ /* virNetworkUpdateFlags */
+ unsigned int fflags ATTRIBUTE_UNUSED)
+{
+ virNetworkDefUpdateNoSupport(def, "forward");
+ return -1;
+}
+
+static int
+virNetworkDefUpdateForwardInterface(virNetworkDefPtr def,
+ int parentIndex ATTRIBUTE_UNUSED,
+ xmlXPathContextPtr ctxt ATTRIBUTE_UNUSED,
+ /* virNetworkUpdateFlags */
+ unsigned int fflags ATTRIBUTE_UNUSED)
+{
+ virNetworkDefUpdateNoSupport(def, "forward interface");
+ return -1;
+}
+
+static int
+virNetworkDefUpdateForwardPF(virNetworkDefPtr def,
+ int parentIndex ATTRIBUTE_UNUSED,
+ xmlXPathContextPtr ctxt ATTRIBUTE_UNUSED,
+ /* virNetworkUpdateFlags */
+ unsigned int fflags ATTRIBUTE_UNUSED)
+{
+ virNetworkDefUpdateNoSupport(def, "forward pf");
+ return -1;
+}
+
+static int
+virNetworkDefUpdatePortgroup(virNetworkDefPtr def,
+ int parentIndex ATTRIBUTE_UNUSED,
+ xmlXPathContextPtr ctxt ATTRIBUTE_UNUSED,
+ /* virNetworkUpdateFlags */
+ unsigned int fflags ATTRIBUTE_UNUSED)
+{
+ virNetworkDefUpdateNoSupport(def, "portgroup");
+ return -1;
+}
+
+static int
+virNetworkDefUpdateDNSHost(virNetworkDefPtr def,
+ int parentIndex ATTRIBUTE_UNUSED,
+ xmlXPathContextPtr ctxt ATTRIBUTE_UNUSED,
+ /* virNetworkUpdateFlags */
+ unsigned int fflags ATTRIBUTE_UNUSED)
+{
+ virNetworkDefUpdateNoSupport(def, "dns host");
+ return -1;
+}
+
+static int
+virNetworkDefUpdateDNSTxt(virNetworkDefPtr def,
+ int parentIndex ATTRIBUTE_UNUSED,
+ xmlXPathContextPtr ctxt ATTRIBUTE_UNUSED,
+ /* virNetworkUpdateFlags */
+ unsigned int fflags ATTRIBUTE_UNUSED)
+{
+ virNetworkDefUpdateNoSupport(def, "dns txt");
+ return -1;
+}
+
+static int
+virNetworkDefUpdateDNSSrv(virNetworkDefPtr def,
+ int parentIndex ATTRIBUTE_UNUSED,
+ xmlXPathContextPtr ctxt ATTRIBUTE_UNUSED,
+ /* virNetworkUpdateFlags */
+ unsigned int fflags ATTRIBUTE_UNUSED)
+{
+ virNetworkDefUpdateNoSupport(def, "dns txt");
+ return -1;
+}
+
+static int
+virNetworkDefUpdateSection(virNetworkDefPtr def,
+ unsigned int section, /* virNetworkUpdateSection */
+ int parentIndex,
+ const char *xml,
+ unsigned int flags) /* virNetworkUpdateFlags */
+{
+ int ret = -1;
+ xmlDocPtr doc;
+ xmlXPathContextPtr ctxt = NULL;
+
+ if (!(doc = virXMLParseStringCtxt(xml, _("network_update_xml"),
&ctxt)))
+ goto cleanup;
+
+ switch (section) {
+ case VIR_NETWORK_SECTION_BRIDGE:
+ ret = virNetworkDefUpdateBridge(def, parentIndex, ctxt, flags);
+ break;
+
+ case VIR_NETWORK_SECTION_DOMAIN:
+ ret = virNetworkDefUpdateDomain(def, parentIndex, ctxt, flags);
+ break;
+ case VIR_NETWORK_SECTION_IP:
+ ret = virNetworkDefUpdateIP(def, parentIndex, ctxt, flags);
+ break;
+ case VIR_NETWORK_SECTION_IP_DHCP_HOST:
+ ret = virNetworkDefUpdateIPDHCPHost(def, parentIndex, ctxt, flags);
+ break;
+ case VIR_NETWORK_SECTION_IP_DHCP_RANGE:
+ ret = virNetworkDefUpdateIPDHCPRange(def, parentIndex, ctxt, flags);
+ break;
+ case VIR_NETWORK_SECTION_FORWARD:
+ ret = virNetworkDefUpdateForward(def, parentIndex, ctxt, flags);
+ break;
+ case VIR_NETWORK_SECTION_FORWARD_INTERFACE:
+ ret = virNetworkDefUpdateForwardInterface(def, parentIndex, ctxt, flags);
+ break;
+ case VIR_NETWORK_SECTION_FORWARD_PF:
+ ret = virNetworkDefUpdateForwardPF(def, parentIndex, ctxt, flags);
+ break;
+ case VIR_NETWORK_SECTION_PORTGROUP:
+ ret = virNetworkDefUpdatePortgroup(def, parentIndex, ctxt, flags);
+ break;
+ case VIR_NETWORK_SECTION_DNS_HOST:
+ ret = virNetworkDefUpdateDNSHost(def, parentIndex, ctxt, flags);
+ break;
+ case VIR_NETWORK_SECTION_DNS_TXT:
+ ret = virNetworkDefUpdateDNSTxt(def, parentIndex, ctxt, flags);
+ break;
+ case VIR_NETWORK_SECTION_DNS_SRV:
+ ret = virNetworkDefUpdateDNSSrv(def, parentIndex, ctxt, flags);
+ break;
+ default:
+ virReportError(VIR_ERR_NO_SUPPORT, "%s",
+ _("can't update unrecognized section of network"));
+ break;
+ }
+
+cleanup:
+ xmlFreeDoc(doc);
+ xmlXPathFreeContext(ctxt);
+ return ret;
+}
+
+/*
+ * virNetworkObjUpdate:
+ *
+ * Apply the supplied update to the given virNetworkObj. Except for
+ * @network pointing to an actual network object rather than the
+ * opaque virNetworkPtr, parameters are identical to the public API
+ * virNetworkUpdate.
+ *
+ * The original virNetworkDefs are copied, and all modifications made
+ * to these copies. The originals are replaced with the copies only
+ * after success has been guaranteed.
+ *
+ * Returns: -1 on error, 0 on success.
+ */
+int
+virNetworkObjUpdate(virNetworkObjPtr network,
+ unsigned int section, /* virNetworkUpdateSection */
+ int parentIndex,
+ const char *xml,
+ unsigned int flags) /* virNetworkUpdateFlags */
+{
+ int ret = -1;
+ virNetworkDefPtr def = NULL;
+
+ /* normalize config data, and check for common invalid requests. */
+ if (virNetworkConfigChangeSetup(network, flags) < 0)
+ goto cleanup;
+
+ if (flags & VIR_NETWORK_UPDATE_AFFECT_LIVE) {
+ /* work on a copy of the def */
+ if (!(def = virNetworkDefCopy(network->def, 0)))
+ goto cleanup;
+ if (virNetworkDefUpdateSection(def, section,
+ parentIndex, xml, flags) < 0) {
+ goto cleanup;
+ }
+ /* successfully modified copy, now replace original */
+ virNetworkDefFree(network->def);
+ network->def = def;
+ def = NULL;
+ }
+
+ if (flags & VIR_NETWORK_UPDATE_AFFECT_CONFIG) {
+ /* work on a copy of the def */
+ if (!(def = virNetworkDefCopy(virNetworkObjGetPersistentDef(network),
+ VIR_NETWORK_XML_INACTIVE))) {
+ goto cleanup;
+ }
+ if (virNetworkDefUpdateSection(def, section,
+ parentIndex, xml, flags) < 0) {
+ goto cleanup;
+ }
+ /* successfully modified copy, now replace original */
+ if (virNetworkObjReplacePersistentDef(network, def) < 0)
+ goto cleanup;
+ def = NULL;
+ }
+
+ ret = 0;
+cleanup:
+ virNetworkDefFree(def);
+ return ret;
+}
+
/*
* virNetworkObjIsDuplicate:
* @doms : virNetworkObjListPtr to search
diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index 0d37a8b..3d12f58 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -326,6 +326,13 @@ int virNetworkSetBridgeName(const virNetworkObjListPtr nets,
void virNetworkSetBridgeMacAddr(virNetworkDefPtr def);
+int
+virNetworkObjUpdate(virNetworkObjPtr obj,
+ unsigned int section, /* virNetworkUpdateSection */
+ int parentIndex,
+ const char *xml,
+ unsigned int flags); /* virNetworkUpdateFlags */
+
int virNetworkObjIsDuplicate(virNetworkObjListPtr doms,
virNetworkDefPtr def,
unsigned int check_active);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 9e87357..a24f626 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -863,6 +863,7 @@ virNetworkObjLock;
virNetworkObjReplacePersistentDef;
virNetworkObjSetDefTransient;
virNetworkObjUnlock;
+virNetworkObjUpdate;
virNetworkRemoveInactive;
virNetworkSaveConfig;
virNetworkSaveStatus;
--
1.7.11.4