[libvirt] [PATCH 0/5] esx: implement virConnectListAllStoragePools

Make the virConnectListAllStoragePools API work for esx storage pools by implementing the internal connectListAllStoragePools storage API. Pino Toscano (5): esx: split datastoreToStoragePoolPtr helper esx: split datastorePoolType helper esx: split targetToStoragePool helper esx: implement connectListAllStoragePools docs: document virConnectListAllStoragePools in esx docs/news.xml | 9 ++ src/esx/esx_storage_backend_iscsi.c | 104 +++++++++++++-- src/esx/esx_storage_backend_vmfs.c | 192 +++++++++++++++++++++++----- src/esx/esx_storage_driver.c | 68 ++++++++++ 4 files changed, 332 insertions(+), 41 deletions(-) -- 2.21.0

Move the creation of a virStoragePtr object from the esxVI_ObjectContent object of a datastore out of esxStoragePoolLookupByName in an own helper. This way it can be used also in other functions. Signed-off-by: Pino Toscano <ptoscano@redhat.com> --- src/esx/esx_storage_backend_vmfs.c | 45 ++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/src/esx/esx_storage_backend_vmfs.c b/src/esx/esx_storage_backend_vmfs.c index 5f25f80072..78fe2b598d 100644 --- a/src/esx/esx_storage_backend_vmfs.c +++ b/src/esx/esx_storage_backend_vmfs.c @@ -195,26 +195,16 @@ esxConnectListStoragePools(virConnectPtr conn, char **const names, static virStoragePoolPtr -esxStoragePoolLookupByName(virConnectPtr conn, - const char *name) +datastoreToStoragePoolPtr(virConnectPtr conn, + const char *name, + esxVI_ObjectContent *datastore) { esxPrivate *priv = conn->privateData; - esxVI_ObjectContent *datastore = NULL; esxVI_DatastoreHostMount *hostMount = NULL; /* VIR_CRYPTO_HASH_SIZE_MD5 = VIR_UUID_BUFLEN = 16 */ unsigned char md5[VIR_CRYPTO_HASH_SIZE_MD5]; virStoragePoolPtr pool = NULL; - if (esxVI_LookupDatastoreByName(priv->primary, name, NULL, &datastore, - esxVI_Occurrence_OptionalItem) < 0) { - goto cleanup; - } - - if (!datastore) { - /* Not found, let the base storage driver handle error reporting */ - goto cleanup; - } - /* * Datastores don't have a UUID, but we can use the 'host.mountInfo.path' * property as source for a UUID. The mount path is unique per host and @@ -239,7 +229,6 @@ esxStoragePoolLookupByName(virConnectPtr conn, pool = virGetStoragePool(conn, name, md5, &esxStorageBackendVMFS, NULL); cleanup: - esxVI_ObjectContent_Free(&datastore); esxVI_DatastoreHostMount_Free(&hostMount); return pool; @@ -247,6 +236,34 @@ esxStoragePoolLookupByName(virConnectPtr conn, +static virStoragePoolPtr +esxStoragePoolLookupByName(virConnectPtr conn, + const char *name) +{ + esxPrivate *priv = conn->privateData; + esxVI_ObjectContent *datastore = NULL; + virStoragePoolPtr pool = NULL; + + if (esxVI_LookupDatastoreByName(priv->primary, name, NULL, &datastore, + esxVI_Occurrence_OptionalItem) < 0) { + goto cleanup; + } + + if (!datastore) { + /* Not found, let the base storage driver handle error reporting */ + goto cleanup; + } + + pool = datastoreToStoragePoolPtr(conn, name, datastore); + + cleanup: + esxVI_ObjectContent_Free(&datastore); + + return pool; +} + + + static virStoragePoolPtr esxStoragePoolLookupByUUID(virConnectPtr conn, const unsigned char *uuid) -- 2.21.0

Move the detection of the type of a vmfs pool out of esxLookupVMFSStoragePoolType in an own helper. This way it can be used also in other functions. Signed-off-by: Pino Toscano <ptoscano@redhat.com> --- src/esx/esx_storage_backend_vmfs.c | 49 ++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/src/esx/esx_storage_backend_vmfs.c b/src/esx/esx_storage_backend_vmfs.c index 78fe2b598d..b890825a40 100644 --- a/src/esx/esx_storage_backend_vmfs.c +++ b/src/esx/esx_storage_backend_vmfs.c @@ -54,26 +54,12 @@ verify(VIR_CRYPTO_HASH_SIZE_MD5 == VIR_UUID_BUFLEN); static int -esxLookupVMFSStoragePoolType(esxVI_Context *ctx, const char *poolName, - int *poolType) +datastorePoolType(esxVI_ObjectContent *datastore, int *poolType) { int result = -1; - esxVI_String *propertyNameList = NULL; - esxVI_ObjectContent *datastore = NULL; esxVI_DynamicProperty *dynamicProperty = NULL; esxVI_DatastoreInfo *datastoreInfo = NULL; - if (esxVI_String_AppendValueToList(&propertyNameList, "info") < 0 || - esxVI_LookupDatastoreByName(ctx, poolName, propertyNameList, &datastore, - esxVI_Occurrence_OptionalItem) < 0) { - goto cleanup; - } - - if (!datastore) { - /* Not found, let the base storage driver handle error reporting */ - goto cleanup; - } - for (dynamicProperty = datastore->propSet; dynamicProperty; dynamicProperty = dynamicProperty->_next) { if (STREQ(dynamicProperty->name, "info")) { @@ -100,10 +86,41 @@ esxLookupVMFSStoragePoolType(esxVI_Context *ctx, const char *poolName, result = 0; + cleanup: + esxVI_DatastoreInfo_Free(&datastoreInfo); + + return result; +} + + + +static int +esxLookupVMFSStoragePoolType(esxVI_Context *ctx, const char *poolName, + int *poolType) +{ + int result = -1; + esxVI_String *propertyNameList = NULL; + esxVI_ObjectContent *datastore = NULL; + + if (esxVI_String_AppendValueToList(&propertyNameList, "info") < 0 || + esxVI_LookupDatastoreByName(ctx, poolName, propertyNameList, &datastore, + esxVI_Occurrence_OptionalItem) < 0) { + goto cleanup; + } + + if (!datastore) { + /* Not found, let the base storage driver handle error reporting */ + goto cleanup; + } + + if (datastorePoolType(datastore, poolType) < 0) + goto cleanup; + + result = 0; + cleanup: esxVI_String_Free(&propertyNameList); esxVI_ObjectContent_Free(&datastore); - esxVI_DatastoreInfo_Free(&datastoreInfo); return result; } -- 2.21.0

Move the creation of a virStoragePtr object from the esxVI_HostInternetScsiHbaStaticTarget object of a target out of esxStoragePoolLookupByName in an own helper. This way it can be used also in other functions. Signed-off-by: Pino Toscano <ptoscano@redhat.com> --- src/esx/esx_storage_backend_iscsi.c | 32 +++++++++++++++++++---------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/esx/esx_storage_backend_iscsi.c b/src/esx/esx_storage_backend_iscsi.c index 61354a6938..72ab0d3cb0 100644 --- a/src/esx/esx_storage_backend_iscsi.c +++ b/src/esx/esx_storage_backend_iscsi.c @@ -147,14 +147,32 @@ esxConnectListStoragePools(virConnectPtr conn, char **const names, +static virStoragePoolPtr +targetToStoragePool(virConnectPtr conn, + const char *name, + esxVI_HostInternetScsiHbaStaticTarget *target) +{ + /* VIR_CRYPTO_HASH_SIZE_MD5 = VIR_UUID_BUFLEN = 16 */ + unsigned char md5[VIR_CRYPTO_HASH_SIZE_MD5]; + + /* + * HostInternetScsiHbaStaticTarget does not provide a uuid field, + * but iScsiName (or widely known as IQN) is unique across the multiple + * hosts, using it to compute key + */ + if (virCryptoHashBuf(VIR_CRYPTO_HASH_MD5, target->iScsiName, md5) < 0) + return NULL; + + return virGetStoragePool(conn, name, md5, &esxStorageBackendISCSI, NULL); +} + + static virStoragePoolPtr esxStoragePoolLookupByName(virConnectPtr conn, const char *name) { esxPrivate *priv = conn->privateData; esxVI_HostInternetScsiHbaStaticTarget *target = NULL; - /* VIR_CRYPTO_HASH_SIZE_MD5 = VIR_UUID_BUFLEN = 16 */ - unsigned char md5[VIR_CRYPTO_HASH_SIZE_MD5]; virStoragePoolPtr pool = NULL; /* @@ -172,15 +190,7 @@ esxStoragePoolLookupByName(virConnectPtr conn, goto cleanup; } - /* - * HostInternetScsiHbaStaticTarget does not provide a uuid field, - * but iScsiName (or widely known as IQN) is unique across the multiple - * hosts, using it to compute key - */ - if (virCryptoHashBuf(VIR_CRYPTO_HASH_MD5, target->iScsiName, md5) < 0) - goto cleanup; - - pool = virGetStoragePool(conn, name, md5, &esxStorageBackendISCSI, NULL); + pool = targetToStoragePool(conn, name, target); cleanup: esxVI_HostInternetScsiHbaStaticTarget_Free(&target); -- 2.21.0

Implement the .connectListAllStoragePools storage API in the esx storage driver, and in all its subdrivers. Signed-off-by: Pino Toscano <ptoscano@redhat.com> --- src/esx/esx_storage_backend_iscsi.c | 72 +++++++++++++++++++++ src/esx/esx_storage_backend_vmfs.c | 98 +++++++++++++++++++++++++++++ src/esx/esx_storage_driver.c | 68 ++++++++++++++++++++ 3 files changed, 238 insertions(+) diff --git a/src/esx/esx_storage_backend_iscsi.c b/src/esx/esx_storage_backend_iscsi.c index 72ab0d3cb0..4f5d8e5e24 100644 --- a/src/esx/esx_storage_backend_iscsi.c +++ b/src/esx/esx_storage_backend_iscsi.c @@ -779,6 +779,77 @@ esxStorageVolGetPath(virStorageVolPtr volume) +#define MATCH(FLAG) (flags & (FLAG)) +static int +esxConnectListAllStoragePools(virConnectPtr conn, + virStoragePoolPtr **pools, + unsigned int flags) +{ + bool success = false; + size_t count = 0; + esxPrivate *priv = conn->privateData; + esxVI_HostInternetScsiHba *hostInternetScsiHba = NULL; + esxVI_HostInternetScsiHbaStaticTarget *target; + size_t i; + + /* this driver provides only iSCSI pools */ + if (MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_POOL_TYPE) && + !(MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_ISCSI))) + return 0; + + if (esxVI_LookupHostInternetScsiHba(priv->primary, + &hostInternetScsiHba) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to obtain iSCSI adapter")); + goto cleanup; + } + + /* FIXME: code looks for software iSCSI adapter only */ + if (!hostInternetScsiHba) { + /* iSCSI adapter may not be enabled for this host */ + return 0; + } + + /* + * ESX has two kind of targets: + * 1. staticIscsiTargets + * 2. dynamicIscsiTargets + * For each dynamic target if its reachable a static target is added. + * return iSCSI names for all static targets to avoid duplicate names. + */ + for (target = hostInternetScsiHba->configuredStaticTarget; + target; target = target->_next) { + virStoragePoolPtr pool; + + pool = targetToStoragePool(conn, target->iScsiName, target); + if (!pool) + goto cleanup; + + if (VIR_APPEND_ELEMENT(*pools, count, pool) < 0) + goto cleanup; + } + + success = true; + + cleanup: + if (! success) { + if (*pools) { + for (i = 0; i < count; ++i) + VIR_FREE((*pools)[i]); + VIR_FREE(*pools); + } + + count = -1; + } + + esxVI_HostInternetScsiHba_Free(&hostInternetScsiHba); + + return count; +} +#undef MATCH + + + virStorageDriver esxStorageBackendISCSI = { .connectNumOfStoragePools = esxConnectNumOfStoragePools, /* 1.0.1 */ .connectListStoragePools = esxConnectListStoragePools, /* 1.0.1 */ @@ -799,4 +870,5 @@ virStorageDriver esxStorageBackendISCSI = { .storageVolDelete = esxStorageVolDelete, /* 1.0.1 */ .storageVolWipe = esxStorageVolWipe, /* 1.0.1 */ .storageVolGetPath = esxStorageVolGetPath, /* 1.0.1 */ + .connectListAllStoragePools = esxConnectListAllStoragePools, /* 5.10.0 */ }; diff --git a/src/esx/esx_storage_backend_vmfs.c b/src/esx/esx_storage_backend_vmfs.c index b890825a40..05b273aed7 100644 --- a/src/esx/esx_storage_backend_vmfs.c +++ b/src/esx/esx_storage_backend_vmfs.c @@ -1460,6 +1460,103 @@ esxStorageVolGetPath(virStorageVolPtr volume) +#define MATCH(FLAG) (flags & (FLAG)) +static int +esxConnectListAllStoragePools(virConnectPtr conn, + virStoragePoolPtr **pools, + unsigned int flags) +{ + bool success = false; + esxPrivate *priv = conn->privateData; + esxVI_String *propertyNameList = NULL; + esxVI_DynamicProperty *dynamicProperty = NULL; + esxVI_ObjectContent *datastoreList = NULL; + esxVI_ObjectContent *datastore = NULL; + size_t count = 0; + size_t i; + virStoragePoolPtr pool; + const bool checkPoolType = MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_POOL_TYPE); + + if (esxVI_String_AppendValueToList(&propertyNameList, + "summary.name") < 0) { + goto cleanup; + } + + if (checkPoolType && + esxVI_String_AppendValueToList(&propertyNameList, + "info") < 0) { + goto cleanup; + } + + if (esxVI_LookupDatastoreList(priv->primary, propertyNameList, + &datastoreList) < 0) { + goto cleanup; + } + + for (datastore = datastoreList; datastore; + datastore = datastore->_next) { + const char *name = NULL; + + for (dynamicProperty = datastore->propSet; dynamicProperty; + dynamicProperty = dynamicProperty->_next) { + if (STREQ(dynamicProperty->name, "summary.name")) { + if (esxVI_AnyType_ExpectType(dynamicProperty->val, + esxVI_Type_String) < 0) { + goto cleanup; + } + + name = dynamicProperty->val->string; + } + } + + if (!name) + goto cleanup; + + if (checkPoolType) { + int poolType; + + if (datastorePoolType(datastore, &poolType) < 0) + goto cleanup; + + if (!((MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_DIR) && + (poolType == VIR_STORAGE_POOL_DIR)) || + (MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_FS) && + (poolType == VIR_STORAGE_POOL_FS)) || + (MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_NETFS) && + (poolType == VIR_STORAGE_POOL_NETFS)))) + continue; + } + + pool = datastoreToStoragePoolPtr(conn, name, datastore); + if (!pool) + goto cleanup; + + if (VIR_APPEND_ELEMENT(*pools, count, pool) < 0) + goto cleanup; + } + + success = true; + + cleanup: + if (! success) { + if (*pools) { + for (i = 0; i < count; ++i) + VIR_FREE((*pools)[i]); + VIR_FREE(*pools); + } + + count = -1; + } + + esxVI_String_Free(&propertyNameList); + esxVI_ObjectContent_Free(&datastoreList); + + return count; +} +#undef MATCH + + + virStorageDriver esxStorageBackendVMFS = { .connectNumOfStoragePools = esxConnectNumOfStoragePools, /* 0.8.2 */ .connectListStoragePools = esxConnectListStoragePools, /* 0.8.2 */ @@ -1480,4 +1577,5 @@ virStorageDriver esxStorageBackendVMFS = { .storageVolGetInfo = esxStorageVolGetInfo, /* 0.8.4 */ .storageVolGetXMLDesc = esxStorageVolGetXMLDesc, /* 0.8.4 */ .storageVolGetPath = esxStorageVolGetPath, /* 0.8.4 */ + .connectListAllStoragePools = esxConnectListAllStoragePools, /* 5.10.0 */ }; diff --git a/src/esx/esx_storage_driver.c b/src/esx/esx_storage_driver.c index 8a34732b45..6d17ac28ea 100644 --- a/src/esx/esx_storage_driver.c +++ b/src/esx/esx_storage_driver.c @@ -517,6 +517,73 @@ esxStoragePoolIsPersistent(virStoragePoolPtr pool G_GNUC_UNUSED) +#define MATCH(FLAG) (flags & (FLAG)) +static int +esxConnectListAllStoragePools(virConnectPtr conn, + virStoragePoolPtr **pools, + unsigned int flags) +{ + bool success = false; + esxPrivate *priv = conn->privateData; + size_t count = 0; + size_t i, j; + int tmp; + + virCheckFlags(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ALL, -1); + + /* + * ESX storage pools are always active, persistent, and + * autostarted, so return zero elements in case we are asked + * for pools different than that. + * + * Filtering by type will be done by each backend. + */ + if (MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ACTIVE) && + !(MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_ACTIVE))) + return 0; + if (MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_PERSISTENT) && + !(MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_PERSISTENT))) + return 0; + if (MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_AUTOSTART) && + !(MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_AUTOSTART))) + return 0; + + if (esxVI_EnsureSession(priv->primary) < 0) + return -1; + + for (i = 0; i < LAST_BACKEND; ++i) { + virStoragePoolPtr *new_pools = 0; + tmp = backends[i]->connectListAllStoragePools(conn, &new_pools, flags); + + if (tmp < 0) + goto cleanup; + + for (j = 0; j < tmp; ++j) { + if (VIR_APPEND_ELEMENT(*pools, count, new_pools[j]) < 0) + goto cleanup; + } + VIR_FREE(new_pools); + } + + success = true; + + cleanup: + if (! success) { + if (*pools) { + for (i = 0; i < count; ++i) + VIR_FREE((*pools)[i]); + VIR_FREE(*pools); + } + + count = -1; + } + + return count; +} +#undef MATCH + + + virStorageDriver esxStorageDriver = { .connectNumOfStoragePools = esxConnectNumOfStoragePools, /* 0.8.2 */ .connectListStoragePools = esxConnectListStoragePools, /* 0.8.2 */ @@ -544,4 +611,5 @@ virStorageDriver esxStorageDriver = { .storageVolGetPath = esxStorageVolGetPath, /* 0.8.4 */ .storagePoolIsActive = esxStoragePoolIsActive, /* 0.8.2 */ .storagePoolIsPersistent = esxStoragePoolIsPersistent, /* 0.8.2 */ + .connectListAllStoragePools = esxConnectListAllStoragePools, /* 5.10.0 */ }; -- 2.21.0

Signed-off-by: Pino Toscano <ptoscano@redhat.com> --- docs/news.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/news.xml b/docs/news.xml index c362bf3a15..278697506c 100644 --- a/docs/news.xml +++ b/docs/news.xml @@ -55,6 +55,15 @@ </change> </section> <section title="Improvements"> + <change> + <summary> + esx driver: implement virConnectListAllStoragePools + </summary> + <description> + The virConnectListAllStoragePools API was implemented in the esx + driver. + </description> + </change> </section> <section title="Bug fixes"> </section> -- 2.21.0

On Wednesday, 13 November 2019 13:46:06 CET Pino Toscano wrote:
Make the virConnectListAllStoragePools API work for esx storage pools by implementing the internal connectListAllStoragePools storage API.
Pino Toscano (5): esx: split datastoreToStoragePoolPtr helper esx: split datastorePoolType helper esx: split targetToStoragePool helper esx: implement connectListAllStoragePools docs: document virConnectListAllStoragePools in esx
docs/news.xml | 9 ++ src/esx/esx_storage_backend_iscsi.c | 104 +++++++++++++-- src/esx/esx_storage_backend_vmfs.c | 192 +++++++++++++++++++++++----- src/esx/esx_storage_driver.c | 68 ++++++++++ 4 files changed, 332 insertions(+), 41 deletions(-)
I added more esx-related changes, so I will submit a v2 of this series. -- Pino Toscano
participants (1)
-
Pino Toscano