Hi team,
When I tried to retrieve the property of storage.perDatastoreUsage under specify virtual
machine and got a invalidProperty error but other properties(eg. summary.storage, guest)
under the same virtual machine are ok.
Then I write a same program use vsphere web service sdk in java and catch the http
package by wireshark.
By comparing, I found that we lost soapAction field in http request header, it seems to
like this: SOAPAction: "urn:vim25/5.0".
I checked the vsphere development document and found some key description as following:
When a client application connects to a Web service running on an vSphere server (ESX/ESXi
or vCenter Server system), the server detects the version of the API that was used to
develop the client and makes available only those operations supported by the client.
Client applications convey information about the API version used in the SOAP messages
that they send to a vSphere server. These SOAP messages include a versionID in the
soapAction attribute. The details are handled transparently by the SOAP toolkit and the
client proxy code. The server adjusts its behavior based on the client's version
information, exposing the API version that the client supports to the client.
If you are developing a client application that must support multiple server versions at
the same time (ESX/ESXi 5.0 and ESX/ESXi 3.x, for example), you must obtain information
about the API versions that are supported on the server and provide logic in your code to
use or not use features, based upon the version information.
Finally, I added the soapAction field into http request header and got a correct result.
So I added some lines in function esxVI_Context_Connect() at src/esx/esx_vi.c
The code change is bold line as follwing:
int esxVI_Context_Connect(esxVI_Context *ctx, const char *url,
const char *ipAddress, const char *username, const char
*password,
esxUtil_ParsedUri *parsedUri) {
char * soapAction = NULL;
int result = -1;
if (ctx == NULL || url == NULL || ipAddress == NULL || username == NULL
|| password == NULL || ctx->url != NULL ||
ctx->service != NULL
|| ctx->curl != NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Invalid argument"));
return -1;
}
if (esxVI_CURL_Alloc(&ctx->curl) < 0
|| esxVI_CURL_Connect(ctx->curl, parsedUri) < 0
|| esxVI_String_DeepCopyValue(&ctx->url, url)
< 0
|| esxVI_String_DeepCopyValue(&ctx->ipAddress,
ipAddress) < 0
|| esxVI_String_DeepCopyValue(&ctx->username,
username) < 0
|| esxVI_String_DeepCopyValue(&ctx->password,
password) < 0) {
return -1;
}
if (VIR_ALLOC(ctx->sessionLock) < 0) {
virReportOOMError();
return -1;
}
if (virMutexInit(ctx->sessionLock) < 0) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
"%s", _("Could not
initialize session mutex"));
return -1;
}
if (esxVI_RetrieveServiceContent(ctx, &ctx->service) < 0) {
return -1;
}
if (virAsprintf(&soapAction, "SOAPAction:
\"urn:vim25/%s\"",
ctx->service->about->apiVersion) < 0) {
virReportOOMError();
goto cleanup;
}
ctx->curl->headers = curl_slist_append(ctx->curl->headers,
soapAction);
if (STREQ(ctx->service->about->apiType, "HostAgent")
|| STREQ(ctx->service->about->apiType,
"VirtualCenter")) {
if (STRPREFIX(ctx->service->about->apiVersion,
"2.5")) {
ctx->apiVersion = esxVI_APIVersion_25;
} else if (STRPREFIX(ctx->service->about->apiVersion,
"4.0")) {
ctx->apiVersion = esxVI_APIVersion_40;
} else if (STRPREFIX(ctx->service->about->apiVersion,
"4.1")) {
ctx->apiVersion = esxVI_APIVersion_41;
} else if (STRPREFIX(ctx->service->about->apiVersion,
"4.")) {
ctx->apiVersion = esxVI_APIVersion_4x;
VIR_WARN(
"Found untested VI API
major/minor version '%s'", ctx->service->about->apiVersion);
} else if (STRPREFIX(ctx->service->about->apiVersion,
"5.0")) {
ctx->apiVersion = esxVI_APIVersion_50;
} else if (STRPREFIX(ctx->service->about->apiVersion,
"5.1")) {
ctx->apiVersion = esxVI_APIVersion_51;
}else if (STRPREFIX(ctx->service->about->apiVersion, "5.")) {
ctx->apiVersion = esxVI_APIVersion_5x;
VIR_WARN(
"Found untested VI API
major/minor version '%s'", ctx->service->about->apiVersion);
} else {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting VI API
major/minor version '2.5', '4.x' or "
"'5.x' but found
'%s'"), ctx->service->about->apiVersion);
return -1;
}
if (STREQ(ctx->service->about->productLineId,
"gsx")) {
if (STRPREFIX(ctx->service->about->version,
"2.0")) {
ctx->productVersion =
esxVI_ProductVersion_GSX20;
} else {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting
GSX major/minor version '2.0' but "
"found
'%s'"), ctx->service->about->version);
return -1;
}
} else if (STREQ(ctx->service->about->productLineId,
"esx")
||
STREQ(ctx->service->about->productLineId, "embeddedEsx")) {
if (STRPREFIX(ctx->service->about->version,
"3.5")) {
ctx->productVersion =
esxVI_ProductVersion_ESX35;
} else if
(STRPREFIX(ctx->service->about->version, "4.0")) {
ctx->productVersion =
esxVI_ProductVersion_ESX40;
} else if
(STRPREFIX(ctx->service->about->version, "4.1")) {
ctx->productVersion =
esxVI_ProductVersion_ESX41;
} else if
(STRPREFIX(ctx->service->about->version, "4.")) {
ctx->productVersion =
esxVI_ProductVersion_ESX4x;
VIR_WARN(
"Found
untested ESX major/minor version '%s'",
ctx->service->about->version);
} else if
(STRPREFIX(ctx->service->about->version, "5.0")) {
ctx->productVersion =
esxVI_ProductVersion_ESX50;
} else if
(STRPREFIX(ctx->service->about->version, "5.1")) {
ctx->productVersion =
esxVI_ProductVersion_ESX51;
}else if
(STRPREFIX(ctx->service->about->version, "5.")) {
ctx->productVersion =
esxVI_ProductVersion_ESX5x;
VIR_WARN(
"Found
untested ESX major/minor version '%s'",
ctx->service->about->version);
} else {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting
ESX major/minor version '3.5', "
"'4.x' or '5.x' but found '%s'"),
ctx->service->about->version);
return -1;
}
} else if (STREQ(ctx->service->about->productLineId,
"vpx")) {
if (STRPREFIX(ctx->service->about->version,
"2.5")) {
ctx->productVersion =
esxVI_ProductVersion_VPX25;
} else if
(STRPREFIX(ctx->service->about->version, "4.0")) {
ctx->productVersion =
esxVI_ProductVersion_VPX40;
} else if
(STRPREFIX(ctx->service->about->version, "4.1")) {
ctx->productVersion =
esxVI_ProductVersion_VPX41;
} else if
(STRPREFIX(ctx->service->about->version, "4.")) {
ctx->productVersion =
esxVI_ProductVersion_VPX4x;
VIR_WARN(
"Found
untested VPX major/minor version '%s'",
ctx->service->about->version);
} else if
(STRPREFIX(ctx->service->about->version, "5.0")) {
ctx->productVersion =
esxVI_ProductVersion_VPX50;
} else if
(STRPREFIX(ctx->service->about->version, "5.1")) {
ctx->productVersion =
esxVI_ProductVersion_VPX51;
}else if
(STRPREFIX(ctx->service->about->version, "5.")) {
ctx->productVersion =
esxVI_ProductVersion_VPX5x;
VIR_WARN(
"Found
untested VPX major/minor version '%s'",
ctx->service->about->version);
} else {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting
VPX major/minor version '2.5', '4.x' "
"or
'5.x' but found '%s'"), ctx->service->about->version);
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);
return -1;
}
} else {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting VI API type
'HostAgent' or 'VirtualCenter' "
"but found '%s'"),
ctx->service->about->apiType);
return -1;
}
if (ctx->productVersion & esxVI_ProductVersion_ESX) {
/*
* FIXME: Actually this should be detected by really calling
* QueryVirtualDiskUuid and checking if a NotImplemented fault is
* returned. But currently we don't deserialized the details of
a
* possbile fault and therefore we don't know if the fault was
a
* NotImplemented fault or not.
*/
ctx->hasQueryVirtualDiskUuid = true;
}
if (ctx->productVersion & esxVI_ProductVersion_VPX) {
ctx->hasSessionIsActive = true;
}
if (esxVI_Login(ctx, username, password, NULL, &ctx->session) < 0
|| esxVI_BuildSelectSetCollection(ctx) < 0) {
return -1;
}
result = 0;
cleanup: VIR_FREE(soapAction);
return result;
}
int esxVI_Context_LookupManagedObjects(esxVI_Context *ctx) {
/* Lookup Datacenter */
if (esxVI_LookupDatacenter(ctx, NULL, ctx->service->rootFolder, NULL,
&ctx->datacenter,
esxVI_Occurrence_RequiredItem) < 0) {
return -1;
}
ctx->datacenterPath = strdup(ctx->datacenter->name);
if (ctx->datacenterPath == NULL) {
virReportOOMError();
return -1;
}
/* Lookup (Cluster)ComputeResource */
if (esxVI_LookupComputeResource(ctx, NULL, ctx->datacenter->hostFolder,
NULL, &ctx->computeResource,
esxVI_Occurrence_RequiredItem) < 0) {
return -1;
}
if (ctx->computeResource->resourcePool == NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
"%s", _("Could not retrieve
resource pool"));
return -1;
}
ctx->computeResourcePath = strdup(ctx->computeResource->name);
if (ctx->computeResourcePath == NULL) {
virReportOOMError();
return -1;
}
if (STRCASEEQ(ctx->computeResource->_reference->type,
"ClusterComputeResource")) {
ctx->computeResourceType = esxVI_ComputeResourceType_Cluster;
} else {
ctx->computeResourceType = esxVI_ComputeResourceType_Basic;
}
/* Lookup HostSystem */
if (esxVI_LookupHostSystem(ctx, NULL, ctx->computeResource->_reference,
NULL, &ctx->hostSystem,
esxVI_Occurrence_RequiredItem) < 0) {
return -1;
}
ctx->hostSystemName = strdup(ctx->hostSystem->name);
if (ctx->hostSystemName == NULL) {
virReportOOMError();
return -1;
}
return 0;
}
int esxVI_Context_LookupHostManagedObjects(esxVI_Context *ctx,
virHostNameList *hostNameListPtr) {
int result = -1;
esxVI_Datacenter *datacenters = NULL;
esxVI_Datacenter *candidateDatacenter = NULL;
esxVI_ComputeResource *computeResources = NULL;
esxVI_ComputeResource *candidateComputeResource = NULL;
esxVI_HostSystem *hostSystems = NULL;
esxVI_HostSystem *candidateHostSystem = NULL;
esxVI_HostContext *current = NULL;
virHostNameEntry *hostNameEntry = NULL;
char *hostName = NULL;
/* create hash table for host contexts*/
ctx->hostCtxs = virHashCreate(500, esxVI_HostContext_HashDataFree);
/* list Datacenter */
if (esxVI_ListDatacenter(ctx, NULL, ctx->service->rootFolder, NULL,
&datacenters, esxVI_Occurrence_OptionalList) <
0) {
goto cleanup;
}
for (candidateDatacenter = datacenters; NULL != candidateDatacenter;
candidateDatacenter = candidateDatacenter->_next)
{
/* list (Cluster)ComputeResource */
if (esxVI_ListComputeResource(ctx, NULL,
candidateDatacenter->hostFolder, NULL,
&computeResources,
esxVI_Occurrence_OptionalList) < 0) {
goto cleanup;
}
for (candidateComputeResource = computeResources;
NULL != candidateComputeResource;
candidateComputeResource =
candidateComputeResource->_next) {
/* list HostSystem */
if (esxVI_ListHostSystem(ctx, NULL,
candidateComputeResource->_reference, NULL, &hostSystems,
esxVI_Occurrence_OptionalList)
< 0) {
goto cleanup;
}
for (candidateHostSystem = hostSystems; NULL !=
candidateHostSystem;
) {
/* Allocate a HostContext entry */
if (esxVI_HostContext_Alloc(¤t)
< 0
||
esxVI_Datacenter_Alloc(¤t->datacenter) < 0
||
esxVI_ComputeResource_Alloc(
¤t->computeResource) < 0) {
goto cleanup;
}
/* Fill the HostContext entry */
esxVI_ManagedObjectReference_DeepCopy(
¤t->datacenter->_reference,
candidateDatacenter->_reference);
esxVI_ManagedObjectReference_DeepCopy(
¤t->datacenter->hostFolder,
candidateDatacenter->hostFolder);
esxVI_ManagedObjectReference_DeepCopy(
¤t->datacenter->vmFolder,
candidateDatacenter->vmFolder);
current->datacenter->name =
strdup(candidateDatacenter->name);
current->datacenterPath =
strdup(candidateDatacenter->name);
esxVI_ManagedObjectReference_DeepCopy(
¤t->computeResource->_reference,
candidateComputeResource->_reference);
esxVI_ManagedObjectReference_DeepCopy(
¤t->computeResource->host,
candidateComputeResource->host);
esxVI_ManagedObjectReference_DeepCopy(
¤t->computeResource->resourcePool,
candidateComputeResource->resourcePool);
current->computeResource->name =
strdup(
candidateComputeResource->name);
current->computeResourcePath = strdup(
candidateComputeResource->name);
if
(STRCASEEQ(candidateComputeResource->_reference->type,
"ClusterComputeResource")) {
current->computeResourceType =
esxVI_ComputeResourceType_Cluster;
} else {
current->computeResourceType =
esxVI_ComputeResourceType_Basic;
}
current->hostSystem =
candidateHostSystem;
candidateHostSystem =
candidateHostSystem->_next;
current->hostSystem->_next = NULL;
current->hostSystemName =
strdup(current->hostSystem->name);
hostName =
strdup(current->hostSystem->name);
current->maxVcpus = -1;
current->supportsVMotion =
esxVI_Boolean_Undefined;
current->supportsLongMode =
esxVI_Boolean_Undefined;
current->usedCpuTimeCounterId = -1;
/* update hash table */
if (virHashAddEntry(ctx->hostCtxs,
hostName, current) < 0) {
goto cleanup;
}
current = NULL;
if (NULL != hostNameListPtr) {
/* fill the hostNameList */
if (VIR_ALLOC(hostNameEntry)
< 0) {
virReportOOMError();
goto cleanup;
}
hostNameEntry->hostName =
strdup(hostName);
hostNameEntry->next =
*hostNameListPtr;
*hostNameListPtr =
hostNameEntry;
hostNameEntry = NULL;
}
free(hostName);
}
hostSystems = NULL;
}
esxVI_ComputeResource_Free(&computeResources);
}
result = 0;
cleanup: esxVI_Datacenter_Free(&datacenters);
esxVI_ComputeResource_Free(&computeResources);
return result;
}
Regards,
Dennis