esx: Add read-only storage pool access

Allows listing existing pools and requesting information about them.

Alter the esxVI_ProductVersion enum in a way that allows to check for
product type by masking.
This commit is contained in:
Matthias Bolte 2010-05-18 18:11:59 +02:00
parent 6e6acb776b
commit ddb4ae0ca9
6 changed files with 794 additions and 29 deletions

View File

@ -20,6 +20,7 @@ src/cpu/cpu_x86.c
src/datatypes.c
src/driver.c
src/esx/esx_driver.c
src/esx/esx_storage_driver.c
src/esx/esx_util.c
src/esx/esx_vi.c
src/esx/esx_vi_methods.c

View File

@ -29,6 +29,7 @@
#include "memory.h"
#include "logging.h"
#include "uuid.h"
#include "storage_conf.h"
#include "esx_private.h"
#include "esx_storage_driver.h"
#include "esx_vi.h"
@ -65,17 +66,587 @@ esxStorageClose(virConnectPtr conn)
static int
esxNumberOfStoragePools(virConnectPtr conn)
{
int count = 0;
esxPrivate *priv = conn->storagePrivateData;
esxVI_ObjectContent *datastoreList = NULL;
esxVI_ObjectContent *datastore = NULL;
if (esxVI_EnsureSession(priv->host) < 0) {
return -1;
}
if (esxVI_LookupObjectContentByType(priv->host, priv->host->datacenter,
"Datastore", NULL, esxVI_Boolean_True,
&datastoreList) < 0) {
return -1;
}
for (datastore = datastoreList; datastore != NULL;
datastore = datastore->_next) {
++count;
}
esxVI_ObjectContent_Free(&datastoreList);
return count;
}
static int
esxListStoragePools(virConnectPtr conn, char **const names, int maxnames)
{
bool success = false;
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) {
return -1;
}
if (esxVI_String_AppendValueToList(&propertyNameList,
"summary.name") < 0 ||
esxVI_LookupObjectContentByType(priv->host, priv->host->datacenter,
"Datastore", propertyNameList,
esxVI_Boolean_True,
&datastoreList) < 0) {
goto cleanup;
}
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 cleanup;
}
names[count] = strdup(dynamicProperty->val->string);
if (names[count] == NULL) {
virReportOOMError();
goto cleanup;
}
++count;
break;
} else {
VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
}
}
}
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
esxNumberOfDefinedStoragePools(virConnectPtr conn ATTRIBUTE_UNUSED)
{
/* ESX storage pools are always active */
return 0;
}
static int
esxListDefinedStoragePools(virConnectPtr conn ATTRIBUTE_UNUSED,
char **const names ATTRIBUTE_UNUSED,
int maxnames ATTRIBUTE_UNUSED)
{
/* ESX storage pools are always active */
return 0;
}
static virStoragePoolPtr
esxStoragePoolLookupByName(virConnectPtr conn, const char *name)
{
esxPrivate *priv = conn->storagePrivateData;
esxVI_String *propertyNameList = NULL;
esxVI_ObjectContent *datastore = NULL;
esxVI_Boolean accessible = esxVI_Boolean_Undefined;
char *summaryUrl = NULL;
char *suffix = NULL;
int suffixLength;
char uuid_string[VIR_UUID_STRING_BUFLEN] = "00000000-00000000-0000-000000000000";
unsigned char uuid[VIR_UUID_BUFLEN];
char *realName = NULL;
virStoragePoolPtr pool = NULL;
if (esxVI_EnsureSession(priv->host) < 0) {
return NULL;
}
if (esxVI_String_AppendValueListToList(&propertyNameList,
"summary.accessible\0"
"summary.name\0"
"summary.url\0") < 0 ||
esxVI_LookupDatastoreByName(priv->host, name,
propertyNameList, &datastore,
esxVI_Occurrence_RequiredItem) < 0 ||
esxVI_GetBoolean(datastore, "summary.accessible",
&accessible, esxVI_Occurrence_RequiredItem) < 0) {
goto cleanup;
}
/*
* Datastores don't have a UUID. We can use the 'summary.url' property as
* source for a "UUID" on ESX, because the property value has this format:
*
* summary.url = /vmfs/volumes/4b0beca7-7fd401f3-1d7f-000ae484a6a3
* summary.url = /vmfs/volumes/b24b7a78-9d82b4f5 (short format)
*
* The 'summary.url' property comes in two forms, with a complete "UUID"
* and a short "UUID".
*
* But this trailing "UUID" is not guaranteed to be there. On the other
* hand we already rely on another implementation detail of the ESX server:
* The object name of virtual machine contains an integer, we use that as
* domain ID.
*
* The 'summary.url' property of an inaccessible datastore is invalid.
*/
if (accessible == esxVI_Boolean_True &&
priv->host->productVersion & esxVI_ProductVersion_ESX) {
if (esxVI_GetStringValue(datastore, "summary.url", &summaryUrl,
esxVI_Occurrence_RequiredItem) < 0) {
goto cleanup;
}
if ((suffix = STRSKIP(summaryUrl, "/vmfs/volumes/")) == NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Datastore URL '%s' has unexpected prefix, "
"expecting '/vmfs/volumes/' prefix"), summaryUrl);
goto cleanup;
}
suffixLength = strlen(suffix);
if ((suffixLength == 35 && /* = strlen("4b0beca7-7fd401f3-1d7f-000ae484a6a3") */
suffix[8] == '-' && suffix[17] == '-' && suffix[22] == '-') ||
(suffixLength == 17 && /* = strlen("b24b7a78-9d82b4f5") */
suffix[8] == '-')) {
/*
* Intentionally use memcpy here, because we want to be able to
* replace a prefix of the initial Zero-UUID. virStrncpy would
* null-terminate the string in an unwanted place.
*/
memcpy(uuid_string, suffix, suffixLength);
} else {
VIR_WARN("Datastore URL suffix '%s' has unexpected format, "
"cannot deduce a UUID from it", suffix);
}
}
if (virUUIDParse(uuid_string, uuid) < 0) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Could not parse UUID from string '%s'"),
uuid_string);
goto cleanup;
}
if (esxVI_GetStringValue(datastore, "summary.name", &realName,
esxVI_Occurrence_RequiredItem) < 0) {
goto cleanup;
}
pool = virGetStoragePool(conn, realName, uuid);
cleanup:
esxVI_String_Free(&propertyNameList);
esxVI_ObjectContent_Free(&datastore);
return pool;
}
static virStoragePoolPtr
esxStoragePoolLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
{
esxPrivate *priv = conn->storagePrivateData;
esxVI_String *propertyNameList = NULL;
esxVI_ObjectContent *datastore = NULL;
char uuid_string[VIR_UUID_STRING_BUFLEN] = "";
char *name = NULL;
virStoragePoolPtr pool = NULL;
if (! (priv->host->productVersion & esxVI_ProductVersion_ESX)) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Lookup by UUID is supported on ESX only"));
return NULL;
}
if (esxVI_EnsureSession(priv->host) < 0) {
return NULL;
}
/*
* Convert from UUID to datastore URL form by stripping the second '-':
*
* <---- 14 ----><-------- 22 --------> <---- 13 ---><-------- 22 -------->
* 4b0beca7-7fd4-01f3-1d7f-000ae484a6a3 -> 4b0beca7-7fd401f3-1d7f-000ae484a6a3
*/
virUUIDFormat(uuid, uuid_string);
memmove(uuid_string + 13, uuid_string + 14, 22 + 1);
/*
* Use esxVI_LookupDatastoreByName because it also does try to match "UUID"
* part of the 'summary.url' property if there is no name match.
*/
if (esxVI_String_AppendValueToList(&propertyNameList, "summary.name") < 0 ||
esxVI_LookupDatastoreByName(priv->host, uuid_string,
propertyNameList, &datastore,
esxVI_Occurrence_OptionalItem) < 0) {
goto cleanup;
}
/*
* If the first try didn't succeed and the trailing 16 digits are zero then
* the "UUID" could be a short one. Strip the 16 zeros and try again:
*
* <------ 17 -----> <------ 17 ----->
* b24b7a78-9d82b4f5-0000-000000000000 -> b24b7a78-9d82b4f5
*/
if (datastore == NULL && STREQ(uuid_string + 17, "-0000-000000000000")) {
uuid_string[17] = '\0';
if (esxVI_LookupDatastoreByName(priv->host, uuid_string,
propertyNameList, &datastore,
esxVI_Occurrence_RequiredItem) < 0) {
goto cleanup;
}
}
if (datastore == NULL) {
virUUIDFormat(uuid, uuid_string);
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Could not find datastore with UUID '%s'"),
uuid_string);
goto cleanup;
}
if (esxVI_GetStringValue(datastore, "summary.name", &name,
esxVI_Occurrence_RequiredItem) < 0) {
goto cleanup;
}
pool = virGetStoragePool(conn, name, uuid);
cleanup:
esxVI_String_Free(&propertyNameList);
esxVI_ObjectContent_Free(&datastore);
return pool;
}
static int
esxStoragePoolRefresh(virStoragePoolPtr pool, unsigned int flags)
{
int result = -1;
esxPrivate *priv = pool->conn->storagePrivateData;
esxVI_ObjectContent *datastore = NULL;
virCheckFlags(0, -1);
if (esxVI_EnsureSession(priv->host) < 0) {
return -1;
}
if (esxVI_LookupDatastoreByName(priv->host, pool->name, NULL, &datastore,
esxVI_Occurrence_RequiredItem) < 0 ||
esxVI_RefreshDatastore(priv->host, datastore->obj) < 0) {
goto cleanup;
}
result = 0;
cleanup:
esxVI_ObjectContent_Free(&datastore);
return result;
}
static int
esxStoragePoolGetInfo(virStoragePoolPtr pool, virStoragePoolInfoPtr info)
{
int result = -1;
esxPrivate *priv = pool->conn->storagePrivateData;
esxVI_String *propertyNameList = NULL;
esxVI_ObjectContent *datastore = NULL;
esxVI_DynamicProperty *dynamicProperty = NULL;
esxVI_Boolean accessible = esxVI_Boolean_Undefined;
memset(info, 0, sizeof (*info));
if (esxVI_EnsureSession(priv->host) < 0) {
return -1;
}
if (esxVI_String_AppendValueListToList(&propertyNameList,
"summary.accessible\0"
"summary.capacity\0"
"summary.freeSpace\0") < 0 ||
esxVI_LookupDatastoreByName(priv->host, pool->name,
propertyNameList, &datastore,
esxVI_Occurrence_RequiredItem) < 0 ||
esxVI_GetBoolean(datastore, "summary.accessible",
&accessible, esxVI_Occurrence_RequiredItem) < 0) {
goto cleanup;
}
if (accessible == esxVI_Boolean_True) {
info->state = VIR_STORAGE_POOL_RUNNING;
for (dynamicProperty = datastore->propSet; dynamicProperty != NULL;
dynamicProperty = dynamicProperty->_next) {
if (STREQ(dynamicProperty->name, "summary.capacity")) {
if (esxVI_AnyType_ExpectType(dynamicProperty->val,
esxVI_Type_Long) < 0) {
goto cleanup;
}
info->capacity = dynamicProperty->val->int64;
} else if (STREQ(dynamicProperty->name, "summary.freeSpace")) {
if (esxVI_AnyType_ExpectType(dynamicProperty->val,
esxVI_Type_Long) < 0) {
goto cleanup;
}
info->available = dynamicProperty->val->int64;
}
}
info->allocation = info->capacity - info->available;
} else {
info->state = VIR_STORAGE_POOL_INACCESSIBLE;
}
result = 0;
cleanup:
if (result < 0) {
memset(info, 0, sizeof (*info));
}
esxVI_String_Free(&propertyNameList);
esxVI_ObjectContent_Free(&datastore);
return result;
}
static char *
esxStoragePoolGetXMLDesc(virStoragePoolPtr pool, unsigned int flags)
{
esxPrivate *priv = pool->conn->storagePrivateData;
esxVI_String *propertyNameList = NULL;
esxVI_ObjectContent *datastore = NULL;
esxVI_DynamicProperty *dynamicProperty = NULL;
esxVI_Boolean accessible = esxVI_Boolean_Undefined;
virStoragePoolDef def;
esxVI_DatastoreInfo *info = NULL;
esxVI_LocalDatastoreInfo *localInfo = NULL;
esxVI_NasDatastoreInfo *nasInfo = NULL;
esxVI_VmfsDatastoreInfo *vmfsInfo = NULL;
char *xml = NULL;
virCheckFlags(0, NULL);
memset(&def, 0, sizeof (def));
if (esxVI_EnsureSession(priv->host) < 0) {
return NULL;
}
if (esxVI_String_AppendValueListToList(&propertyNameList,
"summary.accessible\0"
"summary.capacity\0"
"summary.freeSpace\0"
"info\0") < 0 ||
esxVI_LookupDatastoreByName(priv->host, pool->name,
propertyNameList, &datastore,
esxVI_Occurrence_RequiredItem) < 0 ||
esxVI_GetBoolean(datastore, "summary.accessible",
&accessible, esxVI_Occurrence_RequiredItem) < 0) {
goto cleanup;
}
def.name = pool->name;
memcpy(def.uuid, pool->uuid, VIR_UUID_BUFLEN);
if (accessible == esxVI_Boolean_True) {
for (dynamicProperty = datastore->propSet; dynamicProperty != NULL;
dynamicProperty = dynamicProperty->_next) {
if (STREQ(dynamicProperty->name, "summary.capacity")) {
if (esxVI_AnyType_ExpectType(dynamicProperty->val,
esxVI_Type_Long) < 0) {
goto cleanup;
}
def.capacity = dynamicProperty->val->int64;
} else if (STREQ(dynamicProperty->name, "summary.freeSpace")) {
if (esxVI_AnyType_ExpectType(dynamicProperty->val,
esxVI_Type_Long) < 0) {
goto cleanup;
}
def.available = dynamicProperty->val->int64;
} else if (STREQ(dynamicProperty->name, "info")) {
if (esxVI_DatastoreInfo_CastFromAnyType(dynamicProperty->val,
&info) < 0) {
goto cleanup;
}
}
}
def.allocation = def.capacity - def.available;
/* 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 cleanup;
}
} else if ((vmfsInfo = esxVI_VmfsDatastoreInfo_DynamicCast(info)) != NULL) {
def.type = VIR_STORAGE_POOL_FS;
/*
* FIXME: I'm not sure how to represent the source and target of a
* VMFS based datastore in libvirt terms
*/
} else {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("DatastoreInfo has unexpected type"));
goto cleanup;
}
}
xml = virStoragePoolDefFormat(&def);
cleanup:
esxVI_String_Free(&propertyNameList);
esxVI_ObjectContent_Free(&datastore);
esxVI_DatastoreInfo_Free(&info);
return xml;
}
static int
esxStoragePoolGetAutostart(virStoragePoolPtr pool ATTRIBUTE_UNUSED,
int *autostart)
{
/* ESX storage pools are always active */
*autostart = 1;
return 0;
}
static int
esxStoragePoolSetAutostart(virStoragePoolPtr pool ATTRIBUTE_UNUSED,
int autostart)
{
/* Just accept autostart activation, but fail on autostart deactivation */
autostart = (autostart != 0);
if (! autostart) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Cannot deactivate storage pool autostart"));
return -1;
}
return 0;
}
static int
esxStoragePoolIsActive(virStoragePoolPtr pool ATTRIBUTE_UNUSED)
{
/* ESX storage pools are always active */
return 1;
}
static int
esxStoragePoolIsPersistent(virStoragePoolPtr pool ATTRIBUTE_UNUSED)
{
/* ESX has no concept of transient pools, so all of them are persistent */
return 1;
}
static virStorageDriver esxStorageDriver = {
"ESX", /* name */
esxStorageOpen, /* open */
esxStorageClose, /* close */
NULL, /* numOfPools */
NULL, /* listPools */
NULL, /* numOfDefinedPools */
NULL, /* listDefinedPools */
esxNumberOfStoragePools, /* numOfPools */
esxListStoragePools, /* listPools */
esxNumberOfDefinedStoragePools, /* numOfDefinedPools */
esxListDefinedStoragePools, /* listDefinedPools */
NULL, /* findPoolSources */
NULL, /* poolLookupByName */
NULL, /* poolLookupByUUID */
esxStoragePoolLookupByName, /* poolLookupByName */
esxStoragePoolLookupByUUID, /* poolLookupByUUID */
NULL, /* poolLookupByVolume */
NULL, /* poolCreateXML */
NULL, /* poolDefineXML */
@ -84,11 +655,11 @@ static virStorageDriver esxStorageDriver = {
NULL, /* poolCreate */
NULL, /* poolDestroy */
NULL, /* poolDelete */
NULL, /* poolRefresh */
NULL, /* poolGetInfo */
NULL, /* poolGetXMLDesc */
NULL, /* poolGetAutostart */
NULL, /* poolSetAutostart */
esxStoragePoolRefresh, /* poolRefresh */
esxStoragePoolGetInfo, /* poolGetInfo */
esxStoragePoolGetXMLDesc, /* poolGetXMLDesc */
esxStoragePoolGetAutostart, /* poolGetAutostart */
esxStoragePoolSetAutostart, /* poolSetAutostart */
NULL, /* poolNumOfVolumes */
NULL, /* poolListVolumes */
NULL, /* volLookupByName */
@ -101,8 +672,8 @@ static virStorageDriver esxStorageDriver = {
NULL, /* volGetInfo */
NULL, /* volGetXMLDesc */
NULL, /* volGetPath */
NULL, /* poolIsActive */
NULL, /* poolIsPersistent */
esxStoragePoolIsActive, /* poolIsActive */
esxStoragePoolIsPersistent, /* poolIsPersistent */
};

View File

@ -1529,6 +1529,114 @@ esxVI_GetVirtualMachineQuestionInfo
int
esxVI_GetBoolean(esxVI_ObjectContent *objectContent, const char *propertyName,
esxVI_Boolean *value, esxVI_Occurrence occurence)
{
esxVI_DynamicProperty *dynamicProperty;
if (value == NULL || *value != esxVI_Boolean_Undefined) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
return -1;
}
for (dynamicProperty = objectContent->propSet; dynamicProperty != NULL;
dynamicProperty = dynamicProperty->_next) {
if (STREQ(dynamicProperty->name, propertyName)) {
if (esxVI_AnyType_ExpectType(dynamicProperty->val,
esxVI_Type_Boolean) < 0) {
return -1;
}
*value = dynamicProperty->val->boolean;
break;
}
}
if (*value == esxVI_Boolean_Undefined &&
occurence == esxVI_Occurrence_RequiredItem) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Missing '%s' property"), propertyName);
return -1;
}
return 0;
}
int
esxVI_GetStringValue(esxVI_ObjectContent *objectContent,
const char *propertyName,
char **value, esxVI_Occurrence occurence)
{
esxVI_DynamicProperty *dynamicProperty;
if (value == NULL || *value != NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
return -1;
}
for (dynamicProperty = objectContent->propSet; dynamicProperty != NULL;
dynamicProperty = dynamicProperty->_next) {
if (STREQ(dynamicProperty->name, propertyName)) {
if (esxVI_AnyType_ExpectType(dynamicProperty->val,
esxVI_Type_String) < 0) {
return -1;
}
*value = dynamicProperty->val->string;
break;
}
}
if (*value == NULL && occurence == esxVI_Occurrence_RequiredItem) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Missing '%s' property"), propertyName);
return -1;
}
return 0;
}
int
esxVI_GetManagedObjectReference(esxVI_ObjectContent *objectContent,
const char *propertyName,
esxVI_ManagedObjectReference **value,
esxVI_Occurrence occurence)
{
esxVI_DynamicProperty *dynamicProperty;
if (value == NULL || *value != NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
return -1;
}
for (dynamicProperty = objectContent->propSet; dynamicProperty != NULL;
dynamicProperty = dynamicProperty->_next) {
if (STREQ(dynamicProperty->name, propertyName)) {
if (esxVI_ManagedObjectReference_CastFromAnyType
(dynamicProperty->val, value) < 0) {
return -1;
}
break;
}
}
if (*value == NULL && occurence == esxVI_Occurrence_RequiredItem) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Missing '%s' property"), propertyName);
return -1;
}
return 0;
}
int
esxVI_LookupNumberOfDomainsByPowerState(esxVI_Context *ctx,
esxVI_VirtualMachinePowerState powerState,
@ -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/");
size_t offset = 14; /* = strlen("/vmfs/volumes/") */
int numInaccessibleDatastores = 0;
if (datastore == NULL || *datastore != NULL) {
@ -2227,9 +2335,7 @@ esxVI_LookupDatastoreByName(esxVI_Context *ctx, const char *name,
for (dynamicProperty = candidate->propSet; dynamicProperty != NULL;
dynamicProperty = dynamicProperty->_next) {
if (STREQ(dynamicProperty->name, "summary.accessible")) {
/* Ignore it */
} else if (STREQ(dynamicProperty->name, "summary.name")) {
if (STREQ(dynamicProperty->name, "summary.name")) {
if (esxVI_AnyType_ExpectType(dynamicProperty->val,
esxVI_Type_String) < 0) {
goto failure;
@ -2244,7 +2350,8 @@ esxVI_LookupDatastoreByName(esxVI_Context *ctx, const char *name,
/* Found datastore with matching name */
goto cleanup;
}
} else if (STREQ(dynamicProperty->name, "summary.url")) {
} else if (STREQ(dynamicProperty->name, "summary.url") &&
ctx->productVersion & esxVI_ProductVersion_ESX) {
if (accessible == esxVI_Boolean_False) {
/*
* The 'summary.url' property of an inaccessible datastore
@ -2276,8 +2383,6 @@ esxVI_LookupDatastoreByName(esxVI_Context *ctx, const char *name,
/* Found datastore with matching URL suffix */
goto cleanup;
}
} else {
VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
}
}
}
@ -2309,9 +2414,10 @@ esxVI_LookupDatastoreByName(esxVI_Context *ctx, const char *name,
int esxVI_LookupTaskInfoByTask(esxVI_Context *ctx,
esxVI_ManagedObjectReference *task,
esxVI_TaskInfo **taskInfo)
int
esxVI_LookupTaskInfoByTask(esxVI_Context *ctx,
esxVI_ManagedObjectReference *task,
esxVI_TaskInfo **taskInfo)
{
int result = 0;
esxVI_String *propertyNameList = NULL;

View File

@ -96,13 +96,23 @@ enum _esxVI_APIVersion {
esxVI_APIVersion_40
};
/*
* AAAABBBB: where AAAA0000 is the product and BBBB the version. this format
* allows simple bitmask testing for a product independent of the version
*/
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 = (1 << 0) << 16,
esxVI_ProductVersion_GSX20 = esxVI_ProductVersion_GSX | 1,
esxVI_ProductVersion_ESX = (1 << 1) << 16,
esxVI_ProductVersion_ESX35 = esxVI_ProductVersion_ESX | 1,
esxVI_ProductVersion_ESX40 = esxVI_ProductVersion_ESX | 2,
esxVI_ProductVersion_VPX = (1 << 2) << 16,
esxVI_ProductVersion_VPX25 = esxVI_ProductVersion_VPX | 1,
esxVI_ProductVersion_VPX40 = esxVI_ProductVersion_VPX | 2
};
enum _esxVI_Occurrence {
@ -272,6 +282,19 @@ int esxVI_GetVirtualMachineQuestionInfo
(esxVI_ObjectContent *virtualMachine,
esxVI_VirtualMachineQuestionInfo **questionInfo);
int esxVI_GetBoolean(esxVI_ObjectContent *objectContent,
const char *propertyName,
esxVI_Boolean *value, esxVI_Occurrence occurence);
int esxVI_GetStringValue(esxVI_ObjectContent *objectContent,
const char *propertyName,
char **value, esxVI_Occurrence occurence);
int esxVI_GetManagedObjectReference(esxVI_ObjectContent *objectContent,
const char *propertyName,
esxVI_ManagedObjectReference **value,
esxVI_Occurrence occurence);
int esxVI_LookupNumberOfDomainsByPowerState
(esxVI_Context *ctx, esxVI_VirtualMachinePowerState powerState,
esxVI_Boolean inverse);

View File

@ -146,6 +146,14 @@ object ChoiceOption extends OptionType
end
object DatastoreInfo
String name r
String url r
Long freeSpace r
Long maxFileSize r
end
object Description
String label r
String summary r
@ -186,6 +194,47 @@ object HostCpuIdInfo
end
object HostFileSystemVolume
String type r
String name r
Long capacity r
end
object HostNasVolume extends HostFileSystemVolume
String remoteHost r
String remotePath r
String userName o
end
object HostScsiDiskPartition
String diskName r
Int partition r
end
object HostVmfsVolume extends HostFileSystemVolume
Int blockSizeMb r
Int maxBlocks r
Int majorVersion r
String version r
String uuid r
HostScsiDiskPartition extent rl
Boolean vmfsUpgradable r
end
object LocalDatastoreInfo extends DatastoreInfo
String path o
end
object NasDatastoreInfo extends DatastoreInfo
HostNasVolume nas o
end
object ObjectContent
ManagedObjectReference obj r
DynamicProperty propSet ol
@ -453,6 +502,11 @@ object VirtualMachineSnapshotTree
end
object VmfsDatastoreInfo extends DatastoreInfo
HostVmfsVolume vmfs o
end
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Methods
#
@ -571,6 +625,11 @@ method ReconfigVM_Task returns ManagedObjectReference r
end
method RefreshDatastore
ManagedObjectReference _this r
end
method RegisterVM_Task returns ManagedObjectReference r
ManagedObjectReference _this r
String path r

View File

@ -382,6 +382,9 @@ class Object:
self.properties = properties
self.extended_by = extended_by
if self.extended_by is not None:
self.extended_by.sort();
def generate_struct_members(self, add_banner = False, struct_gap = False):
global objects_by_name
@ -1095,7 +1098,8 @@ additional_enum_features = { "ManagedEntityStatus" : Enum.FEATURE__ANY_TYPE
"VirtualMachinePowerState" : Enum.FEATURE__ANY_TYPE }
additional_object_features = { "Event" : Object.FEATURE__LIST,
additional_object_features = { "DatastoreInfo" : Object.FEATURE__ANY_TYPE | Object.FEATURE__DYNAMIC_CAST,
"Event" : Object.FEATURE__LIST,
"HostCpuIdInfo" : Object.FEATURE__ANY_TYPE | Object.FEATURE__LIST,
"ManagedObjectReference" : Object.FEATURE__ANY_TYPE,
"ObjectContent" : Object.FEATURE__DEEP_COPY | Object.FEATURE__LIST,
@ -1235,6 +1239,7 @@ for obj in objects_by_name.values():
extended_obj.extended_by = [obj.name]
else:
extended_obj.extended_by.append(obj.name)
extended_obj.extended_by.sort()