[libvirt] [PATCH 3/3] network_conf: Drop virNetworkObjIsDuplicate

John Ferlan jferlan at redhat.com
Fri Mar 20 19:59:06 UTC 2015



On 03/16/2015 12:42 PM, Michal Privoznik wrote:
> This function does not make any sense now, that network driver is
> (almost) dropped. I mean, previously, when threads were
> serialized, this function was there to check, if no other network
> with the same name or UUID exists. However, nowadays that threads
> can run more in parallel, this function is useless, in fact it
> gives misleading return values. Consider the following scenario.
> Two threads, both trying to define networks with same name but
> different UUID (e.g. because it was generated during XML parsing
> phase, whatever). Lets assume that both threads are about to call
> networkValidate() which immediately calls
> virNetworkObjIsDuplicate().
> 
> T1: calls virNetworkObjIsDuplicate() and since no network with
> given name or UUID exist, success is returned.
> T2: calls virNetworkObjIsDuplicate() and since no network with
> given name or UUID exist, success is returned.
> 
> T1: calls virNetworkAssignDef() and successfully places its
> network into the virNetworkObjList.
> T2: calls virNetworkAssignDef() and since network with the same
> name exists, the network definition is replaced.
> 
> Okay, this is mainly because virNetworkAssignDef() does not check
> whether name and UUID matches. Well, lets make it so! And drop
> useless function too.
> 
> Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
> ---
>  src/conf/network_conf.c           | 171 ++++++++++++++++++--------------------
>  src/conf/network_conf.h           |  10 +--
>  src/libvirt_private.syms          |   1 -
>  src/network/bridge_driver.c       |  17 ++--
>  src/parallels/parallels_network.c |   4 +-
>  src/test/test_driver.c            |  10 ++-
>  6 files changed, 99 insertions(+), 114 deletions(-)
> 
> diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
> index d7c5dec..1fb06ef 100644
> --- a/src/conf/network_conf.c
> +++ b/src/conf/network_conf.c
> @@ -504,6 +504,81 @@ 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

s/Live/live  (or active or already running)

> + *
> + * 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 no flags is 0....

> + */
> +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)

The next line here is "@live" which is now changed - need to adjust the
comment here then too and of course describe @flags (including why
someone would pass 0) and be sure the description is "valid"


> @@ -519,40 +594,14 @@ virNetworkObjAssignDef(virNetworkObjPtr network,
>  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 +3054,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 +3131,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 +4344,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 3e926f7..f69d999 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),
> +};

Not that I'm any better at names, but the two names are very close to
each other, but the CHECK_LIVE seems to me to say it's only a CHECK.
When looking at the code/usage it seems that it's not allowing a
redefinition if the uuid/name match - so perhaps use FAIL_LIVE_REDEFINE
(or something like that)?

Although it seems

   0 == PERSISTENT
   1 = TRANSIENT
   2 = DO NOT REPLACE ALREADY DEFINED NETWORK

In any case, ACK-able with updating at least the descriptions. Changing
the enum/flag names is up to you.


John
>  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 1fb42ac..02edb75 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 b3dcadc..c3bc6fe 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 1d3b694..0711558 100644
> --- a/src/parallels/parallels_network.c
> +++ b/src/parallels/parallels_network.c
> @@ -226,7 +226,7 @@ parallelsLoadNetwork(parallelsConnPtr privconn, virJSONValuePtr jobj)
>          goto cleanup;
>      }
>  
> -    if (!(net = virNetworkAssignDef(privconn->networks, def, false)))
> +    if (!(net = virNetworkAssignDef(privconn->networks, def, 0)))
>          goto cleanup;
>      net->active = 1;
>      net->autostart = 1;
> @@ -258,7 +258,7 @@ parallelsAddRoutedNetwork(parallelsConnPtr privconn)
>      }
>      def->uuid_specified = 1;
>  
> -    if (!(net = virNetworkAssignDef(privconn->networks, def, false))) {
> +    if (!(net = virNetworkAssignDef(privconn->networks, def, 0))) {
>          virNetworkDefFree(def);
>          goto cleanup;
>      }
> diff --git a/src/test/test_driver.c b/src/test/test_driver.c
> index 1c9d573..07cc032 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;
>  
> 




More information about the libvir-list mailing list