[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