VirtualDisks are .vmdk file based. Other files in a datastore
like .iso or .flp files don't have a UUID attached, fall back
to the path as key for them.
---
src/esx/esx_storage_driver.c | 190 ++++++++++++++++++++++++++++++++++++----
src/esx/esx_util.c | 19 ++++
src/esx/esx_util.h | 2 +
src/esx/esx_vi.c | 53 +++++++++++
src/esx/esx_vi.h | 4 +
src/esx/esx_vi_generator.input | 7 ++
6 files changed, 256 insertions(+), 19 deletions(-)
diff --git a/src/esx/esx_storage_driver.c b/src/esx/esx_storage_driver.c
index 3b959c2..a9a5633 100644
--- a/src/esx/esx_storage_driver.c
+++ b/src/esx/esx_storage_driver.c
@@ -697,7 +697,7 @@ esxStorageVolumeLookupByName(virStoragePoolPtr pool, const char
*name)
virStorageVolPtr volume = NULL;
esxPrivate *priv = pool->conn->storagePrivateData;
char *datastorePath = NULL;
- esxVI_FileInfo *fileInfo = NULL;
+ char *key = NULL;
if (esxVI_EnsureSession(priv->primary) < 0) {
return NULL;
@@ -708,17 +708,16 @@ esxStorageVolumeLookupByName(virStoragePoolPtr pool, const char
*name)
goto cleanup;
}
- if (esxVI_LookupFileInfoByDatastorePath(priv->primary, datastorePath,
- false, &fileInfo,
- esxVI_Occurrence_RequiredItem) < 0) {
+ if (esxVI_LookupStorageVolumeKeyByDatastorePath(priv->primary,
+ datastorePath, &key) < 0) {
goto cleanup;
}
- volume = virGetStorageVol(pool->conn, pool->name, name, datastorePath);
+ volume = virGetStorageVol(pool->conn, pool->name, name, key);
cleanup:
VIR_FREE(datastorePath);
- esxVI_FileInfo_Free(&fileInfo);
+ VIR_FREE(key);
return volume;
}
@@ -726,36 +725,170 @@ esxStorageVolumeLookupByName(virStoragePoolPtr pool, const char
*name)
static virStorageVolPtr
-esxStorageVolumeLookupByKeyOrPath(virConnectPtr conn, const char *keyOrPath)
+esxStorageVolumeLookupByPath(virConnectPtr conn, const char *path)
{
virStorageVolPtr volume = NULL;
esxPrivate *priv = conn->storagePrivateData;
char *datastoreName = NULL;
char *directoryAndFileName = NULL;
- esxVI_FileInfo *fileInfo = NULL;
+ char *key = NULL;
if (esxVI_EnsureSession(priv->primary) < 0) {
return NULL;
}
- if (esxUtil_ParseDatastorePath(keyOrPath, &datastoreName, NULL,
+ if (esxUtil_ParseDatastorePath(path, &datastoreName, NULL,
&directoryAndFileName) < 0) {
goto cleanup;
}
- if (esxVI_LookupFileInfoByDatastorePath(priv->primary, keyOrPath,
- false, &fileInfo,
- esxVI_Occurrence_RequiredItem) < 0) {
+ if (esxVI_LookupStorageVolumeKeyByDatastorePath(priv->primary, path,
+ &key) < 0) {
goto cleanup;
}
- volume = virGetStorageVol(conn, datastoreName, directoryAndFileName,
- keyOrPath);
+ volume = virGetStorageVol(conn, datastoreName, directoryAndFileName, key);
cleanup:
VIR_FREE(datastoreName);
VIR_FREE(directoryAndFileName);
- esxVI_FileInfo_Free(&fileInfo);
+ VIR_FREE(key);
+
+ return volume;
+}
+
+
+
+static virStorageVolPtr
+esxStorageVolumeLookupByKey(virConnectPtr conn, const char *key)
+{
+ virStorageVolPtr volume = NULL;
+ esxPrivate *priv = conn->storagePrivateData;
+ esxVI_String *propertyNameList = NULL;
+ esxVI_ObjectContent *datastoreList = NULL;
+ esxVI_ObjectContent *datastore = NULL;
+ char *datastoreName = NULL;
+ esxVI_HostDatastoreBrowserSearchResults *searchResultsList = NULL;
+ esxVI_HostDatastoreBrowserSearchResults *searchResults = NULL;
+ char *directoryAndFileName = NULL;
+ size_t length;
+ char *datastorePath = NULL;
+ char *volumeName = NULL;
+ esxVI_FileInfo *fileInfo = NULL;
+ char *uuid_string = NULL;
+ char key_candidate[VIR_UUID_STRING_BUFLEN] = "";
+
+ if (STRPREFIX(key, "[")) {
+ /* Key is probably a datastore path */
+ return esxStorageVolumeLookupByPath(conn, key);
+ }
+
+ if (esxVI_EnsureSession(priv->primary) < 0) {
+ return NULL;
+ }
+
+ /* Lookup all datastores */
+ if (esxVI_String_AppendValueToList(&propertyNameList, "summary.name")
< 0 ||
+ esxVI_LookupDatastoreList(priv->primary, propertyNameList,
+ &datastoreList) < 0) {
+ goto cleanup;
+ }
+
+ for (datastore = datastoreList; datastore != NULL;
+ datastore = datastore->_next) {
+ datastoreName = NULL;
+
+ if (esxVI_GetStringValue(datastore, "summary.name",
&datastoreName,
+ esxVI_Occurrence_RequiredItem) < 0) {
+ goto cleanup;
+ }
+
+ /* Lookup datastore content */
+ esxVI_HostDatastoreBrowserSearchResults_Free(&searchResultsList);
+
+ if (esxVI_LookupDatastoreContentByDatastoreName
+ (priv->primary, datastoreName, &searchResultsList) < 0) {
+ goto cleanup;
+ }
+
+ /* Interpret search result */
+ for (searchResults = searchResultsList; searchResults != NULL;
+ searchResults = searchResults->_next) {
+ VIR_FREE(directoryAndFileName);
+
+ if (esxUtil_ParseDatastorePath(searchResults->folderPath, NULL,
+ NULL, &directoryAndFileName) < 0) {
+ goto cleanup;
+ }
+
+ /* Strip trailing separators */
+ length = strlen(directoryAndFileName);
+
+ while (length > 0 && directoryAndFileName[length - 1] ==
'/') {
+ directoryAndFileName[length - 1] = '\0';
+ --length;
+ }
+
+ /* Build datastore path and query the UUID */
+ for (fileInfo = searchResults->file; fileInfo != NULL;
+ fileInfo = fileInfo->_next) {
+ VIR_FREE(datastorePath);
+
+ if (length < 1) {
+ if (virAsprintf(&volumeName, "%s",
+ fileInfo->path) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ } else if (virAsprintf(&volumeName, "%s/%s",
+ directoryAndFileName,
+ fileInfo->path) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (virAsprintf(&datastorePath, "[%s] %s", datastoreName,
+ volumeName) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (esxVI_VmDiskFileInfo_DynamicCast(fileInfo) == NULL) {
+ /* Only a VirtualDisk has a UUID */
+ continue;
+ }
+
+ VIR_FREE(uuid_string);
+
+ if (esxVI_QueryVirtualDiskUuid
+ (priv->primary, datastorePath,
+ priv->primary->datacenter->_reference,
+ &uuid_string) < 0) {
+ goto cleanup;
+ }
+
+ if (esxUtil_ReformatUuid(uuid_string, key_candidate) < 0) {
+ goto cleanup;
+ }
+
+ if (STREQ(key, key_candidate)) {
+ /* Found matching UUID */
+ volume = virGetStorageVol(conn, datastoreName,
+ volumeName, key);
+ goto cleanup;
+ }
+ }
+ }
+ }
+
+ cleanup:
+ esxVI_String_Free(&propertyNameList);
+ esxVI_ObjectContent_Free(&datastoreList);
+ esxVI_HostDatastoreBrowserSearchResults_Free(&searchResultsList);
+ VIR_FREE(directoryAndFileName);
+ VIR_FREE(datastorePath);
+ VIR_FREE(volumeName);
+ VIR_FREE(uuid_string);
return volume;
}
@@ -783,6 +916,8 @@ esxStorageVolumeCreateXML(virStoragePoolPtr pool, const char
*xmldesc,
esxVI_FileBackedVirtualDiskSpec *virtualDiskSpec = NULL;
esxVI_ManagedObjectReference *task = NULL;
esxVI_TaskInfoState taskInfoState;
+ char *uuid_string = NULL;
+ char key[VIR_UUID_STRING_BUFLEN] = "";
virCheckFlags(0, NULL);
@@ -935,6 +1070,16 @@ esxStorageVolumeCreateXML(virStoragePoolPtr pool, const char
*xmldesc,
ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not create
volume"));
goto cleanup;
}
+
+ if (esxVI_QueryVirtualDiskUuid(priv->primary, datastorePath,
+ priv->primary->datacenter->_reference,
+ &uuid_string) < 0) {
+ goto cleanup;
+ }
+
+ if (esxUtil_ReformatUuid(uuid_string, key) < 0) {
+ goto cleanup;
+ }
} else {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Creation of %s volumes is not supported"),
@@ -942,7 +1087,7 @@ esxStorageVolumeCreateXML(virStoragePoolPtr pool, const char
*xmldesc,
goto cleanup;
}
- volume = virGetStorageVol(pool->conn, pool->name, def->name,
datastorePath);
+ volume = virGetStorageVol(pool->conn, pool->name, def->name, key);
cleanup:
if (virtualDiskSpec != NULL) {
@@ -960,6 +1105,7 @@ esxStorageVolumeCreateXML(virStoragePoolPtr pool, const char
*xmldesc,
esxVI_FileInfo_Free(&fileInfo);
esxVI_FileBackedVirtualDiskSpec_Free(&virtualDiskSpec);
esxVI_ManagedObjectReference_Free(&task);
+ VIR_FREE(uuid_string);
return volume;
}
@@ -1090,7 +1236,12 @@ esxStorageVolumeDumpXML(virStorageVolPtr volume, unsigned int
flags)
floppyImageFileInfo = esxVI_FloppyImageFileInfo_DynamicCast(fileInfo);
def.name = volume->name;
- def.key = datastorePath;
+
+ if (esxVI_LookupStorageVolumeKeyByDatastorePath(priv->primary, datastorePath,
+ &def.key) < 0) {
+ goto cleanup;
+ }
+
def.type = VIR_STORAGE_VOL_FILE;
def.target.path = datastorePath;
@@ -1123,6 +1274,7 @@ esxStorageVolumeDumpXML(virStorageVolPtr volume, unsigned int
flags)
esxVI_DatastoreInfo_Free(&datastoreInfo);
VIR_FREE(datastorePath);
esxVI_FileInfo_Free(&fileInfo);
+ VIR_FREE(def.key);
return xml;
}
@@ -1189,8 +1341,8 @@ static virStorageDriver esxStorageDriver = {
esxStoragePoolNumberOfStorageVolumes, /* poolNumOfVolumes */
esxStoragePoolListStorageVolumes, /* poolListVolumes */
esxStorageVolumeLookupByName, /* volLookupByName */
- esxStorageVolumeLookupByKeyOrPath, /* volLookupByKey */
- esxStorageVolumeLookupByKeyOrPath, /* volLookupByPath */
+ esxStorageVolumeLookupByKey, /* volLookupByKey */
+ esxStorageVolumeLookupByPath, /* volLookupByPath */
esxStorageVolumeCreateXML, /* volCreateXML */
NULL, /* volCreateXMLFrom */
NULL, /* volDelete */
diff --git a/src/esx/esx_util.c b/src/esx/esx_util.c
index 08c6c46..99cc4f6 100644
--- a/src/esx/esx_util.c
+++ b/src/esx/esx_util.c
@@ -602,3 +602,22 @@ esxUtil_GetConfigBoolean(virConfPtr conf, const char *name, bool
*boolean_,
return 0;
}
+
+
+
+int
+esxUtil_ReformatUuid(const char *input, char *output)
+{
+ unsigned char uuid[VIR_UUID_BUFLEN];
+
+ if (virUUIDParse(input, uuid) < 0) {
+ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Could not parse UUID from string '%s'"),
+ input);
+ return -1;
+ }
+
+ virUUIDFormat(uuid, output);
+
+ return 0;
+}
diff --git a/src/esx/esx_util.h b/src/esx/esx_util.h
index 4d92333..650f145 100644
--- a/src/esx/esx_util.h
+++ b/src/esx/esx_util.h
@@ -69,4 +69,6 @@ int esxUtil_GetConfigLong(virConfPtr conf, const char *name, long long
*number,
int esxUtil_GetConfigBoolean(virConfPtr conf, const char *name, bool *boolean_,
bool default_, bool optional);
+int esxUtil_ReformatUuid(const char *input, char *output);
+
#endif /* __ESX_UTIL_H__ */
diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c
index 8d83eac..fb2a499 100644
--- a/src/esx/esx_vi.c
+++ b/src/esx/esx_vi.c
@@ -3254,6 +3254,59 @@ esxVI_LookupDatastoreContentByDatastoreName
int
+esxVI_LookupStorageVolumeKeyByDatastorePath(esxVI_Context *ctx,
+ const char *datastorePath,
+ char **key)
+{
+ int result = -1;
+ esxVI_FileInfo *fileInfo = NULL;
+ char *uuid_string = NULL;
+
+ if (key == NULL || *key != NULL) {
+ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid
argument"));
+ return -1;
+ }
+
+ if (esxVI_LookupFileInfoByDatastorePath(ctx, datastorePath, false, &fileInfo,
+ esxVI_Occurrence_RequiredItem) < 0) {
+ goto cleanup;
+ }
+
+ if (esxVI_VmDiskFileInfo_DynamicCast(fileInfo) != NULL) {
+ /* VirtualDisks have a UUID, use it as key */
+ if (esxVI_QueryVirtualDiskUuid(ctx, datastorePath,
+ ctx->datacenter->_reference,
+ &uuid_string) < 0) {
+ goto cleanup;
+ }
+
+ if (VIR_ALLOC_N(*key, VIR_UUID_STRING_BUFLEN) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (esxUtil_ReformatUuid(uuid_string, *key) < 0) {
+ goto cleanup;
+ }
+ } else {
+ /* Other files don't have a UUID, fall back to the path as key */
+ if (esxVI_String_DeepCopyValue(key, datastorePath) < 0) {
+ goto cleanup;
+ }
+ }
+
+ result = 0;
+
+ cleanup:
+ esxVI_FileInfo_Free(&fileInfo);
+ VIR_FREE(uuid_string);
+
+ 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 773a1c6..bd37b05 100644
--- a/src/esx/esx_vi.h
+++ b/src/esx/esx_vi.h
@@ -409,6 +409,10 @@ int esxVI_LookupDatastoreContentByDatastoreName
(esxVI_Context *ctx, const char *datastoreName,
esxVI_HostDatastoreBrowserSearchResults **searchResultsList);
+int esxVI_LookupStorageVolumeKeyByDatastorePath(esxVI_Context *ctx,
+ const char *datastorePath,
+ char **key);
+
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 b911c22..2ee513a 100644
--- a/src/esx/esx_vi_generator.input
+++ b/src/esx/esx_vi_generator.input
@@ -801,6 +801,13 @@ method QueryPerfCounter returns PerfCounterInfo ol
end
+method QueryVirtualDiskUuid returns String r
+ ManagedObjectReference _this:VirtualDiskManager r
+ String name r
+ ManagedObjectReference datacenter o
+end
+
+
method RebootGuest
ManagedObjectReference _this r
end
--
1.7.0.4