[libvirt] [PATCH] esx: Add read-only storage pool access

Eric Blake eblake at redhat.com
Mon May 10 17:51:37 UTC 2010


On 05/07/2010 02:02 PM, Matthias Bolte wrote:
> Add VIR_STORAGE_POOL_INACCESSIBLE to denote a running but inaccessible
> storage pool. For example an NFS pool is inaccessible when the NFS
> server is currently unreachable.
> 
> Add CIFS to the list of network file systems because ESX distinguishes
> between NFS and CIFS.
> 
> Alter the esxVI_ProductVersion enum in a way that allows to check for
> product type by masking.
> 
> Make esxVI_*_CastFromAnyType dynamically dispatched in order to handle
> the DatastoreInfo type and inheriting types properly.
> 
> Allow esxVI_X_DynamicCast to be called successfully on objects with
> type X. This is necessary for handling DatastoreInfo and inheriting
> types properly.

This seems like a lot of things; can any of it be split into smaller
patches (perhaps one patch for dynamic dispatch, and another patch for
plugging in ESX storage pool handling)?

>  
> +static int
> +esxNumberOfStoragePools(virConnectPtr conn)
> +{
> +    int result = 0;
> +    esxPrivate *priv = conn->storagePrivateData;
> +    esxVI_ObjectContent *datastoreList = NULL;
> +    esxVI_ObjectContent *datastore = NULL;
> +
> +    if (esxVI_EnsureSession(priv->host) < 0) {
> +        goto failure;
> +    }
> +
> +    if (esxVI_LookupObjectContentByType(priv->host, priv->host->datacenter,
> +                                        "Datastore", NULL, esxVI_Boolean_True,
> +                                        &datastoreList) < 0) {
> +        goto failure;
> +    }
> +
> +    for (datastore = datastoreList; datastore != NULL;
> +         datastore = datastore->_next) {
> +        ++result;
> +    }
> +
> +  cleanup:
> +    esxVI_ObjectContent_Free(&datastoreList);
> +
> +    return result;
> +
> +  failure:
> +    result = -1;
> +
> +    goto cleanup;

That logic looks bad, with a goto jumping backwards.  Since there is no
other goto cleanup, you might as well inline the result=-1 into the
failure paths, and have a single label.  Or better yet, since
datastoreList is NULL unless esxVI_LooupObjectContentByType succeeded,
you can write this function without any gotos:

if esxVI_EnsureSession(priv->host) < 0) {
    return -1;
}
...

> +
> +static int
> +esxListStoragePools(virConnectPtr conn, char **const names, int maxnames)
> +{
> +    esxPrivate *priv = conn->storagePrivateData;
> +    esxVI_String *propertyNameList = NULL;
> +    esxVI_DynamicProperty *dynamicProperty = NULL;
> +    esxVI_ObjectContent *datastoreList = NULL;
> +    esxVI_ObjectContent *datastore = NULL;
> +    int count = 0;
> +    int i;
> +
> +    if (names == NULL || maxnames < 0) {
> +        ESX_ERROR(VIR_ERR_INVALID_ARG, "%s", _("Invalid argument"));
> +        return -1;
> +    }
> +
> +    if (maxnames == 0) {
> +        return 0;
> +    }
> +
> +    if (esxVI_EnsureSession(priv->host) < 0) {
> +        goto failure;
> +    }
> +
> +    if (esxVI_String_AppendValueToList(&propertyNameList,
> +                                       "summary.name") < 0 ||
> +        esxVI_LookupObjectContentByType(priv->host, priv->host->datacenter,
> +                                        "Datastore", propertyNameList,
> +                                        esxVI_Boolean_True,
> +                                        &datastoreList) < 0) {
> +        goto failure;
> +    }
> +
> +    for (datastore = datastoreList; datastore != NULL;
> +         datastore = datastore->_next) {
> +        for (dynamicProperty = datastore->propSet; dynamicProperty != NULL;
> +             dynamicProperty = dynamicProperty->_next) {
> +            if (STREQ(dynamicProperty->name, "summary.name")) {
> +                if (esxVI_AnyType_ExpectType(dynamicProperty->val,
> +                                             esxVI_Type_String) < 0) {
> +                    goto failure;
> +                }
> +
> +                names[count] = strdup(dynamicProperty->val->string);
> +
> +                if (names[count] == NULL) {
> +                    virReportOOMError();
> +                    goto failure;
> +                }
> +
> +                ++count;
> +                break;
> +            } else {
> +                VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
> +            }
> +        }
> +    }
> +
> +  cleanup:
> +    esxVI_String_Free(&propertyNameList);
> +    esxVI_ObjectContent_Free(&datastoreList);
> +
> +    return count;
> +
> +  failure:
> +    for (i = 0; i < count; ++i) {
> +        VIR_FREE(names[i]);
> +    }
> +
> +    count = -1;
> +
> +    goto cleanup;

Here, I think you need to keep one label, but think it can be written
with one instead of two, by tracking two variables instead of one:

{
    int count = 0;
    bool success = false;

    if (something fails)
        goto cleanup;
...

    success = true;

cleanup:
    if (!success) {
        for (i = 0; i < count; ++i)
            VIR_FREE(names[i]);
        count = -1;
    }
    esxVI_String_Free(&propertyNameList);
    esxVI_ObjectContent_Free(&datastoreList);

    return count;
}

> +
> +static int
> +esxStoragePoolRefresh(virStoragePoolPtr pool,
> +                      unsigned int flags ATTRIBUTE_UNUSED)
> +{
> +    int result = 0;
> +    esxPrivate *priv = pool->conn->storagePrivateData;
> +    esxVI_ObjectContent *datastore = NULL;

Is it worth a virCheckFlags() here?

> +
> +    if (esxVI_EnsureSession(priv->host) < 0) {
> +        goto failure;
> +    }
> +
> +    if (esxVI_LookupDatastoreByName(priv->host, pool->name, NULL, &datastore,
> +                                    esxVI_Occurrence_RequiredItem) < 0 ||
> +        esxVI_RefreshDatastore(priv->host, datastore->obj) < 0) {
> +        goto failure;
> +    }
> +
> +  cleanup:
> +    esxVI_ObjectContent_Free(&datastore);
> +
> +    return result;
> +
> +  failure:
> +    result = -1;
> +
> +    goto cleanup;

Another one of those reverse gotos that could be cleaned up.

> +
> +
> +static char *
> +esxStoragePoolGetXMLDesc(virStoragePoolPtr pool, unsigned int flags)
> +{
...
> +        /* See vSphere API documentation about HostDatastoreSystem for details */
> +        if ((localInfo = esxVI_LocalDatastoreInfo_DynamicCast(info)) != NULL) {
> +            def.type = VIR_STORAGE_POOL_DIR;
> +            def.target.path = localInfo->path;
> +        } else if ((nasInfo = esxVI_NasDatastoreInfo_DynamicCast(info)) != NULL) {
> +            def.type = VIR_STORAGE_POOL_NETFS;
> +            def.source.host.name = nasInfo->nas->remoteHost;
> +            def.source.dir = nasInfo->nas->remotePath;
> +
> +            if (STRCASEEQ(nasInfo->nas->type, "NFS")) {
> +                def.source.format = VIR_STORAGE_POOL_NETFS_NFS;
> +            } else  if (STRCASEEQ(nasInfo->nas->type, "CIFS")) {
> +                def.source.format = VIR_STORAGE_POOL_NETFS_CIFS;
> +            } else {
> +                ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
> +                          _("Datastore has unexpected type '%s'"),
> +                          nasInfo->nas->type);
> +                goto failure;
> +            }
> +        } else if ((vmfsInfo = esxVI_VmfsDatastoreInfo_DynamicCast(info)) != NULL) {
> +            def.type = VIR_STORAGE_POOL_FS;
> +            /* FIXME */

Details on what needs fixing?

> +++ b/src/esx/esx_vi.c
> @@ -1530,6 +1530,114 @@ esxVI_GetVirtualMachineQuestionInfo
>  
> @@ -2161,7 +2269,7 @@ esxVI_LookupDatastoreByName(esxVI_Context *ctx, const char *name,
>      esxVI_ObjectContent *candidate = NULL;
>      esxVI_DynamicProperty *dynamicProperty = NULL;
>      esxVI_Boolean accessible = esxVI_Boolean_Undefined;
> -    size_t offset = strlen("/vmfs/volumes/");
> +    int offset = 14; /* = strlen("/vmfs/volumes/") */

Why the change from size_t to int?  Although it probably doesn't affect
code.

> +++ b/src/esx/esx_vi.h
> @@ -98,11 +98,14 @@ enum _esxVI_APIVersion {
>  
>  enum _esxVI_ProductVersion {
>      esxVI_ProductVersion_Undefined = 0,
> -    esxVI_ProductVersion_GSX20,
> -    esxVI_ProductVersion_ESX35,
> -    esxVI_ProductVersion_ESX40,
> -    esxVI_ProductVersion_VPX25,
> -    esxVI_ProductVersion_VPX40
> +    esxVI_ProductVersion_GSX   = 0x1000,
> +    esxVI_ProductVersion_GSX20 = 0x1001,
> +    esxVI_ProductVersion_ESX   = 0x2000,
> +    esxVI_ProductVersion_ESX35 = 0x2001,
> +    esxVI_ProductVersion_ESX40 = 0x2002,
> +    esxVI_ProductVersion_VPX   = 0x4000,
> +    esxVI_ProductVersion_VPX25 = 0x4001,
> +    esxVI_ProductVersion_VPX40 = 0x4002

Is it worth documenting the convention you used here, in case someone
has to add to the enum later on?

-- 
Eric Blake   eblake at redhat.com    +1-801-349-2682
Libvirt virtualization library http://libvirt.org




More information about the libvir-list mailing list