[libvirt] [PATCH] esx: Split VMX code into a general and an ESX specific part

Matthias Bolte matthias.bolte at googlemail.com
Thu Aug 5 15:47:28 UTC 2010


Introduce esxVMX_Context containing functions pointers to
glue both parts together in an generic way.

Move the ESX specific part to esx_driver.c.

This is a step towards making the VMX code reusable in a
potential VMware Workstation and VMware Player driver.
---
 src/esx/esx_driver.c |  417 ++++++++++++++++++++++++++++++++++++++++++++++-
 src/esx/esx_vmx.c    |  448 +++++---------------------------------------------
 src/esx/esx_vmx.h    |   71 +++++----
 tests/vmx2xmltest.c  |   52 ++++++-
 tests/xml2vmxtest.c  |   64 +++++++-
 5 files changed, 611 insertions(+), 441 deletions(-)

diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index d824371..b0ef704 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -50,6 +50,369 @@
 
 static int esxDomainGetMaxVcpus(virDomainPtr domain);
 
+typedef struct _esxVMX_Data esxVMX_Data;
+
+struct _esxVMX_Data {
+    esxVI_Context *ctx;
+    const char *datastoreName;
+    const char *directoryName;
+};
+
+
+
+static char *
+esxAbsolutePathToDatastorePath(esxVI_Context *ctx, const char *absolutePath)
+{
+    bool success = false;
+    char *copyOfAbsolutePath = NULL;
+    char *tmp = NULL;
+    char *saveptr = NULL;
+    esxVI_String *propertyNameList = NULL;
+    esxVI_ObjectContent *datastore = NULL;
+
+    char *datastorePath = NULL;
+    char *preliminaryDatastoreName = NULL;
+    char *directoryAndFileName = NULL;
+    char *datastoreName = NULL;
+
+    if (esxVI_String_DeepCopyValue(&copyOfAbsolutePath, absolutePath) < 0) {
+        return NULL;
+    }
+
+    /* Expected format: '/vmfs/volumes/<datastore>/<path>' */
+    if ((tmp = STRSKIP(copyOfAbsolutePath, "/vmfs/volumes/")) == NULL ||
+        (preliminaryDatastoreName = strtok_r(tmp, "/", &saveptr)) == NULL ||
+        (directoryAndFileName = strtok_r(NULL, "", &saveptr)) == NULL) {
+        ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
+                  _("Absolute path '%s' doesn't have expected format "
+                    "'/vmfs/volumes/<datastore>/<path>'"), absolutePath);
+        goto cleanup;
+    }
+
+    if (esxVI_String_AppendValueToList(&propertyNameList,
+                                       "summary.name") < 0 ||
+        esxVI_LookupDatastoreByAbsolutePath(ctx, absolutePath,
+                                            propertyNameList, &datastore,
+                                            esxVI_Occurrence_OptionalItem) < 0) {
+        goto cleanup;
+    }
+
+    if (datastore == NULL) {
+        if (esxVI_LookupDatastoreByName(ctx, preliminaryDatastoreName,
+                                        propertyNameList, &datastore,
+                                        esxVI_Occurrence_OptionalItem) < 0) {
+            goto cleanup;
+        }
+    }
+
+    if (datastore != NULL) {
+        if (esxVI_GetStringValue(datastore, "summary.name", &datastoreName,
+                                 esxVI_Occurrence_RequiredItem)) {
+            goto cleanup;
+        }
+    }
+
+    if (datastoreName == NULL) {
+        VIR_WARN("Could not retrieve datastore name for absolute "
+                 "path '%s', falling back to preliminary name '%s'",
+                 absolutePath, preliminaryDatastoreName);
+
+        datastoreName = preliminaryDatastoreName;
+    }
+
+    if (virAsprintf(&datastorePath, "[%s] %s", datastoreName,
+                    directoryAndFileName) < 0) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
+    /* FIXME: Check if referenced path/file really exists */
+
+    success = true;
+
+  cleanup:
+    if (! success) {
+        VIR_FREE(datastorePath);
+    }
+
+    VIR_FREE(copyOfAbsolutePath);
+    esxVI_String_Free(&propertyNameList);
+    esxVI_ObjectContent_Free(&datastore);
+
+    return datastorePath;
+}
+
+
+
+static char *
+esxParseVMXFileName(const char *fileName, void *opaque)
+{
+    char *src = NULL;
+    esxVMX_Data *data = opaque;
+
+    if (STRPREFIX(fileName, "/vmfs/volumes/")) {
+        /* Found absolute path referencing a file inside a datastore */
+        return esxAbsolutePathToDatastorePath(data->ctx, fileName);
+    } else if (STRPREFIX(fileName, "/")) {
+        /* Found absolute path referencing a file outside a datastore */
+        src = strdup(fileName);
+
+        if (src == NULL) {
+            virReportOOMError();
+            return NULL;
+        }
+
+        /* FIXME: Check if referenced path/file really exists */
+
+        return src;
+    } else if (strchr(fileName, '/') != NULL) {
+        /* Found relative path, this is not supported */
+        ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
+                  _("Found relative path '%s' in VMX file, this is not "
+                    "supported"), fileName);
+        return NULL;
+    } else {
+        /* Found single file name referencing a file inside a datastore */
+        if (virAsprintf(&src, "[%s] %s/%s", data->datastoreName,
+                        data->directoryName, fileName) < 0) {
+            virReportOOMError();
+            return NULL;
+        }
+
+        /* FIXME: Check if referenced path/file really exists */
+
+        return src;
+    }
+}
+
+
+
+static char *
+esxFormatVMXFileName(const char *src, void *opaque ATTRIBUTE_UNUSED)
+{
+    bool success = false;
+    char *datastoreName = NULL;
+    char *directoryName = NULL;
+    char *fileName = NULL;
+    char *absolutePath = NULL;
+
+    if (STRPREFIX(src, "[")) {
+        /* Found potential datastore path */
+        if (esxUtil_ParseDatastorePath(src, &datastoreName, &directoryName,
+                                       &fileName) < 0) {
+            goto cleanup;
+        }
+
+        if (directoryName == NULL) {
+            if (virAsprintf(&absolutePath, "/vmfs/volumes/%s/%s",
+                            datastoreName, fileName) < 0) {
+                virReportOOMError();
+                goto cleanup;
+            }
+        } else {
+            if (virAsprintf(&absolutePath, "/vmfs/volumes/%s/%s/%s",
+                            datastoreName, directoryName, fileName) < 0) {
+                virReportOOMError();
+                goto cleanup;
+            }
+        }
+    } else if (STRPREFIX(src, "/")) {
+        /* Found absolute path */
+        absolutePath = strdup(src);
+
+        if (absolutePath == NULL) {
+            virReportOOMError();
+            goto cleanup;
+        }
+    } else {
+        /* Found relative path, this is not supported */
+        ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
+                  _("Found relative path '%s' in domain XML, this is not "
+                    "supported"), src);
+        goto cleanup;
+    }
+
+    /* FIXME: Check if referenced path/file really exists */
+
+    success = true;
+
+  cleanup:
+    if (! success) {
+        VIR_FREE(absolutePath);
+    }
+
+    VIR_FREE(datastoreName);
+    VIR_FREE(directoryName);
+    VIR_FREE(fileName);
+
+    return absolutePath;
+}
+
+
+
+static int
+esxAutodetectSCSIControllerModel(virDomainDiskDefPtr def, int *model,
+                                 void *opaque)
+{
+    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_VmDiskFileInfo *vmDiskFileInfo = NULL;
+
+    if (def->device != VIR_DOMAIN_DISK_DEVICE_DISK ||
+        def->bus != VIR_DOMAIN_DISK_BUS_SCSI ||
+        def->type != VIR_DOMAIN_DISK_TYPE_FILE ||
+        def->src == NULL ||
+        ! STRPREFIX(def->src, "[")) {
+        /*
+         * This isn't a file-based SCSI disk device with a datastore related
+         * source path => do nothing.
+         */
+        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) {
+        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);
+
+    if (vmDiskFileInfo == NULL || vmDiskFileInfo->controllerType == NULL) {
+        ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
+                  _("Could not lookup controller model for '%s'"), def->src);
+        goto cleanup;
+    }
+
+    if (STRCASEEQ(vmDiskFileInfo->controllerType,
+                  "VirtualBusLogicController")) {
+        *model = VIR_DOMAIN_CONTROLLER_MODEL_BUSLOGIC;
+    } else if (STRCASEEQ(vmDiskFileInfo->controllerType,
+                         "VirtualLsiLogicController")) {
+        *model = VIR_DOMAIN_CONTROLLER_MODEL_LSILOGIC;
+    } else if (STRCASEEQ(vmDiskFileInfo->controllerType,
+                         "VirtualLsiLogicSASController")) {
+        *model = VIR_DOMAIN_CONTROLLER_MODEL_LSISAS1068;
+    } else if (STRCASEEQ(vmDiskFileInfo->controllerType,
+                         "ParaVirtualSCSIController")) {
+        *model = VIR_DOMAIN_CONTROLLER_MODEL_VMPVSCSI;
+    } else {
+        ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
+                  _("Found unexpected controller model '%s' for disk '%s'"),
+                  vmDiskFileInfo->controllerType, def->src);
+        goto cleanup;
+    }
+
+    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);
+
+    return result;
+}
+
 
 
 static esxVI_Boolean
@@ -2176,6 +2539,8 @@ esxDomainDumpXML(virDomainPtr domain, int flags)
     virBuffer buffer = VIR_BUFFER_INITIALIZER;
     char *url = NULL;
     char *vmx = NULL;
+    esxVMX_Context ctx;
+    esxVMX_Data data;
     virDomainDefPtr def = NULL;
     char *xml = NULL;
 
@@ -2223,8 +2588,17 @@ esxDomainDumpXML(virDomainPtr domain, int flags)
         goto cleanup;
     }
 
-    def = esxVMX_ParseConfig(priv->primary, priv->caps, vmx, datastoreName,
-                             directoryName, priv->primary->productVersion);
+    data.ctx = priv->primary;
+    data.datastoreName = datastoreName;
+    data.directoryName = directoryName;
+
+    ctx.opaque = &data;
+    ctx.parseFileName = esxParseVMXFileName;
+    ctx.formatFileName = NULL;
+    ctx.autodetectSCSIControllerModel = NULL;
+
+    def = esxVMX_ParseConfig(&ctx, priv->caps, vmx,
+                             priv->primary->productVersion);
 
     if (def != NULL) {
         xml = virDomainDefFormat(def, flags);
@@ -2255,6 +2629,8 @@ esxDomainXMLFromNative(virConnectPtr conn, const char *nativeFormat,
                        unsigned int flags ATTRIBUTE_UNUSED)
 {
     esxPrivate *priv = conn->privateData;
+    esxVMX_Context ctx;
+    esxVMX_Data data;
     virDomainDefPtr def = NULL;
     char *xml = NULL;
 
@@ -2264,7 +2640,16 @@ esxDomainXMLFromNative(virConnectPtr conn, const char *nativeFormat,
         return NULL;
     }
 
-    def = esxVMX_ParseConfig(priv->primary, priv->caps, nativeConfig, "?", "?",
+    data.ctx = priv->primary;
+    data.datastoreName = "?";
+    data.directoryName = "?";
+
+    ctx.opaque = &data;
+    ctx.parseFileName = esxParseVMXFileName;
+    ctx.formatFileName = NULL;
+    ctx.autodetectSCSIControllerModel = NULL;
+
+    def = esxVMX_ParseConfig(&ctx, priv->caps, nativeConfig,
                              priv->primary->productVersion);
 
     if (def != NULL) {
@@ -2284,6 +2669,8 @@ esxDomainXMLToNative(virConnectPtr conn, const char *nativeFormat,
                      unsigned int flags ATTRIBUTE_UNUSED)
 {
     esxPrivate *priv = conn->privateData;
+    esxVMX_Context ctx;
+    esxVMX_Data data;
     virDomainDefPtr def = NULL;
     char *vmx = NULL;
 
@@ -2299,7 +2686,16 @@ esxDomainXMLToNative(virConnectPtr conn, const char *nativeFormat,
         return NULL;
     }
 
-    vmx = esxVMX_FormatConfig(priv->primary, priv->caps, def,
+    data.ctx = priv->primary;
+    data.datastoreName = NULL;
+    data.directoryName = NULL;
+
+    ctx.opaque = &data;
+    ctx.parseFileName = NULL;
+    ctx.formatFileName = esxFormatVMXFileName;
+    ctx.autodetectSCSIControllerModel = esxAutodetectSCSIControllerModel;
+
+    vmx = esxVMX_FormatConfig(&ctx, priv->caps, def,
                               priv->primary->productVersion);
 
     virDomainDefFree(def);
@@ -2488,6 +2884,8 @@ esxDomainDefineXML(virConnectPtr conn, const char *xml ATTRIBUTE_UNUSED)
     int i;
     virDomainDiskDefPtr disk = NULL;
     esxVI_ObjectContent *virtualMachine = NULL;
+    esxVMX_Context ctx;
+    esxVMX_Data data;
     char *datastoreName = NULL;
     char *directoryName = NULL;
     char *fileName = NULL;
@@ -2529,7 +2927,16 @@ esxDomainDefineXML(virConnectPtr conn, const char *xml ATTRIBUTE_UNUSED)
     }
 
     /* Build VMX from domain XML */
-    vmx = esxVMX_FormatConfig(priv->primary, priv->caps, def,
+    data.ctx = priv->primary;
+    data.datastoreName = NULL;
+    data.directoryName = NULL;
+
+    ctx.opaque = &data;
+    ctx.parseFileName = NULL;
+    ctx.formatFileName = esxFormatVMXFileName;
+    ctx.autodetectSCSIControllerModel = esxAutodetectSCSIControllerModel;
+
+    vmx = esxVMX_FormatConfig(&ctx, priv->caps, def,
                               priv->primary->productVersion);
 
     if (vmx == NULL) {
diff --git a/src/esx/esx_vmx.c b/src/esx/esx_vmx.c
index 1a5e8d3..d5d9ff0 100644
--- a/src/esx/esx_vmx.c
+++ b/src/esx/esx_vmx.c
@@ -29,9 +29,7 @@
 #include "virterror_internal.h"
 #include "memory.h"
 #include "logging.h"
-#include "esx_vi_methods.h"
 #include "esx_private.h"
-#include "esx_util.h"
 #include "esx_vmx.h"
 
 /*
@@ -441,6 +439,11 @@ VIR_ENUM_IMPL(esxVMX_SCSIControllerModel, VIR_DOMAIN_CONTROLLER_MODEL_LAST,
               "pvscsi");
 
 
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Helpers
+ */
+
 int
 esxVMX_SCSIDiskNameToControllerAndUnit(const char *name, int *controller, int *unit)
 {
@@ -718,171 +721,7 @@ esxVMX_HandleLegacySCSIDiskDriverName(virDomainDefPtr def,
 
 
 int
-esxVMX_AutodetectSCSIControllerModel(esxVI_Context *ctx,
-                                     virDomainDiskDefPtr def, int *model)
-{
-    int result = -1;
-    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_VmDiskFileInfo *vmDiskFileInfo = NULL;
-
-    if (def->device != VIR_DOMAIN_DISK_DEVICE_DISK ||
-        def->bus != VIR_DOMAIN_DISK_BUS_SCSI ||
-        def->type != VIR_DOMAIN_DISK_TYPE_FILE ||
-        def->src == NULL ||
-        ! STRPREFIX(def->src, "[")) {
-        /*
-         * This isn't a file-based SCSI disk device with a datastore related
-         * source path => do nothing.
-         */
-        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(ctx, datastoreName, propertyNameList,
-                                    &datastore,
-                                    esxVI_Occurrence_RequiredItem) < 0 ||
-        esxVI_GetManagedObjectReference(datastore, "browser",
-                                        &hostDatastoreBrowser,
-                                        esxVI_Occurrence_RequiredItem) < 0) {
-        goto cleanup;
-    }
-
-    /* Build HostDatastoreBrowserSearchSpec */
-    if (esxVI_HostDatastoreBrowserSearchSpec_Alloc(&searchSpec) < 0 ||
-        esxVI_FileQueryFlags_Alloc(&searchSpec->details) < 0) {
-        goto cleanup;
-    }
-
-    searchSpec->details->fileType = esxVI_Boolean_True;
-    searchSpec->details->fileSize = esxVI_Boolean_False;
-    searchSpec->details->modification = esxVI_Boolean_False;
-
-    if (esxVI_VmDiskFileQuery_Alloc(&vmDiskFileQuery) < 0 ||
-        esxVI_VmDiskFileQueryFlags_Alloc(&vmDiskFileQuery->details) < 0 ||
-        esxVI_FileQuery_AppendToList
-          (&searchSpec->query,
-           esxVI_FileQuery_DynamicCast(vmDiskFileQuery)) < 0) {
-        goto cleanup;
-    }
-
-    vmDiskFileQuery->details->diskType = esxVI_Boolean_False;
-    vmDiskFileQuery->details->capacityKb = esxVI_Boolean_False;
-    vmDiskFileQuery->details->hardwareVersion = esxVI_Boolean_False;
-    vmDiskFileQuery->details->controllerType = esxVI_Boolean_True;
-    vmDiskFileQuery->details->diskExtents = esxVI_Boolean_False;
-
-    if (esxVI_String_Alloc(&searchSpec->matchPattern) < 0) {
-        goto cleanup;
-    }
-
-    searchSpec->matchPattern->value = fileName;
-
-    /* Search datastore for file */
-    if (esxVI_SearchDatastore_Task(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_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 */
-    vmDiskFileInfo = esxVI_VmDiskFileInfo_DynamicCast(searchResults->file);
-
-    if (vmDiskFileInfo == NULL || vmDiskFileInfo->controllerType == NULL) {
-        ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
-                  _("Could not lookup controller model for '%s'"), def->src);
-        goto cleanup;
-    }
-
-    if (STRCASEEQ(vmDiskFileInfo->controllerType,
-                  "VirtualBusLogicController")) {
-        *model = VIR_DOMAIN_CONTROLLER_MODEL_BUSLOGIC;
-    } else if (STRCASEEQ(vmDiskFileInfo->controllerType,
-                         "VirtualLsiLogicController")) {
-        *model = VIR_DOMAIN_CONTROLLER_MODEL_LSILOGIC;
-    } else if (STRCASEEQ(vmDiskFileInfo->controllerType,
-                         "VirtualLsiLogicSASController")) {
-        *model = VIR_DOMAIN_CONTROLLER_MODEL_LSISAS1068;
-    } else if (STRCASEEQ(vmDiskFileInfo->controllerType,
-                         "ParaVirtualSCSIController")) {
-        *model = VIR_DOMAIN_CONTROLLER_MODEL_VMPVSCSI;
-    } else {
-        ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
-                  _("Found unexpected controller model '%s' for disk '%s'"),
-                  vmDiskFileInfo->controllerType, def->src);
-        goto cleanup;
-    }
-
-    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);
-
-    return result;
-}
-
-
-
-int
-esxVMX_GatherSCSIControllers(esxVI_Context *ctx, virDomainDefPtr def,
+esxVMX_GatherSCSIControllers(esxVMX_Context *ctx, virDomainDefPtr def,
                              int virtualDev[4], bool present[4])
 {
     int result = -1;
@@ -923,8 +762,8 @@ esxVMX_GatherSCSIControllers(esxVI_Context *ctx, virDomainDefPtr def,
             continue;
         }
 
-        if (ctx != NULL &&
-            controller->model == VIR_DOMAIN_CONTROLLER_MODEL_AUTO) {
+        if (controller->model == VIR_DOMAIN_CONTROLLER_MODEL_AUTO &&
+            ctx->autodetectSCSIControllerModel != NULL) {
             count = 0;
 
             // try to autodetect the SCSI controller model by collecting
@@ -934,8 +773,9 @@ esxVMX_GatherSCSIControllers(esxVI_Context *ctx, virDomainDefPtr def,
 
                 if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI &&
                     disk->info.addr.drive.controller == controller->idx) {
-                    if (esxVMX_AutodetectSCSIControllerModel
-                          (ctx, disk, &autodetectedModels[count]) < 0) {
+                    if (ctx->autodetectSCSIControllerModel
+                               (disk, &autodetectedModels[count],
+                                ctx->opaque) < 0) {
                         goto cleanup;
                     }
 
@@ -985,144 +825,12 @@ esxVMX_GatherSCSIControllers(esxVI_Context *ctx, virDomainDefPtr def,
 
 
 
-char *
-esxVMX_AbsolutePathToDatastorePath(esxVI_Context *ctx, const char *absolutePath)
-{
-    bool success = false;
-    char *copyOfAbsolutePath = NULL;
-    char *tmp = NULL;
-    char *saveptr = NULL;
-    esxVI_String *propertyNameList = NULL;
-    esxVI_ObjectContent *datastore = NULL;
-
-    char *datastorePath = NULL;
-    char *preliminaryDatastoreName = NULL;
-    char *directoryAndFileName = NULL;
-    char *datastoreName = NULL;
-
-    if (esxVI_String_DeepCopyValue(&copyOfAbsolutePath, absolutePath) < 0) {
-        return NULL;
-    }
-
-    /* Expected format: '/vmfs/volumes/<datastore>/<path>' */
-    if ((tmp = STRSKIP(copyOfAbsolutePath, "/vmfs/volumes/")) == NULL ||
-        (preliminaryDatastoreName = strtok_r(tmp, "/", &saveptr)) == NULL ||
-        (directoryAndFileName = strtok_r(NULL, "", &saveptr)) == NULL) {
-        ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
-                  _("Absolute path '%s' doesn't have expected format "
-                    "'/vmfs/volumes/<datastore>/<path>'"), absolutePath);
-        goto cleanup;
-    }
-
-    if (ctx != NULL) {
-        if (esxVI_String_AppendValueToList(&propertyNameList,
-                                           "summary.name") < 0 ||
-            esxVI_LookupDatastoreByAbsolutePath(ctx, absolutePath,
-                                                propertyNameList, &datastore,
-                                                esxVI_Occurrence_OptionalItem) < 0) {
-            goto cleanup;
-        }
-
-        if (datastore == NULL) {
-            if (esxVI_LookupDatastoreByName(ctx, preliminaryDatastoreName,
-                                            propertyNameList, &datastore,
-                                            esxVI_Occurrence_OptionalItem) < 0) {
-                goto cleanup;
-            }
-        }
-
-        if (datastore != NULL) {
-            if (esxVI_GetStringValue(datastore, "summary.name", &datastoreName,
-                                     esxVI_Occurrence_RequiredItem)) {
-                goto cleanup;
-            }
-        }
-
-        if (datastoreName == NULL) {
-            VIR_WARN("Could not retrieve datastore name for absolute "
-                     "path '%s', falling back to preliminary name '%s'",
-                     absolutePath, preliminaryDatastoreName);
-
-            datastoreName = preliminaryDatastoreName;
-        }
-    } else {
-        datastoreName = preliminaryDatastoreName;
-    }
-
-    if (virAsprintf(&datastorePath, "[%s] %s", datastoreName,
-                    directoryAndFileName) < 0) {
-        virReportOOMError();
-        goto cleanup;
-    }
-
-    /* FIXME: Check if referenced path/file really exists */
-
-    success = true;
-
-  cleanup:
-    if (! success) {
-        VIR_FREE(datastorePath);
-    }
-
-    VIR_FREE(copyOfAbsolutePath);
-    esxVI_String_Free(&propertyNameList);
-    esxVI_ObjectContent_Free(&datastore);
-
-    return datastorePath;
-}
-
-
-
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * VMX -> Domain XML
  */
 
-char *
-esxVMX_ParseFileName(esxVI_Context *ctx, const char *fileName,
-                     const char *datastoreName, const char *directoryName)
-{
-    char *src = NULL;
-
-    if (STRPREFIX(fileName, "/vmfs/volumes/")) {
-        /* Found absolute path referencing a file inside a datastore */
-        return esxVMX_AbsolutePathToDatastorePath(ctx, fileName);
-    } else if (STRPREFIX(fileName, "/")) {
-        /* Found absolute path referencing a file outside a datastore */
-        src = strdup(fileName);
-
-        if (src == NULL) {
-            virReportOOMError();
-            return NULL;
-        }
-
-        /* FIXME: Check if referenced path/file really exists */
-
-        return src;
-    } else if (strchr(fileName, '/') != NULL) {
-        /* Found relative path, this is not supported */
-        ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
-                  _("Found relative path '%s' in VMX file, this is not "
-                    "supported"), fileName);
-        return NULL;
-    } else {
-        /* Found single file name referencing a file inside a datastore */
-        if (virAsprintf(&src, "[%s] %s/%s", datastoreName, directoryName,
-                        fileName) < 0) {
-            virReportOOMError();
-            return NULL;
-        }
-
-        /* FIXME: Check if referenced path/file really exists */
-
-        return src;
-    }
-}
-
-
-
 virDomainDefPtr
-esxVMX_ParseConfig(esxVI_Context *ctx, virCapsPtr caps, const char *vmx,
-                   const char *datastoreName, const char *directoryName,
+esxVMX_ParseConfig(esxVMX_Context *ctx, virCapsPtr caps, const char *vmx,
                    esxVI_ProductVersion productVersion)
 {
     bool success = false;
@@ -1142,6 +850,12 @@ esxVMX_ParseConfig(esxVI_Context *ctx, virCapsPtr caps, const char *vmx,
     int scsi_virtualDev[4] = { -1, -1, -1, -1 };
     int unit;
 
+    if (ctx->parseFileName == NULL) {
+        ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
+                  _("esxVMX_Context has no parseFileName function set"));
+        return NULL;
+    }
+
     conf = virConfReadMem(vmx, strlen(vmx), VIR_CONF_FLAG_VMX_FORMAT);
 
     if (conf == NULL) {
@@ -1429,7 +1143,6 @@ esxVMX_ParseConfig(esxVI_Context *ctx, virCapsPtr caps, const char *vmx,
 
             if (esxVMX_ParseDisk(ctx, caps, conf, VIR_DOMAIN_DISK_DEVICE_DISK,
                                  VIR_DOMAIN_DISK_BUS_SCSI, controller, unit,
-                                 datastoreName, directoryName,
                                  &def->disks[def->ndisks]) < 0) {
                 goto cleanup;
             }
@@ -1441,7 +1154,6 @@ esxVMX_ParseConfig(esxVI_Context *ctx, virCapsPtr caps, const char *vmx,
 
             if (esxVMX_ParseDisk(ctx, caps, conf, VIR_DOMAIN_DISK_DEVICE_CDROM,
                                  VIR_DOMAIN_DISK_BUS_SCSI, controller, unit,
-                                 datastoreName, directoryName,
                                  &def->disks[def->ndisks]) < 0) {
                 goto cleanup;
             }
@@ -1457,7 +1169,6 @@ esxVMX_ParseConfig(esxVI_Context *ctx, virCapsPtr caps, const char *vmx,
         for (unit = 0; unit < 2; ++unit) {
             if (esxVMX_ParseDisk(ctx, caps, conf, VIR_DOMAIN_DISK_DEVICE_DISK,
                                  VIR_DOMAIN_DISK_BUS_IDE, bus, unit,
-                                 datastoreName, directoryName,
                                  &def->disks[def->ndisks]) < 0) {
                 goto cleanup;
             }
@@ -1469,7 +1180,6 @@ esxVMX_ParseConfig(esxVI_Context *ctx, virCapsPtr caps, const char *vmx,
 
             if (esxVMX_ParseDisk(ctx, caps, conf, VIR_DOMAIN_DISK_DEVICE_CDROM,
                                  VIR_DOMAIN_DISK_BUS_IDE, bus, unit,
-                                 datastoreName, directoryName,
                                  &def->disks[def->ndisks]) < 0) {
                 goto cleanup;
             }
@@ -1484,7 +1194,6 @@ esxVMX_ParseConfig(esxVI_Context *ctx, virCapsPtr caps, const char *vmx,
     for (unit = 0; unit < 2; ++unit) {
         if (esxVMX_ParseDisk(ctx, caps, conf, VIR_DOMAIN_DISK_DEVICE_FLOPPY,
                              VIR_DOMAIN_DISK_BUS_FDC, 0, unit,
-                             datastoreName, directoryName,
                              &def->disks[def->ndisks]) < 0) {
             goto cleanup;
         }
@@ -1555,7 +1264,7 @@ esxVMX_ParseConfig(esxVI_Context *ctx, virCapsPtr caps, const char *vmx,
     def->nserials = 0;
 
     for (port = 0; port < 4; ++port) {
-        if (esxVMX_ParseSerial(ctx, conf, port, datastoreName, directoryName,
+        if (esxVMX_ParseSerial(ctx, conf, port,
                                &def->serials[def->nserials]) < 0) {
             goto cleanup;
         }
@@ -1574,7 +1283,7 @@ esxVMX_ParseConfig(esxVI_Context *ctx, virCapsPtr caps, const char *vmx,
     def->nparallels = 0;
 
     for (port = 0; port < 3; ++port) {
-        if (esxVMX_ParseParallel(ctx, conf, port, datastoreName, directoryName,
+        if (esxVMX_ParseParallel(ctx, conf, port,
                                  &def->parallels[def->nparallels]) < 0) {
             goto cleanup;
         }
@@ -1752,9 +1461,8 @@ struct _virDomainDiskDef {
 };*/
 
 int
-esxVMX_ParseDisk(esxVI_Context *ctx, virCapsPtr caps, virConfPtr conf,
+esxVMX_ParseDisk(esxVMX_Context *ctx, virCapsPtr caps, virConfPtr conf,
                  int device, int busType, int controllerOrBus, int unit,
-                 const char *datastoreName, const char *directoryName,
                  virDomainDiskDefPtr *def)
 {
     /*
@@ -1996,8 +1704,7 @@ esxVMX_ParseDisk(esxVI_Context *ctx, virCapsPtr caps, virConfPtr conf,
             }
 
             (*def)->type = VIR_DOMAIN_DISK_TYPE_FILE;
-            (*def)->src = esxVMX_ParseFileName(ctx, fileName, datastoreName,
-                                               directoryName);
+            (*def)->src = ctx->parseFileName(fileName, ctx->opaque);
             (*def)->cachemode = writeThrough ? VIR_DOMAIN_DISK_CACHE_WRITETHRU
                                              : VIR_DOMAIN_DISK_CACHE_DEFAULT;
 
@@ -2031,8 +1738,7 @@ esxVMX_ParseDisk(esxVI_Context *ctx, virCapsPtr caps, virConfPtr conf,
             }
 
             (*def)->type = VIR_DOMAIN_DISK_TYPE_FILE;
-            (*def)->src = esxVMX_ParseFileName(ctx, fileName, datastoreName,
-                                               directoryName);
+            (*def)->src = ctx->parseFileName(fileName, ctx->opaque);
 
             if ((*def)->src == NULL) {
                 goto cleanup;
@@ -2068,8 +1774,7 @@ esxVMX_ParseDisk(esxVI_Context *ctx, virCapsPtr caps, virConfPtr conf,
             }
 
             (*def)->type = VIR_DOMAIN_DISK_TYPE_FILE;
-            (*def)->src = esxVMX_ParseFileName(ctx, fileName, datastoreName,
-                                               directoryName);
+            (*def)->src = ctx->parseFileName(fileName, ctx->opaque);
 
             if ((*def)->src == NULL) {
                 goto cleanup;
@@ -2358,8 +2063,7 @@ esxVMX_ParseEthernet(virConfPtr conf, int controller, virDomainNetDefPtr *def)
 
 
 int
-esxVMX_ParseSerial(esxVI_Context *ctx, virConfPtr conf, int port,
-                   const char *datastoreName, const char *directoryName,
+esxVMX_ParseSerial(esxVMX_Context *ctx, virConfPtr conf, int port,
                    virDomainChrDefPtr *def)
 {
     int result = -1;
@@ -2439,9 +2143,7 @@ esxVMX_ParseSerial(esxVI_Context *ctx, virConfPtr conf, int port,
     } else if (STRCASEEQ(fileType, "file")) {
         (*def)->target.port = port;
         (*def)->type = VIR_DOMAIN_CHR_TYPE_FILE;
-        (*def)->data.file.path = esxVMX_ParseFileName(ctx, fileName,
-                                                      datastoreName,
-                                                      directoryName);
+        (*def)->data.file.path = ctx->parseFileName(fileName, ctx->opaque);
 
         if ((*def)->data.file.path == NULL) {
             goto cleanup;
@@ -2488,8 +2190,7 @@ esxVMX_ParseSerial(esxVI_Context *ctx, virConfPtr conf, int port,
 
 
 int
-esxVMX_ParseParallel(esxVI_Context *ctx, virConfPtr conf, int port,
-                     const char *datastoreName, const char *directoryName,
+esxVMX_ParseParallel(esxVMX_Context *ctx, virConfPtr conf, int port,
                      virDomainChrDefPtr *def)
 {
     int result = -1;
@@ -2569,9 +2270,7 @@ esxVMX_ParseParallel(esxVI_Context *ctx, virConfPtr conf, int port,
     } else if (STRCASEEQ(fileType, "file")) {
         (*def)->target.port = port;
         (*def)->type = VIR_DOMAIN_CHR_TYPE_FILE;
-        (*def)->data.file.path = esxVMX_ParseFileName(ctx, fileName,
-                                                      datastoreName,
-                                                      directoryName);
+        (*def)->data.file.path = ctx->parseFileName(fileName, ctx->opaque);
 
         if ((*def)->data.file.path == NULL) {
             goto cleanup;
@@ -2612,70 +2311,7 @@ esxVMX_ParseParallel(esxVI_Context *ctx, virConfPtr conf, int port,
  */
 
 char *
-esxVMX_FormatFileName(esxVI_Context *ctx ATTRIBUTE_UNUSED, const char *src)
-{
-    bool success = false;
-    char *datastoreName = NULL;
-    char *directoryName = NULL;
-    char *fileName = NULL;
-    char *absolutePath = NULL;
-
-    if (STRPREFIX(src, "[")) {
-        /* Found potential datastore related path */
-        if (esxUtil_ParseDatastorePath(src, &datastoreName, &directoryName,
-                                       &fileName) < 0) {
-            goto cleanup;
-        }
-
-        if (directoryName == NULL) {
-            if (virAsprintf(&absolutePath, "/vmfs/volumes/%s/%s",
-                            datastoreName, fileName) < 0) {
-                virReportOOMError();
-                goto cleanup;
-            }
-        } else {
-            if (virAsprintf(&absolutePath, "/vmfs/volumes/%s/%s/%s",
-                            datastoreName, directoryName, fileName) < 0) {
-                virReportOOMError();
-                goto cleanup;
-            }
-        }
-    } else if (STRPREFIX(src, "/")) {
-        /* Found absolute path */
-        absolutePath = strdup(src);
-
-        if (absolutePath == NULL) {
-            virReportOOMError();
-            goto cleanup;
-        }
-    } else {
-        /* Found relative path, this is not supported */
-        ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
-                  _("Found relative path '%s' in domain XML, this is not "
-                    "supported"), src);
-        goto cleanup;
-    }
-
-    /* FIXME: Check if referenced path/file really exists */
-
-    success = true;
-
-  cleanup:
-    if (! success) {
-        VIR_FREE(absolutePath);
-    }
-
-    VIR_FREE(datastoreName);
-    VIR_FREE(directoryName);
-    VIR_FREE(fileName);
-
-    return absolutePath;
-}
-
-
-
-char *
-esxVMX_FormatConfig(esxVI_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
+esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
                     esxVI_ProductVersion productVersion)
 {
     int i;
@@ -2685,6 +2321,12 @@ esxVMX_FormatConfig(esxVI_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
     bool scsi_present[4] = { false, false, false, false };
     int scsi_virtualDev[4] = { -1, -1, -1, -1 };
 
+    if (ctx->formatFileName == NULL) {
+        ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
+                  _("esxVMX_Context has no formatFileName function set"));
+        return NULL;
+    }
+
     memset(zero, 0, VIR_UUID_BUFLEN);
 
     if (def->virtType != VIR_DOMAIN_VIRT_VMWARE) { /* FIXME: maybe add VIR_DOMAIN_VIRT_ESX ? */
@@ -2990,7 +2632,7 @@ esxVMX_FormatVNC(virDomainGraphicsDefPtr def, virBufferPtr buffer)
 
 
 int
-esxVMX_FormatHardDisk(esxVI_Context *ctx, virDomainDiskDefPtr def,
+esxVMX_FormatHardDisk(esxVMX_Context *ctx, virDomainDiskDefPtr def,
                       virBufferPtr buffer)
 {
     int controllerOrBus, unit;
@@ -3050,7 +2692,7 @@ esxVMX_FormatHardDisk(esxVI_Context *ctx, virDomainDiskDefPtr def,
             return -1;
         }
 
-        fileName = esxVMX_FormatFileName(ctx, def->src);
+        fileName = ctx->formatFileName(def->src, ctx->opaque);
 
         if (fileName == NULL) {
             return -1;
@@ -3081,7 +2723,7 @@ esxVMX_FormatHardDisk(esxVI_Context *ctx, virDomainDiskDefPtr def,
 
 
 int
-esxVMX_FormatCDROM(esxVI_Context *ctx, virDomainDiskDefPtr def,
+esxVMX_FormatCDROM(esxVMX_Context *ctx, virDomainDiskDefPtr def,
                    virBufferPtr buffer)
 {
     int controllerOrBus, unit;
@@ -3132,7 +2774,7 @@ esxVMX_FormatCDROM(esxVI_Context *ctx, virDomainDiskDefPtr def,
                 return -1;
             }
 
-            fileName = esxVMX_FormatFileName(ctx, def->src);
+            fileName = ctx->formatFileName(def->src, ctx->opaque);
 
             if (fileName == NULL) {
                 return -1;
@@ -3167,7 +2809,7 @@ esxVMX_FormatCDROM(esxVI_Context *ctx, virDomainDiskDefPtr def,
 
 
 int
-esxVMX_FormatFloppy(esxVI_Context *ctx, virDomainDiskDefPtr def,
+esxVMX_FormatFloppy(esxVMX_Context *ctx, virDomainDiskDefPtr def,
                     virBufferPtr buffer)
 {
     int unit;
@@ -3195,7 +2837,7 @@ esxVMX_FormatFloppy(esxVI_Context *ctx, virDomainDiskDefPtr def,
                 return -1;
             }
 
-            fileName = esxVMX_FormatFileName(ctx, def->src);
+            fileName = ctx->formatFileName(def->src, ctx->opaque);
 
             if (fileName == NULL) {
                 return -1;
@@ -3331,7 +2973,7 @@ esxVMX_FormatEthernet(virDomainNetDefPtr def, int controller,
 
 
 int
-esxVMX_FormatSerial(esxVI_Context *ctx, virDomainChrDefPtr def,
+esxVMX_FormatSerial(esxVMX_Context *ctx, virDomainChrDefPtr def,
                     virBufferPtr buffer)
 {
     char *fileName = NULL;
@@ -3365,7 +3007,7 @@ esxVMX_FormatSerial(esxVI_Context *ctx, virDomainChrDefPtr def,
         virBufferVSprintf(buffer, "serial%d.fileType = \"file\"\n",
                           def->target.port);
 
-        fileName = esxVMX_FormatFileName(ctx, def->data.file.path);
+        fileName = ctx->formatFileName(def->data.file.path, ctx->opaque);
 
         if (fileName == NULL) {
             return -1;
@@ -3408,7 +3050,7 @@ esxVMX_FormatSerial(esxVI_Context *ctx, virDomainChrDefPtr def,
 
 
 int
-esxVMX_FormatParallel(esxVI_Context *ctx, virDomainChrDefPtr def,
+esxVMX_FormatParallel(esxVMX_Context *ctx, virDomainChrDefPtr def,
                       virBufferPtr buffer)
 {
     char *fileName = NULL;
@@ -3443,7 +3085,7 @@ esxVMX_FormatParallel(esxVI_Context *ctx, virDomainChrDefPtr def,
         virBufferVSprintf(buffer, "parallel%d.fileType = \"file\"\n",
                           def->target.port);
 
-        fileName = esxVMX_FormatFileName(ctx, def->data.file.path);
+        fileName = ctx->formatFileName(def->data.file.path, ctx->opaque);
 
         if (fileName == NULL) {
             return -1;
diff --git a/src/esx/esx_vmx.h b/src/esx/esx_vmx.h
index bda98f0..a77264a 100644
--- a/src/esx/esx_vmx.h
+++ b/src/esx/esx_vmx.h
@@ -30,6 +30,37 @@
 # include "domain_conf.h"
 # include "esx_vi.h"
 
+typedef struct _esxVMX_Context esxVMX_Context;
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Context
+ */
+
+typedef char * (*esxVMX_ParseFileName)(const char *fileName, void *opaque);
+typedef char * (*esxVMX_FormatFileName)(const char *src, void *opaque);
+typedef int (*esxVMX_AutodetectSCSIControllerModel)(virDomainDiskDefPtr def,
+                                                    int *model, void *opaque);
+
+/*
+ * esxVMX_ParseFileName is only used by esxVMX_ParseConfig.
+ * esxVMX_FormatFileName is only used by esxVMX_FormatConfig.
+ * esxVMX_AutodetectSCSIControllerModel is optionally used by esxVMX_FormatConfig.
+ */
+struct _esxVMX_Context {
+    void *opaque;
+    esxVMX_ParseFileName parseFileName;
+    esxVMX_FormatFileName formatFileName;
+    esxVMX_AutodetectSCSIControllerModel autodetectSCSIControllerModel;
+};
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Helpers
+ */
+
 int
 esxVMX_SCSIDiskNameToControllerAndUnit(const char *name, int *controller,
                                        int *unit);
@@ -48,29 +79,17 @@ esxVMX_HandleLegacySCSIDiskDriverName(virDomainDefPtr def,
                                       virDomainDiskDefPtr disk);
 
 int
-esxVMX_AutodetectSCSIControllerModel(esxVI_Context *ctx,
-                                     virDomainDiskDefPtr def, int *model);
-
-int
-esxVMX_GatherSCSIControllers(esxVI_Context *ctx, virDomainDefPtr def,
+esxVMX_GatherSCSIControllers(esxVMX_Context *ctx, virDomainDefPtr def,
                              int virtualDev[4], bool present[4]);
 
-char *
-esxVMX_AbsolutePathToDatastorePath(esxVI_Context *ctx, const char *absolutePath);
-
 
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * VMX -> Domain XML
  */
 
-char *
-esxVMX_ParseFileName(esxVI_Context *ctx, const char *fileName,
-                     const char *datastoreName, const char *directoryName);
-
 virDomainDefPtr
-esxVMX_ParseConfig(esxVI_Context *ctx, virCapsPtr caps, const char *vmx,
-                   const char *datastoreName, const char *directoryName,
+esxVMX_ParseConfig(esxVMX_Context *ctx, virCapsPtr caps, const char *vmx,
                    esxVI_ProductVersion productVersion);
 
 int
@@ -81,21 +100,18 @@ esxVMX_ParseSCSIController(virConfPtr conf, int controller, bool *present,
                            int *virtualDev);
 
 int
-esxVMX_ParseDisk(esxVI_Context *ctx, virCapsPtr caps, virConfPtr conf,
+esxVMX_ParseDisk(esxVMX_Context *ctx, virCapsPtr caps, virConfPtr conf,
                  int device, int busType, int controllerOrBus, int unit,
-                 const char *datastoreName, const char *directoryName,
                  virDomainDiskDefPtr *def);
 int
 esxVMX_ParseEthernet(virConfPtr conf, int controller, virDomainNetDefPtr *def);
 
 int
-esxVMX_ParseSerial(esxVI_Context *ctx, virConfPtr conf, int port,
-                   const char *datastoreName, const char *directoryName,
+esxVMX_ParseSerial(esxVMX_Context *ctx, virConfPtr conf, int port,
                    virDomainChrDefPtr *def);
 
 int
-esxVMX_ParseParallel(esxVI_Context *ctx, virConfPtr conf, int port,
-                     const char *datastoreName, const char *directoryName,
+esxVMX_ParseParallel(esxVMX_Context *ctx, virConfPtr conf, int port,
                      virDomainChrDefPtr *def);
 
 
@@ -105,25 +121,22 @@ esxVMX_ParseParallel(esxVI_Context *ctx, virConfPtr conf, int port,
  */
 
 char *
-esxVMX_FormatFileName(esxVI_Context *ctx, const char *src);
-
-char *
-esxVMX_FormatConfig(esxVI_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
+esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
                     esxVI_ProductVersion productVersion);
 
 int
 esxVMX_FormatVNC(virDomainGraphicsDefPtr def, virBufferPtr buffer);
 
 int
-esxVMX_FormatHardDisk(esxVI_Context *ctx, virDomainDiskDefPtr def,
+esxVMX_FormatHardDisk(esxVMX_Context *ctx, virDomainDiskDefPtr def,
                       virBufferPtr buffer);
 
 int
-esxVMX_FormatCDROM(esxVI_Context *ctx, virDomainDiskDefPtr def,
+esxVMX_FormatCDROM(esxVMX_Context *ctx, virDomainDiskDefPtr def,
                    virBufferPtr buffer);
 
 int
-esxVMX_FormatFloppy(esxVI_Context *ctx, virDomainDiskDefPtr def,
+esxVMX_FormatFloppy(esxVMX_Context *ctx, virDomainDiskDefPtr def,
                     virBufferPtr buffer);
 
 int
@@ -131,11 +144,11 @@ esxVMX_FormatEthernet(virDomainNetDefPtr def, int controller,
                       virBufferPtr buffer);
 
 int
-esxVMX_FormatSerial(esxVI_Context *ctx, virDomainChrDefPtr def,
+esxVMX_FormatSerial(esxVMX_Context *ctx, virDomainChrDefPtr def,
                     virBufferPtr buffer);
 
 int
-esxVMX_FormatParallel(esxVI_Context *ctx, virDomainChrDefPtr def,
+esxVMX_FormatParallel(esxVMX_Context *ctx, virDomainChrDefPtr def,
                       virBufferPtr buffer);
 
 #endif /* __ESX_VMX_H__ */
diff --git a/tests/vmx2xmltest.c b/tests/vmx2xmltest.c
index f1d2471..50e7d0c 100644
--- a/tests/vmx2xmltest.c
+++ b/tests/vmx2xmltest.c
@@ -14,6 +14,7 @@
 static char *progname = NULL;
 static char *abs_srcdir = NULL;
 static virCapsPtr caps = NULL;
+static esxVMX_Context ctx;
 
 # define MAX_FILE 4096
 
@@ -87,8 +88,7 @@ testCompareFiles(const char *vmx, const char *xml,
         goto failure;
     }
 
-    def = esxVMX_ParseConfig(NULL, caps, vmxData, "datastore", "directory",
-                             productVersion);
+    def = esxVMX_ParseConfig(&ctx, caps, vmxData, productVersion);
 
     if (def == NULL) {
         err = virGetLastError();
@@ -139,6 +139,49 @@ testCompareHelper(const void *data)
     return testCompareFiles(vmx, xml, info->version);
 }
 
+static char *
+testParseVMXFileName(const char *fileName, void *opaque ATTRIBUTE_UNUSED)
+{
+    char *copyOfFileName = NULL;
+    char *tmp = NULL;
+    char *saveptr = NULL;
+    char *datastoreName = NULL;
+    char *directoryAndFileName = NULL;
+    char *src = NULL;
+
+    if (STRPREFIX(fileName, "/vmfs/volumes/")) {
+        /* Found absolute path referencing a file inside a datastore */
+        copyOfFileName = strdup(fileName);
+
+        if (copyOfFileName == NULL) {
+            goto cleanup;
+        }
+
+        /* Expected format: '/vmfs/volumes/<datastore>/<path>' */
+        if ((tmp = STRSKIP(copyOfFileName, "/vmfs/volumes/")) == NULL ||
+            (datastoreName = strtok_r(tmp, "/", &saveptr)) == NULL ||
+            (directoryAndFileName = strtok_r(NULL, "", &saveptr)) == NULL) {
+            goto cleanup;
+        }
+
+        virAsprintf(&src, "[%s] %s", datastoreName, directoryAndFileName);
+    } else if (STRPREFIX(fileName, "/")) {
+        /* Found absolute path referencing a file outside a datastore */
+        src = strdup(fileName);
+    } else if (strchr(fileName, '/') != NULL) {
+        /* Found relative path, this is not supported */
+        src = NULL;
+    } else {
+        /* Found single file name referencing a file inside a datastore */
+        virAsprintf(&src, "[datastore] directory/%s", fileName);
+    }
+
+  cleanup:
+    VIR_FREE(copyOfFileName);
+
+    return src;
+}
+
 static int
 mymain(int argc, char **argv)
 {
@@ -179,6 +222,11 @@ mymain(int argc, char **argv)
         return EXIT_FAILURE;
     }
 
+    ctx.opaque = NULL;
+    ctx.parseFileName = testParseVMXFileName;
+    ctx.formatFileName = NULL;
+    ctx.autodetectSCSIControllerModel = NULL;
+
     DO_TEST("case-insensitive-1", "case-insensitive-1", esxVI_ProductVersion_ESX35);
     DO_TEST("case-insensitive-2", "case-insensitive-2", esxVI_ProductVersion_ESX35);
 
diff --git a/tests/xml2vmxtest.c b/tests/xml2vmxtest.c
index 0a9bc53..eed3ac0 100644
--- a/tests/xml2vmxtest.c
+++ b/tests/xml2vmxtest.c
@@ -14,6 +14,7 @@
 static char *progname = NULL;
 static char *abs_srcdir = NULL;
 static virCapsPtr caps = NULL;
+static esxVMX_Context ctx;
 
 # define MAX_FILE 4096
 
@@ -92,7 +93,7 @@ testCompareFiles(const char *xml, const char *vmx,
         goto failure;
     }
 
-    formatted = esxVMX_FormatConfig(NULL, caps, def, productVersion);
+    formatted = esxVMX_FormatConfig(&ctx, caps, def, productVersion);
 
     if (formatted == NULL) {
         goto failure;
@@ -134,6 +135,60 @@ testCompareHelper(const void *data)
 }
 
 static int
+testAutodetectSCSIControllerModel(virDomainDiskDefPtr def ATTRIBUTE_UNUSED,
+                                  int *model, void *opaque ATTRIBUTE_UNUSED)
+{
+    *model = VIR_DOMAIN_CONTROLLER_MODEL_LSILOGIC;
+
+    return 0;
+}
+
+static char *
+testFormatVMXFileName(const char *src, void *opaque ATTRIBUTE_UNUSED)
+{
+    bool success = false;
+    char *datastoreName = NULL;
+    char *directoryName = NULL;
+    char *fileName = NULL;
+    char *absolutePath = NULL;
+
+    if (STRPREFIX(src, "[")) {
+        /* Found potential datastore path */
+        if (esxUtil_ParseDatastorePath(src, &datastoreName, &directoryName,
+                                       &fileName) < 0) {
+            goto cleanup;
+        }
+
+        if (directoryName == NULL) {
+            virAsprintf(&absolutePath, "/vmfs/volumes/%s/%s", datastoreName,
+                        fileName);
+        } else {
+            virAsprintf(&absolutePath, "/vmfs/volumes/%s/%s/%s", datastoreName,
+                        directoryName, fileName);
+        }
+    } else if (STRPREFIX(src, "/")) {
+        /* Found absolute path */
+        absolutePath = strdup(src);
+    } else {
+        /* Found relative path, this is not supported */
+        goto cleanup;
+    }
+
+    success = true;
+
+  cleanup:
+    if (! success) {
+        VIR_FREE(absolutePath);
+    }
+
+    VIR_FREE(datastoreName);
+    VIR_FREE(directoryName);
+    VIR_FREE(fileName);
+
+    return absolutePath;
+}
+
+static int
 mymain(int argc, char **argv)
 {
     int result = 0;
@@ -157,7 +212,7 @@ mymain(int argc, char **argv)
         return EXIT_FAILURE;
     }
 
-# define DO_TEST(_in, _out, _version)                                      \
+# define DO_TEST(_in, _out, _version)                                         \
         do {                                                                  \
             struct testInfo info = { _in, _out, _version };                   \
             virResetLastError();                                              \
@@ -173,6 +228,11 @@ mymain(int argc, char **argv)
         return EXIT_FAILURE;
     }
 
+    ctx.opaque = NULL;
+    ctx.parseFileName = NULL;
+    ctx.formatFileName = testFormatVMXFileName;
+    ctx.autodetectSCSIControllerModel = testAutodetectSCSIControllerModel;
+
     DO_TEST("minimal", "minimal", esxVI_ProductVersion_ESX35);
     DO_TEST("minimal-64bit", "minimal-64bit", esxVI_ProductVersion_ESX35);
 
-- 
1.7.0.4




More information about the libvir-list mailing list