]> xenbits.xensource.com Git - libvirt.git/commitdiff
esx: Use the VirtualDisk UUID as storage volume key
authorMatthias Bolte <matthias.bolte@googlemail.com>
Sun, 29 Aug 2010 17:33:49 +0000 (19:33 +0200)
committerMatthias Bolte <matthias.bolte@googlemail.com>
Fri, 3 Sep 2010 22:36:15 +0000 (00:36 +0200)
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
src/esx/esx_util.c
src/esx/esx_util.h
src/esx/esx_vi.c
src/esx/esx_vi.h
src/esx/esx_vi_generator.input

index c7ce9b494c4106ccba075d6157ffe8f5387e2579..76f87691b55f99d9fc387e93897cc1834c49d192 100644 (file)
@@ -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;
 }
@@ -782,6 +915,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);
 
@@ -932,6 +1067,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"),
@@ -939,7 +1084,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) {
@@ -957,6 +1102,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;
 }
@@ -1087,7 +1233,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;
 
@@ -1120,6 +1271,7 @@ esxStorageVolumeDumpXML(virStorageVolPtr volume, unsigned int flags)
     esxVI_DatastoreInfo_Free(&datastoreInfo);
     VIR_FREE(datastorePath);
     esxVI_FileInfo_Free(&fileInfo);
+    VIR_FREE(def.key);
 
     return xml;
 }
@@ -1186,8 +1338,8 @@ static virStorageDriver esxStorageDriver = {
     esxStoragePoolNumberOfStorageVolumes,  /* poolNumOfVolumes */
     esxStoragePoolListStorageVolumes,      /* poolListVolumes */
     esxStorageVolumeLookupByName,          /* volLookupByName */
-    esxStorageVolumeLookupByKeyOrPath,     /* volLookupByKey */
-    esxStorageVolumeLookupByKeyOrPath,     /* volLookupByPath */
+    esxStorageVolumeLookupByKey,           /* volLookupByKey */
+    esxStorageVolumeLookupByPath,          /* volLookupByPath */
     esxStorageVolumeCreateXML,             /* volCreateXML */
     NULL,                                  /* volCreateXMLFrom */
     NULL,                                  /* volDelete */
index 08c6c46235daf8593f9660d783f3a725e71f92a6..99cc4f6b538bca68f71faee8dab88346adaa26ba 100644 (file)
@@ -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;
+}
index 4d92333616f2ce7a01d677de470043cc8d2ba966..650f14536ba846674401f6a9d55441a2016c5ec3 100644 (file)
@@ -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__ */
index 6b6175554b79c18f496036faeaf4559b290a340c..00e15f0a051e37f9cc4c9d7fd813a23459101670 100644 (file)
@@ -3253,6 +3253,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,
index 773a1c69f6cf1ae085e41ff851100fa9ac03f354..bd37b058e8b11316b1a14db4f930c31be4b35c74 100644 (file)
@@ -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,
index b911c22b6d35e575f30da3aec3db85d94b816b09..2ee513a2f188bdcadbf321563e703e6fcf403104 100644 (file)
@@ -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