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(©OfAbsolutePath, 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(©OfAbsolutePath, 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list