[libvirt] [PATCHv2 3/9] network: utility functions for updating network config
Daniel Veillard
veillard at redhat.com
Tue Sep 18 07:52:58 UTC 2012
On Tue, Sep 18, 2012 at 03:38:59AM -0400, Laine Stump wrote:
> 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;
Okay, this incorporate Eric's feedabck as far as I can tell, ACK
Daniel
--
Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/
daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library http://libvirt.org/
More information about the libvir-list
mailing list