[libvirt] [PATCHv2 3/9] network: utility functions for updating network config

Laine Stump laine at laine.org
Tue Sep 18 07:38:59 UTC 2012


These new functions are highly inspired by those in domain_conf.c (but
not identical), and are intended to make it simpler to update the
various combinations of live/persistent network configs.

The network driver wasn't previously as careful about the separation
between the live "status" in network->def and the persistent "config"
in network->newDef (or sometimes in network->def). This series
attempts to remedy some of that, but probably doesn't go all the way
(enough to get these functions working and enable continued work on
virNetworkUpdate though).

bridge_driver.c and test_driver.c were updated in a few places to take
advantage of the new functions and/or account for changes in argument
lists.
---
 src/conf/network_conf.c     | 234 ++++++++++++++++++++++++++++++++++++++++++--
 src/conf/network_conf.h     |  16 ++-
 src/libvirt_private.syms    |  10 +-
 src/network/bridge_driver.c |  14 ++-
 src/test/test_driver.c      |   9 +-
 5 files changed, 262 insertions(+), 21 deletions(-)

diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index 88e1492..a48eb9e 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -228,20 +228,74 @@ void virNetworkObjListFree(virNetworkObjListPtr nets)
     nets->count = 0;
 }
 
-virNetworkObjPtr virNetworkAssignDef(virNetworkObjListPtr nets,
-                                     const virNetworkDefPtr def)
+/*
+ * virNetworkObjAssignDef:
+ * @network: the network object to update
+ * @def: the new NetworkDef (will be consumed by this function iff successful)
+ * @live: is this new def the "live" version, or the "persistent" version
+ *
+ * Replace the appropriate copy of the given network's NetworkDef
+ * with def. Use "live" and current state of the network to determine
+ * which to replace.
+ *
+ * Returns 0 on success, -1 on failure.
+ */
+int
+virNetworkObjAssignDef(virNetworkObjPtr network,
+                       const virNetworkDefPtr def,
+                       bool live)
 {
-    virNetworkObjPtr network;
-
-    if ((network = virNetworkFindByName(nets, def->name))) {
-        if (!virNetworkObjIsActive(network)) {
+    if (virNetworkObjIsActive(network)) {
+        if (live) {
             virNetworkDefFree(network->def);
             network->def = def;
-        } else {
+        } else if (network->persistent) {
+            /* save current configuration to be restored on network shutdown */
             virNetworkDefFree(network->newDef);
             network->newDef = def;
+        } else {
+            virReportError(VIR_ERR_OPERATION_INVALID,
+                           _("cannot save persistent config of transient "
+                             "network '%s'"), network->def->name);
+            return -1;
         }
+    } else if (!live) {
+        virNetworkDefFree(network->newDef); /* should be unnecessary */
+        virNetworkDefFree(network->def);
+        network->def = def;
+    } else {
+        virReportError(VIR_ERR_OPERATION_INVALID,
+                       _("cannot save live config of inactive "
+                         "network '%s'"), network->def->name);
+        return -1;
+    }
+    return 0;
+}
+
+/*
+ * virNetworkAssignDef:
+ * @nets: list of all networks
+ * @def: the new NetworkDef (will be consumed by this function iff successful)
+ * @live: is this new def the "live" version, or the "persistent" version
+ *
+ * Either replace the appropriate copy of the NetworkDef with name
+ * matching def->name or, if not found, create a new NetworkObj with
+ * def. For an existing network, use "live" and current state of the
+ * network to determine which to replace.
+ *
+ * Returns -1 on failure, 0 on success.
+ */
+virNetworkObjPtr
+virNetworkAssignDef(virNetworkObjListPtr nets,
+                    const virNetworkDefPtr def,
+                    bool live)
+{
+    virNetworkObjPtr network;
 
+    if ((network = virNetworkFindByName(nets, def->name))) {
+        if (virNetworkObjAssignDef(network, def, live) < 0) {
+            return NULL;
+        }
         return network;
     }
 
@@ -270,6 +324,150 @@ virNetworkObjPtr virNetworkAssignDef(virNetworkObjListPtr nets,
 
 }
 
+/*
+ * virNetworkObjSetDefTransient:
+ * @network: network object pointer
+ * @live: if true, run this operation even for an inactive network.
+ *   this allows freely updated network->def with runtime defaults
+ *   before starting the network, which will be discarded on network
+ *   shutdown. Any cleanup paths need to be sure to handle newDef if
+ *   the network is never started.
+ *
+ * Mark the active network config as transient. Ensures live-only update
+ * operations do not persist past network destroy.
+ *
+ * Returns 0 on success, -1 on failure
+ */
+int
+virNetworkObjSetDefTransient(virNetworkObjPtr network, bool live)
+{
+    if (!virNetworkObjIsActive(network) && !live)
+        return 0;
+
+    if (!network->persistent || network->newDef)
+        return 0;
+
+    network->newDef = virNetworkDefCopy(network->def, VIR_NETWORK_XML_INACTIVE);
+    return network->newDef ? 0 : -1;
+}
+
+/*
+ * virNetworkObjGetPersistentDef:
+ * @network: network object pointer
+ *
+ * Return the persistent network configuration. If network is transient,
+ * return the running config.
+ *
+ * Returns NULL on error, virNetworkDefPtr on success.
+ */
+virNetworkDefPtr
+virNetworkObjGetPersistentDef(virNetworkObjPtr network)
+{
+    if (network->newDef)
+        return network->newDef;
+    else
+        return network->def;
+}
+
+/*
+ * virNetworkObjReplacePersistentDef:
+ * @network: network object pointer
+ * @def: new virNetworkDef to replace current persistent config
+ *
+ * Replace the "persistent" network configuration with the given new
+ * virNetworkDef. This pays attention to whether or not the network
+ * is active.
+ *
+ * Returns -1 on error, 0 on success
+ */
+int
+virNetworkObjReplacePersistentDef(virNetworkObjPtr network,
+                                  virNetworkDefPtr def)
+{
+    if (virNetworkObjIsActive(network)) {
+        virNetworkDefFree(network->newDef);
+        network->newDef = def;
+    } else {
+        virNetworkDefFree(network->def);
+        network->def = def;
+    }
+    return 0;
+}
+
+/*
+ * virNetworkDefCopy:
+ * @def: NetworkDef to copy
+ * @flags: VIR_NETWORK_XML_INACTIVE if appropriate
+ *
+ * make a deep copy of the given NetworkDef
+ *
+ * Returns a new NetworkDef on success, or NULL on failure.
+ */
+virNetworkDefPtr
+virNetworkDefCopy(virNetworkDefPtr def, unsigned int flags)
+{
+    char *xml = NULL;
+    virNetworkDefPtr newDef = NULL;
+
+    if (!def) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       "%s", _("NULL NetworkDef"));
+        return NULL;
+    }
+
+    /* deep copy with a format/parse cycle */
+    if (!(xml = virNetworkDefFormat(def, flags)))
+        goto cleanup;
+    newDef = virNetworkDefParseString(xml);
+cleanup:
+    VIR_FREE(xml);
+    return newDef;
+}
+
+/*
+ * virNetworkConfigChangeSetup:
+ *
+ * 1) checks whether network state is consistent with the requested
+ *    type of modification.
+ *
+ * 3) make sure there are separate "def" and "newDef" copies of
+ *    networkDef if appropriate.
+ *
+ * Returns 0 on success, -1 on error.
+ */
+int
+virNetworkConfigChangeSetup(virNetworkObjPtr network, unsigned int flags)
+{
+    bool isActive;
+    int ret = -1;
+
+    isActive = virNetworkObjIsActive(network);
+
+    if (!isActive && (flags & VIR_NETWORK_UPDATE_AFFECT_LIVE)) {
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                       _("network is not running"));
+        goto cleanup;
+    }
+
+    if (flags & VIR_NETWORK_UPDATE_AFFECT_CONFIG) {
+        if (!network->persistent) {
+            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                           _("cannot change persistent config of a "
+                             "transient network"));
+            goto cleanup;
+        }
+        /* this should already have been done by the driver, but do it
+         * anyway just in case.
+         */
+        if (isActive && (virNetworkObjSetDefTransient(network, false) < 0))
+            goto cleanup;
+    }
+
+    ret = 0;
+cleanup:
+    return ret;
+}
+
 void virNetworkRemoveInactive(virNetworkObjListPtr nets,
                               const virNetworkObjPtr net)
 {
@@ -1791,7 +1989,7 @@ int virNetworkSaveConfig(const char *configDir,
     int ret = -1;
     char *xml;
 
-    if (!(xml = virNetworkDefFormat(def, 0)))
+    if (!(xml = virNetworkDefFormat(def, VIR_NETWORK_XML_INACTIVE)))
         goto cleanup;
 
     if (virNetworkSaveXML(configDir, def, xml))
@@ -1804,6 +2002,24 @@ cleanup:
 }
 
 
+int virNetworkSaveStatus(const char *statusDir,
+                         virNetworkObjPtr network)
+{
+    int ret = -1;
+    char *xml;
+
+    if (!(xml = virNetworkDefFormat(network->def, 0)))
+        goto cleanup;
+
+    if (virNetworkSaveXML(statusDir, network->def, xml))
+        goto cleanup;
+
+    ret = 0;
+cleanup:
+    VIR_FREE(xml);
+    return ret;
+}
+
 virNetworkObjPtr virNetworkLoadConfig(virNetworkObjListPtr nets,
                                       const char *configDir,
                                       const char *autostartDir,
@@ -1844,7 +2060,7 @@ virNetworkObjPtr virNetworkLoadConfig(virNetworkObjListPtr nets,
             goto error;
     }
 
-    if (!(net = virNetworkAssignDef(nets, def)))
+    if (!(net = virNetworkAssignDef(nets, def, false)))
         goto error;
 
     net->autostart = autostart;
diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index 5dbf50d..0d37a8b 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -247,7 +247,18 @@ void virNetworkObjFree(virNetworkObjPtr net);
 void virNetworkObjListFree(virNetworkObjListPtr vms);
 
 virNetworkObjPtr virNetworkAssignDef(virNetworkObjListPtr nets,
-                                     const virNetworkDefPtr def);
+                                     const virNetworkDefPtr def,
+                                     bool live);
+int virNetworkObjAssignDef(virNetworkObjPtr network,
+                           const virNetworkDefPtr def,
+                           bool live);
+int virNetworkObjSetDefTransient(virNetworkObjPtr network, bool live);
+virNetworkDefPtr virNetworkObjGetPersistentDef(virNetworkObjPtr network);
+int virNetworkObjReplacePersistentDef(virNetworkObjPtr network,
+                                      virNetworkDefPtr def);
+virNetworkDefPtr virNetworkDefCopy(virNetworkDefPtr def, unsigned int flags);
+int virNetworkConfigChangeSetup(virNetworkObjPtr dom, unsigned int flags);
+
 void virNetworkRemoveInactive(virNetworkObjListPtr nets,
                               const virNetworkObjPtr net);
 
@@ -283,6 +294,9 @@ int virNetworkSaveXML(const char *configDir,
 int virNetworkSaveConfig(const char *configDir,
                          virNetworkDefPtr def);
 
+int virNetworkSaveStatus(const char *statusDir,
+                         virNetworkObjPtr net) ATTRIBUTE_RETURN_CHECK;
+
 virNetworkObjPtr virNetworkLoadConfig(virNetworkObjListPtr nets,
                                       const char *configDir,
                                       const char *autostartDir,
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index e8f3fa5..39e06e4 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -839,6 +839,8 @@ virNetDevVPortTypeToString;
 # network_conf.h
 virNetworkAssignDef;
 virNetworkConfigFile;
+virNetworkConfigChangeSetup;
+virNetworkDefCopy;
 virNetworkDefFormat;
 virNetworkDefFree;
 virNetworkDefGetIpByIndex;
@@ -852,15 +854,21 @@ virNetworkIpDefNetmask;
 virNetworkIpDefPrefix;
 virNetworkList;
 virNetworkLoadAllConfigs;
+virNetworkObjAssignDef;
+virNetworkObjFree;
+virNetworkObjGetPersistentDef;
 virNetworkObjIsDuplicate;
 virNetworkObjListFree;
 virNetworkObjLock;
+virNetworkObjReplacePersistentDef;
+virNetworkObjSetDefTransient;
 virNetworkObjUnlock;
-virNetworkObjFree;
 virNetworkRemoveInactive;
 virNetworkSaveConfig;
+virNetworkSaveStatus;
 virNetworkSetBridgeMacAddr;
 virNetworkSetBridgeName;
+virNetworkSetDefTransient;
 virPortGroupFindByName;
 
 
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 4faad5d..8dbb050 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -2023,6 +2023,9 @@ networkStartNetwork(struct network_driver *driver,
         return -1;
     }
 
+    if (virNetworkObjSetDefTransient(network, true) < 0)
+        return -1;
+
     switch (network->def->forwardType) {
 
     case VIR_NETWORK_FORWARD_NONE:
@@ -2046,7 +2049,7 @@ networkStartNetwork(struct network_driver *driver,
     /* Persist the live configuration now that anything autogenerated
      * is setup.
      */
-    if ((ret = virNetworkSaveConfig(NETWORK_STATE_DIR, network->def)) < 0) {
+    if ((ret = virNetworkSaveStatus(NETWORK_STATE_DIR, network)) < 0) {
         goto error;
     }
 
@@ -2389,8 +2392,10 @@ static virNetworkPtr networkCreate(virConnectPtr conn, const char *xml) {
     if (networkValidate(def) < 0)
        goto cleanup;
 
-    if (!(network = virNetworkAssignDef(&driver->networks,
-                                        def)))
+    /* NB: "live" is false because this transient network hasn't yet
+     * been started
+     */
+    if (!(network = virNetworkAssignDef(&driver->networks, def, false)))
         goto cleanup;
     def = NULL;
 
@@ -2465,8 +2470,7 @@ static virNetworkPtr networkDefine(virConnectPtr conn, const char *xml) {
     if (networkValidate(def) < 0)
        goto cleanup;
 
-    if (!(network = virNetworkAssignDef(&driver->networks,
-                                        def)))
+    if (!(network = virNetworkAssignDef(&driver->networks, def, false)))
         goto cleanup;
     freeDef = false;
 
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index fbd8ed0..1bd0d61 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -579,7 +579,7 @@ static int testOpenDefault(virConnectPtr conn) {
 
     if (!(netdef = virNetworkDefParseString(defaultNetworkXML)))
         goto error;
-    if (!(netobj = virNetworkAssignDef(&privconn->networks, netdef))) {
+    if (!(netobj = virNetworkAssignDef(&privconn->networks, netdef, false))) {
         virNetworkDefFree(netdef);
         goto error;
     }
@@ -948,8 +948,7 @@ static int testOpenFromFile(virConnectPtr conn,
             if ((def = virNetworkDefParseNode(xml, networks[i])) == NULL)
                 goto error;
         }
-        if (!(net = virNetworkAssignDef(&privconn->networks,
-                                        def))) {
+        if (!(net = virNetworkAssignDef(&privconn->networks, def, false))) {
             virNetworkDefFree(def);
             goto error;
         }
@@ -3112,7 +3111,7 @@ static virNetworkPtr testNetworkCreate(virConnectPtr conn, const char *xml) {
     if ((def = virNetworkDefParseString(xml)) == NULL)
         goto cleanup;
 
-    if ((net = virNetworkAssignDef(&privconn->networks, def)) == NULL)
+    if (!(net = virNetworkAssignDef(&privconn->networks, def, false)))
         goto cleanup;
     def = NULL;
     net->active = 1;
@@ -3137,7 +3136,7 @@ static virNetworkPtr testNetworkDefine(virConnectPtr conn, const char *xml) {
     if ((def = virNetworkDefParseString(xml)) == NULL)
         goto cleanup;
 
-    if ((net = virNetworkAssignDef(&privconn->networks, def)) == NULL)
+    if (!(net = virNetworkAssignDef(&privconn->networks, def, false)))
         goto cleanup;
     def = NULL;
     net->persistent = 1;
-- 
1.7.11.4




More information about the libvir-list mailing list