]> xenbits.xensource.com Git - libvirt.git/commitdiff
virstorageobj: Move virStoragePoolObjSourceFindDuplicate and friends up
authorMichal Privoznik <mprivozn@redhat.com>
Fri, 17 Aug 2018 12:50:59 +0000 (14:50 +0200)
committerMichal Privoznik <mprivozn@redhat.com>
Tue, 4 Sep 2018 08:11:40 +0000 (10:11 +0200)
This function is going to be made static in used in
virStoragePoolObjAssignDef(). Therefore move it and all the
static functions it calls a few lines up.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: John Ferlan <jferlan@redhat.com>
src/conf/virstorageobj.c

index dbc3e3f57bbc5c619ea6127766a4bd553390ce01..f17f6cec6b0bd7d76d7767ca7c08e26192fb28e2 100644 (file)
@@ -1118,284 +1118,392 @@ virStoragePoolObjIsDuplicate(virStoragePoolObjListPtr pools,
 }
 
 
-/**
- * virStoragePoolObjAssignDef:
- * @pools: Storage Pool object list pointer
- * @def: Storage pool definition to add or update
- * @check_active: If true, ensure that pool is not active
- *
- * Lookup the @def to see if it already exists in the @pools in order
- * to either update or add if it does not exist.
- *
- * Returns locked and reffed object pointer or NULL on error
- */
-virStoragePoolObjPtr
-virStoragePoolObjAssignDef(virStoragePoolObjListPtr pools,
-                           virStoragePoolDefPtr def,
-                           bool check_active)
+static int
+getSCSIHostNumber(virStorageAdapterSCSIHostPtr scsi_host,
+                  unsigned int *hostnum)
 {
-    virStoragePoolObjPtr obj = NULL;
-    char uuidstr[VIR_UUID_STRING_BUFLEN];
-    int rc;
-
-    virObjectRWLockWrite(pools);
+    int ret = -1;
+    unsigned int num;
+    char *name = NULL;
 
-    rc = virStoragePoolObjIsDuplicate(pools, def, check_active, &obj);
+    if (scsi_host->has_parent) {
+        virPCIDeviceAddressPtr addr = &scsi_host->parentaddr;
+        unsigned int unique_id = scsi_host->unique_id;
 
-    if (rc < 0)
-        goto error;
-    if (rc > 0) {
-        if (!virStoragePoolObjIsActive(obj)) {
-            virStoragePoolDefFree(obj->def);
-            obj->def = def;
-        } else {
-            virStoragePoolDefFree(obj->newDef);
-            obj->newDef = def;
-        }
-        virObjectRWUnlock(pools);
-        return obj;
+        if (!(name = virSCSIHostGetNameByParentaddr(addr->domain,
+                                                    addr->bus,
+                                                    addr->slot,
+                                                    addr->function,
+                                                    unique_id)))
+            goto cleanup;
+        if (virSCSIHostGetNumber(name, &num) < 0)
+            goto cleanup;
+    } else {
+        if (virSCSIHostGetNumber(scsi_host->name, &num) < 0)
+            goto cleanup;
     }
 
-    if (!(obj = virStoragePoolObjNew()))
-        goto error;
+    *hostnum = num;
+    ret = 0;
 
-    virUUIDFormat(def->uuid, uuidstr);
-    if (virHashAddEntry(pools->objs, uuidstr, obj) < 0)
-        goto error;
-    virObjectRef(obj);
+ cleanup:
+    VIR_FREE(name);
+    return ret;
+}
 
-    if (virHashAddEntry(pools->objsName, def->name, obj) < 0) {
-        virHashRemoveEntry(pools->objs, uuidstr);
-        goto error;
-    }
-    virObjectRef(obj);
-    obj->def = def;
-    virObjectRWUnlock(pools);
-    return obj;
 
- error:
-    virStoragePoolObjEndAPI(&obj);
-    virObjectRWUnlock(pools);
-    return NULL;
+static bool
+virStorageIsSameHostnum(const char *name,
+                        unsigned int scsi_hostnum)
+{
+    unsigned int fc_hostnum;
+
+    if (virSCSIHostGetNumber(name, &fc_hostnum) == 0 &&
+        scsi_hostnum == fc_hostnum)
+        return true;
+
+    return false;
 }
 
 
-static virStoragePoolObjPtr
-virStoragePoolObjLoad(virStoragePoolObjListPtr pools,
-                      const char *file,
-                      const char *path,
-                      const char *autostartLink)
+/*
+ * matchFCHostToSCSIHost:
+ *
+ * @conn: Connection pointer
+ * @fchost: fc_host adapter ptr (either def or pool->def)
+ * @scsi_hostnum: Already determined "scsi_pool" hostnum
+ *
+ * Returns true/false whether there is a match between the incoming
+ *         fc_adapter host# and the scsi_host host#
+ */
+static bool
+matchFCHostToSCSIHost(virConnectPtr conn,
+                      virStorageAdapterFCHostPtr fchost,
+                      unsigned int scsi_hostnum)
 {
-    virStoragePoolDefPtr def;
-    virStoragePoolObjPtr obj;
+    bool ret = false;
+    char *name = NULL;
+    char *scsi_host_name = NULL;
+    char *parent_name = NULL;
 
-    if (!(def = virStoragePoolDefParseFile(path)))
-        return NULL;
+    /* If we have a parent defined, get its hostnum, and compare to the
+     * scsi_hostnum. If they are the same, then we have a match
+     */
+    if (fchost->parent &&
+        virStorageIsSameHostnum(fchost->parent, scsi_hostnum))
+        return true;
 
-    if (!virFileMatchesNameSuffix(file, def->name, ".xml")) {
-        virReportError(VIR_ERR_XML_ERROR,
-                       _("Storage pool config filename '%s' does "
-                         "not match pool name '%s'"),
-                       path, def->name);
-        virStoragePoolDefFree(def);
-        return NULL;
-    }
+    /* If we find an fc adapter name, then either libvirt created a vHBA
+     * for this fc_host or a 'virsh nodedev-create' generated a vHBA.
+     */
+    if ((name = virVHBAGetHostByWWN(NULL, fchost->wwnn, fchost->wwpn))) {
 
-    if (!(obj = virStoragePoolObjAssignDef(pools, def, false))) {
-        virStoragePoolDefFree(def);
-        return NULL;
-    }
+        /* Get the scsi_hostN for the vHBA in order to see if it
+         * matches our scsi_hostnum
+         */
+        if (virStorageIsSameHostnum(name, scsi_hostnum)) {
+            ret = true;
+            goto cleanup;
+        }
 
-    VIR_FREE(obj->configFile);  /* for driver reload */
-    if (VIR_STRDUP(obj->configFile, path) < 0) {
-        virStoragePoolObjRemove(pools, obj);
-        virObjectUnref(obj);
-        return NULL;
-    }
-    VIR_FREE(obj->autostartLink); /* for driver reload */
-    if (VIR_STRDUP(obj->autostartLink, autostartLink) < 0) {
-        virStoragePoolObjRemove(pools, obj);
-        virObjectUnref(obj);
-        return NULL;
+        /* We weren't provided a parent, so we have to query the node
+         * device driver in order to ascertain the parent of the vHBA.
+         * If the parent fc_hostnum is the same as the scsi_hostnum, we
+         * have a match.
+         */
+        if (conn && !fchost->parent) {
+            if (virAsprintf(&scsi_host_name, "scsi_%s", name) < 0)
+                goto cleanup;
+            if ((parent_name = virNodeDeviceGetParentName(conn,
+                                                          scsi_host_name))) {
+                if (virStorageIsSameHostnum(parent_name, scsi_hostnum)) {
+                    ret = true;
+                    goto cleanup;
+                }
+            } else {
+                /* Throw away the error and fall through */
+                virResetLastError();
+                VIR_DEBUG("Could not determine parent vHBA");
+            }
+        }
     }
 
-    obj->autostart = virFileLinkPointsTo(obj->autostartLink,
-                                         obj->configFile);
+    /* NB: Lack of a name means that this vHBA hasn't yet been created,
+     *     which means our scsi_host cannot be using the vHBA. Furthermore,
+     *     lack of a provided parent means libvirt is going to choose the
+     *     "best" fc_host capable adapter based on availabilty. That could
+     *     conflict with an existing scsi_host definition, but there's no
+     *     way to know that now.
+     */
 
-    return obj;
+ cleanup:
+    VIR_FREE(name);
+    VIR_FREE(parent_name);
+    VIR_FREE(scsi_host_name);
+    return ret;
 }
 
 
-static virStoragePoolObjPtr
-virStoragePoolObjLoadState(virStoragePoolObjListPtr pools,
-                           const char *stateDir,
-                           const char *name)
+static bool
+matchSCSIAdapterParent(virStorageAdapterSCSIHostPtr pool_scsi_host,
+                       virStorageAdapterSCSIHostPtr def_scsi_host)
 {
-    char *stateFile = NULL;
-    virStoragePoolDefPtr def = NULL;
-    virStoragePoolObjPtr obj = NULL;
-    xmlDocPtr xml = NULL;
-    xmlXPathContextPtr ctxt = NULL;
-    xmlNodePtr node = NULL;
+    virPCIDeviceAddressPtr pooladdr = &pool_scsi_host->parentaddr;
+    virPCIDeviceAddressPtr defaddr = &def_scsi_host->parentaddr;
 
-    if (!(stateFile = virFileBuildPath(stateDir, name, ".xml")))
-        goto error;
+    if (pooladdr->domain == defaddr->domain &&
+        pooladdr->bus == defaddr->bus &&
+        pooladdr->slot == defaddr->slot &&
+        pooladdr->function == defaddr->function &&
+        pool_scsi_host->unique_id == def_scsi_host->unique_id)
+        return true;
 
-    if (!(xml = virXMLParseCtxt(stateFile, NULL, _("(pool state)"), &ctxt)))
-        goto error;
+    return false;
+}
 
-    if (!(node = virXPathNode("//pool", ctxt))) {
-        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                       _("Could not find any 'pool' element in state file"));
-        goto error;
-    }
 
-    ctxt->node = node;
-    if (!(def = virStoragePoolDefParseXML(ctxt)))
-        goto error;
+static bool
+virStoragePoolSourceMatchSingleHost(virStoragePoolSourcePtr poolsrc,
+                                    virStoragePoolSourcePtr defsrc)
+{
+    if (poolsrc->nhost != 1 && defsrc->nhost != 1)
+        return false;
 
-    if (STRNEQ(name, def->name)) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Storage pool state file '%s' does not match "
-                         "pool name '%s'"),
-                       stateFile, def->name);
-        goto error;
-    }
+    if (defsrc->hosts[0].port &&
+        poolsrc->hosts[0].port != defsrc->hosts[0].port)
+        return false;
 
-    /* create the object */
-    if (!(obj = virStoragePoolObjAssignDef(pools, def, true)))
-        goto error;
+    return STREQ(poolsrc->hosts[0].name, defsrc->hosts[0].name);
+}
 
-    /* XXX: future handling of some additional useful status data,
-     * for now, if a status file for a pool exists, the pool will be marked
-     * as active
-     */
 
-    obj->active = true;
+static bool
+virStoragePoolSourceISCSIMatch(virStoragePoolObjPtr obj,
+                               virStoragePoolDefPtr def)
+{
+    virStoragePoolSourcePtr poolsrc = &obj->def->source;
+    virStoragePoolSourcePtr defsrc = &def->source;
 
- cleanup:
-    VIR_FREE(stateFile);
-    xmlFreeDoc(xml);
-    xmlXPathFreeContext(ctxt);
-    return obj;
+    /* NB: Do not check the source host name */
+    if (STRNEQ_NULLABLE(poolsrc->initiator.iqn, defsrc->initiator.iqn))
+        return false;
 
- error:
-    virStoragePoolDefFree(def);
-    goto cleanup;
+    return true;
 }
 
 
-int
-virStoragePoolObjLoadAllState(virStoragePoolObjListPtr pools,
-                              const char *stateDir)
+static virStoragePoolObjPtr
+virStoragePoolObjSourceMatchTypeDIR(virStoragePoolObjPtr obj,
+                                    virStoragePoolDefPtr def)
 {
-    DIR *dir;
-    struct dirent *entry;
-    int ret = -1;
-    int rc;
+    if (obj->def->type == VIR_STORAGE_POOL_DIR) {
+        if (STREQ(obj->def->target.path, def->target.path))
+            return obj;
+    } else if (obj->def->type == VIR_STORAGE_POOL_GLUSTER) {
+        if (STREQ(obj->def->source.name, def->source.name) &&
+            STREQ_NULLABLE(obj->def->source.dir, def->source.dir) &&
+            virStoragePoolSourceMatchSingleHost(&obj->def->source,
+                                                &def->source))
+            return obj;
+    } else if (obj->def->type == VIR_STORAGE_POOL_NETFS) {
+        if (STREQ(obj->def->source.dir, def->source.dir) &&
+            virStoragePoolSourceMatchSingleHost(&obj->def->source,
+                                                &def->source))
+            return obj;
+    }
 
-    if ((rc = virDirOpenIfExists(&dir, stateDir)) <= 0)
-        return rc;
+    return NULL;
+}
 
-    while ((ret = virDirRead(dir, &entry, stateDir)) > 0) {
-        virStoragePoolObjPtr obj;
 
-        if (!virFileStripSuffix(entry->d_name, ".xml"))
-            continue;
+static virStoragePoolObjPtr
+virStoragePoolObjSourceMatchTypeISCSI(virStoragePoolObjPtr obj,
+                                      virStoragePoolDefPtr def,
+                                      virConnectPtr conn)
+{
+    virStorageAdapterPtr pool_adapter = &obj->def->source.adapter;
+    virStorageAdapterPtr def_adapter = &def->source.adapter;
+    virStorageAdapterSCSIHostPtr pool_scsi_host;
+    virStorageAdapterSCSIHostPtr def_scsi_host;
+    virStorageAdapterFCHostPtr pool_fchost;
+    virStorageAdapterFCHostPtr def_fchost;
+    unsigned int pool_hostnum;
+    unsigned int def_hostnum;
+    unsigned int scsi_hostnum;
 
-        if (!(obj = virStoragePoolObjLoadState(pools, stateDir, entry->d_name)))
-            continue;
-        virStoragePoolObjEndAPI(&obj);
+    if (pool_adapter->type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST &&
+        def_adapter->type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST) {
+        pool_fchost = &pool_adapter->data.fchost;
+        def_fchost = &def_adapter->data.fchost;
+
+        if (STREQ(pool_fchost->wwnn, def_fchost->wwnn) &&
+            STREQ(pool_fchost->wwpn, def_fchost->wwpn))
+            return obj;
+    } else if (pool_adapter->type == VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST &&
+               def_adapter->type == VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST) {
+        pool_scsi_host = &pool_adapter->data.scsi_host;
+        def_scsi_host = &def_adapter->data.scsi_host;
+
+        if (pool_scsi_host->has_parent &&
+            def_scsi_host->has_parent &&
+            matchSCSIAdapterParent(pool_scsi_host, def_scsi_host))
+            return obj;
+
+        if (getSCSIHostNumber(pool_scsi_host, &pool_hostnum) < 0 ||
+            getSCSIHostNumber(def_scsi_host, &def_hostnum) < 0)
+            return NULL;
+        if (pool_hostnum == def_hostnum)
+            return obj;
+    } else if (pool_adapter->type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST &&
+               def_adapter->type == VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST) {
+        pool_fchost = &pool_adapter->data.fchost;
+        def_scsi_host = &def_adapter->data.scsi_host;
+
+        /* Get the scsi_hostN for the scsi_host source adapter def */
+        if (getSCSIHostNumber(def_scsi_host, &scsi_hostnum) < 0)
+            return NULL;
+
+        if (matchFCHostToSCSIHost(conn, pool_fchost, scsi_hostnum))
+            return obj;
+
+    } else if (pool_adapter->type == VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST &&
+               def_adapter->type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST) {
+        pool_scsi_host = &pool_adapter->data.scsi_host;
+        def_fchost = &def_adapter->data.fchost;
+
+        if (getSCSIHostNumber(pool_scsi_host, &scsi_hostnum) < 0)
+            return NULL;
+
+        if (matchFCHostToSCSIHost(conn, def_fchost, scsi_hostnum))
+            return obj;
     }
 
-    VIR_DIR_CLOSE(dir);
-    return ret;
+    return NULL;
 }
 
 
-int
-virStoragePoolObjLoadAllConfigs(virStoragePoolObjListPtr pools,
-                                const char *configDir,
-                                const char *autostartDir)
+static virStoragePoolObjPtr
+virStoragePoolObjSourceMatchTypeDEVICE(virStoragePoolObjPtr obj,
+                                       virStoragePoolDefPtr def)
 {
-    DIR *dir;
-    struct dirent *entry;
-    int ret;
-    int rc;
+    virStoragePoolObjPtr matchobj = NULL;
 
-    if ((rc = virDirOpenIfExists(&dir, configDir)) <= 0)
-        return rc;
+    if (obj->def->type == VIR_STORAGE_POOL_ISCSI) {
+        if (def->type != VIR_STORAGE_POOL_ISCSI)
+            return NULL;
 
-    while ((ret = virDirRead(dir, &entry, configDir)) > 0) {
-        char *path;
-        char *autostartLink;
-        virStoragePoolObjPtr obj;
+        if ((matchobj = virStoragePoolSourceFindDuplicateDevices(obj, def))) {
+            if (!virStoragePoolSourceISCSIMatch(matchobj, def))
+                return NULL;
+        }
+        return matchobj;
+    }
 
-        if (!virFileHasSuffix(entry->d_name, ".xml"))
-            continue;
+    if (def->type == VIR_STORAGE_POOL_ISCSI)
+        return NULL;
 
-        if (!(path = virFileBuildPath(configDir, entry->d_name, NULL)))
-            continue;
+    /* VIR_STORAGE_POOL_FS
+     * VIR_STORAGE_POOL_LOGICAL
+     * VIR_STORAGE_POOL_DISK
+     * VIR_STORAGE_POOL_ZFS */
+    return virStoragePoolSourceFindDuplicateDevices(obj, def);
+}
 
-        if (!(autostartLink = virFileBuildPath(autostartDir, entry->d_name,
-                                               NULL))) {
-            VIR_FREE(path);
-            continue;
-        }
 
-        obj = virStoragePoolObjLoad(pools, entry->d_name, path, autostartLink);
-        virStoragePoolObjEndAPI(&obj);
+struct _virStoragePoolObjFindDuplicateData {
+    virConnectPtr conn;
+    virStoragePoolDefPtr def;
+};
 
-        VIR_FREE(path);
-        VIR_FREE(autostartLink);
-    }
+static int
+virStoragePoolObjSourceFindDuplicateCb(const void *payload,
+                                       const void *name ATTRIBUTE_UNUSED,
+                                       const void *opaque)
+{
+    virStoragePoolObjPtr obj = (virStoragePoolObjPtr) payload;
+    struct _virStoragePoolObjFindDuplicateData *data =
+        (struct _virStoragePoolObjFindDuplicateData *) opaque;
 
-    VIR_DIR_CLOSE(dir);
-    return ret;
-}
+    /* Don't match against ourself if re-defining existing pool ! */
+    if (STREQ(obj->def->name, data->def->name))
+        return 0;
+
+    switch ((virStoragePoolType)obj->def->type) {
+    case VIR_STORAGE_POOL_DIR:
+    case VIR_STORAGE_POOL_GLUSTER:
+    case VIR_STORAGE_POOL_NETFS:
+        if (data->def->type == obj->def->type &&
+            virStoragePoolObjSourceMatchTypeDIR(obj, data->def))
+            return 1;
+        break;
+
+    case VIR_STORAGE_POOL_SCSI:
+        if (data->def->type == obj->def->type &&
+            virStoragePoolObjSourceMatchTypeISCSI(obj, data->def, data->conn))
+            return 1;
+        break;
+
+    case VIR_STORAGE_POOL_ISCSI:
+    case VIR_STORAGE_POOL_ISCSI_DIRECT:
+    case VIR_STORAGE_POOL_FS:
+    case VIR_STORAGE_POOL_LOGICAL:
+    case VIR_STORAGE_POOL_DISK:
+    case VIR_STORAGE_POOL_ZFS:
+        if ((data->def->type == VIR_STORAGE_POOL_ISCSI ||
+             data->def->type == VIR_STORAGE_POOL_ISCSI_DIRECT ||
+             data->def->type == VIR_STORAGE_POOL_FS ||
+             data->def->type == VIR_STORAGE_POOL_LOGICAL ||
+             data->def->type == VIR_STORAGE_POOL_DISK ||
+             data->def->type == VIR_STORAGE_POOL_ZFS) &&
+            virStoragePoolObjSourceMatchTypeDEVICE(obj, data->def))
+            return 1;
+        break;
 
+    case VIR_STORAGE_POOL_SHEEPDOG:
+        if (data->def->type == obj->def->type &&
+            virStoragePoolSourceMatchSingleHost(&obj->def->source,
+                                                &data->def->source))
+            return 1;
+        break;
 
-int
-virStoragePoolObjSaveDef(virStorageDriverStatePtr driver,
-                         virStoragePoolObjPtr obj,
-                         virStoragePoolDefPtr def)
-{
-    if (!obj->configFile) {
-        if (virFileMakePath(driver->configDir) < 0) {
-            virReportSystemError(errno,
-                                 _("cannot create config directory %s"),
-                                 driver->configDir);
-            return -1;
-        }
+    case VIR_STORAGE_POOL_MPATH:
+        /* Only one mpath pool is valid per host */
+        if (data->def->type == obj->def->type)
+            return 1;
+        break;
 
-        if (!(obj->configFile = virFileBuildPath(driver->configDir,
-                                                 def->name, ".xml"))) {
-            return -1;
-        }
+    case VIR_STORAGE_POOL_VSTORAGE:
+        if (data->def->type == obj->def->type &&
+            STREQ(obj->def->source.name, data->def->source.name))
+            return 1;
+        break;
 
-        if (!(obj->autostartLink = virFileBuildPath(driver->autostartDir,
-                                                    def->name, ".xml"))) {
-            VIR_FREE(obj->configFile);
-            return -1;
-        }
+    case VIR_STORAGE_POOL_RBD:
+    case VIR_STORAGE_POOL_LAST:
+        break;
     }
 
-    return virStoragePoolSaveConfig(obj->configFile, def);
+    return 0;
 }
 
 
 int
-virStoragePoolObjDeleteDef(virStoragePoolObjPtr obj)
+virStoragePoolObjSourceFindDuplicate(virConnectPtr conn,
+                                     virStoragePoolObjListPtr pools,
+                                     virStoragePoolDefPtr def)
 {
-    if (!obj->configFile) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("no config file for %s"), obj->def->name);
-        return -1;
-    }
+    struct _virStoragePoolObjFindDuplicateData data = { .conn = conn,
+                                                        .def = def };
+    virStoragePoolObjPtr obj = NULL;
 
-    if (unlink(obj->configFile) < 0) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("cannot remove config for %s"),
+    virObjectRWLockRead(pools);
+    obj = virHashSearch(pools->objs, virStoragePoolObjSourceFindDuplicateCb,
+                        &data, NULL);
+    virObjectRWUnlock(pools);
+
+    if (obj) {
+        virReportError(VIR_ERR_OPERATION_FAILED,
+                       _("Storage source conflict with pool: '%s'"),
                        obj->def->name);
         return -1;
     }
@@ -1404,522 +1512,414 @@ virStoragePoolObjDeleteDef(virStoragePoolObjPtr obj)
 }
 
 
-struct _virStoragePoolCountData {
-    virConnectPtr conn;
-    virStoragePoolObjListACLFilter filter;
-    bool wantActive;
-    int count;
-};
-
-
-static int
-virStoragePoolObjNumOfStoragePoolsCb(void *payload,
-                                     const void *name ATTRIBUTE_UNUSED,
-                                     void *opaque)
+/**
+ * virStoragePoolObjAssignDef:
+ * @pools: Storage Pool object list pointer
+ * @def: Storage pool definition to add or update
+ * @check_active: If true, ensure that pool is not active
+ *
+ * Lookup the @def to see if it already exists in the @pools in order
+ * to either update or add if it does not exist.
+ *
+ * Returns locked and reffed object pointer or NULL on error
+ */
+virStoragePoolObjPtr
+virStoragePoolObjAssignDef(virStoragePoolObjListPtr pools,
+                           virStoragePoolDefPtr def,
+                           bool check_active)
 {
-    virStoragePoolObjPtr obj = payload;
-    struct _virStoragePoolCountData *data = opaque;
-
-    virObjectLock(obj);
-
-    if (data->filter && !data->filter(data->conn, obj->def))
-        goto cleanup;
+    virStoragePoolObjPtr obj = NULL;
+    char uuidstr[VIR_UUID_STRING_BUFLEN];
+    int rc;
 
-    if (data->wantActive != virStoragePoolObjIsActive(obj))
-        goto cleanup;
+    virObjectRWLockWrite(pools);
 
-    data->count++;
+    rc = virStoragePoolObjIsDuplicate(pools, def, check_active, &obj);
 
- cleanup:
-    virObjectUnlock(obj);
-    return 0;
-}
+    if (rc < 0)
+        goto error;
+    if (rc > 0) {
+        if (!virStoragePoolObjIsActive(obj)) {
+            virStoragePoolDefFree(obj->def);
+            obj->def = def;
+        } else {
+            virStoragePoolDefFree(obj->newDef);
+            obj->newDef = def;
+        }
+        virObjectRWUnlock(pools);
+        return obj;
+    }
 
+    if (!(obj = virStoragePoolObjNew()))
+        goto error;
 
-int
-virStoragePoolObjNumOfStoragePools(virStoragePoolObjListPtr pools,
-                                   virConnectPtr conn,
-                                   bool wantActive,
-                                   virStoragePoolObjListACLFilter filter)
-{
-    struct _virStoragePoolCountData data = {
-        .conn = conn, .filter = filter, .wantActive = wantActive, .count = 0 };
+    virUUIDFormat(def->uuid, uuidstr);
+    if (virHashAddEntry(pools->objs, uuidstr, obj) < 0)
+        goto error;
+    virObjectRef(obj);
 
-    virObjectRWLockRead(pools);
-    virHashForEach(pools->objs, virStoragePoolObjNumOfStoragePoolsCb, &data);
+    if (virHashAddEntry(pools->objsName, def->name, obj) < 0) {
+        virHashRemoveEntry(pools->objs, uuidstr);
+        goto error;
+    }
+    virObjectRef(obj);
+    obj->def = def;
     virObjectRWUnlock(pools);
+    return obj;
 
-    return data.count;
+ error:
+    virStoragePoolObjEndAPI(&obj);
+    virObjectRWUnlock(pools);
+    return NULL;
 }
 
 
-struct _virStoragePoolNameData {
-    virConnectPtr conn;
-    virStoragePoolObjListACLFilter filter;
-    bool wantActive;
-    bool error;
-    int nnames;
-    int maxnames;
-    char **const names;
-};
-
-
-static int
-virStoragePoolObjGetNamesCb(void *payload,
-                            const void *name ATTRIBUTE_UNUSED,
-                            void *opaque)
+static virStoragePoolObjPtr
+virStoragePoolObjLoad(virStoragePoolObjListPtr pools,
+                      const char *file,
+                      const char *path,
+                      const char *autostartLink)
 {
-    virStoragePoolObjPtr obj = payload;
-    struct _virStoragePoolNameData *data = opaque;
-
-    if (data->error)
-        return 0;
-
-    if (data->maxnames >= 0 && data->nnames == data->maxnames)
-        return 0;
+    virStoragePoolDefPtr def;
+    virStoragePoolObjPtr obj;
 
-    virObjectLock(obj);
+    if (!(def = virStoragePoolDefParseFile(path)))
+        return NULL;
 
-    if (data->filter && !data->filter(data->conn, obj->def))
-        goto cleanup;
+    if (!virFileMatchesNameSuffix(file, def->name, ".xml")) {
+        virReportError(VIR_ERR_XML_ERROR,
+                       _("Storage pool config filename '%s' does "
+                         "not match pool name '%s'"),
+                       path, def->name);
+        virStoragePoolDefFree(def);
+        return NULL;
+    }
 
-    if (data->wantActive != virStoragePoolObjIsActive(obj))
-        goto cleanup;
+    if (!(obj = virStoragePoolObjAssignDef(pools, def, false))) {
+        virStoragePoolDefFree(def);
+        return NULL;
+    }
 
-    if (data->names) {
-        if (VIR_STRDUP(data->names[data->nnames], obj->def->name) < 0) {
-            data->error = true;
-            goto cleanup;
-        }
+    VIR_FREE(obj->configFile);  /* for driver reload */
+    if (VIR_STRDUP(obj->configFile, path) < 0) {
+        virStoragePoolObjRemove(pools, obj);
+        virObjectUnref(obj);
+        return NULL;
+    }
+    VIR_FREE(obj->autostartLink); /* for driver reload */
+    if (VIR_STRDUP(obj->autostartLink, autostartLink) < 0) {
+        virStoragePoolObjRemove(pools, obj);
+        virObjectUnref(obj);
+        return NULL;
     }
 
-    data->nnames++;
+    obj->autostart = virFileLinkPointsTo(obj->autostartLink,
+                                         obj->configFile);
 
- cleanup:
-    virObjectUnlock(obj);
-    return 0;
+    return obj;
 }
 
 
-int
-virStoragePoolObjGetNames(virStoragePoolObjListPtr pools,
-                          virConnectPtr conn,
-                          bool wantActive,
-                          virStoragePoolObjListACLFilter filter,
-                          char **const names,
-                          int maxnames)
+static virStoragePoolObjPtr
+virStoragePoolObjLoadState(virStoragePoolObjListPtr pools,
+                           const char *stateDir,
+                           const char *name)
 {
-    struct _virStoragePoolNameData data = {
-        .conn = conn, .filter = filter, .wantActive = wantActive,
-        .error = false, .nnames = 0, .maxnames = maxnames, .names = names };
-
-    virObjectRWLockRead(pools);
-    virHashForEach(pools->objs, virStoragePoolObjGetNamesCb, &data);
-    virObjectRWUnlock(pools);
-
-    if (data.error)
-        goto error;
-
-    return data.nnames;
+    char *stateFile = NULL;
+    virStoragePoolDefPtr def = NULL;
+    virStoragePoolObjPtr obj = NULL;
+    xmlDocPtr xml = NULL;
+    xmlXPathContextPtr ctxt = NULL;
+    xmlNodePtr node = NULL;
 
- error:
-    while (data.nnames)
-        VIR_FREE(data.names[--data.nnames]);
-    return -1;
-}
+    if (!(stateFile = virFileBuildPath(stateDir, name, ".xml")))
+        goto error;
 
+    if (!(xml = virXMLParseCtxt(stateFile, NULL, _("(pool state)"), &ctxt)))
+        goto error;
 
-static int
-getSCSIHostNumber(virStorageAdapterSCSIHostPtr scsi_host,
-                  unsigned int *hostnum)
-{
-    int ret = -1;
-    unsigned int num;
-    char *name = NULL;
+    if (!(node = virXPathNode("//pool", ctxt))) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Could not find any 'pool' element in state file"));
+        goto error;
+    }
 
-    if (scsi_host->has_parent) {
-        virPCIDeviceAddressPtr addr = &scsi_host->parentaddr;
-        unsigned int unique_id = scsi_host->unique_id;
+    ctxt->node = node;
+    if (!(def = virStoragePoolDefParseXML(ctxt)))
+        goto error;
 
-        if (!(name = virSCSIHostGetNameByParentaddr(addr->domain,
-                                                    addr->bus,
-                                                    addr->slot,
-                                                    addr->function,
-                                                    unique_id)))
-            goto cleanup;
-        if (virSCSIHostGetNumber(name, &num) < 0)
-            goto cleanup;
-    } else {
-        if (virSCSIHostGetNumber(scsi_host->name, &num) < 0)
-            goto cleanup;
+    if (STRNEQ(name, def->name)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Storage pool state file '%s' does not match "
+                         "pool name '%s'"),
+                       stateFile, def->name);
+        goto error;
     }
 
-    *hostnum = num;
-    ret = 0;
-
- cleanup:
-    VIR_FREE(name);
-    return ret;
-}
+    /* create the object */
+    if (!(obj = virStoragePoolObjAssignDef(pools, def, true)))
+        goto error;
 
+    /* XXX: future handling of some additional useful status data,
+     * for now, if a status file for a pool exists, the pool will be marked
+     * as active
+     */
 
-static bool
-virStorageIsSameHostnum(const char *name,
-                        unsigned int scsi_hostnum)
-{
-    unsigned int fc_hostnum;
+    obj->active = true;
 
-    if (virSCSIHostGetNumber(name, &fc_hostnum) == 0 &&
-        scsi_hostnum == fc_hostnum)
-        return true;
+ cleanup:
+    VIR_FREE(stateFile);
+    xmlFreeDoc(xml);
+    xmlXPathFreeContext(ctxt);
+    return obj;
 
-    return false;
+ error:
+    virStoragePoolDefFree(def);
+    goto cleanup;
 }
 
 
-/*
- * matchFCHostToSCSIHost:
- *
- * @conn: Connection pointer
- * @fchost: fc_host adapter ptr (either def or pool->def)
- * @scsi_hostnum: Already determined "scsi_pool" hostnum
- *
- * Returns true/false whether there is a match between the incoming
- *         fc_adapter host# and the scsi_host host#
- */
-static bool
-matchFCHostToSCSIHost(virConnectPtr conn,
-                      virStorageAdapterFCHostPtr fchost,
-                      unsigned int scsi_hostnum)
+int
+virStoragePoolObjLoadAllState(virStoragePoolObjListPtr pools,
+                              const char *stateDir)
 {
-    bool ret = false;
-    char *name = NULL;
-    char *scsi_host_name = NULL;
-    char *parent_name = NULL;
+    DIR *dir;
+    struct dirent *entry;
+    int ret = -1;
+    int rc;
 
-    /* If we have a parent defined, get its hostnum, and compare to the
-     * scsi_hostnum. If they are the same, then we have a match
-     */
-    if (fchost->parent &&
-        virStorageIsSameHostnum(fchost->parent, scsi_hostnum))
-        return true;
+    if ((rc = virDirOpenIfExists(&dir, stateDir)) <= 0)
+        return rc;
 
-    /* If we find an fc adapter name, then either libvirt created a vHBA
-     * for this fc_host or a 'virsh nodedev-create' generated a vHBA.
-     */
-    if ((name = virVHBAGetHostByWWN(NULL, fchost->wwnn, fchost->wwpn))) {
+    while ((ret = virDirRead(dir, &entry, stateDir)) > 0) {
+        virStoragePoolObjPtr obj;
 
-        /* Get the scsi_hostN for the vHBA in order to see if it
-         * matches our scsi_hostnum
-         */
-        if (virStorageIsSameHostnum(name, scsi_hostnum)) {
-            ret = true;
-            goto cleanup;
-        }
+        if (!virFileStripSuffix(entry->d_name, ".xml"))
+            continue;
 
-        /* We weren't provided a parent, so we have to query the node
-         * device driver in order to ascertain the parent of the vHBA.
-         * If the parent fc_hostnum is the same as the scsi_hostnum, we
-         * have a match.
-         */
-        if (conn && !fchost->parent) {
-            if (virAsprintf(&scsi_host_name, "scsi_%s", name) < 0)
-                goto cleanup;
-            if ((parent_name = virNodeDeviceGetParentName(conn,
-                                                          scsi_host_name))) {
-                if (virStorageIsSameHostnum(parent_name, scsi_hostnum)) {
-                    ret = true;
-                    goto cleanup;
-                }
-            } else {
-                /* Throw away the error and fall through */
-                virResetLastError();
-                VIR_DEBUG("Could not determine parent vHBA");
-            }
-        }
+        if (!(obj = virStoragePoolObjLoadState(pools, stateDir, entry->d_name)))
+            continue;
+        virStoragePoolObjEndAPI(&obj);
     }
 
-    /* NB: Lack of a name means that this vHBA hasn't yet been created,
-     *     which means our scsi_host cannot be using the vHBA. Furthermore,
-     *     lack of a provided parent means libvirt is going to choose the
-     *     "best" fc_host capable adapter based on availabilty. That could
-     *     conflict with an existing scsi_host definition, but there's no
-     *     way to know that now.
-     */
-
- cleanup:
-    VIR_FREE(name);
-    VIR_FREE(parent_name);
-    VIR_FREE(scsi_host_name);
+    VIR_DIR_CLOSE(dir);
     return ret;
 }
 
 
-static bool
-matchSCSIAdapterParent(virStorageAdapterSCSIHostPtr pool_scsi_host,
-                       virStorageAdapterSCSIHostPtr def_scsi_host)
+int
+virStoragePoolObjLoadAllConfigs(virStoragePoolObjListPtr pools,
+                                const char *configDir,
+                                const char *autostartDir)
 {
-    virPCIDeviceAddressPtr pooladdr = &pool_scsi_host->parentaddr;
-    virPCIDeviceAddressPtr defaddr = &def_scsi_host->parentaddr;
-
-    if (pooladdr->domain == defaddr->domain &&
-        pooladdr->bus == defaddr->bus &&
-        pooladdr->slot == defaddr->slot &&
-        pooladdr->function == defaddr->function &&
-        pool_scsi_host->unique_id == def_scsi_host->unique_id)
-        return true;
-
-    return false;
-}
+    DIR *dir;
+    struct dirent *entry;
+    int ret;
+    int rc;
 
+    if ((rc = virDirOpenIfExists(&dir, configDir)) <= 0)
+        return rc;
 
-static bool
-virStoragePoolSourceMatchSingleHost(virStoragePoolSourcePtr poolsrc,
-                                    virStoragePoolSourcePtr defsrc)
-{
-    if (poolsrc->nhost != 1 && defsrc->nhost != 1)
-        return false;
+    while ((ret = virDirRead(dir, &entry, configDir)) > 0) {
+        char *path;
+        char *autostartLink;
+        virStoragePoolObjPtr obj;
 
-    if (defsrc->hosts[0].port &&
-        poolsrc->hosts[0].port != defsrc->hosts[0].port)
-        return false;
+        if (!virFileHasSuffix(entry->d_name, ".xml"))
+            continue;
 
-    return STREQ(poolsrc->hosts[0].name, defsrc->hosts[0].name);
-}
+        if (!(path = virFileBuildPath(configDir, entry->d_name, NULL)))
+            continue;
 
+        if (!(autostartLink = virFileBuildPath(autostartDir, entry->d_name,
+                                               NULL))) {
+            VIR_FREE(path);
+            continue;
+        }
 
-static bool
-virStoragePoolSourceISCSIMatch(virStoragePoolObjPtr obj,
-                               virStoragePoolDefPtr def)
-{
-    virStoragePoolSourcePtr poolsrc = &obj->def->source;
-    virStoragePoolSourcePtr defsrc = &def->source;
+        obj = virStoragePoolObjLoad(pools, entry->d_name, path, autostartLink);
+        virStoragePoolObjEndAPI(&obj);
 
-    /* NB: Do not check the source host name */
-    if (STRNEQ_NULLABLE(poolsrc->initiator.iqn, defsrc->initiator.iqn))
-        return false;
+        VIR_FREE(path);
+        VIR_FREE(autostartLink);
+    }
 
-    return true;
+    VIR_DIR_CLOSE(dir);
+    return ret;
 }
 
 
-static virStoragePoolObjPtr
-virStoragePoolObjSourceMatchTypeDIR(virStoragePoolObjPtr obj,
-                                    virStoragePoolDefPtr def)
+int
+virStoragePoolObjSaveDef(virStorageDriverStatePtr driver,
+                         virStoragePoolObjPtr obj,
+                         virStoragePoolDefPtr def)
 {
-    if (obj->def->type == VIR_STORAGE_POOL_DIR) {
-        if (STREQ(obj->def->target.path, def->target.path))
-            return obj;
-    } else if (obj->def->type == VIR_STORAGE_POOL_GLUSTER) {
-        if (STREQ(obj->def->source.name, def->source.name) &&
-            STREQ_NULLABLE(obj->def->source.dir, def->source.dir) &&
-            virStoragePoolSourceMatchSingleHost(&obj->def->source,
-                                                &def->source))
-            return obj;
-    } else if (obj->def->type == VIR_STORAGE_POOL_NETFS) {
-        if (STREQ(obj->def->source.dir, def->source.dir) &&
-            virStoragePoolSourceMatchSingleHost(&obj->def->source,
-                                                &def->source))
-            return obj;
+    if (!obj->configFile) {
+        if (virFileMakePath(driver->configDir) < 0) {
+            virReportSystemError(errno,
+                                 _("cannot create config directory %s"),
+                                 driver->configDir);
+            return -1;
+        }
+
+        if (!(obj->configFile = virFileBuildPath(driver->configDir,
+                                                 def->name, ".xml"))) {
+            return -1;
+        }
+
+        if (!(obj->autostartLink = virFileBuildPath(driver->autostartDir,
+                                                    def->name, ".xml"))) {
+            VIR_FREE(obj->configFile);
+            return -1;
+        }
     }
 
-    return NULL;
+    return virStoragePoolSaveConfig(obj->configFile, def);
 }
 
 
-static virStoragePoolObjPtr
-virStoragePoolObjSourceMatchTypeISCSI(virStoragePoolObjPtr obj,
-                                      virStoragePoolDefPtr def,
-                                      virConnectPtr conn)
+int
+virStoragePoolObjDeleteDef(virStoragePoolObjPtr obj)
 {
-    virStorageAdapterPtr pool_adapter = &obj->def->source.adapter;
-    virStorageAdapterPtr def_adapter = &def->source.adapter;
-    virStorageAdapterSCSIHostPtr pool_scsi_host;
-    virStorageAdapterSCSIHostPtr def_scsi_host;
-    virStorageAdapterFCHostPtr pool_fchost;
-    virStorageAdapterFCHostPtr def_fchost;
-    unsigned int pool_hostnum;
-    unsigned int def_hostnum;
-    unsigned int scsi_hostnum;
+    if (!obj->configFile) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("no config file for %s"), obj->def->name);
+        return -1;
+    }
 
-    if (pool_adapter->type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST &&
-        def_adapter->type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST) {
-        pool_fchost = &pool_adapter->data.fchost;
-        def_fchost = &def_adapter->data.fchost;
+    if (unlink(obj->configFile) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("cannot remove config for %s"),
+                       obj->def->name);
+        return -1;
+    }
 
-        if (STREQ(pool_fchost->wwnn, def_fchost->wwnn) &&
-            STREQ(pool_fchost->wwpn, def_fchost->wwpn))
-            return obj;
-    } else if (pool_adapter->type == VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST &&
-               def_adapter->type == VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST) {
-        pool_scsi_host = &pool_adapter->data.scsi_host;
-        def_scsi_host = &def_adapter->data.scsi_host;
+    return 0;
+}
 
-        if (pool_scsi_host->has_parent &&
-            def_scsi_host->has_parent &&
-            matchSCSIAdapterParent(pool_scsi_host, def_scsi_host))
-            return obj;
 
-        if (getSCSIHostNumber(pool_scsi_host, &pool_hostnum) < 0 ||
-            getSCSIHostNumber(def_scsi_host, &def_hostnum) < 0)
-            return NULL;
-        if (pool_hostnum == def_hostnum)
-            return obj;
-    } else if (pool_adapter->type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST &&
-               def_adapter->type == VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST) {
-        pool_fchost = &pool_adapter->data.fchost;
-        def_scsi_host = &def_adapter->data.scsi_host;
+struct _virStoragePoolCountData {
+    virConnectPtr conn;
+    virStoragePoolObjListACLFilter filter;
+    bool wantActive;
+    int count;
+};
 
-        /* Get the scsi_hostN for the scsi_host source adapter def */
-        if (getSCSIHostNumber(def_scsi_host, &scsi_hostnum) < 0)
-            return NULL;
 
-        if (matchFCHostToSCSIHost(conn, pool_fchost, scsi_hostnum))
-            return obj;
+static int
+virStoragePoolObjNumOfStoragePoolsCb(void *payload,
+                                     const void *name ATTRIBUTE_UNUSED,
+                                     void *opaque)
+{
+    virStoragePoolObjPtr obj = payload;
+    struct _virStoragePoolCountData *data = opaque;
 
-    } else if (pool_adapter->type == VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST &&
-               def_adapter->type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST) {
-        pool_scsi_host = &pool_adapter->data.scsi_host;
-        def_fchost = &def_adapter->data.fchost;
+    virObjectLock(obj);
 
-        if (getSCSIHostNumber(pool_scsi_host, &scsi_hostnum) < 0)
-            return NULL;
+    if (data->filter && !data->filter(data->conn, obj->def))
+        goto cleanup;
 
-        if (matchFCHostToSCSIHost(conn, def_fchost, scsi_hostnum))
-            return obj;
-    }
+    if (data->wantActive != virStoragePoolObjIsActive(obj))
+        goto cleanup;
 
-    return NULL;
+    data->count++;
+
+ cleanup:
+    virObjectUnlock(obj);
+    return 0;
 }
 
 
-static virStoragePoolObjPtr
-virStoragePoolObjSourceMatchTypeDEVICE(virStoragePoolObjPtr obj,
-                                       virStoragePoolDefPtr def)
+int
+virStoragePoolObjNumOfStoragePools(virStoragePoolObjListPtr pools,
+                                   virConnectPtr conn,
+                                   bool wantActive,
+                                   virStoragePoolObjListACLFilter filter)
 {
-    virStoragePoolObjPtr matchobj = NULL;
-
-    if (obj->def->type == VIR_STORAGE_POOL_ISCSI) {
-        if (def->type != VIR_STORAGE_POOL_ISCSI)
-            return NULL;
-
-        if ((matchobj = virStoragePoolSourceFindDuplicateDevices(obj, def))) {
-            if (!virStoragePoolSourceISCSIMatch(matchobj, def))
-                return NULL;
-        }
-        return matchobj;
-    }
+    struct _virStoragePoolCountData data = {
+        .conn = conn, .filter = filter, .wantActive = wantActive, .count = 0 };
 
-    if (def->type == VIR_STORAGE_POOL_ISCSI)
-        return NULL;
+    virObjectRWLockRead(pools);
+    virHashForEach(pools->objs, virStoragePoolObjNumOfStoragePoolsCb, &data);
+    virObjectRWUnlock(pools);
 
-    /* VIR_STORAGE_POOL_FS
-     * VIR_STORAGE_POOL_LOGICAL
-     * VIR_STORAGE_POOL_DISK
-     * VIR_STORAGE_POOL_ZFS */
-    return virStoragePoolSourceFindDuplicateDevices(obj, def);
+    return data.count;
 }
 
 
-struct _virStoragePoolObjFindDuplicateData {
+struct _virStoragePoolNameData {
     virConnectPtr conn;
-    virStoragePoolDefPtr def;
+    virStoragePoolObjListACLFilter filter;
+    bool wantActive;
+    bool error;
+    int nnames;
+    int maxnames;
+    char **const names;
 };
 
+
 static int
-virStoragePoolObjSourceFindDuplicateCb(const void *payload,
-                                       const void *name ATTRIBUTE_UNUSED,
-                                       const void *opaque)
+virStoragePoolObjGetNamesCb(void *payload,
+                            const void *name ATTRIBUTE_UNUSED,
+                            void *opaque)
 {
-    virStoragePoolObjPtr obj = (virStoragePoolObjPtr) payload;
-    struct _virStoragePoolObjFindDuplicateData *data =
-        (struct _virStoragePoolObjFindDuplicateData *) opaque;
+    virStoragePoolObjPtr obj = payload;
+    struct _virStoragePoolNameData *data = opaque;
 
-    /* Don't match against ourself if re-defining existing pool ! */
-    if (STREQ(obj->def->name, data->def->name))
+    if (data->error)
         return 0;
 
-    switch ((virStoragePoolType)obj->def->type) {
-    case VIR_STORAGE_POOL_DIR:
-    case VIR_STORAGE_POOL_GLUSTER:
-    case VIR_STORAGE_POOL_NETFS:
-        if (data->def->type == obj->def->type &&
-            virStoragePoolObjSourceMatchTypeDIR(obj, data->def))
-            return 1;
-        break;
-
-    case VIR_STORAGE_POOL_SCSI:
-        if (data->def->type == obj->def->type &&
-            virStoragePoolObjSourceMatchTypeISCSI(obj, data->def, data->conn))
-            return 1;
-        break;
-
-    case VIR_STORAGE_POOL_ISCSI:
-    case VIR_STORAGE_POOL_ISCSI_DIRECT:
-    case VIR_STORAGE_POOL_FS:
-    case VIR_STORAGE_POOL_LOGICAL:
-    case VIR_STORAGE_POOL_DISK:
-    case VIR_STORAGE_POOL_ZFS:
-        if ((data->def->type == VIR_STORAGE_POOL_ISCSI ||
-             data->def->type == VIR_STORAGE_POOL_ISCSI_DIRECT ||
-             data->def->type == VIR_STORAGE_POOL_FS ||
-             data->def->type == VIR_STORAGE_POOL_LOGICAL ||
-             data->def->type == VIR_STORAGE_POOL_DISK ||
-             data->def->type == VIR_STORAGE_POOL_ZFS) &&
-            virStoragePoolObjSourceMatchTypeDEVICE(obj, data->def))
-            return 1;
-        break;
+    if (data->maxnames >= 0 && data->nnames == data->maxnames)
+        return 0;
 
-    case VIR_STORAGE_POOL_SHEEPDOG:
-        if (data->def->type == obj->def->type &&
-            virStoragePoolSourceMatchSingleHost(&obj->def->source,
-                                                &data->def->source))
-            return 1;
-        break;
+    virObjectLock(obj);
 
-    case VIR_STORAGE_POOL_MPATH:
-        /* Only one mpath pool is valid per host */
-        if (data->def->type == obj->def->type)
-            return 1;
-        break;
+    if (data->filter && !data->filter(data->conn, obj->def))
+        goto cleanup;
 
-    case VIR_STORAGE_POOL_VSTORAGE:
-        if (data->def->type == obj->def->type &&
-            STREQ(obj->def->source.name, data->def->source.name))
-            return 1;
-        break;
+    if (data->wantActive != virStoragePoolObjIsActive(obj))
+        goto cleanup;
 
-    case VIR_STORAGE_POOL_RBD:
-    case VIR_STORAGE_POOL_LAST:
-        break;
+    if (data->names) {
+        if (VIR_STRDUP(data->names[data->nnames], obj->def->name) < 0) {
+            data->error = true;
+            goto cleanup;
+        }
     }
 
+    data->nnames++;
+
+ cleanup:
+    virObjectUnlock(obj);
     return 0;
 }
 
 
 int
-virStoragePoolObjSourceFindDuplicate(virConnectPtr conn,
-                                     virStoragePoolObjListPtr pools,
-                                     virStoragePoolDefPtr def)
+virStoragePoolObjGetNames(virStoragePoolObjListPtr pools,
+                          virConnectPtr conn,
+                          bool wantActive,
+                          virStoragePoolObjListACLFilter filter,
+                          char **const names,
+                          int maxnames)
 {
-    struct _virStoragePoolObjFindDuplicateData data = { .conn = conn,
-                                                        .def = def };
-    virStoragePoolObjPtr obj = NULL;
+    struct _virStoragePoolNameData data = {
+        .conn = conn, .filter = filter, .wantActive = wantActive,
+        .error = false, .nnames = 0, .maxnames = maxnames, .names = names };
 
     virObjectRWLockRead(pools);
-    obj = virHashSearch(pools->objs, virStoragePoolObjSourceFindDuplicateCb,
-                        &data, NULL);
+    virHashForEach(pools->objs, virStoragePoolObjGetNamesCb, &data);
     virObjectRWUnlock(pools);
 
-    if (obj) {
-        virReportError(VIR_ERR_OPERATION_FAILED,
-                       _("Storage source conflict with pool: '%s'"),
-                       obj->def->name);
-        return -1;
-    }
+    if (data.error)
+        goto error;
 
-    return 0;
+    return data.nnames;
+
+ error:
+    while (data.nnames)
+        VIR_FREE(data.names[--data.nnames]);
+    return -1;
 }