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;
}
}
- /* 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=");
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);
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);
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;
}
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);
return NULL;
}
- vmx = esxVMX_FormatConfig(conn, def, priv->host->apiVersion);
+ vmx = esxVMX_FormatConfig(conn, priv->host, def, priv->host->apiVersion);
virDomainDefFree(def);
+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)
{
esxListDefinedDomains, /* listDefinedDomains */
esxNumberOfDefinedDomains, /* numOfDefinedDomains */
esxDomainCreate, /* domainCreate */
- NULL, /* domainDefineXML */
+ esxDomainDefineXML, /* domainDefineXML */
esxDomainUndefine, /* domainUndefine */
NULL, /* domainAttachDevice */
NULL, /* domainDetachDevice */
+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)
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);
});
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);
#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:
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) {
}
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;
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);
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,
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));
"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",
/* Recurse through all hosts */
if (esxVI_BuildFullTraversalSpecItem(conn, fullTraversalSpecList,
- "HostSystemToVm",
+ "hostSystemToVm",
"HostSystem", "vm",
"visitFolders\0") < 0) {
goto failure;
}
ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
- "Missing '%s' property", propertyName);
+ "Missing '%s' property while looking for ManagedEntityStatus",
+ propertyName);
return -1;
}
+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,
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);
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);
+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)
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);
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;
}
(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;
}
#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)
+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;
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;
}
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;
}
/* 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;
}
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;
}
/* 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;
}
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;
}
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;
}
};*/
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}
}
/* Setup virDomainDiskDef */
- /* FIXME: Need the datastore name for fileName */
if (device == VIR_DOMAIN_DISK_DEVICE_DISK) {
if (esxUtil_EqualSuffix(fileName, ".vmdk")) {
if (deviceType != NULL) {
}
(*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")) {
/*
}
(*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
}
(*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;
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] = "";
} 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
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] = "";
} 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 "
*/
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;
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;
}
/* 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;
}
}
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");
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) {
"%s harddisk '%s' has unsupported cache mode '%s'",
busName, def->dst,
virDomainDiskCacheTypeToString(def->cachemode));
- return -1;
+ return -1;
}
}
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");
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' "
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");
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' "
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;
}
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 "
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);
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:
/* 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:
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",
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);
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:
return -1;
}
- /* def:data.file.path -> vmx:fileName */
- virBufferVSprintf(buffer, "parallel%d.fileName = \"%s\"\n",
- def->dstPort, def->data.file.path);
-
return 0;
}
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);
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
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);
*/
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__ */
#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",
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)
{
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;
}
<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>
<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>
<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'>
<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'>
<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'>
<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'>
<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'>
<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>
<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>
<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'>
<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'>
<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'>
<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'>
<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>
<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>
<on_crash>destroy</on_crash>
<devices>
<parallel type='file'>
- <source path='parallel0.file'/>
+ <source path='[datastore] directory/parallel0.file'/>
<target port='0'/>
</parallel>
</devices>
<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>
<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>
<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>
goto failure;
}
- def = esxVMX_ParseConfig(NULL, vmxData, apiVersion);
+ def = esxVMX_ParseConfig(NULL, NULL, vmxData, "datastore", "directory",
+ apiVersion);
if (def == NULL) {
goto failure;
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"
</os>
<devices>
<disk type='file' device='cdrom'>
- <source file='cdrom.iso'/>
+ <source file='[testing] isos/cdrom.iso'/>
<target dev='hda' bus='ide'/>
</disk>
</devices>
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"
</os>
<devices>
<disk type='file' device='cdrom'>
- <source file='cdrom.iso'/>
+ <source file='[testing] isos/cdrom.iso'/>
<target dev='sda' bus='scsi'/>
</disk>
</devices>
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"
<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'>
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"
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"
<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'>
<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'>
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"
<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'>
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"
<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'>
<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>
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"
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"
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"
numvcpus = "1"
floppy0.present = "true"
floppy0.fileType = "file"
-floppy0.fileName = "floppy.flp"
+floppy0.fileName = "/vmfs/volumes/testing/floppy.flp"
</os>
<devices>
<disk type='file' device='floppy'>
- <source file='floppy.flp'/>
+ <source file='[testing] floppy.flp'/>
<target dev='fda' bus='fdc'/>
</disk>
</devices>
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"
<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'>
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"
<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'>
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"
<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'>
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"
<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'>
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"
</os>
<devices>
<disk type='file' device='disk'>
- <source file='harddisk.vmdk'/>
+ <source file='[datastore] directory/harddisk.vmdk'/>
<target dev='hda' bus='ide'/>
</disk>
</devices>
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"
</os>
<devices>
<disk type='file' device='disk'>
- <source file='harddisk.vmdk'/>
+ <source file='[datastore] directory/harddisk.vmdk'/>
<target dev='sda' bus='scsi'/>
</disk>
</devices>
numvcpus = "1"
parallel0.present = "true"
parallel0.fileType = "file"
-parallel0.fileName = "parallel0.file"
+parallel0.fileName = "/vmfs/volumes/datastore/directory/parallel0.file"
</os>
<devices>
<parallel type='file'>
- <source path='parallel0.file'/>
+ <source path='[datastore] directory/parallel0.file'/>
<target port='0'/>
</parallel>
</devices>
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"
<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>
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"
<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>
numvcpus = "1"
serial0.present = "true"
serial0.fileType = "file"
-serial0.fileName = "serial0.file"
+serial0.fileName = "/vmfs/volumes/datastore/directory/serial0.file"
serial0.yieldOnMsrRead = "true"
</os>
<devices>
<serial type='file'>
- <source path='serial0.file'/>
+ <source path='[datastore] directory/serial0.file'/>
<target port='0'/>
</serial>
</devices>
goto failure;
}
- formatted = esxVMX_FormatConfig(NULL, def, apiVersion);
+ formatted = esxVMX_FormatConfig(NULL, NULL, def, apiVersion);
if (formatted == NULL) {
goto failure;