mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-20 11:35:19 +00:00
esx: Split VMX code into a general and an ESX specific part
Introduce esxVMX_Context containing functions pointers to glue both parts together in a 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.
This commit is contained in:
parent
79c27a620a
commit
3de8245560
@ -50,6 +50,369 @@
|
|||||||
|
|
||||||
static int esxDomainGetMaxVcpus(virDomainPtr domain);
|
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
|
static esxVI_Boolean
|
||||||
@ -2176,6 +2539,8 @@ esxDomainDumpXML(virDomainPtr domain, int flags)
|
|||||||
virBuffer buffer = VIR_BUFFER_INITIALIZER;
|
virBuffer buffer = VIR_BUFFER_INITIALIZER;
|
||||||
char *url = NULL;
|
char *url = NULL;
|
||||||
char *vmx = NULL;
|
char *vmx = NULL;
|
||||||
|
esxVMX_Context ctx;
|
||||||
|
esxVMX_Data data;
|
||||||
virDomainDefPtr def = NULL;
|
virDomainDefPtr def = NULL;
|
||||||
char *xml = NULL;
|
char *xml = NULL;
|
||||||
|
|
||||||
@ -2223,8 +2588,17 @@ esxDomainDumpXML(virDomainPtr domain, int flags)
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
def = esxVMX_ParseConfig(priv->primary, priv->caps, vmx, datastoreName,
|
data.ctx = priv->primary;
|
||||||
directoryName, priv->primary->productVersion);
|
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) {
|
if (def != NULL) {
|
||||||
xml = virDomainDefFormat(def, flags);
|
xml = virDomainDefFormat(def, flags);
|
||||||
@ -2255,6 +2629,8 @@ esxDomainXMLFromNative(virConnectPtr conn, const char *nativeFormat,
|
|||||||
unsigned int flags ATTRIBUTE_UNUSED)
|
unsigned int flags ATTRIBUTE_UNUSED)
|
||||||
{
|
{
|
||||||
esxPrivate *priv = conn->privateData;
|
esxPrivate *priv = conn->privateData;
|
||||||
|
esxVMX_Context ctx;
|
||||||
|
esxVMX_Data data;
|
||||||
virDomainDefPtr def = NULL;
|
virDomainDefPtr def = NULL;
|
||||||
char *xml = NULL;
|
char *xml = NULL;
|
||||||
|
|
||||||
@ -2264,7 +2640,16 @@ esxDomainXMLFromNative(virConnectPtr conn, const char *nativeFormat,
|
|||||||
return NULL;
|
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);
|
priv->primary->productVersion);
|
||||||
|
|
||||||
if (def != NULL) {
|
if (def != NULL) {
|
||||||
@ -2284,6 +2669,8 @@ esxDomainXMLToNative(virConnectPtr conn, const char *nativeFormat,
|
|||||||
unsigned int flags ATTRIBUTE_UNUSED)
|
unsigned int flags ATTRIBUTE_UNUSED)
|
||||||
{
|
{
|
||||||
esxPrivate *priv = conn->privateData;
|
esxPrivate *priv = conn->privateData;
|
||||||
|
esxVMX_Context ctx;
|
||||||
|
esxVMX_Data data;
|
||||||
virDomainDefPtr def = NULL;
|
virDomainDefPtr def = NULL;
|
||||||
char *vmx = NULL;
|
char *vmx = NULL;
|
||||||
|
|
||||||
@ -2299,7 +2686,16 @@ esxDomainXMLToNative(virConnectPtr conn, const char *nativeFormat,
|
|||||||
return NULL;
|
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);
|
priv->primary->productVersion);
|
||||||
|
|
||||||
virDomainDefFree(def);
|
virDomainDefFree(def);
|
||||||
@ -2488,6 +2884,8 @@ esxDomainDefineXML(virConnectPtr conn, const char *xml ATTRIBUTE_UNUSED)
|
|||||||
int i;
|
int i;
|
||||||
virDomainDiskDefPtr disk = NULL;
|
virDomainDiskDefPtr disk = NULL;
|
||||||
esxVI_ObjectContent *virtualMachine = NULL;
|
esxVI_ObjectContent *virtualMachine = NULL;
|
||||||
|
esxVMX_Context ctx;
|
||||||
|
esxVMX_Data data;
|
||||||
char *datastoreName = NULL;
|
char *datastoreName = NULL;
|
||||||
char *directoryName = NULL;
|
char *directoryName = NULL;
|
||||||
char *fileName = NULL;
|
char *fileName = NULL;
|
||||||
@ -2529,7 +2927,16 @@ esxDomainDefineXML(virConnectPtr conn, const char *xml ATTRIBUTE_UNUSED)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Build VMX from domain XML */
|
/* 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);
|
priv->primary->productVersion);
|
||||||
|
|
||||||
if (vmx == NULL) {
|
if (vmx == NULL) {
|
||||||
|
@ -29,9 +29,7 @@
|
|||||||
#include "virterror_internal.h"
|
#include "virterror_internal.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
#include "esx_vi_methods.h"
|
|
||||||
#include "esx_private.h"
|
#include "esx_private.h"
|
||||||
#include "esx_util.h"
|
|
||||||
#include "esx_vmx.h"
|
#include "esx_vmx.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -441,6 +439,11 @@ VIR_ENUM_IMPL(esxVMX_SCSIControllerModel, VIR_DOMAIN_CONTROLLER_MODEL_LAST,
|
|||||||
"pvscsi");
|
"pvscsi");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Helpers
|
||||||
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
esxVMX_SCSIDiskNameToControllerAndUnit(const char *name, int *controller, int *unit)
|
esxVMX_SCSIDiskNameToControllerAndUnit(const char *name, int *controller, int *unit)
|
||||||
{
|
{
|
||||||
@ -718,171 +721,7 @@ esxVMX_HandleLegacySCSIDiskDriverName(virDomainDefPtr def,
|
|||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
esxVMX_AutodetectSCSIControllerModel(esxVI_Context *ctx,
|
esxVMX_GatherSCSIControllers(esxVMX_Context *ctx, virDomainDefPtr def,
|
||||||
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,
|
|
||||||
int virtualDev[4], bool present[4])
|
int virtualDev[4], bool present[4])
|
||||||
{
|
{
|
||||||
int result = -1;
|
int result = -1;
|
||||||
@ -923,8 +762,8 @@ esxVMX_GatherSCSIControllers(esxVI_Context *ctx, virDomainDefPtr def,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx != NULL &&
|
if (controller->model == VIR_DOMAIN_CONTROLLER_MODEL_AUTO &&
|
||||||
controller->model == VIR_DOMAIN_CONTROLLER_MODEL_AUTO) {
|
ctx->autodetectSCSIControllerModel != NULL) {
|
||||||
count = 0;
|
count = 0;
|
||||||
|
|
||||||
// try to autodetect the SCSI controller model by collecting
|
// 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 &&
|
if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI &&
|
||||||
disk->info.addr.drive.controller == controller->idx) {
|
disk->info.addr.drive.controller == controller->idx) {
|
||||||
if (esxVMX_AutodetectSCSIControllerModel
|
if (ctx->autodetectSCSIControllerModel
|
||||||
(ctx, disk, &autodetectedModels[count]) < 0) {
|
(disk, &autodetectedModels[count],
|
||||||
|
ctx->opaque) < 0) {
|
||||||
goto cleanup;
|
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
|
* 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
|
virDomainDefPtr
|
||||||
esxVMX_ParseConfig(esxVI_Context *ctx, virCapsPtr caps, const char *vmx,
|
esxVMX_ParseConfig(esxVMX_Context *ctx, virCapsPtr caps, const char *vmx,
|
||||||
const char *datastoreName, const char *directoryName,
|
|
||||||
esxVI_ProductVersion productVersion)
|
esxVI_ProductVersion productVersion)
|
||||||
{
|
{
|
||||||
bool success = false;
|
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 scsi_virtualDev[4] = { -1, -1, -1, -1 };
|
||||||
int unit;
|
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);
|
conf = virConfReadMem(vmx, strlen(vmx), VIR_CONF_FLAG_VMX_FORMAT);
|
||||||
|
|
||||||
if (conf == NULL) {
|
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,
|
if (esxVMX_ParseDisk(ctx, caps, conf, VIR_DOMAIN_DISK_DEVICE_DISK,
|
||||||
VIR_DOMAIN_DISK_BUS_SCSI, controller, unit,
|
VIR_DOMAIN_DISK_BUS_SCSI, controller, unit,
|
||||||
datastoreName, directoryName,
|
|
||||||
&def->disks[def->ndisks]) < 0) {
|
&def->disks[def->ndisks]) < 0) {
|
||||||
goto cleanup;
|
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,
|
if (esxVMX_ParseDisk(ctx, caps, conf, VIR_DOMAIN_DISK_DEVICE_CDROM,
|
||||||
VIR_DOMAIN_DISK_BUS_SCSI, controller, unit,
|
VIR_DOMAIN_DISK_BUS_SCSI, controller, unit,
|
||||||
datastoreName, directoryName,
|
|
||||||
&def->disks[def->ndisks]) < 0) {
|
&def->disks[def->ndisks]) < 0) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
@ -1457,7 +1169,6 @@ esxVMX_ParseConfig(esxVI_Context *ctx, virCapsPtr caps, const char *vmx,
|
|||||||
for (unit = 0; unit < 2; ++unit) {
|
for (unit = 0; unit < 2; ++unit) {
|
||||||
if (esxVMX_ParseDisk(ctx, caps, conf, VIR_DOMAIN_DISK_DEVICE_DISK,
|
if (esxVMX_ParseDisk(ctx, caps, conf, VIR_DOMAIN_DISK_DEVICE_DISK,
|
||||||
VIR_DOMAIN_DISK_BUS_IDE, bus, unit,
|
VIR_DOMAIN_DISK_BUS_IDE, bus, unit,
|
||||||
datastoreName, directoryName,
|
|
||||||
&def->disks[def->ndisks]) < 0) {
|
&def->disks[def->ndisks]) < 0) {
|
||||||
goto cleanup;
|
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,
|
if (esxVMX_ParseDisk(ctx, caps, conf, VIR_DOMAIN_DISK_DEVICE_CDROM,
|
||||||
VIR_DOMAIN_DISK_BUS_IDE, bus, unit,
|
VIR_DOMAIN_DISK_BUS_IDE, bus, unit,
|
||||||
datastoreName, directoryName,
|
|
||||||
&def->disks[def->ndisks]) < 0) {
|
&def->disks[def->ndisks]) < 0) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
@ -1484,7 +1194,6 @@ esxVMX_ParseConfig(esxVI_Context *ctx, virCapsPtr caps, const char *vmx,
|
|||||||
for (unit = 0; unit < 2; ++unit) {
|
for (unit = 0; unit < 2; ++unit) {
|
||||||
if (esxVMX_ParseDisk(ctx, caps, conf, VIR_DOMAIN_DISK_DEVICE_FLOPPY,
|
if (esxVMX_ParseDisk(ctx, caps, conf, VIR_DOMAIN_DISK_DEVICE_FLOPPY,
|
||||||
VIR_DOMAIN_DISK_BUS_FDC, 0, unit,
|
VIR_DOMAIN_DISK_BUS_FDC, 0, unit,
|
||||||
datastoreName, directoryName,
|
|
||||||
&def->disks[def->ndisks]) < 0) {
|
&def->disks[def->ndisks]) < 0) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
@ -1555,7 +1264,7 @@ esxVMX_ParseConfig(esxVI_Context *ctx, virCapsPtr caps, const char *vmx,
|
|||||||
def->nserials = 0;
|
def->nserials = 0;
|
||||||
|
|
||||||
for (port = 0; port < 4; ++port) {
|
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) {
|
&def->serials[def->nserials]) < 0) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
@ -1574,7 +1283,7 @@ esxVMX_ParseConfig(esxVI_Context *ctx, virCapsPtr caps, const char *vmx,
|
|||||||
def->nparallels = 0;
|
def->nparallels = 0;
|
||||||
|
|
||||||
for (port = 0; port < 3; ++port) {
|
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) {
|
&def->parallels[def->nparallels]) < 0) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
@ -1752,9 +1461,8 @@ struct _virDomainDiskDef {
|
|||||||
};*/
|
};*/
|
||||||
|
|
||||||
int
|
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,
|
int device, int busType, int controllerOrBus, int unit,
|
||||||
const char *datastoreName, const char *directoryName,
|
|
||||||
virDomainDiskDefPtr *def)
|
virDomainDiskDefPtr *def)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -1996,8 +1704,7 @@ esxVMX_ParseDisk(esxVI_Context *ctx, virCapsPtr caps, virConfPtr conf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
(*def)->type = VIR_DOMAIN_DISK_TYPE_FILE;
|
(*def)->type = VIR_DOMAIN_DISK_TYPE_FILE;
|
||||||
(*def)->src = esxVMX_ParseFileName(ctx, fileName, datastoreName,
|
(*def)->src = ctx->parseFileName(fileName, ctx->opaque);
|
||||||
directoryName);
|
|
||||||
(*def)->cachemode = writeThrough ? VIR_DOMAIN_DISK_CACHE_WRITETHRU
|
(*def)->cachemode = writeThrough ? VIR_DOMAIN_DISK_CACHE_WRITETHRU
|
||||||
: VIR_DOMAIN_DISK_CACHE_DEFAULT;
|
: 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)->type = VIR_DOMAIN_DISK_TYPE_FILE;
|
||||||
(*def)->src = esxVMX_ParseFileName(ctx, fileName, datastoreName,
|
(*def)->src = ctx->parseFileName(fileName, ctx->opaque);
|
||||||
directoryName);
|
|
||||||
|
|
||||||
if ((*def)->src == NULL) {
|
if ((*def)->src == NULL) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -2068,8 +1774,7 @@ esxVMX_ParseDisk(esxVI_Context *ctx, virCapsPtr caps, virConfPtr conf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
(*def)->type = VIR_DOMAIN_DISK_TYPE_FILE;
|
(*def)->type = VIR_DOMAIN_DISK_TYPE_FILE;
|
||||||
(*def)->src = esxVMX_ParseFileName(ctx, fileName, datastoreName,
|
(*def)->src = ctx->parseFileName(fileName, ctx->opaque);
|
||||||
directoryName);
|
|
||||||
|
|
||||||
if ((*def)->src == NULL) {
|
if ((*def)->src == NULL) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -2358,8 +2063,7 @@ esxVMX_ParseEthernet(virConfPtr conf, int controller, virDomainNetDefPtr *def)
|
|||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
esxVMX_ParseSerial(esxVI_Context *ctx, virConfPtr conf, int port,
|
esxVMX_ParseSerial(esxVMX_Context *ctx, virConfPtr conf, int port,
|
||||||
const char *datastoreName, const char *directoryName,
|
|
||||||
virDomainChrDefPtr *def)
|
virDomainChrDefPtr *def)
|
||||||
{
|
{
|
||||||
int result = -1;
|
int result = -1;
|
||||||
@ -2439,9 +2143,7 @@ esxVMX_ParseSerial(esxVI_Context *ctx, virConfPtr conf, int port,
|
|||||||
} else if (STRCASEEQ(fileType, "file")) {
|
} else if (STRCASEEQ(fileType, "file")) {
|
||||||
(*def)->target.port = port;
|
(*def)->target.port = port;
|
||||||
(*def)->type = VIR_DOMAIN_CHR_TYPE_FILE;
|
(*def)->type = VIR_DOMAIN_CHR_TYPE_FILE;
|
||||||
(*def)->data.file.path = esxVMX_ParseFileName(ctx, fileName,
|
(*def)->data.file.path = ctx->parseFileName(fileName, ctx->opaque);
|
||||||
datastoreName,
|
|
||||||
directoryName);
|
|
||||||
|
|
||||||
if ((*def)->data.file.path == NULL) {
|
if ((*def)->data.file.path == NULL) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -2488,8 +2190,7 @@ esxVMX_ParseSerial(esxVI_Context *ctx, virConfPtr conf, int port,
|
|||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
esxVMX_ParseParallel(esxVI_Context *ctx, virConfPtr conf, int port,
|
esxVMX_ParseParallel(esxVMX_Context *ctx, virConfPtr conf, int port,
|
||||||
const char *datastoreName, const char *directoryName,
|
|
||||||
virDomainChrDefPtr *def)
|
virDomainChrDefPtr *def)
|
||||||
{
|
{
|
||||||
int result = -1;
|
int result = -1;
|
||||||
@ -2569,9 +2270,7 @@ esxVMX_ParseParallel(esxVI_Context *ctx, virConfPtr conf, int port,
|
|||||||
} else if (STRCASEEQ(fileType, "file")) {
|
} else if (STRCASEEQ(fileType, "file")) {
|
||||||
(*def)->target.port = port;
|
(*def)->target.port = port;
|
||||||
(*def)->type = VIR_DOMAIN_CHR_TYPE_FILE;
|
(*def)->type = VIR_DOMAIN_CHR_TYPE_FILE;
|
||||||
(*def)->data.file.path = esxVMX_ParseFileName(ctx, fileName,
|
(*def)->data.file.path = ctx->parseFileName(fileName, ctx->opaque);
|
||||||
datastoreName,
|
|
||||||
directoryName);
|
|
||||||
|
|
||||||
if ((*def)->data.file.path == NULL) {
|
if ((*def)->data.file.path == NULL) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -2612,70 +2311,7 @@ esxVMX_ParseParallel(esxVI_Context *ctx, virConfPtr conf, int port,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
char *
|
char *
|
||||||
esxVMX_FormatFileName(esxVI_Context *ctx ATTRIBUTE_UNUSED, const char *src)
|
esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
|
||||||
{
|
|
||||||
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,
|
|
||||||
esxVI_ProductVersion productVersion)
|
esxVI_ProductVersion productVersion)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -2685,6 +2321,12 @@ esxVMX_FormatConfig(esxVI_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
|
|||||||
bool scsi_present[4] = { false, false, false, false };
|
bool scsi_present[4] = { false, false, false, false };
|
||||||
int scsi_virtualDev[4] = { -1, -1, -1, -1 };
|
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);
|
memset(zero, 0, VIR_UUID_BUFLEN);
|
||||||
|
|
||||||
if (def->virtType != VIR_DOMAIN_VIRT_VMWARE) { /* FIXME: maybe add VIR_DOMAIN_VIRT_ESX ? */
|
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
|
int
|
||||||
esxVMX_FormatHardDisk(esxVI_Context *ctx, virDomainDiskDefPtr def,
|
esxVMX_FormatHardDisk(esxVMX_Context *ctx, virDomainDiskDefPtr def,
|
||||||
virBufferPtr buffer)
|
virBufferPtr buffer)
|
||||||
{
|
{
|
||||||
int controllerOrBus, unit;
|
int controllerOrBus, unit;
|
||||||
@ -3050,7 +2692,7 @@ esxVMX_FormatHardDisk(esxVI_Context *ctx, virDomainDiskDefPtr def,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fileName = esxVMX_FormatFileName(ctx, def->src);
|
fileName = ctx->formatFileName(def->src, ctx->opaque);
|
||||||
|
|
||||||
if (fileName == NULL) {
|
if (fileName == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
@ -3081,7 +2723,7 @@ esxVMX_FormatHardDisk(esxVI_Context *ctx, virDomainDiskDefPtr def,
|
|||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
esxVMX_FormatCDROM(esxVI_Context *ctx, virDomainDiskDefPtr def,
|
esxVMX_FormatCDROM(esxVMX_Context *ctx, virDomainDiskDefPtr def,
|
||||||
virBufferPtr buffer)
|
virBufferPtr buffer)
|
||||||
{
|
{
|
||||||
int controllerOrBus, unit;
|
int controllerOrBus, unit;
|
||||||
@ -3132,7 +2774,7 @@ esxVMX_FormatCDROM(esxVI_Context *ctx, virDomainDiskDefPtr def,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fileName = esxVMX_FormatFileName(ctx, def->src);
|
fileName = ctx->formatFileName(def->src, ctx->opaque);
|
||||||
|
|
||||||
if (fileName == NULL) {
|
if (fileName == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
@ -3167,7 +2809,7 @@ esxVMX_FormatCDROM(esxVI_Context *ctx, virDomainDiskDefPtr def,
|
|||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
esxVMX_FormatFloppy(esxVI_Context *ctx, virDomainDiskDefPtr def,
|
esxVMX_FormatFloppy(esxVMX_Context *ctx, virDomainDiskDefPtr def,
|
||||||
virBufferPtr buffer)
|
virBufferPtr buffer)
|
||||||
{
|
{
|
||||||
int unit;
|
int unit;
|
||||||
@ -3195,7 +2837,7 @@ esxVMX_FormatFloppy(esxVI_Context *ctx, virDomainDiskDefPtr def,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fileName = esxVMX_FormatFileName(ctx, def->src);
|
fileName = ctx->formatFileName(def->src, ctx->opaque);
|
||||||
|
|
||||||
if (fileName == NULL) {
|
if (fileName == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
@ -3331,7 +2973,7 @@ esxVMX_FormatEthernet(virDomainNetDefPtr def, int controller,
|
|||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
esxVMX_FormatSerial(esxVI_Context *ctx, virDomainChrDefPtr def,
|
esxVMX_FormatSerial(esxVMX_Context *ctx, virDomainChrDefPtr def,
|
||||||
virBufferPtr buffer)
|
virBufferPtr buffer)
|
||||||
{
|
{
|
||||||
char *fileName = NULL;
|
char *fileName = NULL;
|
||||||
@ -3365,7 +3007,7 @@ esxVMX_FormatSerial(esxVI_Context *ctx, virDomainChrDefPtr def,
|
|||||||
virBufferVSprintf(buffer, "serial%d.fileType = \"file\"\n",
|
virBufferVSprintf(buffer, "serial%d.fileType = \"file\"\n",
|
||||||
def->target.port);
|
def->target.port);
|
||||||
|
|
||||||
fileName = esxVMX_FormatFileName(ctx, def->data.file.path);
|
fileName = ctx->formatFileName(def->data.file.path, ctx->opaque);
|
||||||
|
|
||||||
if (fileName == NULL) {
|
if (fileName == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
@ -3408,7 +3050,7 @@ esxVMX_FormatSerial(esxVI_Context *ctx, virDomainChrDefPtr def,
|
|||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
esxVMX_FormatParallel(esxVI_Context *ctx, virDomainChrDefPtr def,
|
esxVMX_FormatParallel(esxVMX_Context *ctx, virDomainChrDefPtr def,
|
||||||
virBufferPtr buffer)
|
virBufferPtr buffer)
|
||||||
{
|
{
|
||||||
char *fileName = NULL;
|
char *fileName = NULL;
|
||||||
@ -3443,7 +3085,7 @@ esxVMX_FormatParallel(esxVI_Context *ctx, virDomainChrDefPtr def,
|
|||||||
virBufferVSprintf(buffer, "parallel%d.fileType = \"file\"\n",
|
virBufferVSprintf(buffer, "parallel%d.fileType = \"file\"\n",
|
||||||
def->target.port);
|
def->target.port);
|
||||||
|
|
||||||
fileName = esxVMX_FormatFileName(ctx, def->data.file.path);
|
fileName = ctx->formatFileName(def->data.file.path, ctx->opaque);
|
||||||
|
|
||||||
if (fileName == NULL) {
|
if (fileName == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -30,6 +30,37 @@
|
|||||||
# include "domain_conf.h"
|
# include "domain_conf.h"
|
||||||
# include "esx_vi.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
|
int
|
||||||
esxVMX_SCSIDiskNameToControllerAndUnit(const char *name, int *controller,
|
esxVMX_SCSIDiskNameToControllerAndUnit(const char *name, int *controller,
|
||||||
int *unit);
|
int *unit);
|
||||||
@ -48,29 +79,17 @@ esxVMX_HandleLegacySCSIDiskDriverName(virDomainDefPtr def,
|
|||||||
virDomainDiskDefPtr disk);
|
virDomainDiskDefPtr disk);
|
||||||
|
|
||||||
int
|
int
|
||||||
esxVMX_AutodetectSCSIControllerModel(esxVI_Context *ctx,
|
esxVMX_GatherSCSIControllers(esxVMX_Context *ctx, virDomainDefPtr def,
|
||||||
virDomainDiskDefPtr def, int *model);
|
|
||||||
|
|
||||||
int
|
|
||||||
esxVMX_GatherSCSIControllers(esxVI_Context *ctx, virDomainDefPtr def,
|
|
||||||
int virtualDev[4], bool present[4]);
|
int virtualDev[4], bool present[4]);
|
||||||
|
|
||||||
char *
|
|
||||||
esxVMX_AbsolutePathToDatastorePath(esxVI_Context *ctx, const char *absolutePath);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
* VMX -> Domain XML
|
* VMX -> Domain XML
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char *
|
|
||||||
esxVMX_ParseFileName(esxVI_Context *ctx, const char *fileName,
|
|
||||||
const char *datastoreName, const char *directoryName);
|
|
||||||
|
|
||||||
virDomainDefPtr
|
virDomainDefPtr
|
||||||
esxVMX_ParseConfig(esxVI_Context *ctx, virCapsPtr caps, const char *vmx,
|
esxVMX_ParseConfig(esxVMX_Context *ctx, virCapsPtr caps, const char *vmx,
|
||||||
const char *datastoreName, const char *directoryName,
|
|
||||||
esxVI_ProductVersion productVersion);
|
esxVI_ProductVersion productVersion);
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -81,21 +100,18 @@ esxVMX_ParseSCSIController(virConfPtr conf, int controller, bool *present,
|
|||||||
int *virtualDev);
|
int *virtualDev);
|
||||||
|
|
||||||
int
|
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,
|
int device, int busType, int controllerOrBus, int unit,
|
||||||
const char *datastoreName, const char *directoryName,
|
|
||||||
virDomainDiskDefPtr *def);
|
virDomainDiskDefPtr *def);
|
||||||
int
|
int
|
||||||
esxVMX_ParseEthernet(virConfPtr conf, int controller, virDomainNetDefPtr *def);
|
esxVMX_ParseEthernet(virConfPtr conf, int controller, virDomainNetDefPtr *def);
|
||||||
|
|
||||||
int
|
int
|
||||||
esxVMX_ParseSerial(esxVI_Context *ctx, virConfPtr conf, int port,
|
esxVMX_ParseSerial(esxVMX_Context *ctx, virConfPtr conf, int port,
|
||||||
const char *datastoreName, const char *directoryName,
|
|
||||||
virDomainChrDefPtr *def);
|
virDomainChrDefPtr *def);
|
||||||
|
|
||||||
int
|
int
|
||||||
esxVMX_ParseParallel(esxVI_Context *ctx, virConfPtr conf, int port,
|
esxVMX_ParseParallel(esxVMX_Context *ctx, virConfPtr conf, int port,
|
||||||
const char *datastoreName, const char *directoryName,
|
|
||||||
virDomainChrDefPtr *def);
|
virDomainChrDefPtr *def);
|
||||||
|
|
||||||
|
|
||||||
@ -105,25 +121,22 @@ esxVMX_ParseParallel(esxVI_Context *ctx, virConfPtr conf, int port,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
char *
|
char *
|
||||||
esxVMX_FormatFileName(esxVI_Context *ctx, const char *src);
|
esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
|
||||||
|
|
||||||
char *
|
|
||||||
esxVMX_FormatConfig(esxVI_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
|
|
||||||
esxVI_ProductVersion productVersion);
|
esxVI_ProductVersion productVersion);
|
||||||
|
|
||||||
int
|
int
|
||||||
esxVMX_FormatVNC(virDomainGraphicsDefPtr def, virBufferPtr buffer);
|
esxVMX_FormatVNC(virDomainGraphicsDefPtr def, virBufferPtr buffer);
|
||||||
|
|
||||||
int
|
int
|
||||||
esxVMX_FormatHardDisk(esxVI_Context *ctx, virDomainDiskDefPtr def,
|
esxVMX_FormatHardDisk(esxVMX_Context *ctx, virDomainDiskDefPtr def,
|
||||||
virBufferPtr buffer);
|
virBufferPtr buffer);
|
||||||
|
|
||||||
int
|
int
|
||||||
esxVMX_FormatCDROM(esxVI_Context *ctx, virDomainDiskDefPtr def,
|
esxVMX_FormatCDROM(esxVMX_Context *ctx, virDomainDiskDefPtr def,
|
||||||
virBufferPtr buffer);
|
virBufferPtr buffer);
|
||||||
|
|
||||||
int
|
int
|
||||||
esxVMX_FormatFloppy(esxVI_Context *ctx, virDomainDiskDefPtr def,
|
esxVMX_FormatFloppy(esxVMX_Context *ctx, virDomainDiskDefPtr def,
|
||||||
virBufferPtr buffer);
|
virBufferPtr buffer);
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -131,11 +144,11 @@ esxVMX_FormatEthernet(virDomainNetDefPtr def, int controller,
|
|||||||
virBufferPtr buffer);
|
virBufferPtr buffer);
|
||||||
|
|
||||||
int
|
int
|
||||||
esxVMX_FormatSerial(esxVI_Context *ctx, virDomainChrDefPtr def,
|
esxVMX_FormatSerial(esxVMX_Context *ctx, virDomainChrDefPtr def,
|
||||||
virBufferPtr buffer);
|
virBufferPtr buffer);
|
||||||
|
|
||||||
int
|
int
|
||||||
esxVMX_FormatParallel(esxVI_Context *ctx, virDomainChrDefPtr def,
|
esxVMX_FormatParallel(esxVMX_Context *ctx, virDomainChrDefPtr def,
|
||||||
virBufferPtr buffer);
|
virBufferPtr buffer);
|
||||||
|
|
||||||
#endif /* __ESX_VMX_H__ */
|
#endif /* __ESX_VMX_H__ */
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
static char *progname = NULL;
|
static char *progname = NULL;
|
||||||
static char *abs_srcdir = NULL;
|
static char *abs_srcdir = NULL;
|
||||||
static virCapsPtr caps = NULL;
|
static virCapsPtr caps = NULL;
|
||||||
|
static esxVMX_Context ctx;
|
||||||
|
|
||||||
# define MAX_FILE 4096
|
# define MAX_FILE 4096
|
||||||
|
|
||||||
@ -87,8 +88,7 @@ testCompareFiles(const char *vmx, const char *xml,
|
|||||||
goto failure;
|
goto failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
def = esxVMX_ParseConfig(NULL, caps, vmxData, "datastore", "directory",
|
def = esxVMX_ParseConfig(&ctx, caps, vmxData, productVersion);
|
||||||
productVersion);
|
|
||||||
|
|
||||||
if (def == NULL) {
|
if (def == NULL) {
|
||||||
err = virGetLastError();
|
err = virGetLastError();
|
||||||
@ -139,6 +139,49 @@ testCompareHelper(const void *data)
|
|||||||
return testCompareFiles(vmx, xml, info->version);
|
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
|
static int
|
||||||
mymain(int argc, char **argv)
|
mymain(int argc, char **argv)
|
||||||
{
|
{
|
||||||
@ -179,6 +222,11 @@ mymain(int argc, char **argv)
|
|||||||
return EXIT_FAILURE;
|
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-1", "case-insensitive-1", esxVI_ProductVersion_ESX35);
|
||||||
DO_TEST("case-insensitive-2", "case-insensitive-2", esxVI_ProductVersion_ESX35);
|
DO_TEST("case-insensitive-2", "case-insensitive-2", esxVI_ProductVersion_ESX35);
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
static char *progname = NULL;
|
static char *progname = NULL;
|
||||||
static char *abs_srcdir = NULL;
|
static char *abs_srcdir = NULL;
|
||||||
static virCapsPtr caps = NULL;
|
static virCapsPtr caps = NULL;
|
||||||
|
static esxVMX_Context ctx;
|
||||||
|
|
||||||
# define MAX_FILE 4096
|
# define MAX_FILE 4096
|
||||||
|
|
||||||
@ -92,7 +93,7 @@ testCompareFiles(const char *xml, const char *vmx,
|
|||||||
goto failure;
|
goto failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
formatted = esxVMX_FormatConfig(NULL, caps, def, productVersion);
|
formatted = esxVMX_FormatConfig(&ctx, caps, def, productVersion);
|
||||||
|
|
||||||
if (formatted == NULL) {
|
if (formatted == NULL) {
|
||||||
goto failure;
|
goto failure;
|
||||||
@ -133,6 +134,60 @@ testCompareHelper(const void *data)
|
|||||||
return testCompareFiles(xml, vmx, info->version);
|
return testCompareFiles(xml, vmx, info->version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
static int
|
||||||
mymain(int argc, char **argv)
|
mymain(int argc, char **argv)
|
||||||
{
|
{
|
||||||
@ -173,6 +228,11 @@ mymain(int argc, char **argv)
|
|||||||
return EXIT_FAILURE;
|
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", "minimal", esxVI_ProductVersion_ESX35);
|
||||||
DO_TEST("minimal-64bit", "minimal-64bit", esxVI_ProductVersion_ESX35);
|
DO_TEST("minimal-64bit", "minimal-64bit", esxVI_ProductVersion_ESX35);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user