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

Matthias Bolte matthias.bolte at googlemail.com
Sun Aug 22 22:25:19 UTC 2010


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 c6bd3b8..5eeee1b 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) {
-        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) {
+    if (esxVI_LookupFileInfoByDatastorePath(data->ctx, def->src, &fileInfo,
+                                            esxVI_Occurrence_RequiredItem) < 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 26747bb..af8876a 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)
 {
@@ -556,6 +565,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)
 {
     /* ESX storage pools are always active */
@@ -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 3773a5f..cb3d544 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,
    esxVI_VirtualMachineQuestionInfo *questionInfo,
diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h
index d5dc9d5..42f535f 100644
--- a/src/esx/esx_vi.h
+++ b/src/esx/esx_vi.h
@@ -397,6 +397,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 ab50ea5..0fb9448 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
-- 
1.7.0.4




More information about the libvir-list mailing list