[libvirt] [PATCH] esx: Make storage pool lookup by name and UUID more robust

Matthias Bolte matthias.bolte at googlemail.com
Sun Aug 1 23:25:12 UTC 2010


Don't rely on summary.url anymore, because its value is different
between an esx:// and vpx:// connection. Use host.mountInfo.path
instead.

Don't fallback to lookup by UUID (actually lookup by absolute path)
in esxVI_LookupDatastoreByName when lookup by name fails. Add a
seperate function for this: esxVI_LookupDatastoreByAbsolutePath
---
 src/esx/esx_driver.c           |    8 +-
 src/esx/esx_storage_driver.c   |  107 ++++++++++++++------------
 src/esx/esx_util.c             |   22 +++---
 src/esx/esx_util.h             |    5 +-
 src/esx/esx_vi.c               |  171 ++++++++++++++++++++--------------------
 src/esx/esx_vi.h               |    6 ++
 src/esx/esx_vi_generator.input |   13 +++
 src/esx/esx_vi_generator.py    |    3 +-
 src/esx/esx_vmx.c              |   65 +++++++--------
 src/esx/esx_vmx.h              |    3 +-
 tests/esxutilstest.c           |   14 ++--
 11 files changed, 221 insertions(+), 196 deletions(-)

diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index fd87078..d824371 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -2193,8 +2193,8 @@ esxDomainDumpXML(virDomainPtr domain, int flags)
         goto cleanup;
     }
 
-    if (esxUtil_ParseDatastoreRelatedPath(vmPathName, &datastoreName,
-                                          &directoryName, &fileName) < 0) {
+    if (esxUtil_ParseDatastorePath(vmPathName, &datastoreName, &directoryName,
+                                   &fileName) < 0) {
         goto cleanup;
     }
 
@@ -2572,8 +2572,8 @@ esxDomainDefineXML(virConnectPtr conn, const char *xml ATTRIBUTE_UNUSED)
         goto cleanup;
     }
 
-    if (esxUtil_ParseDatastoreRelatedPath(disk->src, &datastoreName,
-                                          &directoryName, &fileName) < 0) {
+    if (esxUtil_ParseDatastorePath(disk->src, &datastoreName, &directoryName,
+                                   &fileName) < 0) {
         goto cleanup;
     }
 
diff --git a/src/esx/esx_storage_driver.c b/src/esx/esx_storage_driver.c
index b0ccc32..e0680a1 100644
--- a/src/esx/esx_storage_driver.c
+++ b/src/esx/esx_storage_driver.c
@@ -196,61 +196,64 @@ 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;
+    esxVI_DynamicProperty *dynamicProperty = NULL;
+    esxVI_DatastoreHostMount *datastoreHostMountList = NULL;
+    esxVI_DatastoreHostMount *datastoreHostMount = 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->primary) < 0) {
         return NULL;
     }
 
-    if (esxVI_String_AppendValueListToList(&propertyNameList,
-                                           "summary.accessible\0"
-                                           "summary.name\0"
-                                           "summary.url\0") < 0 ||
+    if (esxVI_String_AppendValueToList(&propertyNameList, "host") < 0 ||
         esxVI_LookupDatastoreByName(priv->primary, name,
                                     propertyNameList, &datastore,
-                                    esxVI_Occurrence_RequiredItem) < 0 ||
-        esxVI_GetBoolean(datastore, "summary.accessible",
-                         &accessible, esxVI_Occurrence_RequiredItem) < 0) {
+                                    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:
+     * Datastores don't have a UUID. We can use the 'host.mountInfo.path'
+     * 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)
+     *   host.mountInfo.path = /vmfs/volumes/4b0beca7-7fd401f3-1d7f-000ae484a6a3
+     *   host.mountInfo.path = /vmfs/volumes/b24b7a78-9d82b4f5    (short format)
      *
-     * The 'summary.url' property comes in two forms, with a complete "UUID"
-     * and a short "UUID".
+     * The 'host.mountInfo.path' 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.
      */
-    /* FIXME: Need to handle this for a vpx:// connection */
-    if (accessible == esxVI_Boolean_True && priv->host != NULL &&
-        priv->host->productVersion & esxVI_ProductVersion_ESX) {
-        if (esxVI_GetStringValue(datastore, "summary.url", &summaryUrl,
-                                 esxVI_Occurrence_RequiredItem) < 0) {
-            goto cleanup;
+    for (dynamicProperty = datastore->propSet; dynamicProperty != NULL;
+         dynamicProperty = dynamicProperty->_next) {
+        if (STREQ(dynamicProperty->name, "host")) {
+            if (esxVI_DatastoreHostMount_CastListFromAnyType
+                  (dynamicProperty->val, &datastoreHostMountList) < 0) {
+                goto cleanup;
+            }
+
+            break;
         }
+    }
 
-        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;
+    for (datastoreHostMount = datastoreHostMountList; datastoreHostMount != NULL;
+         datastoreHostMount = datastoreHostMount->_next) {
+        if (STRNEQ(priv->primary->hostSystem->_reference->value,
+                   datastoreHostMount->key->value)) {
+            continue;
+        }
+
+        if ((suffix = STRSKIP(datastoreHostMount->mountInfo->path,
+                              "/vmfs/volumes/")) == NULL) {
+            break;
         }
 
         suffixLength = strlen(suffix);
@@ -266,8 +269,8 @@ esxStoragePoolLookupByName(virConnectPtr conn, const char *name)
              */
             memcpy(uuid_string, suffix, suffixLength);
         } else {
-            VIR_WARN("Datastore URL suffix '%s' has unexpected format, "
-                     "cannot deduce a UUID from it", suffix);
+            VIR_WARN("Datastore host mount path suffix '%s' has unexpected "
+                     "format, cannot deduce a UUID from it", suffix);
         }
     }
 
@@ -278,16 +281,12 @@ esxStoragePoolLookupByName(virConnectPtr conn, const char *name)
         goto cleanup;
     }
 
-    if (esxVI_GetStringValue(datastore, "summary.name", &realName,
-                             esxVI_Occurrence_RequiredItem) < 0) {
-        goto cleanup;
-    }
-
-    pool = virGetStoragePool(conn, realName, uuid);
+    pool = virGetStoragePool(conn, name, uuid);
 
   cleanup:
     esxVI_String_Free(&propertyNameList);
     esxVI_ObjectContent_Free(&datastore);
+    esxVI_DatastoreHostMount_Free(&datastoreHostMountList);
 
     return pool;
 }
@@ -301,6 +300,7 @@ esxStoragePoolLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
     esxVI_String *propertyNameList = NULL;
     esxVI_ObjectContent *datastore = NULL;
     char uuid_string[VIR_UUID_STRING_BUFLEN] = "";
+    char *absolutePath = NULL;
     char *name = NULL;
     virStoragePoolPtr pool = NULL;
 
@@ -309,7 +309,7 @@ esxStoragePoolLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
     }
 
     /*
-     * Convert from UUID to datastore URL form by stripping the second '-':
+     * Convert UUID to 'host.mountInfo.path' form by stripping the second '-':
      *
      * <---- 14 ----><-------- 22 -------->    <---- 13 ---><-------- 22 -------->
      * 4b0beca7-7fd4-01f3-1d7f-000ae484a6a3 -> 4b0beca7-7fd401f3-1d7f-000ae484a6a3
@@ -317,14 +317,15 @@ esxStoragePoolLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
     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 (virAsprintf(&absolutePath, "/vmfs/volumes/%s", uuid_string) < 0) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
     if (esxVI_String_AppendValueToList(&propertyNameList, "summary.name") < 0 ||
-        esxVI_LookupDatastoreByName(priv->primary, uuid_string,
-                                    propertyNameList, &datastore,
-                                    esxVI_Occurrence_OptionalItem) < 0) {
+        esxVI_LookupDatastoreByAbsolutePath(priv->primary, absolutePath,
+                                            propertyNameList, &datastore,
+                                            esxVI_Occurrence_OptionalItem) < 0) {
         goto cleanup;
     }
 
@@ -338,9 +339,16 @@ esxStoragePoolLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
     if (datastore == NULL && STREQ(uuid_string + 17, "-0000-000000000000")) {
         uuid_string[17] = '\0';
 
-        if (esxVI_LookupDatastoreByName(priv->primary, uuid_string,
-                                        propertyNameList, &datastore,
-                                        esxVI_Occurrence_RequiredItem) < 0) {
+        VIR_FREE(absolutePath);
+
+        if (virAsprintf(&absolutePath, "/vmfs/volumes/%s", uuid_string) < 0) {
+            virReportOOMError();
+            goto cleanup;
+        }
+
+        if (esxVI_LookupDatastoreByAbsolutePath(priv->primary, absolutePath,
+                                                propertyNameList, &datastore,
+                                                esxVI_Occurrence_RequiredItem) < 0) {
             goto cleanup;
         }
     }
@@ -348,7 +356,7 @@ esxStoragePoolLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
     if (datastore == NULL) {
         virUUIDFormat(uuid, uuid_string);
 
-        ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
+        ESX_VI_ERROR(VIR_ERR_NO_STORAGE_POOL,
                      _("Could not find datastore with UUID '%s'"),
                      uuid_string);
 
@@ -363,6 +371,7 @@ esxStoragePoolLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
     pool = virGetStoragePool(conn, name, uuid);
 
   cleanup:
+    VIR_FREE(absolutePath);
     esxVI_String_Free(&propertyNameList);
     esxVI_ObjectContent_Free(&datastore);
 
diff --git a/src/esx/esx_util.c b/src/esx/esx_util.c
index 75a9aaf..7c7c841 100644
--- a/src/esx/esx_util.c
+++ b/src/esx/esx_util.c
@@ -274,12 +274,11 @@ esxUtil_ParseVirtualMachineIDString(const char *id_string, int *id)
 
 
 int
-esxUtil_ParseDatastoreRelatedPath(const char *datastoreRelatedPath,
-                                  char **datastoreName,
-                                  char **directoryName, char **fileName)
+esxUtil_ParseDatastorePath(const char *datastorePath, char **datastoreName,
+                           char **directoryName, char **fileName)
 {
     int result = -1;
-    char *copyOfDatastoreRelatedPath = NULL;
+    char *copyOfDatastorePath = NULL;
     char *tmp = NULL;
     char *saveptr = NULL;
     char *preliminaryDatastoreName = NULL;
@@ -293,18 +292,17 @@ esxUtil_ParseDatastoreRelatedPath(const char *datastoreRelatedPath,
         return -1;
     }
 
-    if (esxVI_String_DeepCopyValue(&copyOfDatastoreRelatedPath,
-                                   datastoreRelatedPath) < 0) {
+    if (esxVI_String_DeepCopyValue(&copyOfDatastorePath, datastorePath) < 0) {
         goto cleanup;
     }
 
     /* Expected format: '[<datastore>] <path>' */
-    if ((tmp = STRSKIP(copyOfDatastoreRelatedPath, "[")) == NULL ||
+    if ((tmp = STRSKIP(copyOfDatastorePath, "[")) == NULL ||
         (preliminaryDatastoreName = strtok_r(tmp, "]", &saveptr)) == NULL ||
         (directoryAndFileName = strtok_r(NULL, "", &saveptr)) == NULL) {
         ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
-                  _("Datastore related path '%s' doesn't have expected format "
-                    "'[<datastore>] <path>'"), datastoreRelatedPath);
+                  _("Datastore path '%s' doesn't have expected format "
+                    "'[<datastore>] <path>'"), datastorePath);
         goto cleanup;
     }
 
@@ -323,8 +321,8 @@ esxUtil_ParseDatastoreRelatedPath(const char *datastoreRelatedPath,
 
         if (*separator == '\0') {
             ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
-                      _("Datastore related path '%s' doesn't reference a file"),
-                      datastoreRelatedPath);
+                      _("Datastore path '%s' doesn't reference a file"),
+                      datastorePath);
             goto cleanup;
         }
 
@@ -348,7 +346,7 @@ esxUtil_ParseDatastoreRelatedPath(const char *datastoreRelatedPath,
         VIR_FREE(*fileName);
     }
 
-    VIR_FREE(copyOfDatastoreRelatedPath);
+    VIR_FREE(copyOfDatastorePath);
 
     return result;
 }
diff --git a/src/esx/esx_util.h b/src/esx/esx_util.h
index 99ce81d..5799730 100644
--- a/src/esx/esx_util.h
+++ b/src/esx/esx_util.h
@@ -51,9 +51,8 @@ void esxUtil_FreeParsedUri(esxUtil_ParsedUri **parsedUri);
 
 int esxUtil_ParseVirtualMachineIDString(const char *id_string, int *id);
 
-int esxUtil_ParseDatastoreRelatedPath(const char *datastoreRelatedPath,
-                                      char **datastoreName,
-                                      char **directoryName, char **fileName);
+int esxUtil_ParseDatastorePath(const char *datastorePath, char **datastoreName,
+                               char **directoryName, char **fileName);
 
 int esxUtil_ResolveHostname(const char *hostname,
                             char *ipAddress, size_t ipAddress_length);
diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c
index 9f2ac36..f421502 100644
--- a/src/esx/esx_vi.c
+++ b/src/esx/esx_vi.c
@@ -2422,10 +2422,7 @@ esxVI_LookupDatastoreByName(esxVI_Context *ctx, const char *name,
     esxVI_String *completePropertyNameList = NULL;
     esxVI_ObjectContent *datastoreList = NULL;
     esxVI_ObjectContent *candidate = NULL;
-    esxVI_DynamicProperty *dynamicProperty = NULL;
-    esxVI_Boolean accessible = esxVI_Boolean_Undefined;
-    size_t offset = 14; /* = strlen("/vmfs/volumes/") */
-    int numInaccessibleDatastores = 0;
+    char *name_candidate;
 
     if (datastore == NULL || *datastore != NULL) {
         ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
@@ -2435,118 +2432,123 @@ esxVI_LookupDatastoreByName(esxVI_Context *ctx, const char *name,
     /* Get all datastores */
     if (esxVI_String_DeepCopyList(&completePropertyNameList,
                                   propertyNameList) < 0 ||
-        esxVI_String_AppendValueListToList(&completePropertyNameList,
-                                           "summary.accessible\0"
-                                           "summary.name\0"
-                                           "summary.url\0") < 0 ||
+        esxVI_String_AppendValueToList(&completePropertyNameList,
+                                       "summary.name") < 0 ||
         esxVI_LookupDatastoreList(ctx, completePropertyNameList,
                                   &datastoreList) < 0) {
         goto cleanup;
     }
 
-    if (datastoreList == NULL) {
-        if (occurrence == esxVI_Occurrence_OptionalItem) {
-            goto success;
-        } else {
-            ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
-                         _("No datastores available"));
+    /* Search for a matching datastore */
+    for (candidate = datastoreList; candidate != NULL;
+         candidate = candidate->_next) {
+        name_candidate = NULL;
+
+        if (esxVI_GetStringValue(candidate, "summary.name", &name_candidate,
+                                 esxVI_Occurrence_RequiredItem) < 0) {
             goto cleanup;
         }
+
+        if (STREQ(name_candidate, name)) {
+            if (esxVI_ObjectContent_DeepCopy(datastore, candidate) < 0) {
+                goto cleanup;
+            }
+
+            // Found datastore with matching name
+            goto success;
+        }
+    }
+
+    if (*datastore == NULL && occurrence != esxVI_Occurrence_OptionalItem) {
+        ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
+                     _("Could not find datastore with name '%s'"), name);
+        goto cleanup;
+    }
+
+  success:
+    result = 0;
+
+  cleanup:
+    esxVI_String_Free(&completePropertyNameList);
+    esxVI_ObjectContent_Free(&datastoreList);
+
+    return result;
+}
+
+
+int
+esxVI_LookupDatastoreByAbsolutePath(esxVI_Context *ctx,
+                                    const char *absolutePath,
+                                    esxVI_String *propertyNameList,
+                                    esxVI_ObjectContent **datastore,
+                                    esxVI_Occurrence occurrence)
+{
+    int result = -1;
+    esxVI_String *completePropertyNameList = NULL;
+    esxVI_ObjectContent *datastoreList = NULL;
+    esxVI_ObjectContent *candidate = NULL;
+    esxVI_DynamicProperty *dynamicProperty = NULL;
+    esxVI_DatastoreHostMount *datastoreHostMountList = NULL;
+    esxVI_DatastoreHostMount *datastoreHostMount = NULL;
+
+    if (datastore == NULL || *datastore != NULL) {
+        ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
+        return -1;
+    }
+
+    /* Get all datastores */
+    if (esxVI_String_DeepCopyList(&completePropertyNameList,
+                                  propertyNameList) < 0 ||
+        esxVI_String_AppendValueToList(&completePropertyNameList, "host") < 0 ||
+        esxVI_LookupDatastoreList(ctx, completePropertyNameList,
+                                  &datastoreList) < 0) {
+        goto cleanup;
     }
 
     /* Search for a matching datastore */
     for (candidate = datastoreList; candidate != NULL;
          candidate = candidate->_next) {
-        accessible = esxVI_Boolean_Undefined;
+        esxVI_DatastoreHostMount_Free(&datastoreHostMountList);
 
         for (dynamicProperty = candidate->propSet; dynamicProperty != NULL;
              dynamicProperty = dynamicProperty->_next) {
-            if (STREQ(dynamicProperty->name, "summary.accessible")) {
-                if (esxVI_AnyType_ExpectType(dynamicProperty->val,
-                                             esxVI_Type_Boolean) < 0) {
+            if (STREQ(dynamicProperty->name, "host")) {
+                if (esxVI_DatastoreHostMount_CastListFromAnyType
+                      (dynamicProperty->val, &datastoreHostMountList) < 0) {
                     goto cleanup;
                 }
 
-                accessible = dynamicProperty->val->boolean;
                 break;
             }
         }
 
-        if (accessible == esxVI_Boolean_Undefined) {
-            ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
-                         _("Got incomplete response while querying for the "
-                           "datastore 'summary.accessible' property"));
-            goto cleanup;
-        }
-
-        if (accessible == esxVI_Boolean_False) {
-            ++numInaccessibleDatastores;
+        if (datastoreHostMountList == NULL) {
+            continue;
         }
 
-        for (dynamicProperty = candidate->propSet; dynamicProperty != NULL;
-             dynamicProperty = dynamicProperty->_next) {
-            if (STREQ(dynamicProperty->name, "summary.name")) {
-                if (esxVI_AnyType_ExpectType(dynamicProperty->val,
-                                             esxVI_Type_String) < 0) {
-                    goto cleanup;
-                }
-
-                if (STREQ(dynamicProperty->val->string, name)) {
-                    if (esxVI_ObjectContent_DeepCopy(datastore,
-                                                     candidate) < 0) {
-                        goto cleanup;
-                    }
-
-                    /* Found datastore with matching name */
-                    goto success;
-                }
-            } 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
-                     * is invalid and cannot be used to identify the datastore.
-                     */
-                    continue;
-                }
+        for (datastoreHostMount = datastoreHostMountList;
+             datastoreHostMount != NULL;
+             datastoreHostMount = datastoreHostMount->_next) {
+            if (STRNEQ(ctx->hostSystem->_reference->value,
+                       datastoreHostMount->key->value)) {
+                continue;
+            }
 
-                if (esxVI_AnyType_ExpectType(dynamicProperty->val,
-                                             esxVI_Type_String) < 0) {
+            if (STRPREFIX(absolutePath, datastoreHostMount->mountInfo->path)) {
+                if (esxVI_ObjectContent_DeepCopy(datastore, candidate) < 0) {
                     goto cleanup;
                 }
 
-                if (! STRPREFIX(dynamicProperty->val->string,
-                                "/vmfs/volumes/")) {
-                    ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
-                                 _("Datastore URL '%s' has unexpected prefix, "
-                                   "expecting '/vmfs/volumes/' prefix"),
-                                 dynamicProperty->val->string);
-                    goto cleanup;
-                }
-
-                if (STREQ(dynamicProperty->val->string + offset, name)) {
-                    if (esxVI_ObjectContent_DeepCopy(datastore,
-                                                     candidate) < 0) {
-                        goto cleanup;
-                    }
-
-                    /* Found datastore with matching URL suffix */
-                    goto success;
-                }
+                /* Found datastore with matching mount path */
+                goto success;
             }
         }
     }
 
-    if (occurrence != esxVI_Occurrence_OptionalItem) {
-        if (numInaccessibleDatastores > 0) {
-            ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
-                         _("Could not find datastore '%s', maybe it's "
-                           "inaccessible"), name);
-        } else {
-            ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
-                         _("Could not find datastore '%s'"), name);
-        }
-
+    if (*datastore == NULL && occurrence != esxVI_Occurrence_OptionalItem) {
+        ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
+                     _("Could not find datastore containing absolute path '%s'"),
+                     absolutePath);
         goto cleanup;
     }
 
@@ -2556,6 +2558,7 @@ esxVI_LookupDatastoreByName(esxVI_Context *ctx, const char *name,
   cleanup:
     esxVI_String_Free(&completePropertyNameList);
     esxVI_ObjectContent_Free(&datastoreList);
+    esxVI_DatastoreHostMount_Free(&datastoreHostMountList);
 
     return result;
 }
diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h
index a23c56d..fdd15f1 100644
--- a/src/esx/esx_vi.h
+++ b/src/esx/esx_vi.h
@@ -364,6 +364,12 @@ int esxVI_LookupDatastoreByName(esxVI_Context *ctx, const char *name,
                                 esxVI_ObjectContent **datastore,
                                 esxVI_Occurrence occurrence);
 
+int esxVI_LookupDatastoreByAbsolutePath(esxVI_Context *ctx,
+                                        const char *absolutePath,
+                                        esxVI_String *propertyNameList,
+                                        esxVI_ObjectContent **datastore,
+                                        esxVI_Occurrence occurrence);
+
 int esxVI_LookupTaskInfoByTask(esxVI_Context *ctx,
                                esxVI_ManagedObjectReference *task,
                                esxVI_TaskInfo **taskInfo);
diff --git a/src/esx/esx_vi_generator.input b/src/esx/esx_vi_generator.input
index b4b33f6..ab50ea5 100644
--- a/src/esx/esx_vi_generator.input
+++ b/src/esx/esx_vi_generator.input
@@ -146,6 +146,12 @@ object ChoiceOption extends OptionType
 end
 
 
+object DatastoreHostMount
+    ManagedObjectReference                   key                            r
+    HostMountInfo                            mountInfo                      r
+end
+
+
 object DatastoreInfo
     String                                   name                           r
     String                                   url                            r
@@ -251,6 +257,13 @@ object HostFileSystemVolume
 end
 
 
+object HostMountInfo
+    String                                   path                           o
+    String                                   accessMode                     r
+    Boolean                                  accessible                     o
+end
+
+
 object HostNasVolume extends HostFileSystemVolume
     String                                   remoteHost                     r
     String                                   remotePath                     r
diff --git a/src/esx/esx_vi_generator.py b/src/esx/esx_vi_generator.py
index 44c3493..e3c3d14 100755
--- a/src/esx/esx_vi_generator.py
+++ b/src/esx/esx_vi_generator.py
@@ -1127,7 +1127,8 @@ additional_enum_features = { "ManagedEntityStatus"      : Enum.FEATURE__ANY_TYPE
                              "VirtualMachinePowerState" : Enum.FEATURE__ANY_TYPE }
 
 
-additional_object_features = { "DatastoreInfo"              : Object.FEATURE__ANY_TYPE | Object.FEATURE__DYNAMIC_CAST,
+additional_object_features = { "DatastoreHostMount"         : Object.FEATURE__LIST | Object.FEATURE__ANY_TYPE,
+                               "DatastoreInfo"              : Object.FEATURE__ANY_TYPE | Object.FEATURE__DYNAMIC_CAST,
                                "Event"                      : Object.FEATURE__LIST,
                                "FileInfo"                   : Object.FEATURE__DYNAMIC_CAST,
                                "FileQuery"                  : Object.FEATURE__DYNAMIC_CAST,
diff --git a/src/esx/esx_vmx.c b/src/esx/esx_vmx.c
index 807c6db..1a5e8d3 100644
--- a/src/esx/esx_vmx.c
+++ b/src/esx/esx_vmx.c
@@ -749,8 +749,8 @@ esxVMX_AutodetectSCSIControllerModel(esxVI_Context *ctx,
         return 0;
     }
 
-    if (esxUtil_ParseDatastoreRelatedPath(def->src, &datastoreName,
-                                          &directoryName, &fileName) < 0) {
+    if (esxUtil_ParseDatastorePath(def->src, &datastoreName, &directoryName,
+                                   &fileName) < 0) {
         goto cleanup;
     }
 
@@ -986,19 +986,19 @@ esxVMX_GatherSCSIControllers(esxVI_Context *ctx, virDomainDefPtr def,
 
 
 char *
-esxVMX_AbsolutePathToDatastoreRelatedPath(esxVI_Context *ctx,
-                                          const char *absolutePath)
+esxVMX_AbsolutePathToDatastorePath(esxVI_Context *ctx, const char *absolutePath)
 {
     bool success = false;
     char *copyOfAbsolutePath = NULL;
     char *tmp = NULL;
     char *saveptr = NULL;
-    char *datastoreRelatedPath = NULL;
+    esxVI_String *propertyNameList = NULL;
+    esxVI_ObjectContent *datastore = NULL;
+
+    char *datastorePath = NULL;
     char *preliminaryDatastoreName = NULL;
     char *directoryAndFileName = NULL;
-    esxVI_DynamicProperty *dynamicProperty = NULL;
-    esxVI_ObjectContent *datastore = NULL;
-    const char *datastoreName = NULL;
+    char *datastoreName = NULL;
 
     if (esxVI_String_DeepCopyValue(&copyOfAbsolutePath, absolutePath) < 0) {
         return NULL;
@@ -1015,30 +1015,26 @@ esxVMX_AbsolutePathToDatastoreRelatedPath(esxVI_Context *ctx,
     }
 
     if (ctx != NULL) {
-        if (esxVI_LookupDatastoreByName(ctx, preliminaryDatastoreName,
-                                        NULL, &datastore,
-                                        esxVI_Occurrence_OptionalItem) < 0) {
+        if (esxVI_String_AppendValueToList(&propertyNameList,
+                                           "summary.name") < 0 ||
+            esxVI_LookupDatastoreByAbsolutePath(ctx, absolutePath,
+                                                propertyNameList, &datastore,
+                                                esxVI_Occurrence_OptionalItem) < 0) {
             goto cleanup;
         }
 
-        if (datastore != NULL) {
-            for (dynamicProperty = datastore->propSet; dynamicProperty != NULL;
-                 dynamicProperty = dynamicProperty->_next) {
-                if (STREQ(dynamicProperty->name, "summary.accessible")) {
-                    /* Ignore it */
-                } else if (STREQ(dynamicProperty->name, "summary.name")) {
-                    if (esxVI_AnyType_ExpectType(dynamicProperty->val,
-                                                 esxVI_Type_String) < 0) {
-                        goto cleanup;
-                    }
+        if (datastore == NULL) {
+            if (esxVI_LookupDatastoreByName(ctx, preliminaryDatastoreName,
+                                            propertyNameList, &datastore,
+                                            esxVI_Occurrence_OptionalItem) < 0) {
+                goto cleanup;
+            }
+        }
 
-                    datastoreName = dynamicProperty->val->string;
-                    break;
-                } else if (STREQ(dynamicProperty->name, "summary.url")) {
-                    /* Ignore it */
-                } else {
-                    VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
-                }
+        if (datastore != NULL) {
+            if (esxVI_GetStringValue(datastore, "summary.name", &datastoreName,
+                                     esxVI_Occurrence_RequiredItem)) {
+                goto cleanup;
             }
         }
 
@@ -1053,7 +1049,7 @@ esxVMX_AbsolutePathToDatastoreRelatedPath(esxVI_Context *ctx,
         datastoreName = preliminaryDatastoreName;
     }
 
-    if (virAsprintf(&datastoreRelatedPath, "[%s] %s", datastoreName,
+    if (virAsprintf(&datastorePath, "[%s] %s", datastoreName,
                     directoryAndFileName) < 0) {
         virReportOOMError();
         goto cleanup;
@@ -1065,13 +1061,14 @@ esxVMX_AbsolutePathToDatastoreRelatedPath(esxVI_Context *ctx,
 
   cleanup:
     if (! success) {
-        VIR_FREE(datastoreRelatedPath);
+        VIR_FREE(datastorePath);
     }
 
     VIR_FREE(copyOfAbsolutePath);
+    esxVI_String_Free(&propertyNameList);
     esxVI_ObjectContent_Free(&datastore);
 
-    return datastoreRelatedPath;
+    return datastorePath;
 }
 
 
@@ -1088,7 +1085,7 @@ esxVMX_ParseFileName(esxVI_Context *ctx, const char *fileName,
 
     if (STRPREFIX(fileName, "/vmfs/volumes/")) {
         /* Found absolute path referencing a file inside a datastore */
-        return esxVMX_AbsolutePathToDatastoreRelatedPath(ctx, fileName);
+        return esxVMX_AbsolutePathToDatastorePath(ctx, fileName);
     } else if (STRPREFIX(fileName, "/")) {
         /* Found absolute path referencing a file outside a datastore */
         src = strdup(fileName);
@@ -2625,8 +2622,8 @@ esxVMX_FormatFileName(esxVI_Context *ctx ATTRIBUTE_UNUSED, const char *src)
 
     if (STRPREFIX(src, "[")) {
         /* Found potential datastore related path */
-        if (esxUtil_ParseDatastoreRelatedPath(src, &datastoreName,
-                                              &directoryName, &fileName) < 0) {
+        if (esxUtil_ParseDatastorePath(src, &datastoreName, &directoryName,
+                                       &fileName) < 0) {
             goto cleanup;
         }
 
diff --git a/src/esx/esx_vmx.h b/src/esx/esx_vmx.h
index 3ccae7a..bda98f0 100644
--- a/src/esx/esx_vmx.h
+++ b/src/esx/esx_vmx.h
@@ -56,8 +56,7 @@ esxVMX_GatherSCSIControllers(esxVI_Context *ctx, virDomainDefPtr def,
                              int virtualDev[4], bool present[4]);
 
 char *
-esxVMX_AbsolutePathToDatastoreRelatedPath(esxVI_Context *ctx,
-                                          const char *absolutePath);
+esxVMX_AbsolutePathToDatastorePath(esxVI_Context *ctx, const char *absolutePath);
 
 
 
diff --git a/tests/esxutilstest.c b/tests/esxutilstest.c
index 2a13282..09470ed 100644
--- a/tests/esxutilstest.c
+++ b/tests/esxutilstest.c
@@ -95,7 +95,7 @@ testDiskNameToIndex(const void *data ATTRIBUTE_UNUSED)
 
 
 struct testPath {
-    const char *datastoreRelatedPath;
+    const char *datastorePath;
     int result;
     const char *datastoreName;
     const char *directoryName;
@@ -111,7 +111,7 @@ static struct testPath paths[] = {
 };
 
 static int
-testParseDatastoreRelatedPath(const void *data ATTRIBUTE_UNUSED)
+testParseDatastorePath(const void *data ATTRIBUTE_UNUSED)
 {
     int i, result = 0;
     char *datastoreName = NULL;
@@ -123,9 +123,9 @@ testParseDatastoreRelatedPath(const void *data ATTRIBUTE_UNUSED)
         VIR_FREE(directoryName);
         VIR_FREE(fileName);
 
-        if (esxUtil_ParseDatastoreRelatedPath(paths[i].datastoreRelatedPath,
-                                              &datastoreName, &directoryName,
-                                              &fileName) != paths[i].result) {
+        if (esxUtil_ParseDatastorePath(paths[i].datastorePath,
+                                       &datastoreName, &directoryName,
+                                       &fileName) != paths[i].result) {
             goto failure;
         }
 
@@ -242,7 +242,7 @@ mymain(int argc, char **argv)
 
     virSetErrorFunc(NULL, testQuietError);
 
-# define DO_TEST(_name)                                                    \
+# define DO_TEST(_name)                                                       \
         do {                                                                  \
             if (virtTestRun("VMware "#_name, 1, test##_name,                  \
                             NULL) < 0) {                                      \
@@ -252,7 +252,7 @@ mymain(int argc, char **argv)
 
     DO_TEST(IndexToDiskName);
     DO_TEST(DiskNameToIndex);
-    DO_TEST(ParseDatastoreRelatedPath);
+    DO_TEST(ParseDatastorePath);
     DO_TEST(ConvertDateTimeToCalendarTime);
 
     return result == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
-- 
1.7.0.4




More information about the libvir-list mailing list