diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c index d7c5dec48e..b334b64037 100644 --- a/src/conf/network_conf.c +++ b/src/conf/network_conf.c @@ -503,56 +503,109 @@ virNetworkObjAssignDef(virNetworkObjPtr network, } } +/* + * If flags & VIR_NETWORK_OBJ_LIST_ADD_CHECK_LIVE then this will + * refuse updating an existing def if the current def is live + * + * If flags & VIR_NETWORK_OBJ_LIST_ADD_LIVE then the @def being + * added is assumed to represent a live config, not a future + * inactive config + * + * If flags is zero, network is considered as inactive and persistent. + */ +static virNetworkObjPtr +virNetworkAssignDefLocked(virNetworkObjListPtr nets, + virNetworkDefPtr def, + unsigned int flags) +{ + virNetworkObjPtr network; + virNetworkObjPtr ret = NULL; + char uuidstr[VIR_UUID_STRING_BUFLEN]; + + /* See if a network with matching UUID already exists */ + if ((network = virNetworkObjFindByUUIDLocked(nets, def->uuid))) { + virObjectLock(network); + /* UUID matches, but if names don't match, refuse it */ + if (STRNEQ(network->def->name, def->name)) { + virUUIDFormat(network->def->uuid, uuidstr); + virReportError(VIR_ERR_OPERATION_FAILED, + _("network '%s' is already defined with uuid %s"), + network->def->name, uuidstr); + goto cleanup; + } + + if (flags & VIR_NETWORK_OBJ_LIST_ADD_CHECK_LIVE) { + /* UUID & name match, but if network is already active, refuse it */ + if (virNetworkObjIsActive(network)) { + virReportError(VIR_ERR_OPERATION_INVALID, + _("network is already active as '%s'"), + network->def->name); + goto cleanup; + } + } + + virNetworkObjAssignDef(network, + def, + !!(flags & VIR_NETWORK_OBJ_LIST_ADD_LIVE)); + } else { + /* UUID does not match, but if a name matches, refuse it */ + if ((network = virNetworkObjFindByNameLocked(nets, def->name))) { + virObjectLock(network); + virUUIDFormat(network->def->uuid, uuidstr); + virReportError(VIR_ERR_OPERATION_FAILED, + _("network '%s' already exists with uuid %s"), + def->name, uuidstr); + goto cleanup; + } + + if (!(network = virNetworkObjNew())) + goto cleanup; + + virObjectLock(network); + + virUUIDFormat(def->uuid, uuidstr); + if (virHashAddEntry(nets->objs, uuidstr, network) < 0) + goto cleanup; + + network->def = def; + network->persistent = !(flags & VIR_NETWORK_OBJ_LIST_ADD_LIVE); + virObjectRef(network); + } + + ret = network; + network = NULL; + + cleanup: + virNetworkObjEndAPI(&network); + return ret; +} + /* * 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 + * @flags: bitwise-OR of VIR_NETWORK_OBJ_LIST_ADD_* flags * * 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. * + * Look at virNetworkAssignDefLocked() for @flags description. + * * Returns NULL on error, virNetworkObjPtr on success. */ virNetworkObjPtr virNetworkAssignDef(virNetworkObjListPtr nets, virNetworkDefPtr def, - bool live) + unsigned int flags) { virNetworkObjPtr network; - char uuidstr[VIR_UUID_STRING_BUFLEN]; virObjectLock(nets); - if ((network = virNetworkObjFindByNameLocked(nets, def->name))) { - virObjectUnlock(nets); - virObjectLock(network); - virNetworkObjAssignDef(network, def, live); - return network; - } - - if (!(network = virNetworkObjNew())) { - virObjectUnlock(nets); - return NULL; - } - virObjectLock(network); - - virUUIDFormat(def->uuid, uuidstr); - if (virHashAddEntry(nets->objs, uuidstr, network) < 0) - goto error; - - network->def = def; - network->persistent = !live; - virObjectRef(network); + network = virNetworkAssignDefLocked(nets, def, flags); virObjectUnlock(nets); return network; - - error: - virObjectUnlock(nets); - virNetworkObjEndAPI(&network); - return NULL; - } /* @@ -3005,7 +3058,7 @@ virNetworkLoadState(virNetworkObjListPtr nets, } /* create the object */ - if (!(net = virNetworkAssignDef(nets, def, true))) + if (!(net = virNetworkAssignDef(nets, def, VIR_NETWORK_OBJ_LIST_ADD_LIVE))) goto error; /* do not put any "goto error" below this comment */ @@ -3082,7 +3135,7 @@ virNetworkObjPtr virNetworkLoadConfig(virNetworkObjListPtr nets, def->mac_specified = false; } - if (!(net = virNetworkAssignDef(nets, def, false))) + if (!(net = virNetworkAssignDef(nets, def, 0))) goto error; net->autostart = autostart; @@ -4295,68 +4348,6 @@ virNetworkObjUpdate(virNetworkObjPtr network, return ret; } -/* - * virNetworkObjIsDuplicate: - * @nets : virNetworkObjListPtr to search - * @def : virNetworkDefPtr definition of network to lookup - * @check_active: If true, ensure that network is not active - * - * Returns: -1 on error - * 0 if network is new - * 1 if network is a duplicate - */ -int -virNetworkObjIsDuplicate(virNetworkObjListPtr nets, - virNetworkDefPtr def, - bool check_active) -{ - int ret = -1; - virNetworkObjPtr net = NULL; - - /* See if a network with matching UUID already exists */ - net = virNetworkObjFindByUUID(nets, def->uuid); - if (net) { - /* UUID matches, but if names don't match, refuse it */ - if (STRNEQ(net->def->name, def->name)) { - char uuidstr[VIR_UUID_STRING_BUFLEN]; - virUUIDFormat(net->def->uuid, uuidstr); - virReportError(VIR_ERR_OPERATION_FAILED, - _("network '%s' is already defined with uuid %s"), - net->def->name, uuidstr); - goto cleanup; - } - - if (check_active) { - /* UUID & name match, but if network is already active, refuse it */ - if (virNetworkObjIsActive(net)) { - virReportError(VIR_ERR_OPERATION_INVALID, - _("network is already active as '%s'"), - net->def->name); - goto cleanup; - } - } - - ret = 1; - } else { - /* UUID does not match, but if a name matches, refuse it */ - net = virNetworkObjFindByName(nets, def->name); - if (net) { - char uuidstr[VIR_UUID_STRING_BUFLEN]; - virUUIDFormat(net->def->uuid, uuidstr); - virReportError(VIR_ERR_OPERATION_FAILED, - _("network '%s' already exists with uuid %s"), - def->name, uuidstr); - goto cleanup; - } - ret = 0; - } - - cleanup: - virNetworkObjEndAPI(&net); - return ret; -} - - #define MATCH(FLAG) (flags & (FLAG)) static bool virNetworkMatch(virNetworkObjPtr netobj, diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h index 3e926f78c5..f69d9999f3 100644 --- a/src/conf/network_conf.h +++ b/src/conf/network_conf.h @@ -316,9 +316,13 @@ void virNetworkDefFree(virNetworkDefPtr def); typedef bool (*virNetworkObjListFilter)(virConnectPtr conn, virNetworkDefPtr def); +enum { + VIR_NETWORK_OBJ_LIST_ADD_LIVE = (1 << 0), + VIR_NETWORK_OBJ_LIST_ADD_CHECK_LIVE = (1 << 1), +}; virNetworkObjPtr virNetworkAssignDef(virNetworkObjListPtr nets, virNetworkDefPtr def, - bool live); + unsigned int flags); void virNetworkObjAssignDef(virNetworkObjPtr network, virNetworkDefPtr def, bool live); @@ -414,10 +418,6 @@ virNetworkObjUpdate(virNetworkObjPtr obj, const char *xml, unsigned int flags); /* virNetworkUpdateFlags */ -int virNetworkObjIsDuplicate(virNetworkObjListPtr nets, - virNetworkDefPtr def, - bool check_active); - VIR_ENUM_DECL(virNetworkForward) # define VIR_CONNECT_LIST_NETWORKS_FILTERS_ACTIVE \ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 7c7a676a2e..8141eba983 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -573,7 +573,6 @@ virNetworkObjFindByNameLocked; virNetworkObjFindByUUID; virNetworkObjFindByUUIDLocked; virNetworkObjGetPersistentDef; -virNetworkObjIsDuplicate; virNetworkObjListExport; virNetworkObjListForEach; virNetworkObjListGetNames; diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 43b2e4ca6e..f865adc576 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -2748,8 +2748,7 @@ static int networkIsPersistent(virNetworkPtr net) static int networkValidate(virNetworkDriverStatePtr driver, - virNetworkDefPtr def, - bool check_active) + virNetworkDefPtr def) { size_t i, j; bool vlanUsed, vlanAllowed, badVlanUse = false; @@ -2759,10 +2758,6 @@ networkValidate(virNetworkDriverStatePtr driver, bool bandwidthAllowed = true; bool usesInterface = false, usesAddress = false; - /* check for duplicate networks */ - if (virNetworkObjIsDuplicate(driver->networks, def, check_active) < 0) - return -1; - /* Only the three L3 network types that are configured by libvirt * need to have a bridge device name / mac address provided */ @@ -2980,14 +2975,16 @@ static virNetworkPtr networkCreateXML(virConnectPtr conn, const char *xml) if (virNetworkCreateXMLEnsureACL(conn, def) < 0) goto cleanup; - if (networkValidate(driver, def, true) < 0) + if (networkValidate(driver, def) < 0) goto cleanup; /* NB: even though this transient network hasn't yet been started, * we assign the def with live = true in anticipation that it will * be started momentarily. */ - if (!(network = virNetworkAssignDef(driver->networks, def, true))) + if (!(network = virNetworkAssignDef(driver->networks, def, + VIR_NETWORK_OBJ_LIST_ADD_LIVE | + VIR_NETWORK_OBJ_LIST_ADD_CHECK_LIVE))) goto cleanup; def = NULL; @@ -3028,10 +3025,10 @@ static virNetworkPtr networkDefineXML(virConnectPtr conn, const char *xml) if (virNetworkDefineXMLEnsureACL(conn, def) < 0) goto cleanup; - if (networkValidate(driver, def, false) < 0) + if (networkValidate(driver, def) < 0) goto cleanup; - if (!(network = virNetworkAssignDef(driver->networks, def, false))) + if (!(network = virNetworkAssignDef(driver->networks, def, 0))) goto cleanup; /* def was assigned to network object */ diff --git a/src/parallels/parallels_network.c b/src/parallels/parallels_network.c index 8caad4a4a0..47f4886e9f 100644 --- a/src/parallels/parallels_network.c +++ b/src/parallels/parallels_network.c @@ -239,7 +239,7 @@ parallelsLoadNetwork(parallelsConnPtr privconn, virJSONValuePtr jobj) goto cleanup; } - if (!(net = virNetworkAssignDef(privconn->networks, def, false))) + if (!(net = virNetworkAssignDef(privconn->networks, def, 0))) goto cleanup; def = NULL; net->active = 1; @@ -273,7 +273,7 @@ parallelsAddRoutedNetwork(parallelsConnPtr privconn) } def->uuid_specified = 1; - if (!(net = virNetworkAssignDef(privconn->networks, def, false))) + if (!(net = virNetworkAssignDef(privconn->networks, def, 0))) goto cleanup; net->active = 1; diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 1c9d573320..07cc032b09 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -782,7 +782,7 @@ testOpenDefault(virConnectPtr conn) if (!(netdef = virNetworkDefParseString(defaultNetworkXML))) goto error; - if (!(netobj = virNetworkAssignDef(privconn->networks, netdef, false))) { + if (!(netobj = virNetworkAssignDef(privconn->networks, netdef, 0))) { virNetworkDefFree(netdef); goto error; } @@ -1149,7 +1149,7 @@ testParseNetworks(testConnPtr privconn, if (!def) goto error; - if (!(obj = virNetworkAssignDef(privconn->networks, def, false))) { + if (!(obj = virNetworkAssignDef(privconn->networks, def, 0))) { virNetworkDefFree(def); goto error; } @@ -3627,7 +3627,9 @@ static virNetworkPtr testNetworkCreateXML(virConnectPtr conn, const char *xml) if ((def = virNetworkDefParseString(xml)) == NULL) goto cleanup; - if (!(net = virNetworkAssignDef(privconn->networks, def, true))) + if (!(net = virNetworkAssignDef(privconn->networks, def, + VIR_NETWORK_OBJ_LIST_ADD_LIVE | + VIR_NETWORK_OBJ_LIST_ADD_CHECK_LIVE))) goto cleanup; def = NULL; net->active = 1; @@ -3658,7 +3660,7 @@ virNetworkPtr testNetworkDefineXML(virConnectPtr conn, const char *xml) if ((def = virNetworkDefParseString(xml)) == NULL) goto cleanup; - if (!(net = virNetworkAssignDef(privconn->networks, def, false))) + if (!(net = virNetworkAssignDef(privconn->networks, def, 0))) goto cleanup; def = NULL;