From 681ff75e88ddd381cc69b634a7d8ef6ecaa0f297 Mon Sep 17 00:00:00 2001 From: Matthias Bolte Date: Sun, 8 Aug 2010 00:24:29 +0200 Subject: [PATCH] esx: Add read-only storage volume access This allows to list existing volumes and to retrieve information about them. --- src/esx/esx_driver.c | 112 +-------- src/esx/esx_storage_driver.c | 433 ++++++++++++++++++++++++++++++++- src/esx/esx_vi.c | 279 +++++++++++++++++++++ src/esx/esx_vi.h | 9 + src/esx/esx_vi_generator.input | 7 + 5 files changed, 724 insertions(+), 116 deletions(-) diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index 9fef1df74b..50d5bc03d8 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -348,19 +348,7 @@ esxAutodetectSCSIControllerModel(virDomainDiskDefPtr def, int *model, { int result = -1; esxVMX_Data *data = opaque; - char *datastoreName = NULL; - char *directoryName = NULL; - char *fileName = NULL; - char *datastorePath = NULL; - esxVI_String *propertyNameList = NULL; - esxVI_ObjectContent *datastore = NULL; - esxVI_ManagedObjectReference *hostDatastoreBrowser = NULL; - esxVI_HostDatastoreBrowserSearchSpec *searchSpec = NULL; - esxVI_VmDiskFileQuery *vmDiskFileQuery = NULL; - esxVI_ManagedObjectReference *task = NULL; - esxVI_TaskInfoState taskInfoState; - esxVI_TaskInfo *taskInfo = NULL; - esxVI_HostDatastoreBrowserSearchResults *searchResults = NULL; + esxVI_FileInfo *fileInfo = NULL; esxVI_VmDiskFileInfo *vmDiskFileInfo = NULL; if (def->device != VIR_DOMAIN_DISK_DEVICE_DISK || @@ -375,87 +363,12 @@ esxAutodetectSCSIControllerModel(virDomainDiskDefPtr def, int *model, return 0; } - if (esxUtil_ParseDatastorePath(def->src, &datastoreName, &directoryName, - &fileName) < 0) { + if (esxVI_LookupFileInfoByDatastorePath(data->ctx, def->src, &fileInfo, + esxVI_Occurrence_RequiredItem) < 0) { goto cleanup; } - if (directoryName == NULL) { - if (virAsprintf(&datastorePath, "[%s]", datastoreName) < 0) { - virReportOOMError(); - goto cleanup; - } - } else { - if (virAsprintf(&datastorePath, "[%s] %s", datastoreName, - directoryName) < 0) { - virReportOOMError(); - goto cleanup; - } - } - - /* Lookup HostDatastoreBrowser */ - if (esxVI_String_AppendValueToList(&propertyNameList, "browser") < 0 || - esxVI_LookupDatastoreByName(data->ctx, datastoreName, propertyNameList, - &datastore, - esxVI_Occurrence_RequiredItem) < 0 || - esxVI_GetManagedObjectReference(datastore, "browser", - &hostDatastoreBrowser, - esxVI_Occurrence_RequiredItem) < 0) { - goto cleanup; - } - - /* Build HostDatastoreBrowserSearchSpec */ - if (esxVI_HostDatastoreBrowserSearchSpec_Alloc(&searchSpec) < 0 || - esxVI_FileQueryFlags_Alloc(&searchSpec->details) < 0) { - goto cleanup; - } - - searchSpec->details->fileType = esxVI_Boolean_True; - searchSpec->details->fileSize = esxVI_Boolean_False; - searchSpec->details->modification = esxVI_Boolean_False; - - if (esxVI_VmDiskFileQuery_Alloc(&vmDiskFileQuery) < 0 || - esxVI_VmDiskFileQueryFlags_Alloc(&vmDiskFileQuery->details) < 0 || - esxVI_FileQuery_AppendToList - (&searchSpec->query, - esxVI_FileQuery_DynamicCast(vmDiskFileQuery)) < 0) { - goto cleanup; - } - - vmDiskFileQuery->details->diskType = esxVI_Boolean_False; - vmDiskFileQuery->details->capacityKb = esxVI_Boolean_False; - vmDiskFileQuery->details->hardwareVersion = esxVI_Boolean_False; - vmDiskFileQuery->details->controllerType = esxVI_Boolean_True; - vmDiskFileQuery->details->diskExtents = esxVI_Boolean_False; - - if (esxVI_String_Alloc(&searchSpec->matchPattern) < 0) { - goto cleanup; - } - - searchSpec->matchPattern->value = fileName; - - /* Search datastore for file */ - if (esxVI_SearchDatastore_Task(data->ctx, hostDatastoreBrowser, - datastorePath, searchSpec, &task) < 0 || - esxVI_WaitForTaskCompletion(data->ctx, task, NULL, esxVI_Occurrence_None, - esxVI_Boolean_False, &taskInfoState) < 0) { - goto cleanup; - } - - if (taskInfoState != esxVI_TaskInfoState_Success) { - ESX_ERROR(VIR_ERR_INTERNAL_ERROR, - _("Could not serach in datastore '%s'"), datastoreName); - goto cleanup; - } - - if (esxVI_LookupTaskInfoByTask(data->ctx, task, &taskInfo) < 0 || - esxVI_HostDatastoreBrowserSearchResults_CastFromAnyType - (taskInfo->result, &searchResults) < 0) { - goto cleanup; - } - - /* Interpret search result */ - vmDiskFileInfo = esxVI_VmDiskFileInfo_DynamicCast(searchResults->file); + vmDiskFileInfo = esxVI_VmDiskFileInfo_DynamicCast(fileInfo); if (vmDiskFileInfo == NULL || vmDiskFileInfo->controllerType == NULL) { ESX_ERROR(VIR_ERR_INTERNAL_ERROR, @@ -485,22 +398,7 @@ esxAutodetectSCSIControllerModel(virDomainDiskDefPtr def, int *model, result = 0; cleanup: - /* Don't double free fileName */ - if (searchSpec != NULL && searchSpec->matchPattern != NULL) { - searchSpec->matchPattern->value = NULL; - } - - VIR_FREE(datastoreName); - VIR_FREE(directoryName); - VIR_FREE(fileName); - VIR_FREE(datastorePath); - esxVI_String_Free(&propertyNameList); - esxVI_ObjectContent_Free(&datastore); - esxVI_ManagedObjectReference_Free(&hostDatastoreBrowser); - esxVI_HostDatastoreBrowserSearchSpec_Free(&searchSpec); - esxVI_ManagedObjectReference_Free(&task); - esxVI_TaskInfo_Free(&taskInfo); - esxVI_HostDatastoreBrowserSearchResults_Free(&searchResults); + esxVI_FileInfo_Free(&fileInfo); return result; } diff --git a/src/esx/esx_storage_driver.c b/src/esx/esx_storage_driver.c index 26747bbfd2..af8876a7df 100644 --- a/src/esx/esx_storage_driver.c +++ b/src/esx/esx_storage_driver.c @@ -32,6 +32,7 @@ #include "logging.h" #include "uuid.h" #include "storage_conf.h" +#include "storage_file.h" #include "esx_private.h" #include "esx_storage_driver.h" #include "esx_vi.h" @@ -310,6 +311,14 @@ esxStoragePoolLookupByUUID(virConnectPtr conn, const unsigned char *uuid) +static virStoragePoolPtr +esxStoragePoolLookupByVolume(virStorageVolPtr volume) +{ + return esxStoragePoolLookupByName(volume->conn, volume->pool); +} + + + static int esxStoragePoolRefresh(virStoragePoolPtr pool, unsigned int flags) { @@ -555,6 +564,411 @@ esxStoragePoolSetAutostart(virStoragePoolPtr pool ATTRIBUTE_UNUSED, +static int +esxStoragePoolNumberOfStorageVolumes(virStoragePoolPtr pool) +{ + bool success = false; + esxPrivate *priv = pool->conn->storagePrivateData; + esxVI_HostDatastoreBrowserSearchResults *searchResultsList = NULL; + esxVI_HostDatastoreBrowserSearchResults *searchResults = NULL; + esxVI_FileInfo *fileInfo = NULL; + int count = 0; + + if (esxVI_EnsureSession(priv->primary) < 0) { + return -1; + } + + if (esxVI_LookupDatastoreContentByDatastoreName(priv->primary, pool->name, + &searchResultsList) < 0) { + goto cleanup; + } + + /* Interpret search result */ + for (searchResults = searchResultsList; searchResults != NULL; + searchResults = searchResults->_next) { + for (fileInfo = searchResults->file; fileInfo != NULL; + fileInfo = fileInfo->_next) { + ++count; + } + } + + success = true; + + cleanup: + esxVI_HostDatastoreBrowserSearchResults_Free(&searchResultsList); + + return success ? count : -1; +} + + + +static int +esxStoragePoolListStorageVolumes(virStoragePoolPtr pool, char **const names, + int maxnames) +{ + bool success = false; + esxPrivate *priv = pool->conn->storagePrivateData; + esxVI_HostDatastoreBrowserSearchResults *searchResultsList = NULL; + esxVI_HostDatastoreBrowserSearchResults *searchResults = NULL; + esxVI_FileInfo *fileInfo = NULL; + char *datastoreName = NULL; + char *directoryName = NULL; + char *fileName = NULL; + char *prefix = 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->primary) < 0) { + return -1; + } + + if (esxVI_LookupDatastoreContentByDatastoreName(priv->primary, pool->name, + &searchResultsList) < 0) { + goto cleanup; + } + + /* Interpret search result */ + for (searchResults = searchResultsList; searchResults != NULL; + searchResults = searchResults->_next) { + VIR_FREE(datastoreName); + VIR_FREE(directoryName); + VIR_FREE(fileName); + VIR_FREE(prefix); + + if (esxUtil_ParseDatastorePath(searchResults->folderPath, &datastoreName, + &directoryName, &fileName) < 0) { + goto cleanup; + } + + if (directoryName != NULL) { + if (virAsprintf(&prefix, "%s/%s", directoryName, fileName) < 0) { + virReportOOMError(); + goto cleanup; + } + } else { + prefix = strdup(fileName); + + if (prefix == NULL) { + virReportOOMError(); + goto cleanup; + } + } + + for (fileInfo = searchResults->file; fileInfo != NULL; + fileInfo = fileInfo->_next) { + if (*prefix == '\0') { + names[count] = strdup(fileInfo->path); + + if (names[count] == NULL) { + virReportOOMError(); + goto cleanup; + } + } else if (virAsprintf(&names[count], "%s/%s", prefix, + fileInfo->path) < 0) { + virReportOOMError(); + goto cleanup; + } + + ++count; + } + } + + success = true; + + cleanup: + if (! success) { + for (i = 0; i < count; ++i) { + VIR_FREE(names[i]); + } + + count = -1; + } + + esxVI_HostDatastoreBrowserSearchResults_Free(&searchResultsList); + VIR_FREE(datastoreName); + VIR_FREE(directoryName); + VIR_FREE(fileName); + VIR_FREE(prefix); + + return count; +} + + + +static virStorageVolPtr +esxStorageVolumeLookupByName(virStoragePoolPtr pool, const char *name) +{ + virStorageVolPtr volume = NULL; + esxPrivate *priv = pool->conn->storagePrivateData; + char *datastorePath = NULL; + esxVI_FileInfo *fileInfo = NULL; + + if (esxVI_EnsureSession(priv->primary) < 0) { + return NULL; + } + + if (virAsprintf(&datastorePath, "[%s] %s", pool->name, name) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (esxVI_LookupFileInfoByDatastorePath(priv->primary, datastorePath, + &fileInfo, + esxVI_Occurrence_RequiredItem) < 0) { + goto cleanup; + } + + volume = virGetStorageVol(pool->conn, pool->name, name, datastorePath); + + cleanup: + VIR_FREE(datastorePath); + esxVI_FileInfo_Free(&fileInfo); + + return volume; +} + + + +static virStorageVolPtr +esxStorageVolumeLookupByKeyOrPath(virConnectPtr conn, const char *keyOrPath) +{ + virStorageVolPtr volume = NULL; + esxPrivate *priv = conn->storagePrivateData; + char *datastoreName = NULL; + char *directoryName = NULL; + char *fileName = NULL; + char *volumeName = NULL; + esxVI_FileInfo *fileInfo = NULL; + + if (esxVI_EnsureSession(priv->primary) < 0) { + return NULL; + } + + if (esxUtil_ParseDatastorePath(keyOrPath, &datastoreName, &directoryName, + &fileName) < 0) { + goto cleanup; + } + + if (directoryName != NULL) { + if (virAsprintf(&volumeName, "%s/%s", directoryName, fileName) < 0) { + virReportOOMError(); + goto cleanup; + } + } else { + volumeName = strdup(fileName); + + if (volumeName == NULL) { + virReportOOMError(); + goto cleanup; + } + } + + if (esxVI_LookupFileInfoByDatastorePath(priv->primary, keyOrPath, &fileInfo, + esxVI_Occurrence_RequiredItem) < 0) { + goto cleanup; + } + + volume = virGetStorageVol(conn, datastoreName, volumeName, keyOrPath); + + cleanup: + VIR_FREE(datastoreName); + VIR_FREE(directoryName); + VIR_FREE(fileName); + VIR_FREE(volumeName); + esxVI_FileInfo_Free(&fileInfo); + + return volume; +} + + + +static int +esxStorageVolumeGetInfo(virStorageVolPtr volume, virStorageVolInfoPtr info) +{ + int result = -1; + esxPrivate *priv = volume->conn->storagePrivateData; + char *datastorePath = NULL; + esxVI_FileInfo *fileInfo = NULL; + esxVI_VmDiskFileInfo *vmDiskFileInfo = NULL; + + memset(info, 0, sizeof (*info)); + + if (esxVI_EnsureSession(priv->primary) < 0) { + return -1; + } + + if (virAsprintf(&datastorePath, "[%s] %s", volume->pool, volume->name) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (esxVI_LookupFileInfoByDatastorePath(priv->primary, datastorePath, + &fileInfo, + esxVI_Occurrence_RequiredItem) < 0) { + goto cleanup; + } + + vmDiskFileInfo = esxVI_VmDiskFileInfo_DynamicCast(fileInfo); + + info->type = VIR_STORAGE_VOL_FILE; + + if (vmDiskFileInfo != NULL) { + info->capacity = vmDiskFileInfo->capacityKb->value * 1024; /* Scale from kilobyte to byte */ + info->allocation = vmDiskFileInfo->fileSize->value; + } else { + info->capacity = fileInfo->fileSize->value; + info->allocation = fileInfo->fileSize->value; + } + + result = 0; + + cleanup: + VIR_FREE(datastorePath); + esxVI_FileInfo_Free(&fileInfo); + + return result; +} + + + +static char * +esxStorageVolumeDumpXML(virStorageVolPtr volume, unsigned int flags) +{ + esxPrivate *priv = volume->conn->storagePrivateData; + esxVI_String *propertyNameList = NULL; + esxVI_ObjectContent *datastore = NULL; + esxVI_DynamicProperty *dynamicProperty = NULL; + esxVI_DatastoreInfo *datastoreInfo = NULL; + virStoragePoolDef pool; + char *datastorePath = NULL; + esxVI_FileInfo *fileInfo = NULL; + esxVI_VmDiskFileInfo *vmDiskFileInfo = NULL; + esxVI_IsoImageFileInfo *isoImageFileInfo = NULL; + esxVI_FloppyImageFileInfo *floppyImageFileInfo = NULL; + virStorageVolDef def; + char *xml = NULL; + + virCheckFlags(0, NULL); + + memset(&pool, 0, sizeof (pool)); + memset(&def, 0, sizeof (def)); + + if (esxVI_EnsureSession(priv->primary) < 0) { + return NULL; + } + + /* Lookup storage pool type */ + if (esxVI_String_AppendValueToList(&propertyNameList, "info") < 0 || + esxVI_LookupDatastoreByName(priv->primary, volume->pool, + propertyNameList, &datastore, + esxVI_Occurrence_RequiredItem) < 0) { + goto cleanup; + } + + for (dynamicProperty = datastore->propSet; dynamicProperty != NULL; + dynamicProperty = dynamicProperty->_next) { + if (STREQ(dynamicProperty->name, "info")) { + if (esxVI_DatastoreInfo_CastFromAnyType(dynamicProperty->val, + &datastoreInfo) < 0) { + goto cleanup; + } + + break; + } + } + + if (esxVI_LocalDatastoreInfo_DynamicCast(datastoreInfo) != NULL) { + pool.type = VIR_STORAGE_POOL_DIR; + } else if (esxVI_NasDatastoreInfo_DynamicCast(datastoreInfo) != NULL) { + pool.type = VIR_STORAGE_POOL_NETFS; + } else if (esxVI_VmfsDatastoreInfo_DynamicCast(datastoreInfo) != NULL) { + pool.type = VIR_STORAGE_POOL_FS; + } else { + ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", + _("DatastoreInfo has unexpected type")); + goto cleanup; + } + + /* Lookup file info */ + if (virAsprintf(&datastorePath, "[%s] %s", volume->pool, volume->name) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (esxVI_LookupFileInfoByDatastorePath(priv->primary, datastorePath, + &fileInfo, + esxVI_Occurrence_RequiredItem) < 0) { + goto cleanup; + } + + vmDiskFileInfo = esxVI_VmDiskFileInfo_DynamicCast(fileInfo); + isoImageFileInfo = esxVI_IsoImageFileInfo_DynamicCast(fileInfo); + floppyImageFileInfo = esxVI_FloppyImageFileInfo_DynamicCast(fileInfo); + + def.name = volume->name; + def.key = datastorePath; + def.type = VIR_STORAGE_VOL_FILE; + def.target.path = datastorePath; + + if (vmDiskFileInfo != NULL) { + def.capacity = vmDiskFileInfo->capacityKb->value * 1024; /* Scale from kilobyte to byte */ + def.allocation = vmDiskFileInfo->fileSize->value; + + def.target.format = VIR_STORAGE_FILE_VMDK; + } else if (isoImageFileInfo != NULL) { + def.capacity = fileInfo->fileSize->value; + def.allocation = fileInfo->fileSize->value; + + def.target.format = VIR_STORAGE_FILE_ISO; + } else if (floppyImageFileInfo != NULL) { + def.capacity = fileInfo->fileSize->value; + def.allocation = fileInfo->fileSize->value; + + def.target.format = VIR_STORAGE_FILE_RAW; + } else { + ESX_ERROR(VIR_ERR_INTERNAL_ERROR, + _("File '%s' has unknown type"), datastorePath); + goto cleanup; + } + + xml = virStorageVolDefFormat(&pool, &def); + + cleanup: + esxVI_String_Free(&propertyNameList); + esxVI_ObjectContent_Free(&datastore); + esxVI_DatastoreInfo_Free(&datastoreInfo); + VIR_FREE(datastorePath); + esxVI_FileInfo_Free(&fileInfo); + + return xml; +} + + + +static char * +esxStorageVolumeGetPath(virStorageVolPtr volume) +{ + char *path; + + if (virAsprintf(&path, "[%s] %s", volume->pool, volume->name) < 0) { + virReportOOMError(); + return NULL; + } + + return path; +} + + + static int esxStoragePoolIsActive(virStoragePoolPtr pool ATTRIBUTE_UNUSED) { @@ -572,6 +986,7 @@ esxStoragePoolIsPersistent(virStoragePoolPtr pool ATTRIBUTE_UNUSED) } + static virStorageDriver esxStorageDriver = { "ESX", /* name */ esxStorageOpen, /* open */ @@ -583,7 +998,7 @@ static virStorageDriver esxStorageDriver = { NULL, /* findPoolSources */ esxStoragePoolLookupByName, /* poolLookupByName */ esxStoragePoolLookupByUUID, /* poolLookupByUUID */ - NULL, /* poolLookupByVolume */ + esxStoragePoolLookupByVolume, /* poolLookupByVolume */ NULL, /* poolCreateXML */ NULL, /* poolDefineXML */ NULL, /* poolBuild */ @@ -596,18 +1011,18 @@ static virStorageDriver esxStorageDriver = { esxStoragePoolGetXMLDesc, /* poolGetXMLDesc */ esxStoragePoolGetAutostart, /* poolGetAutostart */ esxStoragePoolSetAutostart, /* poolSetAutostart */ - NULL, /* poolNumOfVolumes */ - NULL, /* poolListVolumes */ - NULL, /* volLookupByName */ - NULL, /* volLookupByKey */ - NULL, /* volLookupByPath */ + esxStoragePoolNumberOfStorageVolumes, /* poolNumOfVolumes */ + esxStoragePoolListStorageVolumes, /* poolListVolumes */ + esxStorageVolumeLookupByName, /* volLookupByName */ + esxStorageVolumeLookupByKeyOrPath, /* volLookupByKey */ + esxStorageVolumeLookupByKeyOrPath, /* volLookupByPath */ NULL, /* volCreateXML */ NULL, /* volCreateXMLFrom */ NULL, /* volDelete */ NULL, /* volWipe */ - NULL, /* volGetInfo */ - NULL, /* volGetXMLDesc */ - NULL, /* volGetPath */ + esxStorageVolumeGetInfo, /* volGetInfo */ + esxStorageVolumeDumpXML, /* volGetXMLDesc */ + esxStorageVolumeGetPath, /* volGetPath */ esxStoragePoolIsActive, /* poolIsActive */ esxStoragePoolIsPersistent, /* poolIsPersistent */ }; diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c index b5317980f2..1c6f6ffcba 100644 --- a/src/esx/esx_vi.c +++ b/src/esx/esx_vi.c @@ -2933,6 +2933,285 @@ esxVI_LookupCurrentSnapshotTree +int +esxVI_LookupFileInfoByDatastorePath(esxVI_Context *ctx, + const char *datastorePath, + esxVI_FileInfo **fileInfo, + esxVI_Occurrence occurrence) +{ + int result = -1; + char *datastoreName = NULL; + char *directoryName = NULL; + char *fileName = NULL; + char *datastorePathWithoutFileName = NULL; + esxVI_String *propertyNameList = NULL; + esxVI_ObjectContent *datastore = NULL; + esxVI_ManagedObjectReference *hostDatastoreBrowser = NULL; + esxVI_HostDatastoreBrowserSearchSpec *searchSpec = NULL; + esxVI_VmDiskFileQuery *vmDiskFileQuery = NULL; + esxVI_IsoImageFileQuery *isoImageFileQuery = NULL; + esxVI_FloppyImageFileQuery *floppyImageFileQuery = NULL; + esxVI_ManagedObjectReference *task = NULL; + esxVI_TaskInfoState taskInfoState; + esxVI_TaskInfo *taskInfo = NULL; + esxVI_HostDatastoreBrowserSearchResults *searchResults = NULL; + + if (fileInfo == NULL || *fileInfo != NULL) { + ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); + return -1; + } + + if (esxUtil_ParseDatastorePath(datastorePath, &datastoreName, + &directoryName, &fileName) < 0) { + goto cleanup; + } + + if (directoryName == NULL) { + if (virAsprintf(&datastorePathWithoutFileName, "[%s]", + datastoreName) < 0) { + virReportOOMError(); + goto cleanup; + } + } else { + if (virAsprintf(&datastorePathWithoutFileName, "[%s] %s", + datastoreName, directoryName) < 0) { + virReportOOMError(); + goto cleanup; + } + } + + /* Lookup HostDatastoreBrowser */ + if (esxVI_String_AppendValueToList(&propertyNameList, "browser") < 0 || + esxVI_LookupDatastoreByName(ctx, datastoreName, propertyNameList, + &datastore, + esxVI_Occurrence_RequiredItem) < 0 || + esxVI_GetManagedObjectReference(datastore, "browser", + &hostDatastoreBrowser, + esxVI_Occurrence_RequiredItem) < 0) { + goto cleanup; + } + + /* Build HostDatastoreBrowserSearchSpec */ + if (esxVI_HostDatastoreBrowserSearchSpec_Alloc(&searchSpec) < 0 || + esxVI_FileQueryFlags_Alloc(&searchSpec->details) < 0) { + goto cleanup; + } + + searchSpec->details->fileType = esxVI_Boolean_True; + searchSpec->details->fileSize = esxVI_Boolean_True; + searchSpec->details->modification = esxVI_Boolean_False; + + if (esxVI_VmDiskFileQuery_Alloc(&vmDiskFileQuery) < 0 || + esxVI_VmDiskFileQueryFlags_Alloc(&vmDiskFileQuery->details) < 0 || + esxVI_FileQuery_AppendToList + (&searchSpec->query, + esxVI_FileQuery_DynamicCast(vmDiskFileQuery)) < 0) { + goto cleanup; + } + + vmDiskFileQuery->details->diskType = esxVI_Boolean_False; + vmDiskFileQuery->details->capacityKb = esxVI_Boolean_True; + vmDiskFileQuery->details->hardwareVersion = esxVI_Boolean_False; + vmDiskFileQuery->details->controllerType = esxVI_Boolean_True; + vmDiskFileQuery->details->diskExtents = esxVI_Boolean_False; + + if (esxVI_IsoImageFileQuery_Alloc(&isoImageFileQuery) < 0 || + esxVI_FileQuery_AppendToList + (&searchSpec->query, + esxVI_FileQuery_DynamicCast(isoImageFileQuery)) < 0) { + goto cleanup; + } + + if (esxVI_FloppyImageFileQuery_Alloc(&floppyImageFileQuery) < 0 || + esxVI_FileQuery_AppendToList + (&searchSpec->query, + esxVI_FileQuery_DynamicCast(floppyImageFileQuery)) < 0) { + goto cleanup; + } + + if (esxVI_String_Alloc(&searchSpec->matchPattern) < 0) { + goto cleanup; + } + + searchSpec->matchPattern->value = fileName; + + /* Search datastore for file */ + if (esxVI_SearchDatastore_Task(ctx, hostDatastoreBrowser, + datastorePathWithoutFileName, searchSpec, + &task) < 0 || + esxVI_WaitForTaskCompletion(ctx, task, NULL, esxVI_Occurrence_None, + esxVI_Boolean_False, &taskInfoState) < 0) { + goto cleanup; + } + + if (taskInfoState != esxVI_TaskInfoState_Success) { + ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, + _("Could not serach in datastore '%s'"), datastoreName); + goto cleanup; + } + + if (esxVI_LookupTaskInfoByTask(ctx, task, &taskInfo) < 0 || + esxVI_HostDatastoreBrowserSearchResults_CastFromAnyType + (taskInfo->result, &searchResults) < 0) { + goto cleanup; + } + + /* Interpret search result */ + if (searchResults->file == NULL) { + if (occurrence == esxVI_Occurrence_OptionalItem) { + result = 0; + + goto cleanup; + } else { + ESX_VI_ERROR(VIR_ERR_NO_STORAGE_VOL, + _("No storage volume with key or path '%s'"), + datastorePath); + goto cleanup; + } + } + + *fileInfo = searchResults->file; + searchResults->file = NULL; + + result = 0; + + cleanup: + /* Don't double free fileName */ + if (searchSpec != NULL && searchSpec->matchPattern != NULL) { + searchSpec->matchPattern->value = NULL; + } + + VIR_FREE(datastoreName); + VIR_FREE(directoryName); + VIR_FREE(fileName); + VIR_FREE(datastorePathWithoutFileName); + esxVI_String_Free(&propertyNameList); + esxVI_ObjectContent_Free(&datastore); + esxVI_ManagedObjectReference_Free(&hostDatastoreBrowser); + esxVI_HostDatastoreBrowserSearchSpec_Free(&searchSpec); + esxVI_ManagedObjectReference_Free(&task); + esxVI_TaskInfo_Free(&taskInfo); + esxVI_HostDatastoreBrowserSearchResults_Free(&searchResults); + + return result; +} + + + +int +esxVI_LookupDatastoreContentByDatastoreName + (esxVI_Context *ctx, const char *datastoreName, + esxVI_HostDatastoreBrowserSearchResults **searchResultsList) +{ + int result = -1; + esxVI_String *propertyNameList = NULL; + esxVI_ObjectContent *datastore = NULL; + esxVI_ManagedObjectReference *hostDatastoreBrowser = NULL; + esxVI_HostDatastoreBrowserSearchSpec *searchSpec = NULL; + esxVI_VmDiskFileQuery *vmDiskFileQuery = NULL; + esxVI_IsoImageFileQuery *isoImageFileQuery = NULL; + esxVI_FloppyImageFileQuery *floppyImageFileQuery = NULL; + char *datastorePath = NULL; + esxVI_ManagedObjectReference *task = NULL; + esxVI_TaskInfoState taskInfoState; + esxVI_TaskInfo *taskInfo = NULL; + + if (searchResultsList == NULL || *searchResultsList != NULL) { + ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); + return -1; + } + + /* Lookup Datastore and HostDatastoreBrowser */ + if (esxVI_String_AppendValueToList(&propertyNameList, "browser") < 0 || + esxVI_LookupDatastoreByName(ctx, datastoreName, propertyNameList, + &datastore, + esxVI_Occurrence_RequiredItem) < 0 || + esxVI_GetManagedObjectReference(datastore, "browser", + &hostDatastoreBrowser, + esxVI_Occurrence_RequiredItem) < 0) { + goto cleanup; + } + + /* Build HostDatastoreBrowserSearchSpec */ + if (esxVI_HostDatastoreBrowserSearchSpec_Alloc(&searchSpec) < 0 || + esxVI_FileQueryFlags_Alloc(&searchSpec->details) < 0) { + goto cleanup; + } + + searchSpec->details->fileType = esxVI_Boolean_True; + searchSpec->details->fileSize = esxVI_Boolean_True; + searchSpec->details->modification = esxVI_Boolean_False; + + if (esxVI_VmDiskFileQuery_Alloc(&vmDiskFileQuery) < 0 || + esxVI_VmDiskFileQueryFlags_Alloc(&vmDiskFileQuery->details) < 0 || + esxVI_FileQuery_AppendToList + (&searchSpec->query, + esxVI_FileQuery_DynamicCast(vmDiskFileQuery)) < 0) { + goto cleanup; + } + + vmDiskFileQuery->details->diskType = esxVI_Boolean_False; + vmDiskFileQuery->details->capacityKb = esxVI_Boolean_True; + vmDiskFileQuery->details->hardwareVersion = esxVI_Boolean_False; + vmDiskFileQuery->details->controllerType = esxVI_Boolean_True; + vmDiskFileQuery->details->diskExtents = esxVI_Boolean_False; + + if (esxVI_IsoImageFileQuery_Alloc(&isoImageFileQuery) < 0 || + esxVI_FileQuery_AppendToList + (&searchSpec->query, + esxVI_FileQuery_DynamicCast(isoImageFileQuery)) < 0) { + goto cleanup; + } + + if (esxVI_FloppyImageFileQuery_Alloc(&floppyImageFileQuery) < 0 || + esxVI_FileQuery_AppendToList + (&searchSpec->query, + esxVI_FileQuery_DynamicCast(floppyImageFileQuery)) < 0) { + goto cleanup; + } + + /* Search datastore for files */ + if (virAsprintf(&datastorePath, "[%s]", datastoreName) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (esxVI_SearchDatastoreSubFolders_Task(ctx, hostDatastoreBrowser, + datastorePath, searchSpec, + &task) < 0 || + esxVI_WaitForTaskCompletion(ctx, task, NULL, esxVI_Occurrence_None, + esxVI_Boolean_False, &taskInfoState) < 0) { + goto cleanup; + } + + if (taskInfoState != esxVI_TaskInfoState_Success) { + ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, + _("Could not serach in datastore '%s'"), datastoreName); + goto cleanup; + } + + if (esxVI_LookupTaskInfoByTask(ctx, task, &taskInfo) < 0 || + esxVI_HostDatastoreBrowserSearchResults_CastListFromAnyType + (taskInfo->result, searchResultsList) < 0) { + goto cleanup; + } + + result = 0; + + cleanup: + esxVI_String_Free(&propertyNameList); + esxVI_ObjectContent_Free(&datastore); + esxVI_ManagedObjectReference_Free(&hostDatastoreBrowser); + esxVI_HostDatastoreBrowserSearchSpec_Free(&searchSpec); + VIR_FREE(datastorePath); + esxVI_ManagedObjectReference_Free(&task); + esxVI_TaskInfo_Free(&taskInfo); + + return result; +} + + + int esxVI_HandleVirtualMachineQuestion (esxVI_Context *ctx, esxVI_ManagedObjectReference *virtualMachine, diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h index 1431db2478..3d1aee08f2 100644 --- a/src/esx/esx_vi.h +++ b/src/esx/esx_vi.h @@ -399,6 +399,15 @@ int esxVI_LookupCurrentSnapshotTree esxVI_VirtualMachineSnapshotTree **currentSnapshotTree, esxVI_Occurrence occurrence); +int esxVI_LookupFileInfoByDatastorePath(esxVI_Context *ctx, + const char *datastorePath, + esxVI_FileInfo **fileInfo, + esxVI_Occurrence occurrence); + +int esxVI_LookupDatastoreContentByDatastoreName + (esxVI_Context *ctx, const char *datastoreName, + esxVI_HostDatastoreBrowserSearchResults **searchResultsList); + int esxVI_HandleVirtualMachineQuestion (esxVI_Context *ctx, esxVI_ManagedObjectReference *virtualMachine, diff --git a/src/esx/esx_vi_generator.input b/src/esx/esx_vi_generator.input index ab50ea56ce..0fb9448877 100644 --- a/src/esx/esx_vi_generator.input +++ b/src/esx/esx_vi_generator.input @@ -813,6 +813,13 @@ method RevertToSnapshot_Task returns ManagedObjectReference r end +method SearchDatastoreSubFolders_Task returns ManagedObjectReference r + ManagedObjectReference _this r + String datastorePath r + HostDatastoreBrowserSearchSpec searchSpec o +end + + method SearchDatastore_Task returns ManagedObjectReference r ManagedObjectReference _this r String datastorePath r