提交 e4938ce2 编写于 作者: M Matthias Bolte

esx: Restrict vpx:// to handle a single host in a vCenter

Now a vpx:// connection has an explicitly specified host. This
allows to enabled several functions for a vpx:// connection
again, like host UUID, hostname, general node info, max vCPU
count, free memory, migration and defining new domains.

Lookup datacenter, compute resource, resource pool and host
system once and cache them. This simplifies the rest of the
code and reduces overall HTTP(S) traffic a bit.

esx:// and vpx:// can be mixed freely for a migration.

Ensure that migration source and destination refer to the
same vCenter. Also directly encode the resource pool and
host system object IDs into the migration URI in the prepare
function. Then directly build managed object references in
the perform function instead of re-looking up already known
information.
上级 9f85668b
......@@ -28,7 +28,7 @@
Some example remote connection URIs for the driver are:
</p>
<pre>
vpx://example-vcenter.com (VPX over HTTPS)
vpx://example-vcenter.com/dc1/srv1 (VPX over HTTPS, select ESX server 'srv1' in datacenter 'dc1')
esx://example-esx.com (ESX over HTTPS)
gsx://example-gsx.com (GSX over HTTPS)
esx://example-esx.com/?transport=http (ESX over HTTP)
......@@ -48,7 +48,7 @@ esx://example-esx.com/?no_verify=1 (ESX over HTTPS, but doesn't verify the s
URIs have this general form (<code>[...]</code> marks an optional part).
</p>
<pre>
type://[username@]hostname[:port]/[?extraparameters]
type://[username@]hostname[:port]/[datacenter[/cluster]/server][?extraparameters]
</pre>
<p>
The <code>type://</code> is either <code>esx://</code> or
......@@ -58,6 +58,20 @@ type://[username@]hostname[:port]/[?extraparameters]
is 443, for <code>gsx://</code> it is 8333.
If the port parameter is given, it overrides the default port.
</p>
<p>
A <code>vpx://</code> connection is currently restricted to a single
ESX server. This might be relaxed in the future. The path part of the
URI is used to specify the datacenter and the ESX server in it. If the
ESX server is part of a cluster then the cluster has to be specified too.
</p>
<p>
An example: ESX server <code>example-esx.com</code> is managed by
vCenter <code>example-vcenter.com</code> and part of cluster
<code>cluster1</code>. This cluster is part of datacenter <code>dc1</code>.
</p>
<pre>
vpx://example-vcenter.com/dc1/cluster1/example-esx.com
</pre>
<h4>Extra parameters</h4>
......@@ -588,7 +602,7 @@ ethernet0.address = "00:50:56:25:48:C7"
esx://example.com/?vcenter=example-vcenter.com
</pre>
<p>
Here an example how to migrate the domain <code>Fedora11</code> from
Here's an example how to migrate the domain <code>Fedora11</code> from
ESX server <code>example-src.com</code> to ESX server
<code>example-dst.com</code> implicitly involving vCenter
<code>example-vcenter.com</code> using <code>virsh</code>.
......@@ -603,6 +617,19 @@ Enter username for example-dst.com [root]:
Enter root password for example-dst.com:
Enter username for example-vcenter.com [administrator]:
Enter administrator password for example-vcenter.com:
</pre>
<p>
<span class="since">Since 0.8.3</span> you can directly connect to a vCenter.
This simplifies migration a bit. Here's the same migration as above but
using <code>vpx://</code> connections and assuming both ESX server are in
datacenter <code>dc1</code> and aren't part of a cluster.
</p>
<pre>
$ virsh -c vpx://example-vcenter.com/dc1/example-src.com migrate Fedora11 vpx://example-vcenter.com/dc1/example-dst.com
Enter username for example-vcenter.com [administrator]:
Enter administrator password for example-vcenter.com:
Enter username for example-vcenter.com [administrator]:
Enter administrator password for example-vcenter.com:
</pre>
......
......@@ -67,20 +67,14 @@ esxSupportsLongMode(esxPrivate *priv)
return priv->supportsLongMode;
}
if (priv->host == NULL) {
/* FIXME: Currently no host for a vpx:// connection */
return esxVI_Boolean_False;
}
if (esxVI_EnsureSession(priv->host) < 0) {
if (esxVI_EnsureSession(priv->primary) < 0) {
return esxVI_Boolean_Undefined;
}
if (esxVI_String_AppendValueToList(&propertyNameList,
"hardware.cpuFeature") < 0 ||
esxVI_LookupObjectContentByType(priv->host, priv->host->hostFolder,
"HostSystem", propertyNameList,
esxVI_Boolean_True, &hostSystem) < 0) {
esxVI_LookupHostSystemProperties(priv->primary, propertyNameList,
&hostSystem) < 0) {
goto cleanup;
}
......@@ -153,20 +147,14 @@ esxLookupHostSystemBiosUuid(esxPrivate *priv, unsigned char *uuid)
esxVI_ObjectContent *hostSystem = NULL;
esxVI_DynamicProperty *dynamicProperty = NULL;
if (priv->host == NULL) {
/* FIXME: Currently no host for a vpx:// connection */
return 0;
}
if (esxVI_EnsureSession(priv->host) < 0) {
if (esxVI_EnsureSession(priv->primary) < 0) {
return -1;
}
if (esxVI_String_AppendValueToList(&propertyNameList,
"hardware.systemInfo.uuid") < 0 ||
esxVI_LookupObjectContentByType(priv->host, priv->host->hostFolder,
"HostSystem", propertyNameList,
esxVI_Boolean_True, &hostSystem) < 0) {
esxVI_LookupHostSystemProperties(priv->primary, propertyNameList,
&hostSystem) < 0) {
goto cleanup;
}
......@@ -236,7 +224,7 @@ esxCapsInit(esxPrivate *priv)
}
virCapabilitiesSetMacPrefix(caps, (unsigned char[]){ 0x00, 0x0c, 0x29 });
virCapabilitiesAddHostMigrateTransport(caps, "esx");
virCapabilitiesAddHostMigrateTransport(caps, "vpxmigr");
caps->hasWideScsiBus = true;
......@@ -347,7 +335,8 @@ esxConnectToHost(esxPrivate *priv, virConnectAuthPtr auth,
if (esxVI_Context_Alloc(&priv->host) < 0 ||
esxVI_Context_Connect(priv->host, url, ipAddress, username, password,
parsedUri) < 0) {
parsedUri) < 0 ||
esxVI_Context_LookupObjectsByPath(priv->host, parsedUri) < 0) {
goto cleanup;
}
......@@ -373,8 +362,8 @@ esxConnectToHost(esxPrivate *priv, virConnectAuthPtr auth,
if (esxVI_String_AppendValueListToList(&propertyNameList,
"runtime.inMaintenanceMode\0"
"summary.managementServerIp\0") < 0 ||
esxVI_LookupHostSystemByIp(priv->host, ipAddress, propertyNameList,
&hostSystem) < 0 ||
esxVI_LookupHostSystemProperties(priv->host, propertyNameList,
&hostSystem) < 0 ||
esxVI_GetBoolean(hostSystem, "runtime.inMaintenanceMode",
&inMaintenanceMode,
esxVI_Occurrence_RequiredItem) < 0 ||
......@@ -416,6 +405,7 @@ static int
esxConnectToVCenter(esxPrivate *priv, virConnectAuthPtr auth,
const char *hostname, int port,
const char *predefinedUsername,
const char *hostSystemIpAddress,
esxUtil_ParsedUri *parsedUri)
{
int result = -1;
......@@ -424,6 +414,14 @@ esxConnectToVCenter(esxPrivate *priv, virConnectAuthPtr auth,
char *password = NULL;
char *url = NULL;
if (hostSystemIpAddress == NULL &&
(parsedUri->path_datacenter == NULL ||
parsedUri->path_computeResource == NULL)) {
ESX_ERROR(VIR_ERR_INVALID_ARG, "%s",
_("Path has to specify the datacenter and compute resource"));
return -1;
}
if (esxUtil_ResolveHostname(hostname, ipAddress, NI_MAXHOST) < 0) {
return -1;
}
......@@ -473,6 +471,17 @@ esxConnectToVCenter(esxPrivate *priv, virConnectAuthPtr auth,
goto cleanup;
}
if (hostSystemIpAddress != NULL) {
if (esxVI_Context_LookupObjectsByHostSystemIp(priv->vCenter,
hostSystemIpAddress) < 0) {
goto cleanup;
}
} else {
if (esxVI_Context_LookupObjectsByPath(priv->vCenter, parsedUri) < 0) {
goto cleanup;
}
}
result = 0;
cleanup:
......@@ -486,7 +495,8 @@ esxConnectToVCenter(esxPrivate *priv, virConnectAuthPtr auth,
/*
* URI format: {vpx|esx|gsx}://[<username>@]<hostname>[:<port>]/[<query parameter> ...]
* URI format: {vpx|esx|gsx}://[<username>@]<hostname>[:<port>]/[<path>][?<query parameter> ...]
* <path> = <datacenter>/<computeresource>[/<hostsystem>]
*
* If no port is specified the default port is set dependent on the scheme and
* transport parameter:
......@@ -497,6 +507,11 @@ esxConnectToVCenter(esxPrivate *priv, virConnectAuthPtr auth,
* - gsx+http 8222
* - gsx+https 8333
*
* For a vpx:// connection <path> references a host managed by the vCenter.
* In case the host is part of a cluster then <computeresource> is the cluster
* name. Otherwise <computeresource> and <hostsystem> are equal and the later
* can be omitted.
*
* Optional query parameters:
* - transport={http|https}
* - vcenter={<vcenter>|*} only useful for an esx:// connection
......@@ -508,7 +523,7 @@ esxConnectToVCenter(esxPrivate *priv, virConnectAuthPtr auth,
*
* The vcenter parameter is only necessary for migration, because the vCenter
* server is in charge to initiate a migration between two ESX hosts. The
* vcenter parameter can be set to an explicity hostname or to *. If set to *,
* vcenter parameter can be set to an explicitly hostname or to *. If set to *,
* the driver will check if the ESX host is managed by a vCenter and connect to
* it. If the ESX host is not managed by a vCenter an error is reported.
*
......@@ -635,7 +650,8 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED)
}
if (esxConnectToVCenter(priv, auth, vCenterIpAddress,
conn->uri->port, NULL, parsedUri) < 0) {
conn->uri->port, NULL,
priv->host->ipAddress, parsedUri) < 0) {
goto cleanup;
}
}
......@@ -644,7 +660,7 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED)
} else { /* VPX */
/* Connect to vCenter */
if (esxConnectToVCenter(priv, auth, conn->uri->server, conn->uri->port,
conn->uri->user, parsedUri) < 0) {
conn->uri->user, NULL, parsedUri) < 0) {
goto cleanup;
}
......@@ -722,26 +738,19 @@ esxSupportsVMotion(esxPrivate *priv)
{
esxVI_String *propertyNameList = NULL;
esxVI_ObjectContent *hostSystem = NULL;
esxVI_DynamicProperty *dynamicProperty = NULL;
if (priv->supportsVMotion != esxVI_Boolean_Undefined) {
return priv->supportsVMotion;
}
if (priv->host == NULL) {
/* FIXME: Currently no host for a vpx:// connection */
return esxVI_Boolean_False;
}
if (esxVI_EnsureSession(priv->host) < 0) {
if (esxVI_EnsureSession(priv->primary) < 0) {
return esxVI_Boolean_Undefined;
}
if (esxVI_String_AppendValueToList(&propertyNameList,
"capability.vmotionSupported") < 0 ||
esxVI_LookupObjectContentByType(priv->host, priv->host->hostFolder,
"HostSystem", propertyNameList,
esxVI_Boolean_True, &hostSystem) < 0) {
esxVI_LookupHostSystemProperties(priv->primary, propertyNameList,
&hostSystem) < 0) {
goto cleanup;
}
......@@ -751,19 +760,10 @@ esxSupportsVMotion(esxPrivate *priv)
goto cleanup;
}
for (dynamicProperty = hostSystem->propSet; dynamicProperty != NULL;
dynamicProperty = dynamicProperty->_next) {
if (STREQ(dynamicProperty->name, "capability.vmotionSupported")) {
if (esxVI_AnyType_ExpectType(dynamicProperty->val,
esxVI_Type_Boolean) < 0) {
goto cleanup;
}
priv->supportsVMotion = dynamicProperty->val->boolean;
break;
} else {
VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
}
if (esxVI_GetBoolean(hostSystem, "capability.vmotionSupported",
&priv->supportsVMotion,
esxVI_Occurrence_RequiredItem) < 0) {
goto cleanup;
}
cleanup:
......@@ -842,14 +842,7 @@ esxGetHostname(virConnectPtr conn)
const char *domainName = NULL;
char *complete = NULL;
if (priv->host == NULL) {
/* FIXME: Currently no host for a vpx:// connection */
ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not retrieve the hostname for a vpx:// connection"));
return NULL;
}
if (esxVI_EnsureSession(priv->host) < 0) {
if (esxVI_EnsureSession(priv->primary) < 0) {
return NULL;
}
......@@ -857,9 +850,8 @@ esxGetHostname(virConnectPtr conn)
(&propertyNameList,
"config.network.dnsConfig.hostName\0"
"config.network.dnsConfig.domainName\0") < 0 ||
esxVI_LookupObjectContentByType(priv->host, priv->host->hostFolder,
"HostSystem", propertyNameList,
esxVI_Boolean_True, &hostSystem) < 0) {
esxVI_LookupHostSystemProperties(priv->primary, propertyNameList,
&hostSystem) < 0) {
goto cleanup;
}
......@@ -944,14 +936,7 @@ esxNodeGetInfo(virConnectPtr conn, virNodeInfoPtr nodeinfo)
memset(nodeinfo, 0, sizeof (*nodeinfo));
if (priv->host == NULL) {
/* FIXME: Currently no host for a vpx:// connection */
ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Nodeinfo is not available for a vpx:// connection"));
return -1;
}
if (esxVI_EnsureSession(priv->host) < 0) {
if (esxVI_EnsureSession(priv->primary) < 0) {
return -1;
}
......@@ -963,9 +948,8 @@ esxNodeGetInfo(virConnectPtr conn, virNodeInfoPtr nodeinfo)
"hardware.memorySize\0"
"hardware.numaInfo.numNodes\0"
"summary.hardware.cpuModel\0") < 0 ||
esxVI_LookupObjectContentByType(priv->host, priv->host->hostFolder,
"HostSystem", propertyNameList,
esxVI_Boolean_True, &hostSystem) < 0) {
esxVI_LookupHostSystemProperties(priv->primary, propertyNameList,
&hostSystem) < 0) {
goto cleanup;
}
......@@ -1126,10 +1110,8 @@ esxListDomains(virConnectPtr conn, int *ids, int maxids)
if (esxVI_String_AppendValueToList(&propertyNameList,
"runtime.powerState") < 0 ||
esxVI_LookupObjectContentByType(priv->primary, priv->primary->vmFolder,
"VirtualMachine", propertyNameList,
esxVI_Boolean_True,
&virtualMachineList) < 0) {
esxVI_LookupVirtualMachineList(priv->primary, propertyNameList,
&virtualMachineList) < 0) {
goto cleanup;
}
......@@ -1209,10 +1191,8 @@ esxDomainLookupByID(virConnectPtr conn, int id)
"name\0"
"runtime.powerState\0"
"config.uuid\0") < 0 ||
esxVI_LookupObjectContentByType(priv->primary, priv->primary->vmFolder,
"VirtualMachine", propertyNameList,
esxVI_Boolean_True,
&virtualMachineList) < 0) {
esxVI_LookupVirtualMachineList(priv->primary, propertyNameList,
&virtualMachineList) < 0) {
goto cleanup;
}
......@@ -2142,22 +2122,14 @@ esxDomainGetMaxVcpus(virDomainPtr domain)
priv->maxVcpus = -1;
if (priv->host == NULL) {
/* FIXME: Currently no host for a vpx:// connection */
ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("MaxVCPUs value is not available for a vpx:// connection"));
return -1;
}
if (esxVI_EnsureSession(priv->host) < 0) {
if (esxVI_EnsureSession(priv->primary) < 0) {
return -1;
}
if (esxVI_String_AppendValueToList(&propertyNameList,
"capability.maxSupportedVcpus") < 0 ||
esxVI_LookupObjectContentByType(priv->host, priv->host->hostFolder,
"HostSystem", propertyNameList,
esxVI_Boolean_True, &hostSystem) < 0) {
esxVI_LookupHostSystemProperties(priv->primary, propertyNameList,
&hostSystem) < 0) {
goto cleanup;
}
......@@ -2196,11 +2168,8 @@ esxDomainDumpXML(virDomainPtr domain, int flags)
{
esxPrivate *priv = domain->conn->privateData;
esxVI_String *propertyNameList = NULL;
esxVI_ObjectContent *datacenter = NULL;
esxVI_ObjectContent *virtualMachine = NULL;
esxVI_DynamicProperty *dynamicProperty = NULL;
const char *vmPathName = NULL;
char *datacenterName = NULL;
char *vmPathName = NULL;
char *datastoreName = NULL;
char *directoryName = NULL;
char *fileName = NULL;
......@@ -2214,38 +2183,16 @@ esxDomainDumpXML(virDomainPtr domain, int flags)
return NULL;
}
if (esxVI_String_AppendValueToList(&propertyNameList, "name") < 0 ||
esxVI_LookupObjectContentByType(priv->primary, priv->primary->datacenter,
"Datacenter", propertyNameList,
esxVI_Boolean_False, &datacenter) < 0 ||
esxVI_GetStringValue(datacenter, "name", &datacenterName,
esxVI_Occurrence_RequiredItem) < 0) {
goto cleanup;
}
esxVI_String_Free(&propertyNameList);
if (esxVI_String_AppendValueToList(&propertyNameList,
"config.files.vmPathName") < 0 ||
esxVI_LookupVirtualMachineByUuid(priv->primary, domain->uuid,
propertyNameList, &virtualMachine,
esxVI_Occurrence_RequiredItem) < 0) {
esxVI_Occurrence_RequiredItem) < 0 ||
esxVI_GetStringValue(virtualMachine, "config.files.vmPathName",
&vmPathName, esxVI_Occurrence_RequiredItem) < 0) {
goto cleanup;
}
for (dynamicProperty = virtualMachine->propSet; dynamicProperty != NULL;
dynamicProperty = dynamicProperty->_next) {
if (STREQ(dynamicProperty->name, "config.files.vmPathName")) {
if (esxVI_AnyType_ExpectType(dynamicProperty->val,
esxVI_Type_String) < 0) {
goto cleanup;
}
vmPathName = dynamicProperty->val->string;
break;
}
}
if (esxUtil_ParseDatastoreRelatedPath(vmPathName, &datastoreName,
&directoryName, &fileName) < 0) {
goto cleanup;
......@@ -2261,7 +2208,7 @@ esxDomainDumpXML(virDomainPtr domain, int flags)
virBufferURIEncodeString(&buffer, fileName);
virBufferAddLit(&buffer, "?dcPath=");
virBufferURIEncodeString(&buffer, datacenterName);
virBufferURIEncodeString(&buffer, priv->primary->datacenter->name);
virBufferAddLit(&buffer, "&dsName=");
virBufferURIEncodeString(&buffer, datastoreName);
......@@ -2289,7 +2236,6 @@ esxDomainDumpXML(virDomainPtr domain, int flags)
}
esxVI_String_Free(&propertyNameList);
esxVI_ObjectContent_Free(&datacenter);
esxVI_ObjectContent_Free(&virtualMachine);
VIR_FREE(datastoreName);
VIR_FREE(directoryName);
......@@ -2392,10 +2338,8 @@ esxListDefinedDomains(virConnectPtr conn, char **const names, int maxnames)
if (esxVI_String_AppendValueListToList(&propertyNameList,
"name\0"
"runtime.powerState\0") < 0 ||
esxVI_LookupObjectContentByType(priv->primary, priv->primary->vmFolder,
"VirtualMachine", propertyNameList,
esxVI_Boolean_True,
&virtualMachineList) < 0) {
esxVI_LookupVirtualMachineList(priv->primary, propertyNameList,
&virtualMachineList) < 0) {
goto cleanup;
}
......@@ -2557,14 +2501,7 @@ esxDomainDefineXML(virConnectPtr conn, const char *xml ATTRIBUTE_UNUSED)
esxVI_TaskInfoState taskInfoState;
virDomainPtr domain = NULL;
if (priv->host == NULL) {
/* FIXME: Currently no host for a vpx:// connection */
ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not define domain with a vpx:// connection"));
return NULL;
}
if (esxVI_EnsureSession(priv->host) < 0) {
if (esxVI_EnsureSession(priv->primary) < 0) {
return NULL;
}
......@@ -2577,7 +2514,7 @@ esxDomainDefineXML(virConnectPtr conn, const char *xml ATTRIBUTE_UNUSED)
}
/* Check if an existing domain should be edited */
if (esxVI_LookupVirtualMachineByUuid(priv->host, def->uuid, NULL,
if (esxVI_LookupVirtualMachineByUuid(priv->primary, def->uuid, NULL,
&virtualMachine,
esxVI_Occurrence_OptionalItem) < 0) {
goto cleanup;
......@@ -2592,8 +2529,8 @@ esxDomainDefineXML(virConnectPtr conn, const char *xml ATTRIBUTE_UNUSED)
}
/* Build VMX from domain XML */
vmx = esxVMX_FormatConfig(priv->host, priv->caps, def,
priv->host->productVersion);
vmx = esxVMX_FormatConfig(priv->primary, priv->caps, def,
priv->primary->productVersion);
if (vmx == NULL) {
goto cleanup;
......@@ -2657,7 +2594,7 @@ esxDomainDefineXML(virConnectPtr conn, const char *xml ATTRIBUTE_UNUSED)
virBufferURIEncodeString(&buffer, def->name);
virBufferAddLit(&buffer, ".vmx?dcPath=");
virBufferURIEncodeString(&buffer, priv->host->datacenter->value);
virBufferURIEncodeString(&buffer, priv->primary->datacenter->name);
virBufferAddLit(&buffer, "&dsName=");
virBufferURIEncodeString(&buffer, datastoreName);
......@@ -2682,31 +2619,21 @@ esxDomainDefineXML(virConnectPtr conn, const char *xml ATTRIBUTE_UNUSED)
}
}
/* Get resource pool */
if (esxVI_String_AppendValueToList(&propertyNameList, "parent") < 0 ||
esxVI_LookupHostSystemByIp(priv->host, priv->host->ipAddress,
propertyNameList, &hostSystem) < 0) {
goto cleanup;
}
if (esxVI_LookupResourcePoolByHostSystem(priv->host, hostSystem,
&resourcePool) < 0) {
goto cleanup;
}
/* Check, if VMX file already exists */
/* FIXME */
/* Upload VMX file */
if (esxVI_Context_UploadFile(priv->host, url, vmx) < 0) {
if (esxVI_Context_UploadFile(priv->primary, url, vmx) < 0) {
goto cleanup;
}
/* Register the domain */
if (esxVI_RegisterVM_Task(priv->host, priv->host->vmFolder,
if (esxVI_RegisterVM_Task(priv->primary, priv->primary->datacenter->vmFolder,
datastoreRelatedPath, NULL, esxVI_Boolean_False,
resourcePool, hostSystem->obj, &task) < 0 ||
esxVI_WaitForTaskCompletion(priv->host, task, def->uuid,
priv->primary->computeResource->resourcePool,
priv->primary->hostSystem->_reference,
&task) < 0 ||
esxVI_WaitForTaskCompletion(priv->primary, task, def->uuid,
esxVI_Occurrence_OptionalItem,
priv->autoAnswer, &taskInfoState) < 0) {
goto cleanup;
......@@ -3102,32 +3029,25 @@ static int
esxDomainMigratePrepare(virConnectPtr dconn,
char **cookie ATTRIBUTE_UNUSED,
int *cookielen ATTRIBUTE_UNUSED,
const char *uri_in, char **uri_out,
const char *uri_in ATTRIBUTE_UNUSED,
char **uri_out,
unsigned long flags ATTRIBUTE_UNUSED,
const char *dname ATTRIBUTE_UNUSED,
unsigned long resource ATTRIBUTE_UNUSED)
{
int result = -1;
esxUtil_ParsedUri *parsedUri = NULL;
esxPrivate *priv = dconn->privateData;
if (uri_in == NULL) {
if (esxUtil_ParseUri(&parsedUri, dconn->uri) < 0) {
return -1;
}
if (virAsprintf(uri_out, "%s://%s:%d/sdk", parsedUri->transport,
dconn->uri->server, dconn->uri->port) < 0) {
if (virAsprintf(uri_out, "vpxmigr://%s/%s/%s",
priv->vCenter->ipAddress,
priv->vCenter->computeResource->resourcePool->value,
priv->vCenter->hostSystem->_reference->value) < 0) {
virReportOOMError();
goto cleanup;
return -1;
}
}
result = 0;
cleanup:
esxUtil_FreeParsedUri(&parsedUri);
return result;
return 0;
}
......@@ -3143,12 +3063,13 @@ esxDomainMigratePerform(virDomainPtr domain,
{
int result = -1;
esxPrivate *priv = domain->conn->privateData;
xmlURIPtr xmlUri = NULL;
char hostIpAddress[NI_MAXHOST] = "";
xmlURIPtr parsedUri = NULL;
char *saveptr;
char *path_resourcePool;
char *path_hostSystem;
esxVI_ObjectContent *virtualMachine = NULL;
esxVI_String *propertyNameList = NULL;
esxVI_ObjectContent *hostSystem = NULL;
esxVI_ManagedObjectReference *resourcePool = NULL;
esxVI_ManagedObjectReference resourcePool;
esxVI_ManagedObjectReference hostSystem;
esxVI_Event *eventList = NULL;
esxVI_ManagedObjectReference *task = NULL;
esxVI_TaskInfoState taskInfoState;
......@@ -3169,39 +3090,57 @@ esxDomainMigratePerform(virDomainPtr domain,
return -1;
}
/* Parse the destination URI and resolve the hostname */
xmlUri = xmlParseURI(uri);
/* Parse migration URI */
parsedUri = xmlParseURI(uri);
if (xmlUri == NULL) {
if (parsedUri == NULL) {
virReportOOMError();
return -1;
}
if (esxUtil_ResolveHostname(xmlUri->server, hostIpAddress,
NI_MAXHOST) < 0) {
if (parsedUri->scheme == NULL || STRCASENEQ(parsedUri->scheme, "vpxmigr")) {
ESX_ERROR(VIR_ERR_INVALID_ARG, "%s",
_("Only vpxmigr:// migration URIs are supported"));
goto cleanup;
}
/* Lookup VirtualMachine, HostSystem and ResourcePool */
if (esxVI_LookupVirtualMachineByUuidAndPrepareForTask
(priv->vCenter, domain->uuid, NULL, &virtualMachine,
priv->autoAnswer) < 0 ||
esxVI_String_AppendValueToList(&propertyNameList, "parent") < 0 ||
esxVI_LookupHostSystemByIp(priv->vCenter, hostIpAddress,
propertyNameList, &hostSystem) < 0) {
if (STRCASENEQ(priv->vCenter->ipAddress, parsedUri->server)) {
ESX_ERROR(VIR_ERR_INVALID_ARG, "%s",
_("Migration source and destination have to refer to "
"the same vCenter"));
goto cleanup;
}
path_resourcePool = strtok_r(parsedUri->path, "/", &saveptr);
path_hostSystem = strtok_r(NULL, "", &saveptr);
if (path_resourcePool == NULL || path_hostSystem == NULL) {
ESX_ERROR(VIR_ERR_INVALID_ARG, "%s",
_("Migration URI has to specify resource pool and host system"));
goto cleanup;
}
if (esxVI_LookupResourcePoolByHostSystem(priv->vCenter, hostSystem,
&resourcePool) < 0) {
resourcePool._next = NULL;
resourcePool._type = esxVI_Type_ManagedObjectReference;
resourcePool.type = (char *)"ResourcePool";
resourcePool.value = path_resourcePool;
hostSystem._next = NULL;
hostSystem._type = esxVI_Type_ManagedObjectReference;
hostSystem.type = (char *)"HostSystem";
hostSystem.value = path_hostSystem;
/* Lookup VirtualMachine */
if (esxVI_LookupVirtualMachineByUuidAndPrepareForTask
(priv->vCenter, domain->uuid, NULL, &virtualMachine,
priv->autoAnswer) < 0) {
goto cleanup;
}
/* Validate the purposed migration */
if (esxVI_ValidateMigration(priv->vCenter, virtualMachine->obj,
esxVI_VirtualMachinePowerState_Undefined,
NULL, resourcePool, hostSystem->obj,
&eventList) < 0) {
esxVI_VirtualMachinePowerState_Undefined, NULL,
&resourcePool, &hostSystem, &eventList) < 0) {
goto cleanup;
}
......@@ -3224,8 +3163,8 @@ esxDomainMigratePerform(virDomainPtr domain,
}
/* Perform the purposed migration */
if (esxVI_MigrateVM_Task(priv->vCenter, virtualMachine->obj, resourcePool,
hostSystem->obj,
if (esxVI_MigrateVM_Task(priv->vCenter, virtualMachine->obj,
&resourcePool, &hostSystem,
esxVI_VirtualMachineMovePriority_DefaultPriority,
esxVI_VirtualMachinePowerState_Undefined,
&task) < 0 ||
......@@ -3245,11 +3184,8 @@ esxDomainMigratePerform(virDomainPtr domain,
result = 0;
cleanup:
xmlFreeURI(xmlUri);
xmlFreeURI(parsedUri);
esxVI_ObjectContent_Free(&virtualMachine);
esxVI_String_Free(&propertyNameList);
esxVI_ObjectContent_Free(&hostSystem);
esxVI_ManagedObjectReference_Free(&resourcePool);
esxVI_Event_Free(&eventList);
esxVI_ManagedObjectReference_Free(&task);
......@@ -3276,41 +3212,19 @@ esxNodeGetFreeMemory(virConnectPtr conn)
unsigned long long result = 0;
esxPrivate *priv = conn->privateData;
esxVI_String *propertyNameList = NULL;
esxVI_ObjectContent *hostSystem = NULL;
esxVI_ManagedObjectReference *managedObjectReference = NULL;
esxVI_ObjectContent *resourcePool = NULL;
esxVI_DynamicProperty *dynamicProperty = NULL;
esxVI_ResourcePoolResourceUsage *resourcePoolResourceUsage = NULL;
if (priv->host == NULL) {
/* FIXME: Currently no host for a vpx:// connection */
ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not retrieve free memory for a vpx:// connection"));
return 0;
}
if (esxVI_EnsureSession(priv->host) < 0) {
if (esxVI_EnsureSession(priv->primary) < 0) {
return 0;
}
/* Lookup host system with its resource pool */
if (esxVI_String_AppendValueToList(&propertyNameList, "parent") < 0 ||
esxVI_LookupHostSystemByIp(priv->host, priv->host->ipAddress,
propertyNameList, &hostSystem) < 0) {
goto cleanup;
}
if (esxVI_LookupResourcePoolByHostSystem(priv->host, hostSystem,
&managedObjectReference) < 0) {
goto cleanup;
}
esxVI_String_Free(&propertyNameList);
/* Get memory usage of resource pool */
if (esxVI_String_AppendValueToList(&propertyNameList,
"runtime.memory") < 0 ||
esxVI_LookupObjectContentByType(priv->host, managedObjectReference,
esxVI_LookupObjectContentByType(priv->primary,
priv->primary->computeResource->resourcePool,
"ResourcePool", propertyNameList,
esxVI_Boolean_False,
&resourcePool) < 0) {
......@@ -3341,8 +3255,6 @@ esxNodeGetFreeMemory(virConnectPtr conn)
cleanup:
esxVI_String_Free(&propertyNameList);
esxVI_ObjectContent_Free(&hostSystem);
esxVI_ManagedObjectReference_Free(&managedObjectReference);
esxVI_ObjectContent_Free(&resourcePool);
esxVI_ResourcePoolResourceUsage_Free(&resourcePoolResourceUsage);
......
......@@ -78,9 +78,7 @@ esxNumberOfStoragePools(virConnectPtr conn)
return -1;
}
if (esxVI_LookupObjectContentByType(priv->primary, priv->primary->datacenter,
"Datastore", NULL, esxVI_Boolean_True,
&datastoreList) < 0) {
if (esxVI_LookupDatastoreList(priv->primary, NULL, &datastoreList) < 0) {
return -1;
}
......@@ -123,10 +121,8 @@ esxListStoragePools(virConnectPtr conn, char **const names, int maxnames)
if (esxVI_String_AppendValueToList(&propertyNameList,
"summary.name") < 0 ||
esxVI_LookupObjectContentByType(priv->primary, priv->primary->datacenter,
"Datastore", propertyNameList,
esxVI_Boolean_True,
&datastoreList) < 0) {
esxVI_LookupDatastoreList(priv->primary, propertyNameList,
&datastoreList) < 0) {
goto cleanup;
}
......@@ -308,15 +304,7 @@ esxStoragePoolLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
char *name = NULL;
virStoragePoolPtr pool = NULL;
/* FIXME: Need to handle this for a vpx:// connection */
if (priv->host == NULL ||
! (priv->host->productVersion & esxVI_ProductVersion_ESX)) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Lookup by UUID is supported on ESX only"));
return NULL;
}
if (esxVI_EnsureSession(priv->host) < 0) {
if (esxVI_EnsureSession(priv->primary) < 0) {
return NULL;
}
......@@ -334,7 +322,7 @@ esxStoragePoolLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
* part of the 'summary.url' property if there is no name match.
*/
if (esxVI_String_AppendValueToList(&propertyNameList, "summary.name") < 0 ||
esxVI_LookupDatastoreByName(priv->host, uuid_string,
esxVI_LookupDatastoreByName(priv->primary, uuid_string,
propertyNameList, &datastore,
esxVI_Occurrence_OptionalItem) < 0) {
goto cleanup;
......@@ -350,7 +338,7 @@ esxStoragePoolLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
if (datastore == NULL && STREQ(uuid_string + 17, "-0000-000000000000")) {
uuid_string[17] = '\0';
if (esxVI_LookupDatastoreByName(priv->host, uuid_string,
if (esxVI_LookupDatastoreByName(priv->primary, uuid_string,
propertyNameList, &datastore,
esxVI_Occurrence_RequiredItem) < 0) {
goto cleanup;
......
......@@ -101,10 +101,11 @@ ESX_VI__TEMPLATE__FREE(Context,
VIR_FREE(item->password);
esxVI_ServiceContent_Free(&item->service);
esxVI_UserSession_Free(&item->session);
esxVI_ManagedObjectReference_Free(&item->datacenter);
esxVI_ManagedObjectReference_Free(&item->vmFolder);
esxVI_ManagedObjectReference_Free(&item->hostFolder);
esxVI_Datacenter_Free(&item->datacenter);
esxVI_ComputeResource_Free(&item->computeResource);
esxVI_HostSystem_Free(&item->hostSystem);
esxVI_SelectionSpec_Free(&item->fullTraversalSpecList);
esxVI_SelectionSpec_Free(&item->fullTraversalSpecList2);
});
static size_t
......@@ -279,11 +280,6 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url,
const char *ipAddress, const char *username,
const char *password, esxUtil_ParsedUri *parsedUri)
{
int result = -1;
esxVI_String *propertyNameList = NULL;
esxVI_ObjectContent *datacenterList = NULL;
esxVI_DynamicProperty *dynamicProperty = NULL;
if (ctx == NULL || url == NULL || ipAddress == NULL || username == NULL ||
password == NULL || ctx->url != NULL || ctx->service != NULL ||
ctx->curl_handle != NULL || ctx->curl_headers != NULL) {
......@@ -293,7 +289,7 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url,
if (esxVI_String_DeepCopyValue(&ctx->url, url) < 0 ||
esxVI_String_DeepCopyValue(&ctx->ipAddress, ipAddress) < 0) {
goto cleanup;
return -1;
}
ctx->curl_handle = curl_easy_init();
......@@ -301,7 +297,7 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url,
if (ctx->curl_handle == NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not initialize CURL"));
goto cleanup;
return -1;
}
ctx->curl_headers = curl_slist_append(ctx->curl_headers, "Content-Type: "
......@@ -321,7 +317,7 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url,
if (ctx->curl_headers == NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not build CURL header list"));
goto cleanup;
return -1;
}
curl_easy_setopt(ctx->curl_handle, CURLOPT_URL, ctx->url);
......@@ -357,7 +353,7 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url,
if (virMutexInit(&ctx->curl_lock) < 0) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not initialize CURL mutex"));
goto cleanup;
return -1;
}
ctx->username = strdup(username);
......@@ -365,11 +361,11 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url,
if (ctx->username == NULL || ctx->password == NULL) {
virReportOOMError();
goto cleanup;
return -1;
}
if (esxVI_RetrieveServiceContent(ctx, &ctx->service) < 0) {
goto cleanup;
return -1;
}
if (STREQ(ctx->service->about->apiType, "HostAgent") ||
......@@ -389,7 +385,7 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url,
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting VI API major/minor version '2.5' or '4.x' "
"but found '%s'"), ctx->service->about->apiVersion);
goto cleanup;
return -1;
}
if (STREQ(ctx->service->about->productLineId, "gsx")) {
......@@ -399,7 +395,7 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url,
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting GSX major/minor version '2.0' but "
"found '%s'"), ctx->service->about->version);
goto cleanup;
return -1;
}
} else if (STREQ(ctx->service->about->productLineId, "esx") ||
STREQ(ctx->service->about->productLineId, "embeddedEsx")) {
......@@ -419,7 +415,7 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url,
_("Expecting ESX major/minor version '3.5' or "
"'4.x' but found '%s'"),
ctx->service->about->version);
goto cleanup;
return -1;
}
} else if (STREQ(ctx->service->about->productLineId, "vpx")) {
if (STRPREFIX(ctx->service->about->version, "2.5")) {
......@@ -437,36 +433,67 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url,
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting VPX major/minor version '2.5' or '4.x' "
"but found '%s'"), ctx->service->about->version);
goto cleanup;
return -1;
}
} else {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting product 'gsx' or 'esx' or 'embeddedEsx' "
"or 'vpx' but found '%s'"),
ctx->service->about->productLineId);
goto cleanup;
return -1;
}
} else {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting VI API type 'HostAgent' or 'VirtualCenter' "
"but found '%s'"), ctx->service->about->apiType);
goto cleanup;
return -1;
}
if (esxVI_Login(ctx, username, password, NULL, &ctx->session) < 0) {
goto cleanup;
if (esxVI_Login(ctx, username, password, NULL, &ctx->session) < 0 ||
esxVI_BuildFullTraversalSpecList(&ctx->fullTraversalSpecList) < 0) {
return -1;
}
esxVI_BuildFullTraversalSpecList(&ctx->fullTraversalSpecList);
/* Folder -> parent (Folder, Datacenter) */
if (esxVI_BuildFullTraversalSpecItem(&ctx->fullTraversalSpecList2,
"managedEntityToParent",
"ManagedEntity", "parent",
NULL) < 0) {
return -1;
}
if (esxVI_String_AppendValueListToList(&propertyNameList,
"vmFolder\0"
"hostFolder\0") < 0) {
goto cleanup;
/* ComputeResource -> parent (Folder) */
if (esxVI_BuildFullTraversalSpecItem(&ctx->fullTraversalSpecList2,
"computeResourceToParent",
"ComputeResource", "parent",
"managedEntityToParent\0") < 0) {
return -1;
}
/* Get pointer to Datacenter for later use */
if (esxVI_LookupObjectContentByType(ctx, ctx->service->rootFolder,
return 0;
}
int
esxVI_Context_LookupObjectsByPath(esxVI_Context *ctx,
esxUtil_ParsedUri *parsedUri)
{
int result = -1;
esxVI_String *propertyNameList = NULL;
char *name = NULL;
esxVI_ObjectContent *datacenterList = NULL;
esxVI_ObjectContent *datacenter = NULL;
esxVI_ObjectContent *computeResourceList = NULL;
esxVI_ObjectContent *computeResource = NULL;
char *hostSystemName = NULL;
esxVI_ObjectContent *hostSystemList = NULL;
esxVI_ObjectContent *hostSystem = NULL;
/* Lookup Datacenter */
if (esxVI_String_AppendValueListToList(&propertyNameList,
"name\0"
"vmFolder\0"
"hostFolder\0") < 0 ||
esxVI_LookupObjectContentByType(ctx, ctx->service->rootFolder,
"Datacenter", propertyNameList,
esxVI_Boolean_True,
&datacenterList) < 0) {
......@@ -475,36 +502,156 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url,
if (datacenterList == NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not retrieve the 'datacenter' object from the "
"VI host/center"));
_("Could not retrieve datacenter list"));
goto cleanup;
}
ctx->datacenter = datacenterList->obj;
datacenterList->obj = NULL;
if (parsedUri->path_datacenter != NULL) {
for (datacenter = datacenterList; datacenter != NULL;
datacenter = datacenter->_next) {
name = NULL;
/* Get pointer to vmFolder and hostFolder for later use */
for (dynamicProperty = datacenterList->propSet; dynamicProperty != NULL;
dynamicProperty = dynamicProperty->_next) {
if (STREQ(dynamicProperty->name, "vmFolder")) {
if (esxVI_ManagedObjectReference_CastFromAnyType
(dynamicProperty->val, &ctx->vmFolder)) {
if (esxVI_GetStringValue(datacenter, "name", &name,
esxVI_Occurrence_RequiredItem) < 0) {
goto cleanup;
}
} else if (STREQ(dynamicProperty->name, "hostFolder")) {
if (esxVI_ManagedObjectReference_CastFromAnyType
(dynamicProperty->val, &ctx->hostFolder)) {
if (STREQ(name, parsedUri->path_datacenter)) {
break;
}
}
if (datacenter == NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Could not find datacenter '%s'"),
parsedUri->path_datacenter);
goto cleanup;
}
} else {
datacenter = datacenterList;
}
if (esxVI_Datacenter_CastFromObjectContent(datacenter,
&ctx->datacenter) < 0) {
goto cleanup;
}
/* Lookup ComputeResource */
esxVI_String_Free(&propertyNameList);
if (esxVI_String_AppendValueListToList(&propertyNameList,
"name\0"
"host\0"
"resourcePool\0") < 0 ||
esxVI_LookupObjectContentByType(ctx, ctx->datacenter->hostFolder,
"ComputeResource", propertyNameList,
esxVI_Boolean_True,
&computeResourceList) < 0) {
goto cleanup;
}
if (computeResourceList == NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not retrieve compute resource list"));
goto cleanup;
}
if (parsedUri->path_computeResource != NULL) {
for (computeResource = computeResourceList; computeResource != NULL;
computeResource = computeResource->_next) {
name = NULL;
if (esxVI_GetStringValue(computeResource, "name", &name,
esxVI_Occurrence_RequiredItem) < 0) {
goto cleanup;
}
} else {
VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
if (STREQ(name, parsedUri->path_computeResource)) {
break;
}
}
if (computeResource == NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Could not find compute resource '%s'"),
parsedUri->path_computeResource);
goto cleanup;
}
} else {
computeResource = computeResourceList;
}
if (esxVI_ComputeResource_CastFromObjectContent(computeResource,
&ctx->computeResource) < 0) {
goto cleanup;
}
if (ctx->computeResource->resourcePool == NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not retrieve resource pool"));
goto cleanup;
}
/* Lookup HostSystem */
if (parsedUri->path_hostSystem == NULL &&
STREQ(ctx->computeResource->_reference->type,
"ClusterComputeResource")) {
ESX_VI_ERROR(VIR_ERR_INVALID_ARG, "%s",
_("Path has to specify the host system"));
goto cleanup;
}
if (ctx->vmFolder == NULL || ctx->hostFolder == NULL) {
esxVI_String_Free(&propertyNameList);
if (esxVI_String_AppendValueListToList(&propertyNameList,
"name\0") < 0 ||
esxVI_LookupObjectContentByType(ctx, ctx->computeResource->_reference,
"HostSystem", propertyNameList,
esxVI_Boolean_True,
&hostSystemList) < 0) {
goto cleanup;
}
if (hostSystemList == NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("The 'datacenter' object is missing the "
"'vmFolder'/'hostFolder' property"));
_("Could not retrieve host system list"));
goto cleanup;
}
if (parsedUri->path_hostSystem != NULL ||
(parsedUri->path_computeResource != NULL &&
parsedUri->path_hostSystem == NULL)) {
if (parsedUri->path_hostSystem != NULL) {
hostSystemName = parsedUri->path_hostSystem;
} else {
hostSystemName = parsedUri->path_computeResource;
}
for (hostSystem = hostSystemList; hostSystem != NULL;
hostSystem = hostSystem->_next) {
name = NULL;
if (esxVI_GetStringValue(hostSystem, "name", &name,
esxVI_Occurrence_RequiredItem) < 0) {
goto cleanup;
}
if (STREQ(name, hostSystemName)) {
break;
}
}
if (hostSystem == NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Could not find host system '%s'"), hostSystemName);
goto cleanup;
}
} else {
hostSystem = hostSystemList;
}
if (esxVI_HostSystem_CastFromObjectContent(hostSystem,
&ctx->hostSystem) < 0) {
goto cleanup;
}
......@@ -513,6 +660,110 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url,
cleanup:
esxVI_String_Free(&propertyNameList);
esxVI_ObjectContent_Free(&datacenterList);
esxVI_ObjectContent_Free(&computeResourceList);
esxVI_ObjectContent_Free(&hostSystemList);
return result;
}
int
esxVI_Context_LookupObjectsByHostSystemIp(esxVI_Context *ctx,
const char *hostSystemIpAddress)
{
int result = -1;
esxVI_String *propertyNameList = NULL;
esxVI_ManagedObjectReference *managedObjectReference = NULL;
esxVI_ObjectContent *hostSystem = NULL;
esxVI_ObjectContent *computeResource = NULL;
esxVI_ObjectContent *datacenter = NULL;
/* Lookup HostSystem */
if (esxVI_String_AppendValueListToList(&propertyNameList,
"name\0") < 0 ||
esxVI_FindByIp(ctx, NULL, hostSystemIpAddress, esxVI_Boolean_False,
&managedObjectReference) < 0 ||
esxVI_LookupObjectContentByType(ctx, managedObjectReference,
"HostSystem", propertyNameList,
esxVI_Boolean_False, &hostSystem) < 0) {
goto cleanup;
}
if (hostSystem == NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not retrieve host system"));
goto cleanup;
}
if (esxVI_HostSystem_CastFromObjectContent(hostSystem,
&ctx->hostSystem) < 0) {
goto cleanup;
}
/* Lookup ComputeResource */
esxVI_String_Free(&propertyNameList);
if (esxVI_String_AppendValueListToList(&propertyNameList,
"name\0"
"host\0"
"resourcePool\0") < 0 ||
esxVI_LookupObjectContentByType(ctx, hostSystem->obj,
"ComputeResource", propertyNameList,
esxVI_Boolean_True,
&computeResource) < 0) {
goto cleanup;
}
if (computeResource == NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not retrieve compute resource of host system"));
goto cleanup;
}
if (esxVI_ComputeResource_CastFromObjectContent(computeResource,
&ctx->computeResource) < 0) {
goto cleanup;
}
/* Lookup Datacenter */
esxVI_String_Free(&propertyNameList);
if (esxVI_String_AppendValueListToList(&propertyNameList,
"name\0"
"vmFolder\0"
"hostFolder\0") < 0 ||
esxVI_LookupObjectContentByType(ctx, computeResource->obj,
"Datacenter", propertyNameList,
/* FIXME: Passing Undefined here is a hack until
* esxVI_LookupObjectContentByType supports more
* fine grained traversal configuration. Looking
* up the Datacenter from the ComputeResource
* requiers an upward search. Putting this in the
* list with the other downward traversal rules
* would result in cyclic searching */
esxVI_Boolean_Undefined,
&datacenter) < 0) {
goto cleanup;
}
if (datacenter == NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not retrieve datacenter of compute resource"));
goto cleanup;
}
if (esxVI_Datacenter_CastFromObjectContent(datacenter,
&ctx->datacenter) < 0) {
goto cleanup;
}
result = 0;
cleanup:
esxVI_String_Free(&propertyNameList);
esxVI_ManagedObjectReference_Free(&managedObjectReference);
esxVI_ObjectContent_Free(&hostSystem);
esxVI_ObjectContent_Free(&computeResource);
esxVI_ObjectContent_Free(&datacenter);
return result;
}
......@@ -1219,82 +1470,64 @@ esxVI_BuildFullTraversalSpecList(esxVI_SelectionSpec **fullTraversalSpecList)
return -1;
}
/* Folder -> childEntity (ManagedEntity) */
if (esxVI_BuildFullTraversalSpecItem(fullTraversalSpecList,
"visitFolders",
"folderToChildEntity",
"Folder", "childEntity",
"visitFolders\0"
"datacenterToDatastore\0"
"datacenterToVmFolder\0"
"datacenterToHostFolder\0"
"computeResourceToHost\0"
"computeResourceToResourcePool\0"
"hostSystemToVm\0"
"resourcePoolToVm\0") < 0) {
"folderToChildEntity\0") < 0) {
goto failure;
}
/* Traversal through datastore branch */
/* ComputeResource -> host (HostSystem) */
if (esxVI_BuildFullTraversalSpecItem(fullTraversalSpecList,
"datacenterToDatastore",
"Datacenter", "datastore",
"computeResourceToHost",
"ComputeResource", "host",
NULL) < 0) {
goto failure;
}
/* Traversal through vmFolder branch */
if (esxVI_BuildFullTraversalSpecItem(fullTraversalSpecList,
"datacenterToVmFolder",
"Datacenter", "vmFolder",
"visitFolders\0") < 0) {
goto failure;
}
/* Traversal through hostFolder branch */
/* ComputeResource -> datastore (Datastore) */
if (esxVI_BuildFullTraversalSpecItem(fullTraversalSpecList,
"datacenterToHostFolder",
"Datacenter", "hostFolder",
"visitFolders\0") < 0) {
"computeResourceToDatastore",
"ComputeResource", "datastore",
NULL) < 0) {
goto failure;
}
/* Traversal through host branch */
/* ResourcePool -> resourcePool (ResourcePool) */
if (esxVI_BuildFullTraversalSpecItem(fullTraversalSpecList,
"computeResourceToHost",
"ComputeResource", "host",
NULL) < 0) {
"resourcePoolToResourcePool",
"ResourcePool", "resourcePool",
"resourcePoolToResourcePool\0"
"resourcePoolToVm\0") < 0) {
goto failure;
}
/* Traversal through resourcePool branch */
/* ResourcePool -> vm (VirtualMachine) */
if (esxVI_BuildFullTraversalSpecItem(fullTraversalSpecList,
"computeResourceToResourcePool",
"ComputeResource", "resourcePool",
"resourcePoolToResourcePool\0"
"resourcePoolToVm\0") < 0) {
"resourcePoolToVm",
"ResourcePool", "vm", NULL) < 0) {
goto failure;
}
/* Recurse through all resource pools */
/* HostSystem -> parent (ComputeResource) */
if (esxVI_BuildFullTraversalSpecItem(fullTraversalSpecList,
"resourcePoolToResourcePool",
"ResourcePool", "resourcePool",
"resourcePoolToResourcePool\0"
"resourcePoolToVm\0") < 0) {
"hostSystemToParent",
"HostSystem", "parent", NULL) < 0) {
goto failure;
}
/* Recurse through all hosts */
/* HostSystem -> vm (VirtualMachine) */
if (esxVI_BuildFullTraversalSpecItem(fullTraversalSpecList,
"hostSystemToVm",
"HostSystem", "vm",
"visitFolders\0") < 0) {
"HostSystem", "vm", NULL) < 0) {
goto failure;
}
/* Recurse through all resource pools */
/* HostSystem -> datastore (Datastore) */
if (esxVI_BuildFullTraversalSpecItem(fullTraversalSpecList,
"resourcePoolToVm",
"ResourcePool", "vm", NULL) < 0) {
"hostSystemToDatastore",
"HostSystem", "datastore", NULL) < 0) {
goto failure;
}
......@@ -1422,6 +1655,11 @@ esxVI_LookupObjectContentByType(esxVI_Context *ctx,
return -1;
}
if (objectContentList == NULL || *objectContentList != NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
return -1;
}
if (esxVI_ObjectSpec_Alloc(&objectSpec) < 0) {
return -1;
}
......@@ -1431,6 +1669,8 @@ esxVI_LookupObjectContentByType(esxVI_Context *ctx,
if (recurse == esxVI_Boolean_True) {
objectSpec->selectSet = ctx->fullTraversalSpecList;
} else if (recurse == esxVI_Boolean_Undefined) {
objectSpec->selectSet = ctx->fullTraversalSpecList2;
}
if (esxVI_PropertySpec_Alloc(&propertySpec) < 0) {
......@@ -1669,9 +1909,8 @@ esxVI_LookupNumberOfDomainsByPowerState(esxVI_Context *ctx,
if (esxVI_String_AppendValueToList(&propertyNameList,
"runtime.powerState") < 0 ||
esxVI_LookupObjectContentByType(ctx, ctx->vmFolder, "VirtualMachine",
propertyNameList, esxVI_Boolean_True,
&virtualMachineList) < 0) {
esxVI_LookupVirtualMachineList(ctx, propertyNameList,
&virtualMachineList) < 0) {
goto cleanup;
}
......@@ -1965,125 +2204,28 @@ esxVI_GetSnapshotTreeBySnapshot
int
esxVI_LookupResourcePoolByHostSystem
(esxVI_Context *ctx, esxVI_ObjectContent *hostSystem,
esxVI_ManagedObjectReference **resourcePool)
int esxVI_LookupHostSystemProperties(esxVI_Context *ctx,
esxVI_String *propertyNameList,
esxVI_ObjectContent **hostSystem)
{
int result = -1;
esxVI_String *propertyNameList = NULL;
esxVI_DynamicProperty *dynamicProperty = NULL;
esxVI_ManagedObjectReference *managedObjectReference = NULL;
esxVI_ObjectContent *computeResource = NULL;
if (resourcePool == NULL || *resourcePool != NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
return -1;
}
for (dynamicProperty = hostSystem->propSet; dynamicProperty != NULL;
dynamicProperty = dynamicProperty->_next) {
if (STREQ(dynamicProperty->name, "parent")) {
if (esxVI_ManagedObjectReference_CastFromAnyType
(dynamicProperty->val, &managedObjectReference) < 0) {
goto cleanup;
}
break;
} else {
VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
}
}
if (managedObjectReference == NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not retrieve compute resource of host system"));
goto cleanup;
}
if (esxVI_String_AppendValueToList(&propertyNameList, "resourcePool") < 0 ||
esxVI_LookupObjectContentByType(ctx, managedObjectReference,
"ComputeResource", propertyNameList,
esxVI_Boolean_False,
&computeResource) < 0) {
goto cleanup;
}
if (computeResource == NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not retrieve compute resource of host system"));
goto cleanup;
}
for (dynamicProperty = computeResource->propSet; dynamicProperty != NULL;
dynamicProperty = dynamicProperty->_next) {
if (STREQ(dynamicProperty->name, "resourcePool")) {
if (esxVI_ManagedObjectReference_CastFromAnyType
(dynamicProperty->val, resourcePool) < 0) {
goto cleanup;
}
break;
} else {
VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
}
}
if ((*resourcePool) == NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not retrieve resource pool of compute resource"));
goto cleanup;
}
result = 0;
cleanup:
esxVI_String_Free(&propertyNameList);
esxVI_ManagedObjectReference_Free(&managedObjectReference);
esxVI_ObjectContent_Free(&computeResource);
return result;
return esxVI_LookupObjectContentByType(ctx, ctx->hostSystem->_reference,
"HostSystem", propertyNameList,
esxVI_Boolean_False, hostSystem);
}
int
esxVI_LookupHostSystemByIp(esxVI_Context *ctx, const char *ipAddress,
esxVI_String *propertyNameList,
esxVI_ObjectContent **hostSystem)
esxVI_LookupVirtualMachineList(esxVI_Context *ctx,
esxVI_String *propertyNameList,
esxVI_ObjectContent **virtualMachineList)
{
int result = -1;
esxVI_ManagedObjectReference *managedObjectReference = NULL;
if (hostSystem == NULL || *hostSystem != NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
return -1;
}
if (esxVI_FindByIp(ctx, ctx->datacenter, ipAddress, esxVI_Boolean_False,
&managedObjectReference) < 0) {
return -1;
}
if (managedObjectReference == NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Could not find host system with IP address '%s'"),
ipAddress);
goto cleanup;
}
if (esxVI_LookupObjectContentByType(ctx, managedObjectReference,
"HostSystem", propertyNameList,
esxVI_Boolean_False, hostSystem) < 0) {
goto cleanup;
}
result = 0;
cleanup:
esxVI_ManagedObjectReference_Free(&managedObjectReference);
return result;
/* FIXME: Switch from ctx->hostSystem to ctx->computeResource->resourcePool
* for cluster support */
return esxVI_LookupObjectContentByType(ctx, ctx->hostSystem->_reference,
"VirtualMachine", propertyNameList,
esxVI_Boolean_True,
virtualMachineList);
}
......@@ -2105,8 +2247,8 @@ esxVI_LookupVirtualMachineByUuid(esxVI_Context *ctx, const unsigned char *uuid,
virUUIDFormat(uuid, uuid_string);
if (esxVI_FindByUuid(ctx, ctx->datacenter, uuid_string, esxVI_Boolean_True,
&managedObjectReference) < 0) {
if (esxVI_FindByUuid(ctx, ctx->datacenter->_reference, uuid_string,
esxVI_Boolean_True, &managedObjectReference) < 0) {
return -1;
}
......@@ -2158,10 +2300,8 @@ esxVI_LookupVirtualMachineByName(esxVI_Context *ctx, const char *name,
if (esxVI_String_DeepCopyList(&completePropertyNameList,
propertyNameList) < 0 ||
esxVI_String_AppendValueToList(&completePropertyNameList, "name") < 0 ||
esxVI_LookupObjectContentByType(ctx, ctx->vmFolder, "VirtualMachine",
completePropertyNameList,
esxVI_Boolean_True,
&virtualMachineList) < 0) {
esxVI_LookupVirtualMachineList(ctx, completePropertyNameList,
&virtualMachineList) < 0) {
goto cleanup;
}
......@@ -2259,6 +2399,19 @@ esxVI_LookupVirtualMachineByUuidAndPrepareForTask
int
esxVI_LookupDatastoreList(esxVI_Context *ctx, esxVI_String *propertyNameList,
esxVI_ObjectContent **datastoreList)
{
/* FIXME: Switch from ctx->hostSystem to ctx->computeResource for cluster
* support */
return esxVI_LookupObjectContentByType(ctx, ctx->hostSystem->_reference,
"Datastore", propertyNameList,
esxVI_Boolean_True, datastoreList);
}
int
esxVI_LookupDatastoreByName(esxVI_Context *ctx, const char *name,
esxVI_String *propertyNameList,
......@@ -2285,14 +2438,9 @@ esxVI_LookupDatastoreByName(esxVI_Context *ctx, const char *name,
esxVI_String_AppendValueListToList(&completePropertyNameList,
"summary.accessible\0"
"summary.name\0"
"summary.url\0") < 0) {
goto cleanup;
}
if (esxVI_LookupObjectContentByType(ctx, ctx->datacenter, "Datastore",
completePropertyNameList,
esxVI_Boolean_True,
&datastoreList) < 0) {
"summary.url\0") < 0 ||
esxVI_LookupDatastoreList(ctx, completePropertyNameList,
&datastoreList) < 0) {
goto cleanup;
}
......
......@@ -158,10 +158,11 @@ struct _esxVI_Context {
esxVI_APIVersion apiVersion;
esxVI_ProductVersion productVersion;
esxVI_UserSession *session;
esxVI_ManagedObjectReference *datacenter;
esxVI_ManagedObjectReference *vmFolder;
esxVI_ManagedObjectReference *hostFolder;
esxVI_Datacenter *datacenter;
esxVI_ComputeResource *computeResource;
esxVI_HostSystem *hostSystem;
esxVI_SelectionSpec *fullTraversalSpecList;
esxVI_SelectionSpec *fullTraversalSpecList2;
};
int esxVI_Context_Alloc(esxVI_Context **ctx);
......@@ -169,6 +170,10 @@ void esxVI_Context_Free(esxVI_Context **ctx);
int esxVI_Context_Connect(esxVI_Context *ctx, const char *ipAddress,
const char *url, const char *username,
const char *password, esxUtil_ParsedUri *parsedUri);
int esxVI_Context_LookupObjectsByPath(esxVI_Context *ctx,
esxUtil_ParsedUri *parsedUri);
int esxVI_Context_LookupObjectsByHostSystemIp(esxVI_Context *ctx,
const char *hostSystemIpAddress);
int esxVI_Context_DownloadFile(esxVI_Context *ctx, const char *url,
char **content);
int esxVI_Context_UploadFile(esxVI_Context *ctx, const char *url,
......@@ -327,13 +332,13 @@ int esxVI_GetSnapshotTreeBySnapshot
esxVI_ManagedObjectReference *snapshot,
esxVI_VirtualMachineSnapshotTree **snapshotTree);
int esxVI_LookupResourcePoolByHostSystem
(esxVI_Context *ctx, esxVI_ObjectContent *hostSystem,
esxVI_ManagedObjectReference **resourcePool);
int esxVI_LookupHostSystemProperties(esxVI_Context *ctx,
esxVI_String *propertyNameList,
esxVI_ObjectContent **hostSystem);
int esxVI_LookupHostSystemByIp(esxVI_Context *ctx, const char *ipAddress,
esxVI_String *propertyNameList,
esxVI_ObjectContent **hostSystem);
int esxVI_LookupVirtualMachineList(esxVI_Context *ctx,
esxVI_String *propertyNameList,
esxVI_ObjectContent **virtualMachineList);
int esxVI_LookupVirtualMachineByUuid(esxVI_Context *ctx,
const unsigned char *uuid,
......@@ -351,6 +356,9 @@ int esxVI_LookupVirtualMachineByUuidAndPrepareForTask
esxVI_String *propertyNameList, esxVI_ObjectContent **virtualMachine,
esxVI_Boolean autoAnswer);
int esxVI_LookupDatastoreList(esxVI_Context *ctx, esxVI_String *propertyNameList,
esxVI_ObjectContent **datastoreList);
int esxVI_LookupDatastoreByName(esxVI_Context *ctx, const char *name,
esxVI_String *propertyNameList,
esxVI_ObjectContent **datastore,
......
......@@ -2711,6 +2711,10 @@ esxVMX_FormatConfig(esxVI_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
case esxVI_ProductVersion_ESX40:
case esxVI_ProductVersion_ESX41:
case esxVI_ProductVersion_ESX4x:
/* FIXME: Putting VPX* here is a hack until a more fine grained system is in place */
case esxVI_ProductVersion_VPX40:
case esxVI_ProductVersion_VPX41:
case esxVI_ProductVersion_VPX4x:
virBufferAddLit(&buffer, "virtualHW.version = \"7\"\n");
break;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册