ESX add esxDomainDefineXML()

A given domain XML gets converted to a VMX config, uploaded to the host
and registered as new virtual machine.

* src/esx/esx_driver.c: refactor datastore related path parsing into
  esxUtil_ParseDatastoreRelatedPath()
* src/esx/esx_util.[ch]: add esxUtil_ParseDatastoreRelatedPath()
* src/esx/esx_vi.[ch]: add esxVI_Context_UploadFile(), add datastores to
  the traversal in esxVI_BuildFullTraversalSpecList(), add
  esxVI_LookupDatastoreByName()
* src/esx/esx_vi_methods.[ch]: add esxVI_RegisterVM_Task()
* src/esx/esx_vi_types.c: make some error message more verbose
* src/esx/esx_vmx.[ch]: add esxVMX_AbsolutePathToDatastoreRelatedPath()
  to convert a path into a datastore related path, add esxVMX_ParseFileName()
  to convert from VMX path format to domain XML path format, extend the other
  parsing function to be datastore aware, add esxVMX_FormatFileName() to
  convert from domain XML path format to VMX path format, fix VMX ethernet
  entry formating
* tests/esxutilstest.c: add test for esxUtil_ParseDatastoreRelatedPath()
* tests/vmx2xmldata/*: update domain XML files to use datastore related paths
* tests/xml2vmxdata/*: update domain XML files to use datastore related paths,
  update VMX files to use absolute paths
This commit is contained in:
Matthias Bolte 2009-09-23 14:52:36 +02:00 committed by Daniel Veillard
parent c3aa1f8bdb
commit 49faa15e4f
67 changed files with 1186 additions and 233 deletions

View File

@ -2267,7 +2267,8 @@ esxDomainDumpXML(virDomainPtr domain, int flags)
esxVI_DynamicProperty *dynamicProperty = NULL;
const char *vmPathName = NULL;
char *datastoreName = NULL;
char *vmxPath = NULL;
char *directoryName = NULL;
char *fileName = NULL;
virBuffer buffer = VIR_BUFFER_INITIALIZER;
char *url = NULL;
char *vmx = NULL;
@ -2306,17 +2307,21 @@ esxDomainDumpXML(virDomainPtr domain, int flags)
}
}
/* expected format: "[<datastoreName>] <vmxPath>" */
if (sscanf(vmPathName, "[%a[^]%]] %a[^\n]", &datastoreName, &vmxPath) != 2) {
ESX_ERROR(domain->conn, VIR_ERR_OPERATION_INVALID,
"'config.files.vmPathName' property '%s' doesn't have "
"expected format '[<datastore>] <vmx>'", vmPathName);
if (esxUtil_ParseDatastoreRelatedPath(domain->conn, vmPathName,
&datastoreName, &directoryName,
&fileName) < 0) {
goto failure;
}
virBufferVSprintf(&buffer, "%s://%s:%d/folder/", priv->transport,
domain->conn->uri->server, domain->conn->uri->port);
virBufferURIEncodeString(&buffer, vmxPath);
if (directoryName != NULL) {
virBufferURIEncodeString(&buffer, directoryName);
virBufferAddChar(&buffer, '/');
}
virBufferURIEncodeString(&buffer, fileName);
virBufferAddLit(&buffer, "?dcPath=");
virBufferURIEncodeString(&buffer, priv->host->datacenter->value);
virBufferAddLit(&buffer, "&dsName=");
@ -2329,11 +2334,12 @@ esxDomainDumpXML(virDomainPtr domain, int flags)
url = virBufferContentAndReset(&buffer);
if (esxVI_Context_Download(domain->conn, priv->host, url, &vmx) < 0) {
if (esxVI_Context_DownloadFile(domain->conn, priv->host, url, &vmx) < 0) {
goto failure;
}
def = esxVMX_ParseConfig(domain->conn, vmx, priv->host->apiVersion);
def = esxVMX_ParseConfig(domain->conn, priv->host, vmx, datastoreName,
directoryName, priv->host->apiVersion);
if (def != NULL) {
xml = virDomainDefFormat(domain->conn, def, flags);
@ -2343,7 +2349,8 @@ esxDomainDumpXML(virDomainPtr domain, int flags)
esxVI_String_Free(&propertyNameList);
esxVI_ObjectContent_Free(&virtualMachine);
VIR_FREE(datastoreName);
VIR_FREE(vmxPath);
VIR_FREE(directoryName);
VIR_FREE(fileName);
VIR_FREE(url);
VIR_FREE(vmx);
virDomainDefFree(def);
@ -2364,6 +2371,7 @@ esxDomainXMLFromNative(virConnectPtr conn, const char *nativeFormat,
unsigned int flags ATTRIBUTE_UNUSED)
{
esxPrivate *priv = (esxPrivate *)conn->privateData;
esxVI_Context *ctx = NULL;
esxVI_APIVersion apiVersion = esxVI_APIVersion_Unknown;
virDomainDefPtr def = NULL;
char *xml = NULL;
@ -2375,10 +2383,11 @@ esxDomainXMLFromNative(virConnectPtr conn, const char *nativeFormat,
}
if (! priv->phantom) {
ctx = priv->host;
apiVersion = priv->host->apiVersion;
}
def = esxVMX_ParseConfig(conn, nativeConfig, apiVersion);
def = esxVMX_ParseConfig(conn, ctx, nativeConfig, "?", "?", apiVersion);
if (def != NULL) {
xml = virDomainDefFormat(conn, def, VIR_DOMAIN_XML_INACTIVE);
@ -2418,7 +2427,7 @@ esxDomainXMLToNative(virConnectPtr conn, const char *nativeFormat,
return NULL;
}
vmx = esxVMX_FormatConfig(conn, def, priv->host->apiVersion);
vmx = esxVMX_FormatConfig(conn, priv->host, def, priv->host->apiVersion);
virDomainDefFree(def);
@ -2605,6 +2614,195 @@ esxDomainCreate(virDomainPtr domain)
static virDomainPtr
esxDomainDefineXML(virConnectPtr conn, const char *xml ATTRIBUTE_UNUSED)
{
esxPrivate *priv = (esxPrivate *)conn->privateData;
virDomainDefPtr def = NULL;
char *vmx = NULL;
esxVI_ObjectContent *virtualMachine = NULL;
char *datastoreName = NULL;
char *directoryName = NULL;
char *fileName = NULL;
virBuffer buffer = VIR_BUFFER_INITIALIZER;
char *url = NULL;
char *datastoreRelatedPath = NULL;
esxVI_String *propertyNameList = NULL;
esxVI_ObjectContent *hostSystem = NULL;
esxVI_ManagedObjectReference *resourcePool = NULL;
esxVI_ManagedObjectReference *task = NULL;
esxVI_TaskInfoState taskInfoState;
virDomainPtr domain = NULL;
if (priv->phantom) {
ESX_ERROR(conn, VIR_ERR_OPERATION_INVALID,
"Not possible with a phantom connection");
goto failure;
}
if (esxVI_EnsureSession(conn, priv->host) < 0) {
goto failure;
}
/* Parse domain XML */
def = virDomainDefParseString(conn, priv->caps, xml,
VIR_DOMAIN_XML_INACTIVE);
if (def == NULL) {
goto failure;
}
/* Check if an existing domain should be edited */
if (esxVI_LookupVirtualMachineByUuid(conn, priv->host, def->uuid, NULL,
&virtualMachine,
esxVI_Occurence_OptionalItem) < 0) {
goto failure;
}
if (virtualMachine != NULL) {
/* FIXME */
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"Domain already exists, editing existing domains is not "
"supported yet");
goto failure;
}
/* Build VMX from domain XML */
vmx = esxVMX_FormatConfig(conn, priv->host, def, priv->host->apiVersion);
if (vmx == NULL) {
goto failure;
}
/* Build VMX datastore URL */
if (def->ndisks < 1) {
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"Domain XML doesn't contain a disk, cannot deduce datastore "
"and path for VMX file");
goto failure;
}
if (def->disks[0]->src == NULL) {
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"First disk has no source, cannot deduce datastore and path "
"for VMX file");
goto failure;
}
if (esxUtil_ParseDatastoreRelatedPath(conn, def->disks[0]->src,
&datastoreName, &directoryName,
&fileName) < 0) {
goto failure;
}
if (! esxUtil_EqualSuffix(fileName, ".vmdk")) {
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"Expecting source of first disk '%s' to be a VMDK image",
def->disks[0]->src);
goto failure;
}
virBufferVSprintf(&buffer, "%s://%s:%d/folder/", priv->transport,
conn->uri->server, conn->uri->port);
if (directoryName != NULL) {
virBufferURIEncodeString(&buffer, directoryName);
virBufferAddChar(&buffer, '/');
}
virBufferURIEncodeString(&buffer, def->name);
virBufferAddLit(&buffer, ".vmx?dcPath=");
virBufferURIEncodeString(&buffer, priv->host->datacenter->value);
virBufferAddLit(&buffer, "&dsName=");
virBufferURIEncodeString(&buffer, datastoreName);
if (virBufferError(&buffer)) {
virReportOOMError(conn);
goto failure;
}
url = virBufferContentAndReset(&buffer);
if (directoryName != NULL) {
if (virAsprintf(&datastoreRelatedPath, "[%s] %s/%s.vmx", datastoreName,
directoryName, def->name) < 0) {
virReportOOMError(conn);
goto failure;
}
} else {
if (virAsprintf(&datastoreRelatedPath, "[%s] %s.vmx", datastoreName,
def->name) < 0) {
virReportOOMError(conn);
goto failure;
}
}
/* Get resource pool */
if (esxVI_String_AppendValueToList(conn, &propertyNameList, "parent") < 0 ||
esxVI_LookupHostSystemByIp(conn, priv->host, priv->host->ipAddress,
propertyNameList, &hostSystem) < 0) {
goto failure;
}
if (esxVI_GetResourcePool(conn, priv->host, hostSystem,
&resourcePool) < 0) {
goto failure;
}
/* Check, if VMX file already exists */
/* FIXME */
/* Upload VMX file */
if (esxVI_Context_UploadFile(conn, priv->host, url, vmx) < 0) {
goto failure;
}
/* Register the domain */
if (esxVI_RegisterVM_Task(conn, priv->host, priv->host->vmFolder,
datastoreRelatedPath, NULL, esxVI_Boolean_False,
resourcePool, hostSystem->obj, &task) < 0 ||
esxVI_WaitForTaskCompletion(conn, priv->host, task,
&taskInfoState) < 0) {
goto failure;
}
if (taskInfoState != esxVI_TaskInfoState_Success) {
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Could not define domain");
goto failure;
}
domain = virGetDomain(conn, def->name, def->uuid);
if (domain != NULL) {
domain->id = -1;
}
/* FIXME: Add proper rollback in case of an error */
cleanup:
virDomainDefFree(def);
VIR_FREE(vmx);
VIR_FREE(datastoreName);
VIR_FREE(directoryName);
VIR_FREE(fileName);
VIR_FREE(url);
VIR_FREE(datastoreRelatedPath);
esxVI_ObjectContent_Free(&virtualMachine);
esxVI_String_Free(&propertyNameList);
esxVI_ObjectContent_Free(&hostSystem);
esxVI_ManagedObjectReference_Free(&resourcePool);
esxVI_ManagedObjectReference_Free(&task);
return domain;
failure:
domain = NULL;
goto cleanup;
}
static int
esxDomainUndefine(virDomainPtr domain)
{
@ -3297,7 +3495,7 @@ static virDriver esxDriver = {
esxListDefinedDomains, /* listDefinedDomains */
esxNumberOfDefinedDomains, /* numOfDefinedDomains */
esxDomainCreate, /* domainCreate */
NULL, /* domainDefineXML */
esxDomainDefineXML, /* domainDefineXML */
esxDomainUndefine, /* domainUndefine */
NULL, /* domainAttachDevice */
NULL, /* domainDetachDevice */

View File

@ -263,6 +263,89 @@ esxUtil_ParseVirtualMachineIDString(const char *id_string, int *id)
int
esxUtil_ParseDatastoreRelatedPath(virConnectPtr conn,
const char *datastoreRelatedPath,
char **datastoreName,
char **directoryName, char **fileName)
{
int result = 0;
char *directoryAndFileName = NULL;
char *separator = NULL;
if (datastoreName == NULL || *datastoreName != NULL ||
directoryName == NULL || *directoryName != NULL ||
fileName == NULL || *fileName != NULL) {
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
goto failure;
}
/*
* Parse string as '[<datastore>] <path>'. '%as' is similar to '%s', but
* sscanf() will allocate the memory for the string, so the caller doesn't
* need to preallocate a buffer that's large enough.
*
* The s in '%as' can be replaced with a character set, e.g. [a-z].
*
* '%a[^]%]' matches <datastore>. '[^]%]' excludes ']' from the accepted
* characters, otherwise sscanf() wont match what it should.
*
* '%a[^\n]' matches <path>. '[^\n]' excludes '\n' from the accepted
* characters, otherwise sscanf() would only match up to the first space,
* but spaces are valid in <path>.
*/
if (sscanf(datastoreRelatedPath, "[%a[^]%]] %a[^\n]", datastoreName,
&directoryAndFileName) != 2) {
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"Datastore related path '%s' doesn't have expected format "
"'[<datastore>] <path>'", datastoreRelatedPath);
goto failure;
}
/* Split <path> into <directory>/<file>, where <directory> is optional */
separator = strrchr(directoryAndFileName, '/');
if (separator != NULL) {
*separator++ = '\0';
*directoryName = directoryAndFileName;
directoryAndFileName = NULL;
if (*separator == '\0') {
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"Datastore related path '%s' doesn't reference a file",
datastoreRelatedPath);
goto failure;
}
*fileName = strdup(separator);
if (*fileName == NULL) {
virReportOOMError(conn);
goto failure;
}
} else {
*fileName = directoryAndFileName;
directoryAndFileName = NULL;
}
cleanup:
VIR_FREE(directoryAndFileName);
return result;
failure:
VIR_FREE(*datastoreName);
VIR_FREE(*directoryName);
VIR_FREE(*fileName);
result = -1;
goto cleanup;
}
int
esxUtil_ResolveHostname(virConnectPtr conn, const char *hostname,
char *ipAddress, size_t ipAddress_length)

View File

@ -40,6 +40,11 @@ int esxUtil_ParseQuery(virConnectPtr conn, char **transport, char **vCenter,
int esxUtil_ParseVirtualMachineIDString(const char *id_string, int *id);
int esxUtil_ParseDatastoreRelatedPath(virConnectPtr conn,
const char *datastoreRelatedPath,
char **datastoreName,
char **directoryName, char **fileName);
int esxUtil_ResolveHostname(virConnectPtr conn, const char *hostname,
char *ipAddress, size_t ipAddress_length);

View File

@ -138,7 +138,35 @@ ESX_VI__TEMPLATE__FREE(Context,
});
static size_t
_esxVI_CURL_WriteBuffer(char *data, size_t size, size_t nmemb, void *buffer)
esxVI_CURL_ReadString(char *data, size_t size, size_t nmemb, void *ptrptr)
{
const char *content = *(const char **)ptrptr;
size_t available = 0;
size_t requested = size * nmemb;
if (content == NULL) {
return 0;
}
available = strlen(content);
if (available == 0) {
return 0;
}
if (requested > available) {
requested = available;
}
memcpy(data, content, requested);
*(const char **)ptrptr = content + requested;
return requested;
}
static size_t
esxVI_CURL_WriteBuffer(char *data, size_t size, size_t nmemb, void *buffer)
{
if (buffer != NULL) {
virBufferAdd((virBufferPtr) buffer, data, size * nmemb);
@ -153,8 +181,8 @@ _esxVI_CURL_WriteBuffer(char *data, size_t size, size_t nmemb, void *buffer)
#if ESX_VI__CURL__ENABLE_DEBUG_OUTPUT
static int
_esxVI_CURL_Debug(CURL *curl ATTRIBUTE_UNUSED, curl_infotype type,
char *info, size_t size, void *data ATTRIBUTE_UNUSED)
esxVI_CURL_Debug(CURL *curl ATTRIBUTE_UNUSED, curl_infotype type,
char *info, size_t size, void *data ATTRIBUTE_UNUSED)
{
switch (type) {
case CURLINFO_TEXT:
@ -246,11 +274,13 @@ esxVI_Context_Connect(virConnectPtr conn, esxVI_Context *ctx, const char *url,
curl_easy_setopt(ctx->curl_handle, CURLOPT_SSL_VERIFYHOST, noVerify ? 0 : 2);
curl_easy_setopt(ctx->curl_handle, CURLOPT_COOKIEFILE, "");
curl_easy_setopt(ctx->curl_handle, CURLOPT_HTTPHEADER, ctx->curl_headers);
curl_easy_setopt(ctx->curl_handle, CURLOPT_READFUNCTION,
esxVI_CURL_ReadString);
curl_easy_setopt(ctx->curl_handle, CURLOPT_WRITEFUNCTION,
_esxVI_CURL_WriteBuffer);
esxVI_CURL_WriteBuffer);
#if ESX_VI__CURL__ENABLE_DEBUG_OUTPUT
curl_easy_setopt(ctx->curl_handle, CURLOPT_DEBUGFUNCTION,
_esxVI_CURL_Debug);
esxVI_CURL_Debug);
#endif
if (virMutexInit(&ctx->curl_lock) < 0) {
@ -398,8 +428,8 @@ esxVI_Context_Connect(virConnectPtr conn, esxVI_Context *ctx, const char *url,
}
int
esxVI_Context_Download(virConnectPtr conn, esxVI_Context *ctx, const char *url,
char **content)
esxVI_Context_DownloadFile(virConnectPtr conn, esxVI_Context *ctx,
const char *url, char **content)
{
virBuffer buffer = VIR_BUFFER_INITIALIZER;
CURLcode errorCode;
@ -414,6 +444,7 @@ esxVI_Context_Download(virConnectPtr conn, esxVI_Context *ctx, const char *url,
curl_easy_setopt(ctx->curl_handle, CURLOPT_URL, url);
curl_easy_setopt(ctx->curl_handle, CURLOPT_WRITEDATA, &buffer);
curl_easy_setopt(ctx->curl_handle, CURLOPT_UPLOAD, 0);
curl_easy_setopt(ctx->curl_handle, CURLOPT_HTTPGET, 1);
errorCode = curl_easy_perform(ctx->curl_handle);
@ -464,6 +495,61 @@ esxVI_Context_Download(virConnectPtr conn, esxVI_Context *ctx, const char *url,
goto failure;
}
int
esxVI_Context_UploadFile(virConnectPtr conn, esxVI_Context *ctx,
const char *url, const char *content)
{
CURLcode errorCode;
long responseCode;
if (content == NULL) {
ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
return -1;
}
virMutexLock(&ctx->curl_lock);
curl_easy_setopt(ctx->curl_handle, CURLOPT_URL, url);
curl_easy_setopt(ctx->curl_handle, CURLOPT_READDATA, &content);
curl_easy_setopt(ctx->curl_handle, CURLOPT_UPLOAD, 1);
curl_easy_setopt(ctx->curl_handle, CURLOPT_INFILESIZE, strlen(content));
errorCode = curl_easy_perform(ctx->curl_handle);
if (errorCode != CURLE_OK) {
ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"curl_easy_perform() returned an error: %s (%d)",
curl_easy_strerror(errorCode), errorCode);
goto unlock;
}
errorCode = curl_easy_getinfo(ctx->curl_handle, CURLINFO_RESPONSE_CODE,
&responseCode);
if (errorCode != CURLE_OK) {
ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"curl_easy_getinfo() returned an error: %s (%d)",
curl_easy_strerror(errorCode), errorCode);
goto unlock;
}
virMutexUnlock(&ctx->curl_lock);
if (responseCode != 200 && responseCode != 201) {
ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"HTTP response code %d while trying to upload to '%s'",
(int)responseCode, url);
return -1;
}
return 0;
unlock:
virMutexUnlock(&ctx->curl_lock);
return -1;
}
int
esxVI_Context_Execute(virConnectPtr conn, esxVI_Context *ctx,
const char *request, const char *xpathExpression,
@ -486,6 +572,7 @@ esxVI_Context_Execute(virConnectPtr conn, esxVI_Context *ctx,
curl_easy_setopt(ctx->curl_handle, CURLOPT_URL, ctx->url);
curl_easy_setopt(ctx->curl_handle, CURLOPT_WRITEDATA, &buffer);
curl_easy_setopt(ctx->curl_handle, CURLOPT_UPLOAD, 0);
curl_easy_setopt(ctx->curl_handle, CURLOPT_POSTFIELDS, request);
curl_easy_setopt(ctx->curl_handle, CURLOPT_POSTFIELDSIZE, strlen(request));
@ -1085,15 +1172,24 @@ esxVI_BuildFullTraversalSpecList(virConnectPtr conn,
"visitFolders",
"Folder", "childEntity",
"visitFolders\0"
"datacenterToDatastore\0"
"datacenterToVmFolder\0"
"datacenterToHostFolder\0"
"computeResourceToHost\0"
"computeResourceToResourcePool\0"
"HostSystemToVm\0"
"hostSystemToVm\0"
"resourcePoolToVm\0") < 0) {
goto failure;
}
/* Traversal through datastore branch */
if (esxVI_BuildFullTraversalSpecItem(conn, fullTraversalSpecList,
"datacenterToDatastore",
"Datacenter", "datastore",
NULL) < 0) {
goto failure;
}
/* Traversal through vmFolder branch */
if (esxVI_BuildFullTraversalSpecItem(conn, fullTraversalSpecList,
"datacenterToVmFolder",
@ -1138,7 +1234,7 @@ esxVI_BuildFullTraversalSpecList(virConnectPtr conn,
/* Recurse through all hosts */
if (esxVI_BuildFullTraversalSpecItem(conn, fullTraversalSpecList,
"HostSystemToVm",
"hostSystemToVm",
"HostSystem", "vm",
"visitFolders\0") < 0) {
goto failure;
@ -1351,7 +1447,8 @@ esxVI_GetManagedEntityStatus(virConnectPtr conn,
}
ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"Missing '%s' property", propertyName);
"Missing '%s' property while looking for ManagedEntityStatus",
propertyName);
return -1;
}
@ -1725,6 +1822,119 @@ esxVI_LookupVirtualMachineByUuid(virConnectPtr conn, esxVI_Context *ctx,
int
esxVI_LookupDatastoreByName(virConnectPtr conn, esxVI_Context *ctx,
const char *name, esxVI_String *propertyNameList,
esxVI_ObjectContent **datastore,
esxVI_Occurence occurence)
{
int result = 0;
esxVI_String *completePropertyNameList = NULL;
esxVI_ObjectContent *datastoreList = NULL;
esxVI_ObjectContent *candidate = NULL;
esxVI_DynamicProperty *dynamicProperty = NULL;
size_t offset = strlen("/vmfs/volumes/");
if (datastore == NULL || *datastore != NULL) {
ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
return -1;
}
/* Get all datastores */
if (esxVI_String_DeepCopyList(conn, &completePropertyNameList,
propertyNameList) < 0 ||
esxVI_String_AppendValueListToList(conn, &completePropertyNameList,
"info.name\0"
"info.url\0") < 0) {
goto failure;
}
if (esxVI_GetObjectContent(conn, ctx, ctx->datacenter,
"Datastore", completePropertyNameList,
esxVI_Boolean_True, &datastoreList) < 0) {
goto failure;
}
if (datastoreList == NULL) {
if (occurence == esxVI_Occurence_OptionalItem) {
goto cleanup;
} else {
ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"No datastores available");
goto failure;
}
}
/* Search for a matching datastore */
for (candidate = datastoreList; candidate != NULL;
candidate = candidate->_next) {
for (dynamicProperty = candidate->propSet; dynamicProperty != NULL;
dynamicProperty = dynamicProperty->_next) {
if (STREQ(dynamicProperty->name, "info.name")) {
if (esxVI_AnyType_ExpectType(conn, dynamicProperty->val,
esxVI_Type_String) < 0) {
goto failure;
}
if (STREQ(dynamicProperty->val->string, name)) {
if (esxVI_ObjectContent_DeepCopy(conn, datastore,
candidate) < 0) {
goto failure;
}
/* Found datastore with matching name */
goto cleanup;
}
} else if (STREQ(dynamicProperty->name, "info.url")) {
if (esxVI_AnyType_ExpectType(conn, dynamicProperty->val,
esxVI_Type_String) < 0) {
goto failure;
}
if (! STRPREFIX(dynamicProperty->val->string,
"/vmfs/volumes/")) {
ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"Datastore URL '%s' has unexpected prefix, "
"expecting '/vmfs/volumes/' prefix",
dynamicProperty->val->string);
goto failure;
}
if (STREQ(dynamicProperty->val->string + offset, name)) {
if (esxVI_ObjectContent_DeepCopy(conn, datastore,
candidate) < 0) {
goto failure;
}
/* Found datastore with matching URL suffix */
goto cleanup;
}
} else {
VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
}
}
}
if (occurence != esxVI_Occurence_OptionalItem) {
ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"Could not find datastore with name '%s'", name);
goto failure;
}
cleanup:
esxVI_String_Free(&completePropertyNameList);
esxVI_ObjectContent_Free(&datastoreList);
return result;
failure:
result = -1;
goto cleanup;
}
int
esxVI_StartVirtualMachineTask(virConnectPtr conn, esxVI_Context *ctx,
const char *name, const char *request,

View File

@ -95,8 +95,10 @@ int esxVI_Context_Connect(virConnectPtr conn, esxVI_Context *ctx,
const char *ipAddress, const char *url,
const char *username, const char *password,
int noVerify);
int esxVI_Context_Download(virConnectPtr conn, esxVI_Context *ctx,
const char *url, char **content);
int esxVI_Context_DownloadFile(virConnectPtr conn, esxVI_Context *ctx,
const char *url, char **content);
int esxVI_Context_UploadFile(virConnectPtr conn, esxVI_Context *ctx,
const char *url, const char *content);
int esxVI_Context_Execute(virConnectPtr conn, esxVI_Context *ctx,
const char *request, const char *xpathExpression,
esxVI_Response **response, esxVI_Boolean expectList);
@ -246,6 +248,12 @@ int esxVI_LookupVirtualMachineByUuid(virConnectPtr conn, esxVI_Context *ctx,
esxVI_ObjectContent **virtualMachine,
esxVI_Occurence occurence);
int esxVI_LookupDatastoreByName(virConnectPtr conn, esxVI_Context *ctx,
const char *name,
esxVI_String *propertyNameList,
esxVI_ObjectContent **datastore,
esxVI_Occurence occurence);
int esxVI_StartVirtualMachineTask(virConnectPtr conn, esxVI_Context *ctx,
const char *name, const char *request,
esxVI_ManagedObjectReference **task);

View File

@ -520,6 +520,76 @@ esxVI_ReconfigVM_Task(virConnectPtr conn, esxVI_Context *ctx,
int
esxVI_RegisterVM_Task(virConnectPtr conn, esxVI_Context *ctx,
esxVI_ManagedObjectReference *folder,
const char *path, const char *name,
esxVI_Boolean asTemplate,
esxVI_ManagedObjectReference *resourcePool,
esxVI_ManagedObjectReference *hostSystem,
esxVI_ManagedObjectReference **task)
{
int result = 0;
virBuffer buffer = VIR_BUFFER_INITIALIZER;
char *request = NULL;
if (task == NULL || *task != NULL) {
ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
return -1;
}
virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_HEADER);
virBufferAddLit(&buffer, "<RegisterVM_Task xmlns=\"urn:vim25\">");
if (esxVI_ManagedObjectReference_Serialize(conn, folder, "_this", &buffer,
esxVI_Boolean_True) < 0 ||
esxVI_String_SerializeValue(conn, path, "path", &buffer,
esxVI_Boolean_True) < 0 ||
esxVI_String_SerializeValue(conn, name, "name", &buffer,
esxVI_Boolean_False) < 0 ||
esxVI_Boolean_Serialize(conn, asTemplate, "asTemplate", &buffer,
esxVI_Boolean_False) < 0 ||
esxVI_ManagedObjectReference_Serialize(conn, resourcePool, "pool",
&buffer,
esxVI_Boolean_False) < 0 ||
esxVI_ManagedObjectReference_Serialize(conn, hostSystem, "host",
&buffer,
esxVI_Boolean_False) < 0) {
goto failure;
}
virBufferAddLit(&buffer, "</RegisterVM_Task>");
virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_FOOTER);
if (virBufferError(&buffer)) {
virReportOOMError(conn);
goto failure;
}
request = virBufferContentAndReset(&buffer);
if (esxVI_StartVirtualMachineTask(conn, ctx, "RegisterVM", request,
task) < 0) {
goto failure;
}
cleanup:
VIR_FREE(request);
return result;
failure:
if (request == NULL) {
request = virBufferContentAndReset(&buffer);
}
result = -1;
goto cleanup;
}
int
esxVI_UnregisterVM(virConnectPtr conn, esxVI_Context *ctx,
esxVI_ManagedObjectReference *virtualMachine)

View File

@ -72,6 +72,14 @@ int esxVI_ReconfigVM_Task(virConnectPtr conn, esxVI_Context *ctx,
esxVI_VirtualMachineConfigSpec *spec,
esxVI_ManagedObjectReference **task);
int esxVI_RegisterVM_Task(virConnectPtr conn, esxVI_Context *ctx,
esxVI_ManagedObjectReference *folder,
const char *path, const char *name,
esxVI_Boolean asTemplate,
esxVI_ManagedObjectReference *resourcePool,
esxVI_ManagedObjectReference *hostSystem,
esxVI_ManagedObjectReference **task);
int esxVI_UnregisterVM(virConnectPtr conn, esxVI_Context *ctx,
esxVI_ManagedObjectReference *virtualMachine);

View File

@ -633,7 +633,8 @@ esxVI_AnyType_Deserialize(virConnectPtr conn, xmlNodePtr node,
BAD_CAST "http://www.w3.org/2001/XMLSchema-instance");
if ((*anyType)->other == NULL) {
ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Missing 'type' property");
ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"AnyType is missing 'type' property");
goto failure;
}
@ -1388,7 +1389,8 @@ esxVI_ManagedObjectReference_Deserialize
(char *)xmlGetNoNsProp(node, BAD_CAST "type");
if ((*managedObjectReference)->type == NULL) {
ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Missing 'type' property");
ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"ManagedObjectReference is missing 'type' property");
goto failure;
}

View File

@ -414,8 +414,8 @@ def->parallels[0]...
#define VIR_FROM_THIS VIR_FROM_ESX
#define ESX_ERROR(conn, code, fmt...) \
virReportErrorHelper (conn, VIR_FROM_ESX, code, __FILE__, __FUNCTION__, \
__LINE__, fmt)
virReportErrorHelper(conn, VIR_FROM_ESX, code, __FILE__, __FUNCTION__, \
__LINE__, fmt)
@ -583,12 +583,134 @@ esxVMX_GatherSCSIControllers(virConnectPtr conn, virDomainDefPtr def,
char *
esxVMX_AbsolutePathToDatastoreRelatedPath(virConnectPtr conn,
esxVI_Context *ctx,
const char *absolutePath)
{
char *datastoreRelatedPath = NULL;
char *preliminaryDatastoreName = NULL;
char *directoryAndFileName = NULL;
esxVI_DynamicProperty *dynamicProperty = NULL;
esxVI_ObjectContent *datastore = NULL;
const char *datastoreName = NULL;
if (sscanf(absolutePath, "/vmfs/volumes/%a[^/]/%a[^\n]",
&preliminaryDatastoreName, &directoryAndFileName) != 2) {
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"Absolute path '%s' doesn't have expected format "
"'/vmfs/volumes/<datastore>/<path>'", absolutePath);
goto failure;
}
if (ctx != NULL) {
if (esxVI_LookupDatastoreByName(conn, ctx, preliminaryDatastoreName,
NULL, &datastore,
esxVI_Occurence_RequiredItem) < 0) {
goto failure;
}
for (dynamicProperty = datastore->propSet; dynamicProperty != NULL;
dynamicProperty = dynamicProperty->_next) {
if (STREQ(dynamicProperty->name, "info.name")) {
if (esxVI_AnyType_ExpectType(conn, dynamicProperty->val,
esxVI_Type_String) < 0) {
goto failure;
}
datastoreName = dynamicProperty->val->string;
break;
} else if (STREQ(dynamicProperty->name, "info.url")) {
/* Ignore it */
} else {
VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
}
}
if (datastoreName == NULL) {
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"Could not retrieve datastore name for absolute path '%s'",
absolutePath);
goto failure;
}
} else {
datastoreName = preliminaryDatastoreName;
}
if (virAsprintf(&datastoreRelatedPath, "[%s] %s", datastoreName,
directoryAndFileName) < 0) {
virReportOOMError(conn);
goto failure;
}
/* FIXME: Check if referenced path/file really exists */
cleanup:
VIR_FREE(preliminaryDatastoreName);
VIR_FREE(directoryAndFileName);
esxVI_ObjectContent_Free(&datastore);
return datastoreRelatedPath;
failure:
VIR_FREE(datastoreRelatedPath);
goto cleanup;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* VMX -> Domain XML
*/
char *
esxVMX_ParseFileName(virConnectPtr conn, 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_AbsolutePathToDatastoreRelatedPath(conn, ctx, fileName);
} else if (STRPREFIX(fileName, "/")) {
/* Found absolute path referencing a file outside a datastore */
src = strdup(fileName);
if (src == NULL) {
virReportOOMError(conn);
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(conn, 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(conn);
return NULL;
}
/* FIXME: Check if referenced path/file really exists */
return src;
}
}
virDomainDefPtr
esxVMX_ParseConfig(virConnectPtr conn, const char *vmx,
esxVMX_ParseConfig(virConnectPtr conn, esxVI_Context *ctx, const char *vmx,
const char *datastoreName, const char *directoryName,
esxVI_APIVersion apiVersion)
{
virConfPtr conf = NULL;
@ -872,9 +994,9 @@ esxVMX_ParseConfig(virConnectPtr conn, const char *vmx,
continue;
}
if (esxVMX_ParseDisk(conn, conf, VIR_DOMAIN_DISK_DEVICE_DISK,
if (esxVMX_ParseDisk(conn, ctx, conf, VIR_DOMAIN_DISK_DEVICE_DISK,
VIR_DOMAIN_DISK_BUS_SCSI, controller, id,
scsi_virtualDev,
scsi_virtualDev, datastoreName, directoryName,
&def->disks[def->ndisks]) < 0) {
goto failure;
}
@ -884,9 +1006,9 @@ esxVMX_ParseConfig(virConnectPtr conn, const char *vmx,
continue;
}
if (esxVMX_ParseDisk(conn, conf, VIR_DOMAIN_DISK_DEVICE_CDROM,
if (esxVMX_ParseDisk(conn, ctx, conf, VIR_DOMAIN_DISK_DEVICE_CDROM,
VIR_DOMAIN_DISK_BUS_SCSI, controller, id,
scsi_virtualDev,
scsi_virtualDev, datastoreName, directoryName,
&def->disks[def->ndisks]) < 0) {
goto failure;
}
@ -900,9 +1022,10 @@ esxVMX_ParseConfig(virConnectPtr conn, const char *vmx,
/* def:disks (ide) */
for (controller = 0; controller < 2; ++controller) {
for (id = 0; id < 2; ++id) {
if (esxVMX_ParseDisk(conn, conf, VIR_DOMAIN_DISK_DEVICE_DISK,
if (esxVMX_ParseDisk(conn, ctx, conf, VIR_DOMAIN_DISK_DEVICE_DISK,
VIR_DOMAIN_DISK_BUS_IDE, controller, id,
NULL, &def->disks[def->ndisks]) < 0) {
NULL, datastoreName, directoryName,
&def->disks[def->ndisks]) < 0) {
goto failure;
}
@ -911,9 +1034,10 @@ esxVMX_ParseConfig(virConnectPtr conn, const char *vmx,
continue;
}
if (esxVMX_ParseDisk(conn, conf, VIR_DOMAIN_DISK_DEVICE_CDROM,
if (esxVMX_ParseDisk(conn, ctx, conf, VIR_DOMAIN_DISK_DEVICE_CDROM,
VIR_DOMAIN_DISK_BUS_IDE, controller, id,
NULL, &def->disks[def->ndisks]) < 0) {
NULL, datastoreName, directoryName,
&def->disks[def->ndisks]) < 0) {
goto failure;
}
@ -925,8 +1049,9 @@ esxVMX_ParseConfig(virConnectPtr conn, const char *vmx,
/* def:disks (floppy) */
for (controller = 0; controller < 2; ++controller) {
if (esxVMX_ParseDisk(conn, conf, VIR_DOMAIN_DISK_DEVICE_FLOPPY,
if (esxVMX_ParseDisk(conn, ctx, conf, VIR_DOMAIN_DISK_DEVICE_FLOPPY,
VIR_DOMAIN_DISK_BUS_FDC, controller, -1, NULL,
datastoreName, directoryName,
&def->disks[def->ndisks]) < 0) {
goto failure;
}
@ -976,7 +1101,8 @@ esxVMX_ParseConfig(virConnectPtr conn, const char *vmx,
def->nserials = 0;
for (port = 0; port < 4; ++port) {
if (esxVMX_ParseSerial(conn, conf, port,
if (esxVMX_ParseSerial(conn, ctx, conf, port,
datastoreName, directoryName,
&def->serials[def->nserials]) < 0) {
goto failure;
}
@ -995,7 +1121,8 @@ esxVMX_ParseConfig(virConnectPtr conn, const char *vmx,
def->nparallels = 0;
for (port = 0; port < 3; ++port) {
if (esxVMX_ParseParallel(conn, conf, port,
if (esxVMX_ParseParallel(conn, ctx, conf, port,
datastoreName, directoryName,
&def->parallels[def->nparallels]) < 0) {
goto failure;
}
@ -1118,9 +1245,10 @@ struct _virDomainDiskDef {
};*/
int
esxVMX_ParseDisk(virConnectPtr conn, virConfPtr conf, int device, int bus,
int controller, int id, const char *virtualDev,
virDomainDiskDefPtr *def)
esxVMX_ParseDisk(virConnectPtr conn, esxVI_Context *ctx, virConfPtr conf,
int device, int bus, int controller, int id,
const char *virtualDev, const char *datastoreName,
const char *directoryName, virDomainDiskDefPtr *def)
{
/*
* device = {VIR_DOMAIN_DISK_DEVICE_DISK, VIR_DOMAIN_DISK_DEVICE_CDROM}
@ -1345,7 +1473,6 @@ esxVMX_ParseDisk(virConnectPtr conn, virConfPtr conf, int device, int bus,
}
/* Setup virDomainDiskDef */
/* FIXME: Need the datastore name for fileName */
if (device == VIR_DOMAIN_DISK_DEVICE_DISK) {
if (esxUtil_EqualSuffix(fileName, ".vmdk")) {
if (deviceType != NULL) {
@ -1375,11 +1502,14 @@ esxVMX_ParseDisk(virConnectPtr conn, virConfPtr conf, int device, int bus,
}
(*def)->type = VIR_DOMAIN_DISK_TYPE_FILE;
(*def)->src = fileName;
(*def)->src = esxVMX_ParseFileName(conn, ctx, fileName,
datastoreName, directoryName);
(*def)->cachemode = writeThrough ? VIR_DOMAIN_DISK_CACHE_WRITETHRU
: VIR_DOMAIN_DISK_CACHE_DEFAULT;
fileName = NULL;
if ((*def)->src == NULL) {
goto failure;
}
} else if (esxUtil_EqualSuffix(fileName, ".iso") ||
STREQ(deviceType, "atapi-cdrom")) {
/*
@ -1407,9 +1537,12 @@ esxVMX_ParseDisk(virConnectPtr conn, virConfPtr conf, int device, int bus,
}
(*def)->type = VIR_DOMAIN_DISK_TYPE_FILE;
(*def)->src = fileName;
(*def)->src = esxVMX_ParseFileName(conn, ctx, fileName,
datastoreName, directoryName);
fileName = NULL;
if ((*def)->src == NULL) {
goto failure;
}
} else if (esxUtil_EqualSuffix(fileName, ".vmdk")) {
/*
* This function was called in order to parse a CDROM device, but
@ -1441,9 +1574,12 @@ esxVMX_ParseDisk(virConnectPtr conn, virConfPtr conf, int device, int bus,
}
(*def)->type = VIR_DOMAIN_DISK_TYPE_FILE;
(*def)->src = fileName;
(*def)->src = esxVMX_ParseFileName(conn, ctx, fileName,
datastoreName, directoryName);
fileName = NULL;
if ((*def)->src == NULL) {
goto failure;
}
} else if (fileType != NULL && STREQ(fileType, "device")) {
(*def)->type = VIR_DOMAIN_DISK_TYPE_BLOCK;
(*def)->src = fileName;
@ -1695,8 +1831,9 @@ esxVMX_ParseEthernet(virConnectPtr conn, virConfPtr conf, int controller,
int
esxVMX_ParseSerial(virConnectPtr conn, virConfPtr conf, int port,
virDomainChrDefPtr *def)
esxVMX_ParseSerial(virConnectPtr conn, esxVI_Context *ctx, virConfPtr conf,
int port, const char *datastoreName,
const char *directoryName, virDomainChrDefPtr *def)
{
int result = 0;
char prefix[48] = "";
@ -1773,9 +1910,13 @@ esxVMX_ParseSerial(virConnectPtr conn, virConfPtr conf, int port,
} else if (STRCASEEQ(fileType, "file")) {
(*def)->dstPort = port;
(*def)->type = VIR_DOMAIN_CHR_TYPE_FILE;
(*def)->data.file.path = fileName;
(*def)->data.file.path = esxVMX_ParseFileName(conn, ctx, fileName,
datastoreName,
directoryName);
fileName = NULL;
if ((*def)->data.file.path == NULL) {
goto failure;
}
} else if (STRCASEEQ(fileType, "pipe")) {
/*
* FIXME: Differences between client/server and VM/application pipes
@ -1812,8 +1953,9 @@ esxVMX_ParseSerial(virConnectPtr conn, virConfPtr conf, int port,
int
esxVMX_ParseParallel(virConnectPtr conn, virConfPtr conf, int port,
virDomainChrDefPtr *def)
esxVMX_ParseParallel(virConnectPtr conn, esxVI_Context *ctx, virConfPtr conf,
int port, const char *datastoreName,
const char *directoryName, virDomainChrDefPtr *def)
{
int result = 0;
char prefix[48] = "";
@ -1890,9 +2032,13 @@ esxVMX_ParseParallel(virConnectPtr conn, virConfPtr conf, int port,
} else if (STRCASEEQ(fileType, "file")) {
(*def)->dstPort = port;
(*def)->type = VIR_DOMAIN_CHR_TYPE_FILE;
(*def)->data.file.path = fileName;
(*def)->data.file.path = esxVMX_ParseFileName(conn, ctx, fileName,
datastoreName,
directoryName);
fileName = NULL;
if ((*def)->data.file.path == NULL) {
goto failure;
}
} else {
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"Expecting VMX entry '%s' to be 'device' or 'file' but "
@ -1923,8 +2069,70 @@ esxVMX_ParseParallel(virConnectPtr conn, virConfPtr conf, int port,
*/
char *
esxVMX_FormatConfig(virConnectPtr conn, virDomainDefPtr def,
esxVI_APIVersion apiVersion)
esxVMX_FormatFileName(virConnectPtr conn, esxVI_Context *ctx ATTRIBUTE_UNUSED,
const char *src)
{
char *datastoreName = NULL;
char *directoryName = NULL;
char *fileName = NULL;
char *absolutePath = NULL;
if (STRPREFIX(src, "[")) {
/* Found potential datastore related path */
if (esxUtil_ParseDatastoreRelatedPath(conn, src, &datastoreName,
&directoryName, &fileName) < 0) {
goto failure;
}
if (directoryName == NULL) {
if (virAsprintf(&absolutePath, "/vmfs/volumes/%s/%s",
datastoreName, fileName) < 0) {
virReportOOMError(conn);
goto failure;
}
} else {
if (virAsprintf(&absolutePath, "/vmfs/volumes/%s/%s/%s",
datastoreName, directoryName, fileName) < 0) {
virReportOOMError(conn);
goto failure;
}
}
} else if (STRPREFIX(src, "/")) {
/* Found absolute path */
absolutePath = strdup(src);
if (absolutePath == NULL) {
virReportOOMError(conn);
goto failure;
}
} else {
/* Found relative path, this is not supported */
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"Found relative path '%s' in domain XML, this is not "
"supported", src);
goto failure;
}
/* FIXME: Check if referenced path/file really exists */
cleanup:
VIR_FREE(datastoreName);
VIR_FREE(directoryName);
VIR_FREE(fileName);
return absolutePath;
failure:
VIR_FREE(absolutePath);
goto cleanup;
}
char *
esxVMX_FormatConfig(virConnectPtr conn, esxVI_Context *ctx,
virDomainDefPtr def, esxVI_APIVersion apiVersion)
{
int i;
int sched_cpu_affinity_length;
@ -2086,21 +2294,21 @@ esxVMX_FormatConfig(virConnectPtr conn, virDomainDefPtr def,
for (i = 0; i < def->ndisks; ++i) {
switch (def->disks[i]->device) {
case VIR_DOMAIN_DISK_DEVICE_DISK:
if (esxVMX_FormatHardDisk(conn, def->disks[i], &buffer) < 0) {
if (esxVMX_FormatHardDisk(conn, ctx, def->disks[i], &buffer) < 0) {
goto failure;
}
break;
case VIR_DOMAIN_DISK_DEVICE_CDROM:
if (esxVMX_FormatCDROM(conn, def->disks[i], &buffer) < 0) {
if (esxVMX_FormatCDROM(conn, ctx, def->disks[i], &buffer) < 0) {
goto failure;
}
break;
case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
if (esxVMX_FormatFloppy(conn, def->disks[i], &buffer) < 0) {
if (esxVMX_FormatFloppy(conn, ctx, def->disks[i], &buffer) < 0) {
goto failure;
}
@ -2135,14 +2343,14 @@ esxVMX_FormatConfig(virConnectPtr conn, virDomainDefPtr def,
/* def:serials */
for (i = 0; i < def->nserials; ++i) {
if (esxVMX_FormatSerial(conn, def->serials[i], &buffer) < 0) {
if (esxVMX_FormatSerial(conn, ctx, def->serials[i], &buffer) < 0) {
goto failure;
}
}
/* def:parallels */
for (i = 0; i < def->nparallels; ++i) {
if (esxVMX_FormatParallel(conn, def->parallels[i], &buffer) < 0) {
if (esxVMX_FormatParallel(conn, ctx, def->parallels[i], &buffer) < 0) {
goto failure;
}
}
@ -2170,13 +2378,14 @@ esxVMX_FormatConfig(virConnectPtr conn, virDomainDefPtr def,
int
esxVMX_FormatHardDisk(virConnectPtr conn, virDomainDiskDefPtr def,
virBufferPtr buffer)
esxVMX_FormatHardDisk(virConnectPtr conn, esxVI_Context *ctx,
virDomainDiskDefPtr def, virBufferPtr buffer)
{
int controller, id;
const char *busName = NULL;
const char *entryPrefix = NULL;
const char *deviceTypePrefix = NULL;
char *fileName = NULL;
if (def->device != VIR_DOMAIN_DISK_DEVICE_DISK) {
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
@ -2229,8 +2438,16 @@ esxVMX_FormatHardDisk(virConnectPtr conn, virDomainDiskDefPtr def,
return -1;
}
fileName = esxVMX_FormatFileName(conn, ctx, def->src);
if (fileName == NULL) {
return -1;
}
virBufferVSprintf(buffer, "%s%d:%d.fileName = \"%s\"\n",
entryPrefix, controller, id, def->src);
entryPrefix, controller, id, fileName);
VIR_FREE(fileName);
}
if (def->bus == VIR_DOMAIN_DISK_BUS_SCSI) {
@ -2242,7 +2459,7 @@ esxVMX_FormatHardDisk(virConnectPtr conn, virDomainDiskDefPtr def,
"%s harddisk '%s' has unsupported cache mode '%s'",
busName, def->dst,
virDomainDiskCacheTypeToString(def->cachemode));
return -1;
return -1;
}
}
@ -2252,12 +2469,13 @@ esxVMX_FormatHardDisk(virConnectPtr conn, virDomainDiskDefPtr def,
int
esxVMX_FormatCDROM(virConnectPtr conn, virDomainDiskDefPtr def,
virBufferPtr buffer)
esxVMX_FormatCDROM(virConnectPtr conn, esxVI_Context *ctx,
virDomainDiskDefPtr def, virBufferPtr buffer)
{
int controller, id;
const char *busName = NULL;
const char *entryPrefix = NULL;
char *fileName = NULL;
if (def->device != VIR_DOMAIN_DISK_DEVICE_CDROM) {
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
@ -2293,9 +2511,34 @@ esxVMX_FormatCDROM(virConnectPtr conn, virDomainDiskDefPtr def,
if (def->type == VIR_DOMAIN_DISK_TYPE_FILE) {
virBufferVSprintf(buffer, "%s%d:%d.deviceType = \"cdrom-image\"\n",
entryPrefix, controller, id);
if (def->src != NULL) {
if (! esxUtil_EqualSuffix(def->src, ".iso")) {
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"Image file for %s cdrom '%s' has unsupported "
"suffix, expecting '.iso'", busName, def->dst);
return -1;
}
fileName = esxVMX_FormatFileName(conn, ctx, def->src);
if (fileName == NULL) {
return -1;
}
virBufferVSprintf(buffer, "%s%d:%d.fileName = \"%s\"\n",
entryPrefix, controller, id, fileName);
VIR_FREE(fileName);
}
} else if (def->type == VIR_DOMAIN_DISK_TYPE_BLOCK) {
virBufferVSprintf(buffer, "%s%d:%d.deviceType = \"atapi-cdrom\"\n",
entryPrefix, controller, id);
if (def->src != NULL) {
virBufferVSprintf(buffer, "%s%d:%d.fileName = \"%s\"\n",
entryPrefix, controller, id, def->src);
}
} else {
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"%s cdrom '%s' has unsupported type '%s', expecting '%s' "
@ -2306,29 +2549,17 @@ esxVMX_FormatCDROM(virConnectPtr conn, virDomainDiskDefPtr def,
return -1;
}
if (def->src != NULL) {
if (def->type == VIR_DOMAIN_DISK_TYPE_FILE &&
! esxUtil_EqualSuffix(def->src, ".iso")) {
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"Image file for %s cdrom '%s' has unsupported suffix, "
"expecting '.iso'", busName, def->dst);
return -1;
}
virBufferVSprintf(buffer, "%s%d:%d.fileName = \"%s\"\n",
entryPrefix, controller, id, def->src);
}
return 0;
}
int
esxVMX_FormatFloppy(virConnectPtr conn, virDomainDiskDefPtr def,
virBufferPtr buffer)
esxVMX_FormatFloppy(virConnectPtr conn, esxVI_Context *ctx,
virDomainDiskDefPtr def, virBufferPtr buffer)
{
int controller;
char *fileName = NULL;
if (def->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
@ -2344,9 +2575,34 @@ esxVMX_FormatFloppy(virConnectPtr conn, virDomainDiskDefPtr def,
if (def->type == VIR_DOMAIN_DISK_TYPE_FILE) {
virBufferVSprintf(buffer, "floppy%d.fileType = \"file\"\n",
controller);
if (def->src != NULL) {
if (! esxUtil_EqualSuffix(def->src, ".flp")) {
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"Image file for floppy '%s' has unsupported suffix, "
"expecting '.flp'", def->dst);
return -1;
}
fileName = esxVMX_FormatFileName(conn, ctx, def->src);
if (fileName == NULL) {
return -1;
}
virBufferVSprintf(buffer, "floppy%d.fileName = \"%s\"\n",
controller, fileName);
VIR_FREE(fileName);
}
} else if (def->type == VIR_DOMAIN_DISK_TYPE_BLOCK) {
virBufferVSprintf(buffer, "floppy%d.fileType = \"device\"\n",
controller);
if (def->src != NULL) {
virBufferVSprintf(buffer, "floppy%d.fileName = \"%s\"\n",
controller, def->src);
}
} else {
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"Floppy '%s' has unsupported type '%s', expecting '%s' "
@ -2357,19 +2613,6 @@ esxVMX_FormatFloppy(virConnectPtr conn, virDomainDiskDefPtr def,
return -1;
}
if (def->src != NULL) {
if (def->type == VIR_DOMAIN_DISK_TYPE_FILE &&
! esxUtil_EqualSuffix(def->src, ".flp")) {
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"Image file for floppy '%s' has unsupported suffix, "
"expecting '.flp'", def->dst);
return -1;
}
virBufferVSprintf(buffer, "floppy%d.fileName = \"%s\"\n", controller,
def->src);
}
return 0;
}
@ -2433,17 +2676,12 @@ esxVMX_FormatEthernet(virConnectPtr conn, virDomainNetDefPtr def,
virFormatMacAddr(def->mac, mac_string);
if (def->mac[0] == 0x00 && def->mac[1] == 0x0c && def->mac[2] == 0x29) {
if ((def->mac[0] == 0x00 && def->mac[1] == 0x0c && def->mac[2] == 0x29) ||
(def->mac[0] == 0x00 && def->mac[1] == 0x50 && def->mac[2] == 0x56)) {
virBufferVSprintf(buffer, "ethernet%d.addressType = \"generated\"\n",
controller);
virBufferVSprintf(buffer, "ethernet%d.generatedAddress = \"%s\"\n",
controller, mac_string);
} else if (def->mac[0] == 0x00 && def->mac[1] == 0x50 &&
def->mac[2] == 0x56) {
virBufferVSprintf(buffer, "ethernet%d.addressType = \"static\"\n",
controller);
virBufferVSprintf(buffer, "ethernet%d.address = \"%s\"\n",
controller, mac_string);
} else {
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"Unsupported MAC address prefix '%02X:%02X:%02X', expecting "
@ -2458,9 +2696,11 @@ esxVMX_FormatEthernet(virConnectPtr conn, virDomainNetDefPtr def,
int
esxVMX_FormatSerial(virConnectPtr conn, virDomainChrDefPtr def,
virBufferPtr buffer)
esxVMX_FormatSerial(virConnectPtr conn, esxVI_Context *ctx,
virDomainChrDefPtr def, virBufferPtr buffer)
{
char *fileName = NULL;
if (def->dstPort < 0 || def->dstPort > 3) {
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"Serial port index %d out of [0..3] range", def->dstPort);
@ -2476,16 +2716,29 @@ esxVMX_FormatSerial(virConnectPtr conn, virDomainChrDefPtr def,
virBufferVSprintf(buffer, "serial%d.present = \"true\"\n", def->dstPort);
/* def:type -> vmx:fileType */
/* def:type -> vmx:fileType and def:data.file.path -> vmx:fileName */
switch (def->type) {
case VIR_DOMAIN_CHR_TYPE_DEV:
virBufferVSprintf(buffer, "serial%d.fileType = \"device\"\n",
def->dstPort);
virBufferVSprintf(buffer, "serial%d.fileName = \"%s\"\n",
def->dstPort, def->data.file.path);
break;
case VIR_DOMAIN_CHR_TYPE_FILE:
virBufferVSprintf(buffer, "serial%d.fileType = \"file\"\n",
def->dstPort);
fileName = esxVMX_FormatFileName(conn, ctx, def->data.file.path);
if (fileName == NULL) {
return -1;
}
virBufferVSprintf(buffer, "serial%d.fileName = \"%s\"\n",
def->dstPort, fileName);
VIR_FREE(fileName);
break;
case VIR_DOMAIN_CHR_TYPE_PIPE:
@ -2497,6 +2750,8 @@ esxVMX_FormatSerial(virConnectPtr conn, virDomainChrDefPtr def,
/* FIXME: Based on VI Client GUI default */
virBufferVSprintf(buffer, "serial%d.tryNoRxLoss = \"false\"\n",
def->dstPort);
virBufferVSprintf(buffer, "serial%d.fileName = \"%s\"\n",
def->dstPort, def->data.file.path);
break;
default:
@ -2506,10 +2761,6 @@ esxVMX_FormatSerial(virConnectPtr conn, virDomainChrDefPtr def,
return -1;
}
/* def:data.file.path -> vmx:fileName */
virBufferVSprintf(buffer, "serial%d.fileName = \"%s\"\n",
def->dstPort, def->data.file.path);
/* vmx:yieldOnMsrRead */
/* FIXME: Based on VI Client GUI default */
virBufferVSprintf(buffer, "serial%d.yieldOnMsrRead = \"true\"\n",
@ -2521,9 +2772,11 @@ esxVMX_FormatSerial(virConnectPtr conn, virDomainChrDefPtr def,
int
esxVMX_FormatParallel(virConnectPtr conn, virDomainChrDefPtr def,
virBufferPtr buffer)
esxVMX_FormatParallel(virConnectPtr conn, esxVI_Context *ctx,
virDomainChrDefPtr def, virBufferPtr buffer)
{
char *fileName = NULL;
if (def->dstPort < 0 || def->dstPort > 2) {
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"Parallel port index %d out of [0..2] range", def->dstPort);
@ -2539,16 +2792,29 @@ esxVMX_FormatParallel(virConnectPtr conn, virDomainChrDefPtr def,
virBufferVSprintf(buffer, "parallel%d.present = \"true\"\n", def->dstPort);
/* def:type -> vmx:fileType */
/* def:type -> vmx:fileType and def:data.file.path -> vmx:fileName */
switch (def->type) {
case VIR_DOMAIN_CHR_TYPE_DEV:
virBufferVSprintf(buffer, "parallel%d.fileType = \"device\"\n",
def->dstPort);
virBufferVSprintf(buffer, "parallel%d.fileName = \"%s\"\n",
def->dstPort, def->data.file.path);
break;
case VIR_DOMAIN_CHR_TYPE_FILE:
virBufferVSprintf(buffer, "parallel%d.fileType = \"file\"\n",
def->dstPort);
fileName = esxVMX_FormatFileName(conn, ctx, def->data.file.path);
if (fileName == NULL) {
return -1;
}
virBufferVSprintf(buffer, "parallel%d.fileName = \"%s\"\n",
def->dstPort, fileName);
VIR_FREE(fileName);
break;
default:
@ -2558,9 +2824,5 @@ esxVMX_FormatParallel(virConnectPtr conn, virDomainChrDefPtr def,
return -1;
}
/* def:data.file.path -> vmx:fileName */
virBufferVSprintf(buffer, "parallel%d.fileName = \"%s\"\n",
def->dstPort, def->data.file.path);
return 0;
}

View File

@ -34,9 +34,11 @@ esxVMX_IndexToDiskName(virConnectPtr conn, int idx, const char *prefix);
int
esxVMX_SCSIDiskNameToControllerAndID(virConnectPtr conn, const char *name,
int *controller, int *id);
int
esxVMX_IDEDiskNameToControllerAndID(virConnectPtr conn, const char *name,
int *controller, int *id);
int *controller, int *id);
int
esxVMX_FloppyDiskNameToController(virConnectPtr conn, const char *name,
int *controller);
@ -45,14 +47,24 @@ int
esxVMX_GatherSCSIControllers(virConnectPtr conn, virDomainDefPtr conf,
char *virtualDev[4], int present[4]);
char *
esxVMX_AbsolutePathToDatastoreRelatedPath(virConnectPtr conn,
esxVI_Context *ctx,
const char *absolutePath);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* VMX -> Domain XML
*/
char *
esxVMX_ParseFileName(virConnectPtr conn, esxVI_Context *ctx,
const char *fileName, const char *datastoreName,
const char *directoryName);
virDomainDefPtr
esxVMX_ParseConfig(virConnectPtr conn, const char *vmx,
esxVMX_ParseConfig(virConnectPtr conn, esxVI_Context *ctx, const char *vmx,
const char *datastoreName, const char *directoryName,
esxVI_APIVersion apiVersion);
int
@ -60,20 +72,23 @@ esxVMX_ParseSCSIController(virConnectPtr conn, virConfPtr conf,
int controller, int *present, char **virtualDev);
int
esxVMX_ParseDisk(virConnectPtr conn, virConfPtr conf, int device, int bus,
int controller, int id, const char *virtualDev,
virDomainDiskDefPtr *def);
esxVMX_ParseDisk(virConnectPtr conn, esxVI_Context *ctx, virConfPtr conf,
int device, int bus, int controller, int id,
const char *virtualDev, const char *datastoreName,
const char *directoryName, virDomainDiskDefPtr *def);
int
esxVMX_ParseEthernet(virConnectPtr conn, virConfPtr conf, int controller,
virDomainNetDefPtr *def);
int
esxVMX_ParseSerial(virConnectPtr conn, virConfPtr conf, int port,
virDomainChrDefPtr *def);
esxVMX_ParseSerial(virConnectPtr conn, esxVI_Context *ctx, virConfPtr conf,
int port, const char *datastoreName,
const char *directoryName, virDomainChrDefPtr *def);
int
esxVMX_ParseParallel(virConnectPtr conn, virConfPtr conf, int port,
virDomainChrDefPtr *def);
esxVMX_ParseParallel(virConnectPtr conn, esxVI_Context *ctx, virConfPtr conf,
int port, const char *datastoreName,
const char *directoryName, virDomainChrDefPtr *def);
@ -82,31 +97,34 @@ esxVMX_ParseParallel(virConnectPtr conn, virConfPtr conf, int port,
*/
char *
esxVMX_FormatConfig(virConnectPtr conn, virDomainDefPtr def,
esxVI_APIVersion apiVersion);
esxVMX_FormatFileName(virConnectPtr conn, esxVI_Context *ctx, const char *src);
char *
esxVMX_FormatConfig(virConnectPtr conn, esxVI_Context *ctx,
virDomainDefPtr def, esxVI_APIVersion apiVersion);
int
esxVMX_FormatHardDisk(virConnectPtr conn, virDomainDiskDefPtr def,
virBufferPtr buffer);
esxVMX_FormatHardDisk(virConnectPtr conn, esxVI_Context *ctx,
virDomainDiskDefPtr def, virBufferPtr buffer);
int
esxVMX_FormatCDROM(virConnectPtr conn, virDomainDiskDefPtr def,
virBufferPtr buffer);
esxVMX_FormatCDROM(virConnectPtr conn, esxVI_Context *ctx,
virDomainDiskDefPtr def, virBufferPtr buffer);
int
esxVMX_FormatFloppy(virConnectPtr conn, virDomainDiskDefPtr def,
virBufferPtr buffer);
esxVMX_FormatFloppy(virConnectPtr conn, esxVI_Context *ctx,
virDomainDiskDefPtr def, virBufferPtr buffer);
int
esxVMX_FormatEthernet(virConnectPtr conn, virDomainNetDefPtr def,
int controller, virBufferPtr buffer);
int
esxVMX_FormatSerial(virConnectPtr conn, virDomainChrDefPtr def,
virBufferPtr buffer);
esxVMX_FormatSerial(virConnectPtr conn, esxVI_Context *ctx,
virDomainChrDefPtr def, virBufferPtr buffer);
int
esxVMX_FormatParallel(virConnectPtr conn, virDomainChrDefPtr def,
virBufferPtr buffer);
esxVMX_FormatParallel(virConnectPtr conn, esxVI_Context *ctx,
virDomainChrDefPtr def, virBufferPtr buffer);
#endif /* __ESX_VMX_H__ */

View File

@ -9,15 +9,21 @@
#include "internal.h"
#include "memory.h"
#include "testutils.h"
#include "esx/esx_util.h"
#include "esx/esx_vmx.h"
static char *progname;
struct testInfo {
const char *input;
const char *output;
esxVI_APIVersion version;
};
static void
testQuietError(void *userData ATTRIBUTE_UNUSED,
virErrorPtr error ATTRIBUTE_UNUSED)
{
/* nothing */
}
static const char* names[] = {
"sda", "sdb", "sdc", "sdd", "sde", "sdf", "sdg", "sdh", "sdi", "sdj", "sdk", "sdl", "sdm", "sdn", "sdo", "sdp", "sdq", "sdr", "sds", "sdt", "sdu", "sdv", "sdw", "sdx", "sdy", "sdz",
@ -62,6 +68,80 @@ testIndexToDiskName(const void *data ATTRIBUTE_UNUSED)
return 0;
}
struct testPath {
const char *datastoreRelatedPath;
int result;
const char *datastoreName;
const char *directoryName;
const char *fileName;
};
static struct testPath paths[] = {
{ "[datastore] directory/file", 0, "datastore", "directory", "file" },
{ "[datastore] file", 0, "datastore", NULL, "file" },
{ "[] directory/file", -1, NULL, NULL, NULL },
{ "[datastore] directory/", -1, NULL, NULL, NULL },
{ "directory/file", -1, NULL, NULL, NULL },
};
static int
testParseDatastoreRelatedPath(const void *data ATTRIBUTE_UNUSED)
{
int i, result = 0;
char *datastoreName = NULL;
char *directoryName = NULL;
char *fileName = NULL;
for (i = 0; i < ARRAY_CARDINALITY(paths); ++i) {
VIR_FREE(datastoreName);
VIR_FREE(directoryName);
VIR_FREE(fileName);
if (esxUtil_ParseDatastoreRelatedPath(NULL,
paths[i].datastoreRelatedPath,
&datastoreName, &directoryName,
&fileName) != paths[i].result) {
goto failure;
}
if (paths[i].result < 0) {
continue;
}
if (STRNEQ(paths[i].datastoreName, datastoreName)) {
virtTestDifference(stderr, paths[i].datastoreName, datastoreName);
goto failure;
}
if (paths[i].directoryName != NULL &&
STRNEQ(paths[i].directoryName, directoryName)) {
virtTestDifference(stderr, paths[i].directoryName, directoryName);
goto failure;
}
if (STRNEQ(paths[i].fileName, fileName)) {
virtTestDifference(stderr, paths[i].fileName, fileName);
goto failure;
}
}
cleanup:
VIR_FREE(datastoreName);
VIR_FREE(directoryName);
VIR_FREE(fileName);
return result;
failure:
result = -1;
goto cleanup;
}
static int
mymain(int argc, char **argv)
{
@ -79,10 +159,18 @@ mymain(int argc, char **argv)
return EXIT_FAILURE;
}
if (virtTestRun("VMware IndexToDiskName", 1, testIndexToDiskName,
NULL) < 0) {
result = -1;
}
virSetErrorFunc(NULL, testQuietError);
#define DO_TEST(_name) \
do { \
if (virtTestRun("VMware "#_name, 1, test##_name, \
NULL) < 0) { \
result = -1; \
} \
} while (0)
DO_TEST(IndexToDiskName);
DO_TEST(ParseDatastoreRelatedPath);
return result == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}

View File

@ -12,7 +12,7 @@
<on_crash>destroy</on_crash>
<devices>
<disk type='file' device='cdrom'>
<source file='cdrom.iso'/>
<source file='[datastore] directory/cdrom.iso'/>
<target dev='hda' bus='ide'/>
</disk>
</devices>

View File

@ -12,7 +12,7 @@
<on_crash>destroy</on_crash>
<devices>
<disk type='file' device='cdrom'>
<source file='cdrom.iso'/>
<source file='[datastore] directory/cdrom.iso'/>
<target dev='sda' bus='scsi'/>
</disk>
</devices>

View File

@ -14,7 +14,7 @@
<devices>
<disk type='file' device='disk'>
<driver name='lsilogic'/>
<source file='Fedora11.vmdk'/>
<source file='[datastore] directory/Fedora11.vmdk'/>
<target dev='sda' bus='scsi'/>
</disk>
<interface type='bridge'>

View File

@ -14,12 +14,12 @@
<devices>
<disk type='file' device='disk'>
<driver name='lsilogic' cache='writethrough'/>
<source file='Debian1.vmdk'/>
<source file='[datastore] directory/Debian1.vmdk'/>
<target dev='sda' bus='scsi'/>
</disk>
<disk type='file' device='cdrom'>
<driver name='buslogic'/>
<source file='Debian1-cdrom.iso'/>
<source file='[datastore] directory/Debian1-cdrom.iso'/>
<target dev='sdp' bus='scsi'/>
</disk>
<disk type='file' device='cdrom'>
@ -31,7 +31,7 @@
<target dev='hdb' bus='ide'/>
</disk>
<disk type='file' device='disk'>
<source file='Debian1-IDE.vmdk'/>
<source file='[datastore] directory/Debian1-IDE.vmdk'/>
<target dev='hdd' bus='ide'/>
</disk>
<disk type='block' device='floppy'>

View File

@ -14,15 +14,15 @@
<devices>
<disk type='file' device='disk'>
<driver name='lsilogic'/>
<source file='Debian2.vmdk'/>
<source file='[datastore] directory/Debian2.vmdk'/>
<target dev='sda' bus='scsi'/>
</disk>
<disk type='file' device='cdrom'>
<source file='/vmfs/volumes/498076b2-02796c1a-ef5b-000ae484a6a3/Isos/debian-testing-amd64-netinst.iso'/>
<source file='[498076b2-02796c1a-ef5b-000ae484a6a3] Isos/debian-testing-amd64-netinst.iso'/>
<target dev='hda' bus='ide'/>
</disk>
<disk type='file' device='floppy'>
<source file='/vmfs/volumes/498076b2-02796c1a-ef5b-000ae484a6a3/Debian2/dummy.flp'/>
<source file='[498076b2-02796c1a-ef5b-000ae484a6a3] Debian2/dummy.flp'/>
<target dev='fdb' bus='fdc'/>
</disk>
<interface type='bridge'>

View File

@ -14,7 +14,7 @@
<devices>
<disk type='file' device='disk'>
<driver name='lsilogic'/>
<source file='virtMonServ1.vmdk'/>
<source file='[datastore] directory/virtMonServ1.vmdk'/>
<target dev='sda' bus='scsi'/>
</disk>
<interface type='bridge'>
@ -26,15 +26,15 @@
<source bridge='VM Switch 2'/>
</interface>
<serial type='file'>
<source path='/vmfs/volumes/498076b2-02796c1a-ef5b-000ae484a6a3/virtMonServ1/serial1.file'/>
<source path='[498076b2-02796c1a-ef5b-000ae484a6a3] virtMonServ1/serial1.file'/>
<target port='0'/>
</serial>
<parallel type='file'>
<source path='/vmfs/volumes/498076b2-02796c1a-ef5b-000ae484a6a3/virtMonServ1/parallel1.file'/>
<source path='[498076b2-02796c1a-ef5b-000ae484a6a3] virtMonServ1/parallel1.file'/>
<target port='0'/>
</parallel>
<console type='file'>
<source path='/vmfs/volumes/498076b2-02796c1a-ef5b-000ae484a6a3/virtMonServ1/serial1.file'/>
<source path='[498076b2-02796c1a-ef5b-000ae484a6a3] virtMonServ1/serial1.file'/>
<target port='0'/>
</console>
</devices>

View File

@ -12,7 +12,7 @@
<on_crash>destroy</on_crash>
<devices>
<disk type='file' device='floppy'>
<source file='floppy.flp'/>
<source file='[datastore] directory/floppy.flp'/>
<target dev='fda' bus='fdc'/>
</disk>
</devices>

View File

@ -13,7 +13,7 @@
<on_crash>destroy</on_crash>
<devices>
<disk type='file' device='disk'>
<source file='Debian-System1-0-cl2.vmdk'/>
<source file='[datastore] directory/Debian-System1-0-cl2.vmdk'/>
<target dev='hda' bus='ide'/>
</disk>
<interface type='bridge'>

View File

@ -13,7 +13,7 @@
<on_crash>destroy</on_crash>
<devices>
<disk type='file' device='disk'>
<source file='Debian-System1-0-cl3.vmdk'/>
<source file='[datastore] directory/Debian-System1-0-cl3.vmdk'/>
<target dev='hda' bus='ide'/>
</disk>
<interface type='bridge'>

View File

@ -13,7 +13,7 @@
<on_crash>destroy</on_crash>
<devices>
<disk type='file' device='disk'>
<source file='Debian-System1-0-cl1.vmdk'/>
<source file='[datastore] directory/Debian-System1-0-cl1.vmdk'/>
<target dev='hda' bus='ide'/>
</disk>
<interface type='bridge'>

View File

@ -13,7 +13,7 @@
<on_crash>destroy</on_crash>
<devices>
<disk type='file' device='disk'>
<source file='Debian-System1-0-cl2.vmdk'/>
<source file='[datastore] directory/Debian-System1-0-cl2.vmdk'/>
<target dev='hda' bus='ide'/>
</disk>
<interface type='bridge'>

View File

@ -12,7 +12,7 @@
<on_crash>destroy</on_crash>
<devices>
<disk type='file' device='disk'>
<source file='harddisk.vmdk'/>
<source file='[datastore] directory/harddisk.vmdk'/>
<target dev='hda' bus='ide'/>
</disk>
</devices>

View File

@ -12,7 +12,7 @@
<on_crash>destroy</on_crash>
<devices>
<disk type='file' device='disk'>
<source file='harddisk.vmdk'/>
<source file='[datastore] directory/harddisk.vmdk'/>
<target dev='sda' bus='scsi'/>
</disk>
</devices>

View File

@ -12,7 +12,7 @@
<on_crash>destroy</on_crash>
<devices>
<parallel type='file'>
<source path='parallel0.file'/>
<source path='[datastore] directory/parallel0.file'/>
<target port='0'/>
</parallel>
</devices>

View File

@ -13,7 +13,7 @@
<devices>
<disk type='file' device='disk'>
<driver name='buslogic'/>
<source file='harddisk.vmdk'/>
<source file='[datastore] directory/harddisk.vmdk'/>
<target dev='sda' bus='scsi'/>
</disk>
</devices>

View File

@ -13,7 +13,7 @@
<devices>
<disk type='file' device='disk'>
<driver name='buslogic' cache='writethrough'/>
<source file='harddisk.vmdk'/>
<source file='[datastore] directory/harddisk.vmdk'/>
<target dev='sda' bus='scsi'/>
</disk>
</devices>

View File

@ -12,11 +12,11 @@
<on_crash>destroy</on_crash>
<devices>
<serial type='file'>
<source path='serial0.file'/>
<source path='[datastore] directory/serial0.file'/>
<target port='0'/>
</serial>
<console type='file'>
<source path='serial0.file'/>
<source path='[datastore] directory/serial0.file'/>
<target port='0'/>
</console>
</devices>

View File

@ -35,7 +35,8 @@ testCompareFiles(const char *vmx, const char *xml, esxVI_APIVersion apiVersion)
goto failure;
}
def = esxVMX_ParseConfig(NULL, vmxData, apiVersion);
def = esxVMX_ParseConfig(NULL, NULL, vmxData, "datastore", "directory",
apiVersion);
if (def == NULL) {
goto failure;

View File

@ -7,4 +7,4 @@ memsize = "4"
numvcpus = "1"
ide0:0.present = "true"
ide0:0.deviceType = "cdrom-image"
ide0:0.fileName = "cdrom.iso"
ide0:0.fileName = "/vmfs/volumes/testing/isos/cdrom.iso"

View File

@ -7,7 +7,7 @@
</os>
<devices>
<disk type='file' device='cdrom'>
<source file='cdrom.iso'/>
<source file='[testing] isos/cdrom.iso'/>
<target dev='hda' bus='ide'/>
</disk>
</devices>

View File

@ -8,4 +8,4 @@ numvcpus = "1"
scsi0.present = "true"
scsi0:0.present = "true"
scsi0:0.deviceType = "cdrom-image"
scsi0:0.fileName = "cdrom.iso"
scsi0:0.fileName = "/vmfs/volumes/testing/isos/cdrom.iso"

View File

@ -7,7 +7,7 @@
</os>
<devices>
<disk type='file' device='cdrom'>
<source file='cdrom.iso'/>
<source file='[testing] isos/cdrom.iso'/>
<target dev='sda' bus='scsi'/>
</disk>
</devices>

View File

@ -9,9 +9,9 @@ scsi0.present = "true"
scsi0.virtualDev = "lsilogic"
scsi0:0.present = "true"
scsi0:0.deviceType = "scsi-hardDisk"
scsi0:0.fileName = "Fedora11.vmdk"
scsi0:0.fileName = "/vmfs/volumes/498076b2-02796c1a-ef5b-000ae484a6a3/Fedora11/Fedora11.vmdk"
ethernet0.present = "true"
ethernet0.networkName = "VM Network"
ethernet0.connectionType = "bridged"
ethernet0.addressType = "static"
ethernet0.address = "00:50:56:91:48:C7"
ethernet0.addressType = "generated"
ethernet0.generatedAddress = "00:50:56:91:48:C7"

View File

@ -14,7 +14,7 @@
<devices>
<disk type='file' device='disk'>
<driver name='lsilogic'/>
<source file='Fedora11.vmdk'/>
<source file='[498076b2-02796c1a-ef5b-000ae484a6a3] Fedora11/Fedora11.vmdk'/>
<target dev='sda' bus='scsi'/>
</disk>
<interface type='bridge'>

View File

@ -13,11 +13,11 @@ scsi1.present = "true"
scsi1.virtualDev = "buslogic"
scsi0:0.present = "true"
scsi0:0.deviceType = "scsi-hardDisk"
scsi0:0.fileName = "Debian1.vmdk"
scsi0:0.fileName = "/vmfs/volumes/498076b2-02796c1a-ef5b-000ae484a6a3/virtDebian1/Debian1.vmdk"
scsi0:0.writeThrough = "true"
scsi1:0.present = "true"
scsi1:0.deviceType = "cdrom-image"
scsi1:0.fileName = "Debian1-cdrom.iso"
scsi1:0.fileName = "/vmfs/volumes/498076b2-02796c1a-ef5b-000ae484a6a3/virtDebian1/Debian1-cdrom.iso"
ide0:0.present = "true"
ide0:0.deviceType = "cdrom-image"
ide0:0.fileName = "/vmimages/tools-isoimages/linux.iso"
@ -26,7 +26,7 @@ ide0:1.deviceType = "atapi-cdrom"
ide0:1.fileName = "/dev/scd0"
ide1:1.present = "true"
ide1:1.deviceType = "ata-hardDisk"
ide1:1.fileName = "Debian1-IDE.vmdk"
ide1:1.fileName = "/vmfs/volumes/498076b2-02796c1a-ef5b-000ae484a6a3/virtDebian1/Debian1-IDE.vmdk"
floppy0.present = "true"
floppy0.fileType = "device"
floppy0.fileName = "/dev/fd0"

View File

@ -14,12 +14,12 @@
<devices>
<disk type='file' device='disk'>
<driver name='lsilogic' cache='writethrough'/>
<source file='Debian1.vmdk'/>
<source file='[498076b2-02796c1a-ef5b-000ae484a6a3] virtDebian1/Debian1.vmdk'/>
<target dev='sda' bus='scsi'/>
</disk>
<disk type='file' device='cdrom'>
<driver name='buslogic'/>
<source file='Debian1-cdrom.iso'/>
<source file='[498076b2-02796c1a-ef5b-000ae484a6a3] virtDebian1/Debian1-cdrom.iso'/>
<target dev='sdp' bus='scsi'/>
</disk>
<disk type='file' device='cdrom'>
@ -31,7 +31,7 @@
<target dev='hdb' bus='ide'/>
</disk>
<disk type='file' device='disk'>
<source file='Debian1-IDE.vmdk'/>
<source file='[498076b2-02796c1a-ef5b-000ae484a6a3] virtDebian1/Debian1-IDE.vmdk'/>
<target dev='hdd' bus='ide'/>
</disk>
<disk type='block' device='floppy'>

View File

@ -10,7 +10,7 @@ scsi0.present = "true"
scsi0.virtualDev = "lsilogic"
scsi0:0.present = "true"
scsi0:0.deviceType = "scsi-hardDisk"
scsi0:0.fileName = "Debian2.vmdk"
scsi0:0.fileName = "/vmfs/volumes/498076b2-02796c1a-ef5b-000ae484a6a3/Debian2/Debian2.vmdk"
ide0:0.present = "true"
ide0:0.deviceType = "cdrom-image"
ide0:0.fileName = "/vmfs/volumes/498076b2-02796c1a-ef5b-000ae484a6a3/Isos/debian-testing-amd64-netinst.iso"

View File

@ -14,15 +14,15 @@
<devices>
<disk type='file' device='disk'>
<driver name='lsilogic'/>
<source file='Debian2.vmdk'/>
<source file='[498076b2-02796c1a-ef5b-000ae484a6a3] Debian2/Debian2.vmdk'/>
<target dev='sda' bus='scsi'/>
</disk>
<disk type='file' device='cdrom'>
<source file='/vmfs/volumes/498076b2-02796c1a-ef5b-000ae484a6a3/Isos/debian-testing-amd64-netinst.iso'/>
<source file='[498076b2-02796c1a-ef5b-000ae484a6a3] Isos/debian-testing-amd64-netinst.iso'/>
<target dev='hda' bus='ide'/>
</disk>
<disk type='file' device='floppy'>
<source file='/vmfs/volumes/498076b2-02796c1a-ef5b-000ae484a6a3/Debian2/dummy.flp'/>
<source file='[498076b2-02796c1a-ef5b-000ae484a6a3] Debian2/dummy.flp'/>
<target dev='fdb' bus='fdc'/>
</disk>
<interface type='bridge'>

View File

@ -9,17 +9,17 @@ scsi0.present = "true"
scsi0.virtualDev = "lsilogic"
scsi0:0.present = "true"
scsi0:0.deviceType = "scsi-hardDisk"
scsi0:0.fileName = "virtMonServ1.vmdk"
scsi0:0.fileName = "/vmfs/volumes/498076b2-02796c1a-ef5b-000ae484a6a3/virtMonServ1/virtMonServ1.vmdk"
ethernet0.present = "true"
ethernet0.networkName = "VM Network"
ethernet0.connectionType = "bridged"
ethernet0.addressType = "static"
ethernet0.address = "00:50:56:91:66:D4"
ethernet0.addressType = "generated"
ethernet0.generatedAddress = "00:50:56:91:66:D4"
ethernet1.present = "true"
ethernet1.networkName = "VM Switch 2"
ethernet1.connectionType = "bridged"
ethernet1.addressType = "static"
ethernet1.address = "00:50:56:91:0C:51"
ethernet1.addressType = "generated"
ethernet1.generatedAddress = "00:50:56:91:0C:51"
serial0.present = "true"
serial0.fileType = "file"
serial0.fileName = "/vmfs/volumes/498076b2-02796c1a-ef5b-000ae484a6a3/virtMonServ1/serial1.file"

View File

@ -14,7 +14,7 @@
<devices>
<disk type='file' device='disk'>
<driver name='lsilogic'/>
<source file='virtMonServ1.vmdk'/>
<source file='[498076b2-02796c1a-ef5b-000ae484a6a3] virtMonServ1/virtMonServ1.vmdk'/>
<target dev='sda' bus='scsi'/>
</disk>
<interface type='bridge'>
@ -26,15 +26,15 @@
<source bridge='VM Switch 2'/>
</interface>
<serial type='file'>
<source path='/vmfs/volumes/498076b2-02796c1a-ef5b-000ae484a6a3/virtMonServ1/serial1.file'/>
<source path='[498076b2-02796c1a-ef5b-000ae484a6a3] virtMonServ1/serial1.file'/>
<target port='0'/>
</serial>
<parallel type='file'>
<source path='/vmfs/volumes/498076b2-02796c1a-ef5b-000ae484a6a3/virtMonServ1/parallel1.file'/>
<source path='[498076b2-02796c1a-ef5b-000ae484a6a3] virtMonServ1/parallel1.file'/>
<target port='0'/>
</parallel>
<console type='file'>
<source path='/vmfs/volumes/498076b2-02796c1a-ef5b-000ae484a6a3/virtMonServ1/serial1.file'/>
<source path='[498076b2-02796c1a-ef5b-000ae484a6a3] virtMonServ1/serial1.file'/>
<target port='0'/>
</console>
</devices>

View File

@ -8,5 +8,5 @@ numvcpus = "1"
ethernet0.present = "true"
ethernet0.networkName = "VM Network"
ethernet0.connectionType = "bridged"
ethernet0.addressType = "static"
ethernet0.address = "00:50:56:11:22:33"
ethernet0.addressType = "generated"
ethernet0.generatedAddress = "00:50:56:11:22:33"

View File

@ -9,5 +9,5 @@ ethernet0.present = "true"
ethernet0.networkName = "VM Network"
ethernet0.connectionType = "custom"
ethernet0.vnet = "vmnet7"
ethernet0.addressType = "static"
ethernet0.address = "00:50:56:11:22:33"
ethernet0.addressType = "generated"
ethernet0.generatedAddress = "00:50:56:11:22:33"

View File

@ -9,5 +9,5 @@ ethernet0.present = "true"
ethernet0.virtualDev = "e1000"
ethernet0.networkName = "VM Network"
ethernet0.connectionType = "bridged"
ethernet0.addressType = "static"
ethernet0.address = "00:50:56:11:22:33"
ethernet0.addressType = "generated"
ethernet0.generatedAddress = "00:50:56:11:22:33"

View File

@ -7,4 +7,4 @@ memsize = "4"
numvcpus = "1"
floppy0.present = "true"
floppy0.fileType = "file"
floppy0.fileName = "floppy.flp"
floppy0.fileName = "/vmfs/volumes/testing/floppy.flp"

View File

@ -7,7 +7,7 @@
</os>
<devices>
<disk type='file' device='floppy'>
<source file='floppy.flp'/>
<source file='[testing] floppy.flp'/>
<target dev='fda' bus='fdc'/>
</disk>
</devices>

View File

@ -7,7 +7,7 @@ memsize = "32"
numvcpus = "1"
ide0:0.present = "true"
ide0:0.deviceType = "ata-hardDisk"
ide0:0.fileName = "Debian-System1-0-cl2.vmdk"
ide0:0.fileName = "/vmfs/volumes/storage/Server1/Debian-System1-0-cl2.vmdk"
ethernet0.present = "true"
ethernet0.networkName = "net1"
ethernet0.connectionType = "custom"

View File

@ -13,7 +13,7 @@
<on_crash>destroy</on_crash>
<devices>
<disk type='file' device='disk'>
<source file='Debian-System1-0-cl2.vmdk'/>
<source file='[storage] Server1/Debian-System1-0-cl2.vmdk'/>
<target dev='hda' bus='ide'/>
</disk>
<interface type='bridge'>

View File

@ -7,7 +7,7 @@ memsize = "32"
numvcpus = "1"
ide0:0.present = "true"
ide0:0.deviceType = "ata-hardDisk"
ide0:0.fileName = "Debian-System1-0-cl3.vmdk"
ide0:0.fileName = "/vmfs/volumes/storage/Server2/Debian-System1-0-cl3.vmdk"
ethernet0.present = "true"
ethernet0.networkName = "net1"
ethernet0.connectionType = "custom"

View File

@ -13,7 +13,7 @@
<on_crash>destroy</on_crash>
<devices>
<disk type='file' device='disk'>
<source file='Debian-System1-0-cl3.vmdk'/>
<source file='[storage] Server2/Debian-System1-0-cl3.vmdk'/>
<target dev='hda' bus='ide'/>
</disk>
<interface type='bridge'>

View File

@ -7,7 +7,7 @@ memsize = "32"
numvcpus = "1"
ide0:0.present = "true"
ide0:0.deviceType = "ata-hardDisk"
ide0:0.fileName = "Debian-System1-0-cl1.vmdk"
ide0:0.fileName = "/vmfs/volumes/storage/Router/Debian-System1-0-cl1.vmdk"
ethernet0.present = "true"
ethernet0.networkName = "net1"
ethernet0.connectionType = "custom"

View File

@ -13,7 +13,7 @@
<on_crash>destroy</on_crash>
<devices>
<disk type='file' device='disk'>
<source file='Debian-System1-0-cl1.vmdk'/>
<source file='[storage] Router/Debian-System1-0-cl1.vmdk'/>
<target dev='hda' bus='ide'/>
</disk>
<interface type='bridge'>

View File

@ -7,7 +7,7 @@ memsize = "264"
numvcpus = "1"
ide0:0.present = "true"
ide0:0.deviceType = "ata-hardDisk"
ide0:0.fileName = "Debian-System1-0-cl2.vmdk"
ide0:0.fileName = "/vmfs/volumes/storage/Client/Debian-System1-0-cl2.vmdk"
ethernet0.present = "true"
ethernet0.networkName = "net2"
ethernet0.connectionType = "custom"

View File

@ -13,7 +13,7 @@
<on_crash>destroy</on_crash>
<devices>
<disk type='file' device='disk'>
<source file='Debian-System1-0-cl2.vmdk'/>
<source file='[storage] Client/Debian-System1-0-cl2.vmdk'/>
<target dev='hda' bus='ide'/>
</disk>
<interface type='bridge'>

View File

@ -7,4 +7,4 @@ memsize = "4"
numvcpus = "1"
ide0:0.present = "true"
ide0:0.deviceType = "ata-hardDisk"
ide0:0.fileName = "harddisk.vmdk"
ide0:0.fileName = "/vmfs/volumes/datastore/directory/harddisk.vmdk"

View File

@ -7,7 +7,7 @@
</os>
<devices>
<disk type='file' device='disk'>
<source file='harddisk.vmdk'/>
<source file='[datastore] directory/harddisk.vmdk'/>
<target dev='hda' bus='ide'/>
</disk>
</devices>

View File

@ -8,4 +8,4 @@ numvcpus = "1"
scsi0.present = "true"
scsi0:0.present = "true"
scsi0:0.deviceType = "scsi-hardDisk"
scsi0:0.fileName = "harddisk.vmdk"
scsi0:0.fileName = "/vmfs/volumes/datastore/directory/harddisk.vmdk"

View File

@ -7,7 +7,7 @@
</os>
<devices>
<disk type='file' device='disk'>
<source file='harddisk.vmdk'/>
<source file='[datastore] directory/harddisk.vmdk'/>
<target dev='sda' bus='scsi'/>
</disk>
</devices>

View File

@ -7,4 +7,4 @@ memsize = "4"
numvcpus = "1"
parallel0.present = "true"
parallel0.fileType = "file"
parallel0.fileName = "parallel0.file"
parallel0.fileName = "/vmfs/volumes/datastore/directory/parallel0.file"

View File

@ -7,7 +7,7 @@
</os>
<devices>
<parallel type='file'>
<source path='parallel0.file'/>
<source path='[datastore] directory/parallel0.file'/>
<target port='0'/>
</parallel>
</devices>

View File

@ -9,4 +9,4 @@ scsi0.present = "true"
scsi0.virtualDev = "buslogic"
scsi0:0.present = "true"
scsi0:0.deviceType = "scsi-hardDisk"
scsi0:0.fileName = "harddisk.vmdk"
scsi0:0.fileName = "/vmfs/volumes/datastore/directory/harddisk.vmdk"

View File

@ -8,7 +8,7 @@
<devices>
<disk type='file' device='disk'>
<driver name='buslogic'/>
<source file='harddisk.vmdk'/>
<source file='[datastore] directory/harddisk.vmdk'/>
<target dev='sda' bus='scsi'/>
</disk>
</devices>

View File

@ -9,5 +9,5 @@ scsi0.present = "true"
scsi0.virtualDev = "buslogic"
scsi0:0.present = "true"
scsi0:0.deviceType = "scsi-hardDisk"
scsi0:0.fileName = "harddisk.vmdk"
scsi0:0.fileName = "/vmfs/volumes/datastore/directory/harddisk.vmdk"
scsi0:0.writeThrough = "true"

View File

@ -8,7 +8,7 @@
<devices>
<disk type='file' device='disk'>
<driver name='buslogic' cache='writethrough'/>
<source file='harddisk.vmdk'/>
<source file='[datastore] directory/harddisk.vmdk'/>
<target dev='sda' bus='scsi'/>
</disk>
</devices>

View File

@ -7,5 +7,5 @@ memsize = "4"
numvcpus = "1"
serial0.present = "true"
serial0.fileType = "file"
serial0.fileName = "serial0.file"
serial0.fileName = "/vmfs/volumes/datastore/directory/serial0.file"
serial0.yieldOnMsrRead = "true"

View File

@ -7,7 +7,7 @@
</os>
<devices>
<serial type='file'>
<source path='serial0.file'/>
<source path='[datastore] directory/serial0.file'/>
<target port='0'/>
</serial>
</devices>

View File

@ -89,7 +89,7 @@ testCompareFiles(const char *xml, const char *vmx, esxVI_APIVersion apiVersion)
goto failure;
}
formatted = esxVMX_FormatConfig(NULL, def, apiVersion);
formatted = esxVMX_FormatConfig(NULL, NULL, def, apiVersion);
if (formatted == NULL) {
goto failure;