diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c index 422e76acc9753a9c81158eb7efc12a34cc3424d1..9ae1a89a8a9dcb1c5ca73c0fd8a392eec7433386 100644 --- a/src/conf/storage_conf.c +++ b/src/conf/storage_conf.c @@ -1628,6 +1628,69 @@ char *virStoragePoolSourceListFormat(virStoragePoolSourceListPtr def) } +/* + * virStoragePoolObjIsDuplicate: + * @doms : virStoragePoolObjListPtr to search + * @def : virStoragePoolDefPtr definition of pool to lookup + * @check_active: If true, ensure that pool is not active + * + * Returns: -1 on error + * 0 if pool is new + * 1 if pool is a duplicate + */ +int virStoragePoolObjIsDuplicate(virStoragePoolObjListPtr pools, + virStoragePoolDefPtr def, + unsigned int check_active) +{ + int ret = -1; + int dupPool = 0; + virStoragePoolObjPtr pool = NULL; + + /* See if a Pool with matching UUID already exists */ + pool = virStoragePoolObjFindByUUID(pools, def->uuid); + if (pool) { + /* UUID matches, but if names don't match, refuse it */ + if (STRNEQ(pool->def->name, def->name)) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(pool->def->uuid, uuidstr); + virStorageReportError(VIR_ERR_OPERATION_FAILED, + _("pool '%s' is already defined with uuid %s"), + pool->def->name, uuidstr); + goto cleanup; + } + + if (check_active) { + /* UUID & name match, but if Pool is already active, refuse it */ + if (virStoragePoolObjIsActive(pool)) { + virStorageReportError(VIR_ERR_OPERATION_INVALID, + _("pool is already active as '%s'"), + pool->def->name); + goto cleanup; + } + } + + dupPool = 1; + } else { + /* UUID does not match, but if a name matches, refuse it */ + pool = virStoragePoolObjFindByName(pools, def->name); + if (pool) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(pool->def->uuid, uuidstr); + virStorageReportError(VIR_ERR_OPERATION_FAILED, + _("pool '%s' already exists with uuid %s"), + def->name, uuidstr); + goto cleanup; + } + } + + ret = dupPool; +cleanup: + if (pool) + virStoragePoolObjUnlock(pool); + return ret; +} + + void virStoragePoolObjLock(virStoragePoolObjPtr obj) { virMutexLock(&obj->lock); diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h index 5813489db44dc9d0c855ecf08c986706d6707139..bedee9efeeed99b3e4fe82014d51b309cfc53e32 100644 --- a/src/conf/storage_conf.h +++ b/src/conf/storage_conf.h @@ -379,6 +379,10 @@ virStoragePoolSourcePtr virStoragePoolSourceListNewSource(virStoragePoolSourceListPtr list); char *virStoragePoolSourceListFormat(virStoragePoolSourceListPtr def); +int virStoragePoolObjIsDuplicate(virStoragePoolObjListPtr pools, + virStoragePoolDefPtr def, + unsigned int check_active); + void virStoragePoolObjLock(virStoragePoolObjPtr obj); void virStoragePoolObjUnlock(virStoragePoolObjPtr obj); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 4f44064928a832577968232f473ed7a98784824f..4b1276aa01047532b529731c1ee5f1b42b9369d8 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -610,6 +610,7 @@ virStoragePoolTypeFromString; virStoragePartedFsTypeTypeToString; virStoragePoolObjLock; virStoragePoolObjUnlock; +virStoragePoolObjIsDuplicate; # storage_encryption_conf.h virStorageEncryptionFree; diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c index 0870f74a3daa7d42eaec4ed48b1c7d91e0ab6abe..e53317a67630752c0cf3eaf1b68d82093d89753a 100644 --- a/src/storage/storage_driver.c +++ b/src/storage/storage_driver.c @@ -521,17 +521,8 @@ storagePoolCreate(virConnectPtr conn, if (!(def = virStoragePoolDefParseString(xml))) goto cleanup; - pool = virStoragePoolObjFindByUUID(&driver->pools, def->uuid); - if (!pool) - pool = virStoragePoolObjFindByName(&driver->pools, def->name); - - if (pool) { - virStorageReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("storage pool already exists")); - virStoragePoolObjUnlock(pool); - pool = NULL; + if (virStoragePoolObjIsDuplicate(&driver->pools, def, 1) < 0) goto cleanup; - } if ((backend = virStorageBackendForType(def->type)) == NULL) goto cleanup; @@ -579,6 +570,9 @@ storagePoolDefine(virConnectPtr conn, if (!(def = virStoragePoolDefParseString(xml))) goto cleanup; + if (virStoragePoolObjIsDuplicate(&driver->pools, def, 0) < 0) + goto cleanup; + if (virStorageBackendForType(def->type) == NULL) goto cleanup;