[libvirt] libvirt [PATCHv2 2/2] Add iSCSI backend storage driver for ESX.

Matthias Bolte matthias.bolte at googlemail.com
Mon Dec 3 20:13:37 UTC 2012


2012/11/10 Ata E Husain Bohra <ata.husain at hotmail.com>:
> The patch adds the backend driver to support iSCSI format storage pools
> and volumes for ESX host. The mapping of ESX iSCSI specifics to Libvirt
> is as follows:
>
> 1. ESX static iSCSI target <------> Libvirt Storage Pools
> 2. ESX iSCSI LUNs          <------> Libvirt Storage Volumes.
>
> The above understanding is based on http://libvirt.org/storage.html.
>
> The operation supported on iSCSI pools includes:
>
> 1. List storage pools & volumes.
> 2. Get xml descriptor operaion on pools & volumes.
> 3. Lookup operation on pools & volumes by name, uuid and path (if applicable).
>
> iSCSI pools does not support operations such as: Create / remove pools
> and volumes.
> ---
>  src/Makefile.am                     |    1 +
>  src/esx/esx_storage_backend_iscsi.c |  807 +++++++++++++++++++++++++++++++++++
>  src/esx/esx_storage_backend_iscsi.h |   29 ++
>  src/esx/esx_storage_driver.c        |    8 +-
>  src/esx/esx_vi.c                    |  332 ++++++++++++++
>  src/esx/esx_vi.h                    |   18 +
>  src/esx/esx_vi_generator.input      |  302 +++++++++++++
>  src/esx/esx_vi_generator.py         |   19 +
>  8 files changed, 1515 insertions(+), 1 deletion(-)
>  create mode 100644 src/esx/esx_storage_backend_iscsi.c
>  create mode 100644 src/esx/esx_storage_backend_iscsi.h
>

> --- /dev/null
> +++ b/src/esx/esx_storage_backend_iscsi.c

> +static int
> +esxStorageBackendISCSIPoolListStorageVolumes(virStoragePoolPtr pool,
> +                                             char **const names,
> +                                             int maxnames)
> +{
> +    int  count = 0;
> +    esxPrivate *priv = pool->conn->storagePrivateData;
> +    esxVI_HostScsiTopologyLun *hostScsiTopologyLunList = NULL;
> +    const esxVI_HostScsiTopologyLun *hostScsiTopologyLun = NULL;
> +    esxVI_ScsiLun *scsiLunList = NULL;
> +    const esxVI_ScsiLun *scsiLun = NULL;
> +    bool success = false;
> +    int i = 0;
> +
> +    if (esxVI_LookupHostScsiTopologyLunListByTargetName(
> +          priv->primary, pool->name, &hostScsiTopologyLunList) < 0) {
> +        goto cleanup;
> +    }
> +
> +    if (hostScsiTopologyLunList == NULL) {
> +        /* iSCSI adapter may not be enabled on ESX host */
> +        return 0;
> +    }
> +
> +    if (esxVI_LookupScsiLunList(priv->primary, &scsiLunList) < 0) {
> +        goto cleanup;
> +    }
> +
> +    /* O^2 but still faster than hash given N is not that large */

This comment is wrong here, because a hash wouldn't help here. In
order to get the storage volume list this 2-dimensional list need to
be iterated. There is no way to do this faster, except adding a cache
but then you get the problem of ehen to invalidate it. So this 2 level
for loop is totally fine and the comment should be removed, because it
is misleading.

> +    for (scsiLun = scsiLunList; scsiLun != NULL && count < maxnames;
> +         scsiLun = scsiLun->_next) {
> +        for (hostScsiTopologyLun = hostScsiTopologyLunList;
> +             hostScsiTopologyLun != NULL && count < maxnames;
> +             hostScsiTopologyLun = hostScsiTopologyLun->_next) {
> +            if (STREQ(hostScsiTopologyLun->scsiLun, scsiLun->key)) {
> +                names[count] = strdup(scsiLun->deviceName);
> +
> +                if (names[count] == NULL) {
> +                    virReportOOMError();
> +                    goto cleanup;
> +                }
> +                ++count;
> +            }
> +        }
> +    }
> +
> +    success = true;
> +
> +  cleanup:
> +    if (! success) {
> +        for (i = 0; i < count; ++i) {
> +            VIR_FREE(names[i]);
> +        }
> +        count = -1;
> +    }
> +
> +    esxVI_HostScsiTopologyLun_Free(&hostScsiTopologyLunList);
> +    esxVI_ScsiLun_Free(&scsiLunList);
> +
> +    return count;
> +}


> +static int
> +esxStorageBackendISCSIPoolRefresh(virStoragePoolPtr pool,
> +                                  unsigned int flags)
> +{
> +    int result = -1;
> +    esxPrivate *priv = pool->conn->storagePrivateData;
> +    esxVI_ManagedObjectReference *hostStorageSystem = NULL;
> +    esxVI_HostInternetScsiHba *hostInternetScsiHba = NULL;
> +    esxVI_ObjectContent *hostSystem = NULL;
> +    esxVI_String *propertyNameList = NULL;
> +
> +    virCheckFlags(0, -1);
> +
> +    if (esxVI_String_AppendValueToList(&propertyNameList,
> +          "configManager.storageSystem\0") < 0 ||
> +        esxVI_LookupHostSystemProperties(priv->primary,
> +            propertyNameList, &hostSystem) < 0 ||
> +        esxVI_GetManagedObjectReference(hostSystem,
> +            "configManager.storageSystem", &hostStorageSystem,
> +            esxVI_Occurrence_RequiredItem) < 0 ||

No need to look up the hostStorageSystem here. It is already available
here: ctx->hostSystem->configManager->storageSystem

> +        esxVI_LookupHostInternetScsiHba(
> +            priv->primary, &hostInternetScsiHba) < 0) {
> +        goto cleanup;
> +    }
> +
> +     /**
> +      * ESX does not allow rescan on a particular target,
> +      * rescan all the static targets
> +     */
> +    if (esxVI_RescanHba(priv->primary, hostStorageSystem,
> +                        hostInternetScsiHba->device) < 0) {
> +        goto cleanup;
> +    }
> +
> +    result = 0;
> +
> + cleanup:
> +    esxVI_String_Free(&propertyNameList);
> +    esxVI_ManagedObjectReference_Free(&hostStorageSystem);
> +    esxVI_ObjectContent_Free(&hostSystem);
> +    esxVI_HostInternetScsiHba_Free(&hostInternetScsiHba);
> +
> +    return result;
> +
> +}

> +static virStorageVolPtr
> +esxStorageBackendISCSIVolumeCreateXML(virStoragePoolPtr pool ATTRIBUTE_UNUSED,
> +                                      const char *xmldesc ATTRIBUTE_UNUSED,
> +                                      unsigned int flags)
> +{
> +    virCheckFlags(0, NULL);

A VIR_ERR_NO_SUPPORT error should be reported here.

> +    /* not supported operation for iSCSI pools */
> +    return NULL;
> +}
> +
> +
> +
> +static virStorageVolPtr
> +esxStorageBackendISCSIVolumeCreateXMLFrom(
> +  virStoragePoolPtr pool ATTRIBUTE_UNUSED,
> +  const char *xmldesc ATTRIBUTE_UNUSED,
> +  virStorageVolPtr sourceVolume ATTRIBUTE_UNUSED,
> +  unsigned int flags)
> +{
> +    virCheckFlags(0, NULL);

A VIR_ERR_NO_SUPPORT error should be reported here.

> +    /* not supported operation for iSCSI pools */
> +    return NULL;
> +}

> +static int
> +esxStorageBackendISCSIVolumeDelete(virStorageVolPtr volume ATTRIBUTE_UNUSED,
> +                                   unsigned int flags)
> +{
> +    virCheckFlags(0, -1);

A VIR_ERR_NO_SUPPORT error should be reported here.

> +    /* unsupported operation for iSCSI volume */
> +    return 1;

Should return -1;

> +}
> +
> +
> +
> +static int
> +esxStorageBackendISCSIVolumeWipe(virStorageVolPtr volume ATTRIBUTE_UNUSED,
> +                                   unsigned int flags)
> +{
> +    virCheckFlags(0, -1);

A VIR_ERR_NO_SUPPORT error should be reported here.

> +    /* unsupported operation for iSCSI volume */
> +    return 1;

Should return -1;

> +}
> +
> +
> +
> +static char*
> +esxStorageBackendISCSIVolumeGetPath(virStorageVolPtr volume)
> +{
> +    char *path;
> +
> +    if (virAsprintf(&path, "%s", volume->name) < 0) {
> +        virReportOOMError();
> +        return NULL;
> +    }

Can be simplified to strdup.

> +    return path;
> +
> +}

> diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c
> index 9fb2c11..12100d7 100644
> --- a/src/esx/esx_vi.c
> +++ b/src/esx/esx_vi.c

> +int
> +esxVI_LookupScsiLunList(esxVI_Context *ctx,
> +                        esxVI_ScsiLun **ret)
> +{
> +    int result = -1;
> +    esxVI_DynamicProperty *dynamicProperty = NULL;
> +    esxVI_ObjectContent *hostSystem = NULL;
> +    esxVI_String *propertyNameList = NULL;
> +    esxVI_ScsiLun *scsiLunList = NULL;
> +
> +    if (esxVI_String_AppendValueToList(&propertyNameList,
> +        "config.storageDevice.scsiLun\0") < 0 ||
> +        esxVI_LookupHostSystemProperties(
> +            ctx, propertyNameList, &hostSystem) < 0) {
> +        goto cleanup;
> +    }
> +
> +    for (dynamicProperty = hostSystem->propSet;
> +         dynamicProperty != NULL;
> +         dynamicProperty = dynamicProperty->_next) {
> +        if (STREQ(dynamicProperty->name,
> +                     "config.storageDevice.scsiLun")) {
> +            if (esxVI_ScsiLun_CastListFromAnyType(dynamicProperty->val,
> +                                                  &scsiLunList) < 0) {
> +                goto cleanup;
> +            }
> +        } else {
> +            VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
> +        }
> +    }
> +
> +    if (scsiLunList == NULL ||
> +        esxVI_ScsiLun_DeepCopyList(ret, scsiLunList) < 0) {
> +        goto cleanup;
> +    }
> +
> +    result = 0;
> +
> +cleanup:
> +
> +    esxVI_ScsiLun_Free(&scsiLunList);

Needs to free propertyNameList and hostSystem too.

> +    return result;
> +
> +}

> diff --git a/src/esx/esx_vi_generator.input b/src/esx/esx_vi_generator.input
> index c4a3e56..21f5b10 100644
> --- a/src/esx/esx_vi_generator.input
> +++ b/src/esx/esx_vi_generator.input

> @@ -128,6 +136,12 @@ enum VirtualMachinePowerState
>  end
>
>
> +enum vStorageSupport
> +    vStorageUnknown
> +end

This enum is not used anywhere and can be removed.


ACK. No major problems left. I fixed the minor things I mentioned,
made make syntax-check pass and pushed the result. Thanks!

-- 
Matthias Bolte
http://photron.blogspot.com




More information about the libvir-list mailing list