[libvirt] [PATCH 00/13] esx: Automatic question handling and other improvements

Automatic question handling is the most important part of this series, see src/esx/README for more details. Matthias Bolte (13): esx: Add automatic question handling esx: Improve domain lookup by UUID esx: Use more suitable error code in esxVI_LookupVirtualMachineByUuid() esx: Replace libxml1 'xmlChildrenNode' with libxml2 'children' esx: Removed unused inttypes.h include esx: Extend vCenter query parameter esx: Extend documentation about 'vcenter' and add some about 'auto_answer' esx: Fix occurence typo esx: Use occurrence enum to specify expected result of a SOAP call esx: Don't warn about '/' paths esx: Undefine virtual machine on a vCenter if available esx: Destroy virtual machine on a vCenter if available esx: Add more links to external documentation docs/drvesx.html.in | 52 ++++- src/esx/README | 77 +++++++ src/esx/esx_driver.c | 533 +++++++++++++++++++++++--------------------- src/esx/esx_util.c | 22 ++- src/esx/esx_util.h | 2 +- src/esx/esx_vi.c | 546 ++++++++++++++++++++++++++++++++++++++++------ src/esx/esx_vi.h | 53 ++++- src/esx/esx_vi_methods.c | 185 ++++++++++++---- src/esx/esx_vi_methods.h | 7 + src/esx/esx_vi_types.c | 231 +++++++++++++++++++- src/esx/esx_vi_types.h | 106 +++++++++ src/esx/esx_vmx.c | 2 +- 12 files changed, 1420 insertions(+), 396 deletions(-) create mode 100644 src/esx/README

Questions can block tasks, to handle them automatically the driver can answers them with the default answer. The auto_answer query parameter allows to enable this automatic question handling. * src/esx/README: add a detailed explanation for automatic question handling * src/esx/esx_driver.c: add automatic question handling for all task related driver functions * src/esx/esx_util.[ch]: add handling for the auto_answer query parameter * src/esx/esx_vi.[ch], src/esx/esx_vi_methods.[ch], src/esx/esx_vi_types.[ch]: add new VI API methods and types and additional helper functions for automatic question handling --- src/esx/README | 75 +++++++++ src/esx/esx_driver.c | 107 +++++++------- src/esx/esx_util.c | 22 +++- src/esx/esx_util.h | 2 +- src/esx/esx_vi.c | 374 +++++++++++++++++++++++++++++++++++++++++++++- src/esx/esx_vi.h | 31 ++++ src/esx/esx_vi_methods.c | 111 ++++++++++++++ src/esx/esx_vi_methods.h | 7 + src/esx/esx_vi_types.c | 218 +++++++++++++++++++++++++++ src/esx/esx_vi_types.h | 106 +++++++++++++ 10 files changed, 997 insertions(+), 56 deletions(-) create mode 100644 src/esx/README diff --git a/src/esx/README b/src/esx/README new file mode 100644 index 0000000..3619054 --- /dev/null +++ b/src/esx/README @@ -0,0 +1,75 @@ + +Some links to relevant documentation +==================================== + + +VI API reference: http://www.vmware.com/support/developer/vc-sdk/visdk25pubs/ReferenceGuide/ +VMX config: http://www.sanbarrow.com/vmx.html +CPUID: http://www.sandpile.org/ia32/cpuid.htm +Memory model: http://www.vmware.com/pdf/esx3_memory.pdf + + + + +Automatic question handling +=========================== + + +What is a question in the ESX context? +-------------------------------------- + +The VI API contains calls that start tasks, for example PowerOnVM_Task(). Such +tasks may be blocked by a question if the ESX host detects an issue with the +virtual machine that requires user interaction. + +An example: If a virtual machine has a serial port that is realized via a file, +the ESX host will ask a question on power-on of this virtual machine whether +new content should be appended to this file or the file should be replaced. +Until this question is answered the power-on task is blocked and the virtual +machine won't get powered on. + +The ESX driver cannot prompt the user to answer a question, libvirt doesn't +have an API for something like this. The VI API provides a AnswerVM() method to +programmatically answer such questions. A question comes together with a list +of possible answers. One of this answers is marked as the default one. For all +questions I've seen so far the default answer is always a non-destructive one. + +There are two options how to handle a question that is blocking a task: either +answer it automatically or report it as error and try to cancel the blocked +task. + +The auto_answer query parameter defines how the driver should handle questions. +Possible values are 0 for the report-error-and-try-to-cancel option and 1 for +the automatic-answer option. + + +How is automatic question handling implemented? +----------------------------------------------- + +Before any new task is started the driver checks if there is a pending task +blocked by a question. If automatic question handling is disabled the driver +reports an error that includes the question and returns from the driver +function. If automatic question handling is enabled the driver answers the +question with the default answer and returns from the driver function. + +In both cases the actual desired task is not started. If the question was not +answered the blocked task is still blocked and because task can't be executed +in parallel in general it's of no use to start yet another task. If the +question was answered the blocked task may already perform the desired action +and one must wait for its completion, so it's of no use to start yet another +task. + +If there is no question blocking a task or another pending task that had not +finished yet the driver starts the desired task and waits for its completion. +While polling for status updates of the task it also checks for question that +may have been triggered by the current task and handles them according to the +value of the auto_answer query parameter. If automatic question handling is +enabled the driver answers the question with the default answer and continues +polling for status updates. If automatic question handling is disabled the +driver reports an error that includes the question, tries to cancel the blocked +task and returns from the driver function. + +It tries to cancel the blocked task, but this may not be possible, because +there are task like the power-on task that is marked as non-cancelable. So the +driver may leave blocked tasks behind if automatic question handling is +disabled. diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index ea464a3..45da694 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -21,15 +21,6 @@ * */ -/* - * Some links to relevant documentation: - * - * - Memory model: http://www.vmware.com/pdf/esx3_memory.pdf - * - VI API reference: http://www.vmware.com/support/developer/vc-sdk/visdk25pubs/ReferenceGuide/ - * - VMX-file parameters: http://www.sanbarrow.com/vmx.html - * - CPUID: http://www.sandpile.org/ia32/cpuid.htm - */ - #include <config.h> #include <netdb.h> @@ -63,6 +54,7 @@ typedef struct _esxPrivate { int32_t maxVcpus; esxVI_Boolean supportsVMotion; esxVI_Boolean supportsLongMode; /* aka x86_64 */ + esxVI_Boolean autoAnswer; int32_t usedCpuTimeCounterId; } esxPrivate; @@ -242,7 +234,7 @@ esxCapsInit(virConnectPtr conn) /* - * URI format: {esx|gsx}://[<user>@]<server>[:<port>][?transport={http|https}][&vcenter=<vcenter>][&no_verify={0|1}] + * URI format: {esx|gsx}://[<user>@]<server>[:<port>][?transport={http|https}][&vcenter=<vcenter>][&no_verify={0|1}][&auto_answer={0|1}] * * If no port is specified the default port is set dependent on the scheme and * transport parameter: @@ -258,6 +250,10 @@ esxCapsInit(virConnectPtr conn) * * If the no_verify parameter is set to 1, this disables libcurl client checks * of the server's certificate. The default value it 0. + * + * If the auto_answer parameter is set to 1, the driver will respond to all + * virtual machine questions with the default answer, otherwise virtual machine + * questions will be reported as errors. The default value it 0. */ static virDrvOpenStatus esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) @@ -268,6 +264,7 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) char *url = NULL; char *vCenter = NULL; int noVerify = 0; // boolean + int autoAnswer = 0; // boolean char *username = NULL; char *password = NULL; @@ -296,13 +293,19 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) priv->maxVcpus = -1; priv->supportsVMotion = esxVI_Boolean_Undefined; priv->supportsLongMode = esxVI_Boolean_Undefined; + priv->autoAnswer = esxVI_Boolean_False; priv->usedCpuTimeCounterId = -1; - /* Request credentials and login to host/vCenter */ - if (esxUtil_ParseQuery(conn, &priv->transport, &vCenter, &noVerify) < 0) { + if (esxUtil_ParseQuery(conn, &priv->transport, &vCenter, &noVerify, + &autoAnswer) < 0) { goto failure; } + if (autoAnswer) { + priv->autoAnswer = esxVI_Boolean_True; + } + + /* Request credentials and login to host/vCenter */ if (esxUtil_ResolveHostname(conn, conn->uri->server, hostIpAddress, NI_MAXHOST) < 0) { goto failure; @@ -1360,10 +1363,9 @@ esxDomainSuspend(virDomainPtr domain) if (esxVI_String_AppendValueToList(domain->conn, &propertyNameList, "runtime.powerState") < 0 || - esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host, - domain->uuid, propertyNameList, - &virtualMachine, - esxVI_Occurence_RequiredItem) < 0 || + esxVI_LookupVirtualMachineByUuidAndPrepareForTask + (domain->conn, priv->host, domain->uuid, propertyNameList, + &virtualMachine, priv->autoAnswer) < 0 || esxVI_GetVirtualMachinePowerState(domain->conn, virtualMachine, &powerState) < 0) { goto failure; @@ -1378,6 +1380,7 @@ esxDomainSuspend(virDomainPtr domain) if (esxVI_SuspendVM_Task(domain->conn, priv->host, virtualMachine->obj, &task) < 0 || esxVI_WaitForTaskCompletion(domain->conn, priv->host, task, + domain->uuid, priv->autoAnswer, &taskInfoState) < 0) { goto failure; } @@ -1420,10 +1423,9 @@ esxDomainResume(virDomainPtr domain) if (esxVI_String_AppendValueToList(domain->conn, &propertyNameList, "runtime.powerState") < 0 || - esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host, - domain->uuid, propertyNameList, - &virtualMachine, - esxVI_Occurence_RequiredItem) < 0 || + esxVI_LookupVirtualMachineByUuidAndPrepareForTask + (domain->conn, priv->host, domain->uuid, propertyNameList, + &virtualMachine, priv->autoAnswer) < 0 || esxVI_GetVirtualMachinePowerState(domain->conn, virtualMachine, &powerState) < 0) { goto failure; @@ -1438,6 +1440,7 @@ esxDomainResume(virDomainPtr domain) if (esxVI_PowerOnVM_Task(domain->conn, priv->host, virtualMachine->obj, &task) < 0 || esxVI_WaitForTaskCompletion(domain->conn, priv->host, task, + domain->uuid, priv->autoAnswer, &taskInfoState) < 0) { goto failure; } @@ -1577,10 +1580,9 @@ esxDomainDestroy(virDomainPtr domain) if (esxVI_String_AppendValueToList(domain->conn, &propertyNameList, "runtime.powerState") < 0 || - esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host, - domain->uuid, propertyNameList, - &virtualMachine, - esxVI_Occurence_RequiredItem) < 0 || + esxVI_LookupVirtualMachineByUuidAndPrepareForTask + (domain->conn, priv->host, domain->uuid, propertyNameList, + &virtualMachine, priv->autoAnswer) < 0 || esxVI_GetVirtualMachinePowerState(domain->conn, virtualMachine, &powerState) < 0) { goto failure; @@ -1595,6 +1597,7 @@ esxDomainDestroy(virDomainPtr domain) if (esxVI_PowerOffVM_Task(domain->conn, priv->host, virtualMachine->obj, &task) < 0 || esxVI_WaitForTaskCompletion(domain->conn, priv->host, task, + domain->uuid, priv->autoAnswer, &taskInfoState) < 0) { goto failure; } @@ -1707,10 +1710,9 @@ esxDomainSetMaxMemory(virDomainPtr domain, unsigned long memory) goto failure; } - if (esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host, - domain->uuid, NULL, - &virtualMachine, - esxVI_Occurence_RequiredItem) < 0 || + if (esxVI_LookupVirtualMachineByUuidAndPrepareForTask + (domain->conn, priv->host, domain->uuid, NULL, &virtualMachine, + priv->autoAnswer) < 0 || esxVI_VirtualMachineConfigSpec_Alloc(domain->conn, &spec) < 0 || esxVI_Long_Alloc(domain->conn, &spec->memoryMB) < 0) { goto failure; @@ -1722,6 +1724,7 @@ esxDomainSetMaxMemory(virDomainPtr domain, unsigned long memory) if (esxVI_ReconfigVM_Task(domain->conn, priv->host, virtualMachine->obj, spec, &task) < 0 || esxVI_WaitForTaskCompletion(domain->conn, priv->host, task, + domain->uuid, priv->autoAnswer, &taskInfoState) < 0) { goto failure; } @@ -1761,10 +1764,9 @@ esxDomainSetMemory(virDomainPtr domain, unsigned long memory) goto failure; } - if (esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host, - domain->uuid, NULL, - &virtualMachine, - esxVI_Occurence_RequiredItem) < 0 || + if (esxVI_LookupVirtualMachineByUuidAndPrepareForTask + (domain->conn, priv->host, domain->uuid, NULL, &virtualMachine, + priv->autoAnswer) < 0 || esxVI_VirtualMachineConfigSpec_Alloc(domain->conn, &spec) < 0 || esxVI_ResourceAllocationInfo_Alloc(domain->conn, &spec->memoryAllocation) < 0 || @@ -1778,6 +1780,7 @@ esxDomainSetMemory(virDomainPtr domain, unsigned long memory) if (esxVI_ReconfigVM_Task(domain->conn, priv->host, virtualMachine->obj, spec, &task) < 0 || esxVI_WaitForTaskCompletion(domain->conn, priv->host, task, + domain->uuid, priv->autoAnswer, &taskInfoState) < 0) { goto failure; } @@ -2100,10 +2103,9 @@ esxDomainSetVcpus(virDomainPtr domain, unsigned int nvcpus) goto failure; } - if (esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host, - domain->uuid, NULL, - &virtualMachine, - esxVI_Occurence_RequiredItem) < 0 || + if (esxVI_LookupVirtualMachineByUuidAndPrepareForTask + (domain->conn, priv->host, domain->uuid, NULL, &virtualMachine, + priv->autoAnswer) < 0 || esxVI_VirtualMachineConfigSpec_Alloc(domain->conn, &spec) < 0 || esxVI_Int_Alloc(domain->conn, &spec->numCPUs) < 0) { goto failure; @@ -2114,6 +2116,7 @@ esxDomainSetVcpus(virDomainPtr domain, unsigned int nvcpus) if (esxVI_ReconfigVM_Task(domain->conn, priv->host, virtualMachine->obj, spec, &task) < 0 || esxVI_WaitForTaskCompletion(domain->conn, priv->host, task, + domain->uuid, priv->autoAnswer, &taskInfoState) < 0) { goto failure; } @@ -2483,10 +2486,9 @@ esxDomainCreate(virDomainPtr domain) if (esxVI_String_AppendValueToList(domain->conn, &propertyNameList, "runtime.powerState") < 0 || - esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host, - domain->uuid, propertyNameList, - &virtualMachine, - esxVI_Occurence_RequiredItem) < 0 || + esxVI_LookupVirtualMachineByUuidAndPrepareForTask + (domain->conn, priv->host, domain->uuid, propertyNameList, + &virtualMachine, priv->autoAnswer) < 0 || esxVI_GetVirtualMachinePowerState(domain->conn, virtualMachine, &powerState) < 0) { goto failure; @@ -2501,6 +2503,7 @@ esxDomainCreate(virDomainPtr domain) if (esxVI_PowerOnVM_Task(domain->conn, priv->host, virtualMachine->obj, &task) < 0 || esxVI_WaitForTaskCompletion(domain->conn, priv->host, task, + domain->uuid, priv->autoAnswer, &taskInfoState) < 0) { goto failure; } @@ -2690,6 +2693,7 @@ esxDomainDefineXML(virConnectPtr conn, const char *xml ATTRIBUTE_UNUSED) datastoreRelatedPath, NULL, esxVI_Boolean_False, resourcePool, hostSystem->obj, &task) < 0 || esxVI_WaitForTaskCompletion(conn, priv->host, task, + def->uuid, priv->autoAnswer, &taskInfoState) < 0) { goto failure; } @@ -2977,10 +2981,9 @@ esxDomainSetSchedulerParameters(virDomainPtr domain, goto failure; } - if (esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host, - domain->uuid, NULL, - &virtualMachine, - esxVI_Occurence_RequiredItem) < 0 || + if (esxVI_LookupVirtualMachineByUuidAndPrepareForTask + (domain->conn, priv->host, domain->uuid, NULL, &virtualMachine, + priv->autoAnswer) < 0 || esxVI_VirtualMachineConfigSpec_Alloc(domain->conn, &spec) < 0 || esxVI_ResourceAllocationInfo_Alloc(domain->conn, &spec->cpuAllocation) < 0) { @@ -3068,6 +3071,7 @@ esxDomainSetSchedulerParameters(virDomainPtr domain, if (esxVI_ReconfigVM_Task(domain->conn, priv->host, virtualMachine->obj, spec, &task) < 0 || esxVI_WaitForTaskCompletion(domain->conn, priv->host, task, + domain->uuid, priv->autoAnswer, &taskInfoState) < 0) { goto failure; } @@ -3106,7 +3110,7 @@ esxDomainMigratePrepare(virConnectPtr dconn, char *transport = NULL; if (uri_in == NULL) { - if (esxUtil_ParseQuery(dconn, &transport, NULL, NULL) < 0) { + if (esxUtil_ParseQuery(dconn, &transport, NULL, NULL, NULL) < 0) { return -1; } @@ -3181,14 +3185,10 @@ esxDomainMigratePerform(virDomainPtr domain, } /* Lookup VirtualMachine, HostSystem and ResourcePool */ - if (esxVI_LookupVirtualMachineByUuid(domain->conn, priv->vCenter, - domain->uuid, NULL, - &virtualMachine, - esxVI_Occurence_RequiredItem) < 0) { - goto failure; - } - - if (esxVI_String_AppendValueToList(domain->conn, &propertyNameList, + if (esxVI_LookupVirtualMachineByUuidAndPrepareForTask + (domain->conn, priv->vCenter, domain->uuid, NULL, &virtualMachine, + priv->autoAnswer) < 0 || + esxVI_String_AppendValueToList(domain->conn, &propertyNameList, "parent") < 0 || esxVI_LookupHostSystemByIp(domain->conn, priv->vCenter, hostIpAddress, propertyNameList, &hostSystem) < 0) { @@ -3231,6 +3231,7 @@ esxDomainMigratePerform(virDomainPtr domain, if (esxVI_MigrateVM_Task(domain->conn, priv->vCenter, virtualMachine->obj, resourcePool, hostSystem->obj, &task) < 0 || esxVI_WaitForTaskCompletion(domain->conn, priv->vCenter, task, + domain->uuid, priv->autoAnswer, &taskInfoState) < 0) { goto failure; } diff --git a/src/esx/esx_util.c b/src/esx/esx_util.c index 3e53921..33babce 100644 --- a/src/esx/esx_util.c +++ b/src/esx/esx_util.c @@ -133,7 +133,7 @@ esxUtil_RequestPassword(virConnectAuthPtr auth, const char *username, int esxUtil_ParseQuery(virConnectPtr conn, char **transport, char **vCenter, - int *noVerify) + int *noVerify, int *autoAnswer) { int result = 0; int i; @@ -148,6 +148,14 @@ esxUtil_ParseQuery(virConnectPtr conn, char **transport, char **vCenter, *vCenter = NULL; } + if (noVerify != NULL) { + *noVerify = 0; + } + + if (autoAnswer != NULL) { + *autoAnswer = 0; + } + #ifdef HAVE_XMLURI_QUERY_RAW queryParamSet = qparam_query_parse(conn->uri->query_raw); #else @@ -202,6 +210,18 @@ esxUtil_ParseQuery(virConnectPtr conn, char **transport, char **vCenter, "'%s' (should be 0 or 1)", queryParam->value); goto failure; } + } else if (STRCASEEQ(queryParam->name, "auto_answer")) { + if (autoAnswer == NULL) { + continue; + } + + if (virStrToLong_i(queryParam->value, NULL, 10, autoAnswer) < 0 || + (*autoAnswer != 0 && *autoAnswer != 1)) { + ESX_ERROR(conn, VIR_ERR_INVALID_ARG, + "Query parameter 'auto_answer' has unexpected value " + "'%s' (should be 0 or 1)", queryParam->value); + goto failure; + } } else { VIR_WARN("Ignoring unexpected query parameter '%s'", queryParam->name); diff --git a/src/esx/esx_util.h b/src/esx/esx_util.h index c466b44..3987f3e 100644 --- a/src/esx/esx_util.h +++ b/src/esx/esx_util.h @@ -36,7 +36,7 @@ char *esxUtil_RequestPassword(virConnectAuthPtr auth, const char *username, const char *hostname); int esxUtil_ParseQuery(virConnectPtr conn, char **transport, char **vCenter, - int *noVerify); + int *noVerify, int *autoAnswer); int esxUtil_ParseVirtualMachineIDString(const char *id_string, int *id); diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c index 5725b2f..e934bd4 100644 --- a/src/esx/esx_vi.c +++ b/src/esx/esx_vi.c @@ -982,7 +982,6 @@ esxVI_List_CastFromAnyType(virConnectPtr conn, esxVI_AnyType *anyType, goto cleanup; } - int esxVI_List_Serialize(virConnectPtr conn, esxVI_List *list, const char *element, virBufferPtr output, esxVI_Boolean required, @@ -1076,6 +1075,8 @@ esxVI_Alloc(virConnectPtr conn, void **ptrptr, size_t size) return 0; } + + int esxVI_CheckSerializationNecessity(virConnectPtr conn, const char *element, esxVI_Boolean required) @@ -1479,6 +1480,33 @@ esxVI_GetVirtualMachinePowerState(virConnectPtr conn, int +esxVI_GetVirtualMachineQuestionInfo + (virConnectPtr conn, esxVI_ObjectContent *virtualMachine, + esxVI_VirtualMachineQuestionInfo **questionInfo) +{ + esxVI_DynamicProperty *dynamicProperty; + + if (questionInfo == NULL || *questionInfo != NULL) { + ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument"); + return -1; + } + + for (dynamicProperty = virtualMachine->propSet; dynamicProperty != NULL; + dynamicProperty = dynamicProperty->_next) { + if (STREQ(dynamicProperty->name, "runtime.question")) { + if (esxVI_VirtualMachineQuestionInfo_CastFromAnyType + (conn, dynamicProperty->val, questionInfo) < 0) { + return -1; + } + } + } + + return 0; +} + + + +int esxVI_LookupNumberOfDomainsByPowerState(virConnectPtr conn, esxVI_Context *ctx, esxVI_VirtualMachinePowerState powerState, esxVI_Boolean inverse) @@ -1827,6 +1855,60 @@ esxVI_LookupVirtualMachineByUuid(virConnectPtr conn, esxVI_Context *ctx, int +esxVI_LookupVirtualMachineByUuidAndPrepareForTask + (virConnectPtr conn, esxVI_Context *ctx, const unsigned char *uuid, + esxVI_String *propertyNameList, esxVI_ObjectContent **virtualMachine, + esxVI_Boolean autoAnswer) +{ + int result = 0; + esxVI_String *completePropertyNameList = NULL; + esxVI_VirtualMachineQuestionInfo *questionInfo = NULL; + esxVI_TaskInfo *pendingTaskInfoList = NULL; + + if (esxVI_String_DeepCopyList(conn, &completePropertyNameList, + propertyNameList) < 0 || + esxVI_String_AppendValueListToList(conn, &completePropertyNameList, + "runtime.question\0" + "recentTask\0") < 0 || + esxVI_LookupVirtualMachineByUuid(conn, ctx, uuid, + completePropertyNameList, + virtualMachine, + esxVI_Occurence_RequiredItem) < 0 || + esxVI_GetVirtualMachineQuestionInfo(conn, *virtualMachine, + &questionInfo) < 0 || + esxVI_LookupPendingTaskInfoListByVirtualMachine + (conn, ctx, *virtualMachine, &pendingTaskInfoList) < 0) { + goto failure; + } + + if (questionInfo != NULL && + esxVI_HandleVirtualMachineQuestion(conn, ctx, (*virtualMachine)->obj, + questionInfo, autoAnswer) < 0) { + goto failure; + } + + if (pendingTaskInfoList != NULL) { + ESX_VI_ERROR(conn, VIR_ERR_OPERATION_INVALID, + "Other tasks are pending for this domain"); + goto failure; + } + + cleanup: + esxVI_String_Free(&completePropertyNameList); + esxVI_VirtualMachineQuestionInfo_Free(&questionInfo); + esxVI_TaskInfo_Free(&pendingTaskInfoList); + + return result; + + failure: + result = -1; + + goto cleanup; +} + + + +int esxVI_LookupDatastoreByName(virConnectPtr conn, esxVI_Context *ctx, const char *name, esxVI_String *propertyNameList, esxVI_ObjectContent **datastore, @@ -1986,6 +2068,164 @@ esxVI_LookupDatastoreByName(virConnectPtr conn, esxVI_Context *ctx, +int esxVI_LookupTaskInfoByTask(virConnectPtr conn, esxVI_Context *ctx, + esxVI_ManagedObjectReference *task, + esxVI_TaskInfo **taskInfo) +{ + int result = 0; + esxVI_String *propertyNameList = NULL; + esxVI_ObjectContent *objectContent = NULL; + esxVI_DynamicProperty *dynamicProperty = NULL; + + if (taskInfo == NULL || *taskInfo != NULL) { + ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument"); + return -1; + } + + if (esxVI_String_AppendValueToList(conn, &propertyNameList, "info") < 0 || + esxVI_LookupObjectContentByType(conn, ctx, task, "Task", + propertyNameList, esxVI_Boolean_False, + &objectContent) < 0) { + goto failure; + } + + for (dynamicProperty = objectContent->propSet; dynamicProperty != NULL; + dynamicProperty = dynamicProperty->_next) { + if (STREQ(dynamicProperty->name, "info")) { + if (esxVI_TaskInfo_CastFromAnyType(conn, dynamicProperty->val, + taskInfo) < 0) { + goto failure; + } + + break; + } else { + VIR_WARN("Unexpected '%s' property", dynamicProperty->name); + } + } + + cleanup: + esxVI_String_Free(&propertyNameList); + esxVI_ObjectContent_Free(&objectContent); + + return result; + + failure: + result = -1; + + goto cleanup; +} + + + +int +esxVI_LookupPendingTaskInfoListByVirtualMachine + (virConnectPtr conn, esxVI_Context *ctx, esxVI_ObjectContent *virtualMachine, + esxVI_TaskInfo **pendingTaskInfoList) +{ + int result = 0; + esxVI_String *propertyNameList = NULL; + esxVI_ManagedObjectReference *recentTaskList = NULL; + esxVI_ManagedObjectReference *recentTask = NULL; + esxVI_DynamicProperty *dynamicProperty = NULL; + esxVI_TaskInfo *taskInfo = NULL; + + if (pendingTaskInfoList == NULL || *pendingTaskInfoList != NULL) { + ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument"); + return -1; + } + + /* Get list of recent tasks */ + for (dynamicProperty = virtualMachine->propSet; dynamicProperty != NULL; + dynamicProperty = dynamicProperty->_next) { + if (STREQ(dynamicProperty->name, "recentTask")) { + if (esxVI_ManagedObjectReference_CastListFromAnyType + (conn, dynamicProperty->val, &recentTaskList, "Task") < 0) { + goto failure; + } + + break; + } + } + + /* Lookup task info for each task */ + for (recentTask = recentTaskList; recentTask != NULL; + recentTask = recentTask->_next) { + if (esxVI_LookupTaskInfoByTask(conn, ctx, recentTask, &taskInfo) < 0) { + goto failure; + } + + if (taskInfo->state == esxVI_TaskInfoState_Queued || + taskInfo->state == esxVI_TaskInfoState_Running) { + if (esxVI_TaskInfo_AppendToList(conn, pendingTaskInfoList, + taskInfo) < 0) { + goto failure; + } + + taskInfo = NULL; + } else { + esxVI_TaskInfo_Free(&taskInfo); + } + } + + cleanup: + esxVI_String_Free(&propertyNameList); + esxVI_ManagedObjectReference_Free(&recentTaskList); + esxVI_TaskInfo_Free(&taskInfo); + + return result; + + failure: + esxVI_TaskInfo_Free(pendingTaskInfoList); + + result = -1; + + goto cleanup; +} + + + +int +esxVI_LookupAndHandleVirtualMachineQuestion(virConnectPtr conn, + esxVI_Context *ctx, + const unsigned char *uuid, + esxVI_Boolean autoAnswer) +{ + int result = 0; + esxVI_ObjectContent *virtualMachine = NULL; + esxVI_String *propertyNameList = NULL; + esxVI_VirtualMachineQuestionInfo *questionInfo = NULL; + + if (esxVI_String_AppendValueToList(conn, &propertyNameList, + "runtime.question") < 0 || + esxVI_LookupVirtualMachineByUuid(conn, ctx, uuid, propertyNameList, + &virtualMachine, + esxVI_Occurence_RequiredItem) < 0 || + esxVI_GetVirtualMachineQuestionInfo(conn, virtualMachine, + &questionInfo) < 0) { + goto failure; + } + + if (questionInfo != NULL && + esxVI_HandleVirtualMachineQuestion(conn, ctx, virtualMachine->obj, + questionInfo, autoAnswer) < 0) { + goto failure; + } + + cleanup: + esxVI_ObjectContent_Free(&virtualMachine); + esxVI_String_Free(&propertyNameList); + esxVI_VirtualMachineQuestionInfo_Free(&questionInfo); + + return result; + + failure: + result = -1; + + goto cleanup; +} + + + int esxVI_StartVirtualMachineTask(virConnectPtr conn, esxVI_Context *ctx, const char *name, const char *request, @@ -2134,8 +2374,109 @@ esxVI_SimpleVirtualMachineMethod(virConnectPtr conn, esxVI_Context *ctx, int +esxVI_HandleVirtualMachineQuestion + (virConnectPtr conn, esxVI_Context *ctx, + esxVI_ManagedObjectReference *virtualMachine, + esxVI_VirtualMachineQuestionInfo *questionInfo, + esxVI_Boolean autoAnswer) +{ + int result = 0; + esxVI_ElementDescription *elementDescription = NULL; + virBuffer buffer = VIR_BUFFER_INITIALIZER; + esxVI_ElementDescription *answerChoice = NULL; + int answerIndex = 0; + char *possibleAnswers = NULL; + + if (questionInfo->choice->choiceInfo != NULL) { + for (elementDescription = questionInfo->choice->choiceInfo; + elementDescription != NULL; + elementDescription = elementDescription->_next) { + virBufferVSprintf(&buffer, "'%s'", elementDescription->label); + + if (elementDescription->_next != NULL) { + virBufferAddLit(&buffer, ", "); + } + + if (answerChoice == NULL && + questionInfo->choice->defaultIndex != NULL && + questionInfo->choice->defaultIndex->value == answerIndex) { + answerChoice = elementDescription; + } + + ++answerIndex; + } + + if (virBufferError(&buffer)) { + virReportOOMError(conn); + goto failure; + } + + possibleAnswers = virBufferContentAndReset(&buffer); + } + + if (autoAnswer == esxVI_Boolean_True) { + if (possibleAnswers == NULL) { + ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Pending question blocks virtual machine execution, " + "question is '%s', no possible answers", + questionInfo->text); + goto failure; + } else if (answerChoice == NULL) { + ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Pending question blocks virtual machine execution, " + "question is '%s', possible answers are %s, but no " + "default answer is specified", questionInfo->text, + possibleAnswers); + goto failure; + } + + VIR_INFO("Pending question blocks virtual machine execution, " + "question is '%s', possible answers are %s, responding " + "with default answer '%s'", questionInfo->text, + possibleAnswers, answerChoice->label); + + if (esxVI_AnswerVM(conn, ctx, virtualMachine, questionInfo->id, + answerChoice->key) < 0) { + goto failure; + } + } else { + if (possibleAnswers != NULL) { + ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Pending question blocks virtual machine execution, " + "question is '%s', possible answers are %s", + questionInfo->text, possibleAnswers); + } else { + ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Pending question blocks virtual machine execution, " + "question is '%s', no possible answers", + questionInfo->text); + } + + goto failure; + } + + cleanup: + VIR_FREE(possibleAnswers); + + return result; + + failure: + if (possibleAnswers == NULL) { + possibleAnswers = virBufferContentAndReset(&buffer); + } + + result = -1; + + goto cleanup; +} + + + +int esxVI_WaitForTaskCompletion(virConnectPtr conn, esxVI_Context *ctx, esxVI_ManagedObjectReference *task, + const unsigned char *virtualMachineUuid, + esxVI_Boolean autoAnswer, esxVI_TaskInfoState *finalState) { int result = 0; @@ -2150,6 +2491,7 @@ esxVI_WaitForTaskCompletion(virConnectPtr conn, esxVI_Context *ctx, esxVI_PropertyChange *propertyChange = NULL; esxVI_AnyType *propertyValue = NULL; esxVI_TaskInfoState state = esxVI_TaskInfoState_Undefined; + esxVI_TaskInfo *taskInfo = NULL; version = strdup(""); @@ -2187,6 +2529,35 @@ esxVI_WaitForTaskCompletion(virConnectPtr conn, esxVI_Context *ctx, state != esxVI_TaskInfoState_Error) { esxVI_UpdateSet_Free(&updateSet); + if (virtualMachineUuid != NULL) { + if (esxVI_LookupAndHandleVirtualMachineQuestion + (conn, ctx, virtualMachineUuid, autoAnswer) < 0) { + /* + * FIXME: Disable error reporting here, so possible errors from + * esxVI_LookupTaskInfoByTask() and esxVI_CancelTask() + * don't overwrite the actual error + */ + if (esxVI_LookupTaskInfoByTask(conn, ctx, task, &taskInfo)) { + goto failure; + } + + if (taskInfo->cancelable == esxVI_Boolean_True) { + if (esxVI_CancelTask(conn, ctx, task) < 0) { + VIR_ERROR0("Cancelable task is blocked by an " + "unanswered question but cancelation " + "failed"); + } + } else { + VIR_ERROR0("Non-cancelable task is blocked by an " + "unanswered question"); + } + + /* FIXME: Enable error reporting here again */ + + goto failure; + } + } + if (esxVI_WaitForUpdates(conn, ctx, version, &updateSet) < 0) { goto failure; } @@ -2259,6 +2630,7 @@ esxVI_WaitForTaskCompletion(virConnectPtr conn, esxVI_Context *ctx, esxVI_ManagedObjectReference_Free(&propertyFilter); VIR_FREE(version); esxVI_UpdateSet_Free(&updateSet); + esxVI_TaskInfo_Free(&taskInfo); return result; diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h index 4b3005e..a10d874 100644 --- a/src/esx/esx_vi.h +++ b/src/esx/esx_vi.h @@ -229,6 +229,10 @@ int esxVI_GetVirtualMachinePowerState (virConnectPtr conn, esxVI_ObjectContent *virtualMachine, esxVI_VirtualMachinePowerState *powerState); +int esxVI_GetVirtualMachineQuestionInfo + (virConnectPtr conn, esxVI_ObjectContent *virtualMachine, + esxVI_VirtualMachineQuestionInfo **questionInfo); + int esxVI_LookupNumberOfDomainsByPowerState (virConnectPtr conn, esxVI_Context *ctx, esxVI_VirtualMachinePowerState powerState, esxVI_Boolean inverse); @@ -252,12 +256,31 @@ int esxVI_LookupVirtualMachineByUuid(virConnectPtr conn, esxVI_Context *ctx, esxVI_ObjectContent **virtualMachine, esxVI_Occurence occurence); +int esxVI_LookupVirtualMachineByUuidAndPrepareForTask + (virConnectPtr conn, esxVI_Context *ctx, const unsigned char *uuid, + esxVI_String *propertyNameList, esxVI_ObjectContent **virtualMachine, + esxVI_Boolean autoAnswer); + int esxVI_LookupDatastoreByName(virConnectPtr conn, esxVI_Context *ctx, const char *name, esxVI_String *propertyNameList, esxVI_ObjectContent **datastore, esxVI_Occurence occurence); +int esxVI_LookupTaskInfoByTask(virConnectPtr conn, esxVI_Context *ctx, + esxVI_ManagedObjectReference *task, + esxVI_TaskInfo **taskInfo); + +int esxVI_LookupPendingTaskInfoListByVirtualMachine + (virConnectPtr conn, esxVI_Context *ctx, + esxVI_ObjectContent *virtualMachine, + esxVI_TaskInfo **pendingTaskInfoList); + +int esxVI_LookupAndHandleVirtualMachineQuestion(virConnectPtr conn, + esxVI_Context *ctx, + const unsigned char *uuid, + esxVI_Boolean autoAnswer); + int esxVI_StartVirtualMachineTask(virConnectPtr conn, esxVI_Context *ctx, const char *name, const char *request, esxVI_ManagedObjectReference **task); @@ -271,8 +294,16 @@ int esxVI_SimpleVirtualMachineMethod (virConnectPtr conn, esxVI_Context *ctx, const char *name, esxVI_ManagedObjectReference *virtualMachine); +int esxVI_HandleVirtualMachineQuestion + (virConnectPtr conn, esxVI_Context *ctx, + esxVI_ManagedObjectReference *virtualMachine, + esxVI_VirtualMachineQuestionInfo *questionInfo, + esxVI_Boolean autoAnswer); + int esxVI_WaitForTaskCompletion(virConnectPtr conn, esxVI_Context *ctx, esxVI_ManagedObjectReference *task, + const unsigned char *virtualMachineUuid, + esxVI_Boolean autoAnswer, esxVI_TaskInfoState *finalState); #endif /* __ESX_VI_H__ */ diff --git a/src/esx/esx_vi_methods.c b/src/esx/esx_vi_methods.c index 06b5fd4..d18e56b 100644 --- a/src/esx/esx_vi_methods.c +++ b/src/esx/esx_vi_methods.c @@ -577,6 +577,61 @@ esxVI_RegisterVM_Task(virConnectPtr conn, esxVI_Context *ctx, int +esxVI_CancelTask(virConnectPtr conn, esxVI_Context *ctx, + esxVI_ManagedObjectReference *task) +{ + int result = 0; + virBuffer buffer = VIR_BUFFER_INITIALIZER; + char *request = NULL; + esxVI_Response *response = NULL; + + if (ctx->service == NULL) { + ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid call"); + return -1; + } + + virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_HEADER); + virBufferAddLit(&buffer, "<CancelTask xmlns=\"urn:vim25\">"); + + if (esxVI_ManagedObjectReference_Serialize(conn, task, "_this", &buffer, + esxVI_Boolean_True) < 0) { + goto failure; + } + + virBufferAddLit(&buffer, "</CancelTask>"); + virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_FOOTER); + + if (virBufferError(&buffer)) { + virReportOOMError(conn); + goto failure; + } + + request = virBufferContentAndReset(&buffer); + + if (esxVI_Context_Execute(conn, ctx, request, NULL, &response, + esxVI_Boolean_False) < 0) { + goto failure; + } + + cleanup: + VIR_FREE(request); + esxVI_Response_Free(&response); + + return result; + + failure: + if (request == NULL) { + request = virBufferContentAndReset(&buffer); + } + + result = -1; + + goto cleanup; +} + + + +int esxVI_UnregisterVM(virConnectPtr conn, esxVI_Context *ctx, esxVI_ManagedObjectReference *virtualMachine) { @@ -626,6 +681,62 @@ esxVI_UnregisterVM(virConnectPtr conn, esxVI_Context *ctx, int +esxVI_AnswerVM(virConnectPtr conn, esxVI_Context *ctx, + esxVI_ManagedObjectReference *virtualMachine, + const char *questionId, const char *answerChoice) +{ + int result = 0; + virBuffer buffer = VIR_BUFFER_INITIALIZER; + char *request = NULL; + esxVI_Response *response = NULL; + + virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_HEADER); + virBufferAddLit(&buffer, "<AnswerVM xmlns=\"urn:vim25\">"); + + if (esxVI_ManagedObjectReference_Serialize(conn, virtualMachine, "_this", + &buffer, + esxVI_Boolean_True) < 0 || + esxVI_String_SerializeValue(conn, questionId, "questionId", + &buffer, esxVI_Boolean_True) < 0 || + esxVI_String_SerializeValue(conn, answerChoice, "answerChoice", + &buffer, esxVI_Boolean_True) < 0) { + goto failure; + } + + virBufferAddLit(&buffer, "</AnswerVM>"); + virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_FOOTER); + + if (virBufferError(&buffer)) { + virReportOOMError(conn); + goto failure; + } + + request = virBufferContentAndReset(&buffer); + + if (esxVI_Context_Execute(conn, ctx, request, NULL, &response, + esxVI_Boolean_False) < 0) { + goto failure; + } + + cleanup: + VIR_FREE(request); + esxVI_Response_Free(&response); + + return result; + + failure: + if (request == NULL) { + request = virBufferContentAndReset(&buffer); + } + + result = -1; + + goto cleanup; +} + + + +int esxVI_CreateFilter(virConnectPtr conn, esxVI_Context *ctx, esxVI_PropertyFilterSpec *propertyFilterSpec, esxVI_Boolean partialUpdates, diff --git a/src/esx/esx_vi_methods.h b/src/esx/esx_vi_methods.h index 5f3caff..03e4fdf 100644 --- a/src/esx/esx_vi_methods.h +++ b/src/esx/esx_vi_methods.h @@ -80,9 +80,16 @@ int esxVI_RegisterVM_Task(virConnectPtr conn, esxVI_Context *ctx, esxVI_ManagedObjectReference *hostSystem, esxVI_ManagedObjectReference **task); +int esxVI_CancelTask(virConnectPtr conn, esxVI_Context *ctx, + esxVI_ManagedObjectReference *task); + int esxVI_UnregisterVM(virConnectPtr conn, esxVI_Context *ctx, esxVI_ManagedObjectReference *virtualMachine); +int esxVI_AnswerVM(virConnectPtr conn, esxVI_Context *ctx, + esxVI_ManagedObjectReference *virtualMachine, + const char *questionId, const char *answerChoice); + int esxVI_CreateFilter(virConnectPtr conn, esxVI_Context *ctx, esxVI_PropertyFilterSpec *propertyFilterSpec, esxVI_Boolean partialUpdates, diff --git a/src/esx/esx_vi_types.c b/src/esx/esx_vi_types.c index 9af9f73..aa2f968 100644 --- a/src/esx/esx_vi_types.c +++ b/src/esx/esx_vi_types.c @@ -1202,6 +1202,9 @@ static const esxVI_Enumeration _esxVI_TaskInfoState_Enumeration = { /* esxVI_TaskInfoState_CastFromAnyType */ ESX_VI__TEMPLATE__ENUMERATION__CAST_FROM_ANY_TYPE(TaskInfoState); +/* esxVI_TaskInfoState_Deserialize */ +ESX_VI__TEMPLATE__ENUMERATION__DESERIALIZE(TaskInfoState); + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * @@ -1315,6 +1318,9 @@ esxVI_ManagedObjectReference_DeepCopy(virConnectPtr conn, return -1; } +/* esxVI_ManagedObjectReference_AppendToList */ +ESX_VI__TEMPLATE__LIST__APPEND(ManagedObjectReference); + int esxVI_ManagedObjectReference_CastFromAnyType (virConnectPtr conn, esxVI_AnyType *anyType, @@ -1340,6 +1346,76 @@ esxVI_ManagedObjectReference_CastFromAnyType } int +esxVI_ManagedObjectReference_CastListFromAnyType + (virConnectPtr conn, esxVI_AnyType *anyType, + esxVI_ManagedObjectReference **managedObjectReferenceList, + const char *expectedType) +{ + int result = 0; + xmlNodePtr childNode = NULL; + esxVI_AnyType *childAnyType = NULL; + esxVI_ManagedObjectReference *managedObjectReference = NULL; + + if (managedObjectReferenceList == NULL || + *managedObjectReferenceList != NULL) { + ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument"); + goto failure; + } + + if (anyType == NULL) { + return 0; + } + + if (STRNEQ(anyType->other, "ArrayOfManagedObjectReference")) { + ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Expecting type to be 'ArrayOfManagedObjectReference' " + "but found '%s'", anyType->other); + goto failure; + } + + for (childNode = anyType->_node->children; childNode != NULL; + childNode = childNode->next) { + if (childNode->type != XML_ELEMENT_NODE) { + ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Wrong XML element type %d", childNode->type); + goto failure; + } + + esxVI_AnyType_Free(&childAnyType); + + if (esxVI_AnyType_Deserialize(conn, childNode, &childAnyType) < 0) { + goto failure; + } + + managedObjectReference = NULL; + + if (esxVI_ManagedObjectReference_CastFromAnyType + (conn, childAnyType, &managedObjectReference, + expectedType) < 0) { + goto failure; + } + + if (esxVI_ManagedObjectReference_AppendToList + (conn, managedObjectReferenceList, managedObjectReference) < 0) { + goto failure; + } + } + + + cleanup: + esxVI_AnyType_Free(&childAnyType); + + return result; + + failure: + esxVI_ManagedObjectReference_Free(managedObjectReferenceList); + + result = -1; + + goto cleanup; +} + +int esxVI_ManagedObjectReference_Serialize (virConnectPtr conn, esxVI_ManagedObjectReference *managedObjectReference, const char *element, virBufferPtr output, esxVI_Boolean required) @@ -2427,6 +2503,41 @@ ESX_VI__TEMPLATE__DESERIALIZE(UserSession, /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * VI Type: VirtualMachineQuestionInfo + */ + +/* esxVI_VirtualMachineQuestionInfo_Alloc */ +ESX_VI__TEMPLATE__ALLOC(VirtualMachineQuestionInfo); + +/* esxVI_VirtualMachineQuestionInfo_Free */ +ESX_VI__TEMPLATE__FREE(VirtualMachineQuestionInfo, +{ + VIR_FREE(item->id); + VIR_FREE(item->text); + esxVI_ChoiceOption_Free(&item->choice); + /*esxVI_VirtualMachineMessage_Free(&item->message);*//* FIXME */ +}); + +/* esxVI_VirtualMachineQuestionInfo_CastFromAnyType */ +ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE(VirtualMachineQuestionInfo); + +/* esxVI_VirtualMachineQuestionInfo_Deserialize */ +ESX_VI__TEMPLATE__DESERIALIZE(VirtualMachineQuestionInfo, +{ + ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, id); + ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, text); + ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(ChoiceOption, choice); + ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_NOOP(message); /* FIXME */ +}, +{ + ESX_VI__TEMPLATE__PROPERTY__REQUIRED(id); + ESX_VI__TEMPLATE__PROPERTY__REQUIRED(text); + ESX_VI__TEMPLATE__PROPERTY__REQUIRED(choice); +}); + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VI Type: ElementDescription extends Description * * In contrast to SelectionSpec and TraversalSpec just merge @@ -2447,6 +2558,9 @@ ESX_VI__TEMPLATE__FREE(ElementDescription, VIR_FREE(item->key); }); +/* esxVI_ElementDescription_AppendToList */ +ESX_VI__TEMPLATE__LIST__APPEND(ElementDescription); + /* esxVI_ElementDescription_Deserialize */ ESX_VI__TEMPLATE__DESERIALIZE(ElementDescription, { @@ -2463,6 +2577,37 @@ ESX_VI__TEMPLATE__DESERIALIZE(ElementDescription, /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * VI Type: ChoiceOption extends OptionType + * + * In contrast to SelectionSpec and TraversalSpec just merge + * OptionType into ChoiceOption for simplicity, because + * only ChoiceOption is used. + */ + +/* esxVI_ChoiceOption_Alloc */ +ESX_VI__TEMPLATE__ALLOC(ChoiceOption); + +/* esxVI_ChoiceOption_Free */ +ESX_VI__TEMPLATE__FREE(ChoiceOption, +{ + esxVI_ElementDescription_Free(&item->choiceInfo); + esxVI_Int_Free(&item->defaultIndex); +}); + +/* esxVI_ChoiceOption_Deserialize */ +ESX_VI__TEMPLATE__DESERIALIZE(ChoiceOption, +{ + ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(Boolean, valueIsReadonly); + ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_LIST(ElementDescription, choiceInfo); + ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(Int, defaultIndex); +}, +{ + ESX_VI__TEMPLATE__PROPERTY__REQUIRED(choiceInfo); +}); + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VI Type: PerfMetricId */ @@ -2699,3 +2844,76 @@ ESX_VI__TEMPLATE__DESERIALIZE(PerfEntityMetric, /* esxVI_PerfEntityMetric_DeserializeList */ ESX_VI__TEMPLATE__LIST__DESERIALIZE(PerfEntityMetric); + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * VI Type: TaskInfo + */ + +/* esxVI_TaskInfo_Alloc */ +ESX_VI__TEMPLATE__ALLOC(TaskInfo); + +/* esxVI_TaskInfo_Free */ +ESX_VI__TEMPLATE__FREE(TaskInfo, +{ + esxVI_TaskInfo_Free(&item->_next); + + VIR_FREE(item->key); + esxVI_ManagedObjectReference_Free(&item->task); + VIR_FREE(item->name); + VIR_FREE(item->descriptionId); + esxVI_ManagedObjectReference_Free(&item->entity); + VIR_FREE(item->entityName); + /*esxVI_ManagedObjectReference_Free(&item->locked);*//* FIXME */ + /*esxVI_MethodFault_Free(&item->error);*//* FIXME */ + esxVI_AnyType_Free(&item->result); + esxVI_Int_Free(&item->progress); + /*esxVI_TaskReason_Free(&item->reason);*//* FIXME */ + esxVI_DateTime_Free(&item->queueTime); + esxVI_DateTime_Free(&item->startTime); + esxVI_DateTime_Free(&item->completeTime); + esxVI_Int_Free(&item->eventChainId); +}); + +/* esxVI_TaskInfo_CastFromAnyType */ +ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE(TaskInfo); + +/* esxVI_TaskInfo_AppendToList */ +ESX_VI__TEMPLATE__LIST__APPEND(TaskInfo); + +/* esxVI_TaskInfo_Deserialize */ +ESX_VI__TEMPLATE__DESERIALIZE(TaskInfo, +{ + ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, key); + ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_EXPECTED(ManagedObjectReference, + "Task", task); + ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, name); + ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, descriptionId); + ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_EXPECTED(ManagedObjectReference, + NULL, entity); + ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, entityName); + ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_NOOP(locked); /* FIXME */ + ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(TaskInfoState, state); + ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(Boolean, cancelled); + ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(Boolean, cancelable); + ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_NOOP(error); /* FIXME */ + ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(AnyType, result); + ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(Int, progress); + ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_NOOP(reason); /* FIXME */ + ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(DateTime, queueTime); + ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(DateTime, startTime); + ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(DateTime, completeTime); + ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(Int, eventChainId); +}, +{ + ESX_VI__TEMPLATE__PROPERTY__REQUIRED(key); + ESX_VI__TEMPLATE__PROPERTY__REQUIRED(task); + ESX_VI__TEMPLATE__PROPERTY__REQUIRED(descriptionId); + ESX_VI__TEMPLATE__PROPERTY__REQUIRED(state); + ESX_VI__TEMPLATE__PROPERTY__REQUIRED(cancelled); + ESX_VI__TEMPLATE__PROPERTY__REQUIRED(cancelable); + /*ESX_VI__TEMPLATE__PROPERTY__REQUIRED(reason);*//* FIXME */ + ESX_VI__TEMPLATE__PROPERTY__REQUIRED(queueTime); + ESX_VI__TEMPLATE__PROPERTY__REQUIRED(eventChainId); +}); diff --git a/src/esx/esx_vi_types.h b/src/esx/esx_vi_types.h index 32ccda6..4183324 100644 --- a/src/esx/esx_vi_types.h +++ b/src/esx/esx_vi_types.h @@ -90,13 +90,16 @@ typedef struct _esxVI_ResourcePoolResourceUsage esxVI_ResourcePoolResourceUsage; typedef struct _esxVI_VirtualMachineConfigSpec esxVI_VirtualMachineConfigSpec; typedef struct _esxVI_Event esxVI_Event; typedef struct _esxVI_UserSession esxVI_UserSession; +typedef struct _esxVI_VirtualMachineQuestionInfo esxVI_VirtualMachineQuestionInfo; typedef struct _esxVI_ElementDescription esxVI_ElementDescription; +typedef struct _esxVI_ChoiceOption esxVI_ChoiceOption; typedef struct _esxVI_PerfMetricId esxVI_PerfMetricId; typedef struct _esxVI_PerfCounterInfo esxVI_PerfCounterInfo; typedef struct _esxVI_PerfQuerySpec esxVI_PerfQuerySpec; typedef struct _esxVI_PerfSampleInfo esxVI_PerfSampleInfo; typedef struct _esxVI_PerfMetricIntSeries esxVI_PerfMetricIntSeries; typedef struct _esxVI_PerfEntityMetric esxVI_PerfEntityMetric; +typedef struct _esxVI_TaskInfo esxVI_TaskInfo; @@ -403,6 +406,8 @@ enum _esxVI_TaskInfoState { int esxVI_TaskInfoState_CastFromAnyType(virConnectPtr conn, esxVI_AnyType *anyType, esxVI_TaskInfoState *taskInfoState); +int esxVI_TaskInfoState_Deserialize(virConnectPtr conn, xmlNodePtr node, + esxVI_TaskInfoState *taskInfoState); @@ -480,11 +485,19 @@ void esxVI_ManagedObjectReference_Free int esxVI_ManagedObjectReference_DeepCopy(virConnectPtr conn, esxVI_ManagedObjectReference **dest, esxVI_ManagedObjectReference *src); +int esxVI_ManagedObjectReference_AppendToList + (virConnectPtr conn, + esxVI_ManagedObjectReference **managedObjectReferenceList, + esxVI_ManagedObjectReference *managedObjectReference); int esxVI_ManagedObjectReference_CastFromAnyType(virConnectPtr conn, esxVI_AnyType *anyType, esxVI_ManagedObjectReference **managedObjectReference, const char *expectedType); +int esxVI_ManagedObjectReference_CastListFromAnyType + (virConnectPtr conn, esxVI_AnyType *anyType, + esxVI_ManagedObjectReference **managedObjectReferenceList, + const char *expectedType); int esxVI_ManagedObjectReference_Serialize (virConnectPtr conn, esxVI_ManagedObjectReference *managedObjectReference, @@ -1065,6 +1078,32 @@ int esxVI_UserSession_Deserialize(virConnectPtr conn, xmlNodePtr node, /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * VI Type: VirtualMachineQuestionInfo + */ + +/* FIXME: implement the rest */ +struct _esxVI_VirtualMachineQuestionInfo { + char *id; /* required */ + char *text; /* required */ + esxVI_ChoiceOption *choice; /* required */ + /*esxVI_VirtualMachineMessage *message;*/ /* optional, list */ +}; + +int esxVI_VirtualMachineQuestionInfo_Alloc + (virConnectPtr conn, + esxVI_VirtualMachineQuestionInfo **virtualMachineQuestionInfo); +void esxVI_VirtualMachineQuestionInfo_Free + (esxVI_VirtualMachineQuestionInfo **virtualMachineQuestionInfo); +int esxVI_VirtualMachineQuestionInfo_CastFromAnyType + (virConnectPtr conn, esxVI_AnyType *anyType, + esxVI_VirtualMachineQuestionInfo **virtualMachineQuestionInfo); +int esxVI_VirtualMachineQuestionInfo_Deserialize + (virConnectPtr conn, xmlNodePtr node, + esxVI_VirtualMachineQuestionInfo **virtualMachineQuestionInfo); + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VI Type: ElementDescription extends Description * * In contrast to SelectionSpec and TraversalSpec just merge @@ -1087,6 +1126,9 @@ int esxVI_ElementDescription_Alloc (virConnectPtr conn, esxVI_ElementDescription **elementDescription); void esxVI_ElementDescription_Free (esxVI_ElementDescription **elementDescription); +int esxVI_ElementDescription_AppendToList + (virConnectPtr conn, esxVI_ElementDescription **elementDescriptionList, + esxVI_ElementDescription *elementDescription); int esxVI_ElementDescription_Deserialize (virConnectPtr conn, xmlNodePtr node, esxVI_ElementDescription **elementDescription); @@ -1094,6 +1136,31 @@ int esxVI_ElementDescription_Deserialize /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * VI Type: ChoiceOption extends OptionType + * + * In contrast to SelectionSpec and TraversalSpec just merge + * OptionType into ChoiceOption for simplicity, because + * only ChoiceOption is used. + */ + +struct _esxVI_ChoiceOption { + /* OptionType */ + esxVI_Boolean valueIsReadonly; /* optional */ + + /* ChoiceOption */ + esxVI_ElementDescription *choiceInfo; /* required, list */ + esxVI_Int *defaultIndex; /* optional */ +}; + +int esxVI_ChoiceOption_Alloc(virConnectPtr conn, + esxVI_ChoiceOption **choiceOption); +void esxVI_ChoiceOption_Free(esxVI_ChoiceOption **choiceOption); +int esxVI_ChoiceOption_Deserialize(virConnectPtr conn, xmlNodePtr node, + esxVI_ChoiceOption **choiceOption); + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VI Type: PerfMetricId */ @@ -1272,4 +1339,43 @@ int esxVI_PerfEntityMetric_DeserializeList (virConnectPtr conn, xmlNodePtr node, esxVI_PerfEntityMetric **perfEntityMetricList); + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * VI Type: TaskInfo + */ + +struct _esxVI_TaskInfo { + esxVI_TaskInfo *_next; /* optional */ + + char *key; /* required */ + esxVI_ManagedObjectReference *task; /* required */ + char *name; /* optional */ + char *descriptionId; /* required */ + esxVI_ManagedObjectReference *entity; /* optional */ + char *entityName; /* optional */ + /*esxVI_ManagedObjectReference *locked;*/ /* optional, list *//* FIXME */ + esxVI_TaskInfoState state; /* required */ + esxVI_Boolean cancelled; /* required */ + esxVI_Boolean cancelable; /* required */ + /*esxVI_MethodFault *error;*/ /* optional *//* FIXME */ + esxVI_AnyType *result; /* optional */ + esxVI_Int *progress; /* optional */ + /*esxVI_TaskReason *reason;*/ /* required *//* FIXME */ + esxVI_DateTime *queueTime; /* required */ + esxVI_DateTime *startTime; /* optional */ + esxVI_DateTime *completeTime; /* optional */ + esxVI_Int *eventChainId; /* required */ +}; + +int esxVI_TaskInfo_Alloc(virConnectPtr conn, esxVI_TaskInfo **taskInfo); +void esxVI_TaskInfo_Free(esxVI_TaskInfo **taskInfoList); +int esxVI_TaskInfo_CastFromAnyType(virConnectPtr conn, esxVI_AnyType *anyType, + esxVI_TaskInfo **taskInfo); +int esxVI_TaskInfo_AppendToList(virConnectPtr conn, + esxVI_TaskInfo **taskInfoList, + esxVI_TaskInfo *taskInfo); +int esxVI_TaskInfo_Deserialize(virConnectPtr conn, xmlNodePtr node, + esxVI_TaskInfo **taskInfo); + #endif /* __ESX_VI_TYPES_H__ */ -- 1.6.0.4

On Sun, Dec 13, 2009 at 12:20:38AM +0100, Matthias Bolte wrote:
Questions can block tasks, to handle them automatically the driver can answers them with the default answer. The auto_answer query parameter allows to enable this automatic question handling.
* src/esx/README: add a detailed explanation for automatic question handling * src/esx/esx_driver.c: add automatic question handling for all task related driver functions * src/esx/esx_util.[ch]: add handling for the auto_answer query parameter * src/esx/esx_vi.[ch], src/esx/esx_vi_methods.[ch], src/esx/esx_vi_types.[ch]: add new VI API methods and types and additional helper functions for automatic question handling
Well that's a fairly big patch and honnestly you're the one who really understand how this area of the code works :-) I went though it but didn't spot anything, ACK Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

esxDomainLookupByUUID() and esxDomainIsActive() lookup a domain by asking ESX for all known domains and searching manually for the one with the matching UUID. This is inefficient. The VI API allows to lookup by UUID directly: FindByUuid(). * src/esx/esx_driver.c: change esxDomainLookupByUUID() and esxDomainIsActive() to use esxVI_LookupVirtualMachineByUuid(), also reorder some functions to keep them in sync with the driver struct --- src/esx/esx_driver.c | 261 +++++++++++++++++++------------------------------ 1 files changed, 101 insertions(+), 160 deletions(-) diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index 45da694..db379d7 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -507,30 +507,6 @@ esxClose(virConnectPtr conn) } -static int -esxIsSecure(virConnectPtr conn) -{ - esxPrivate *priv = (esxPrivate *)conn->privateData; - - if (STRCASEEQ(priv->transport, "https")) { - return 1; - } else { - return 0; - } -} - - -static int -esxIsEncrypted(virConnectPtr conn) -{ - esxPrivate *priv = (esxPrivate *)conn->privateData; - - if (STRCASEEQ(priv->transport, "https")) { - return 1; - } else { - return 0; - } -} static esxVI_Boolean esxSupportsVMotion(virConnectPtr conn) @@ -749,7 +725,6 @@ esxGetHostname(virConnectPtr conn) - static int esxNodeGetInfo(virConnectPtr conn, virNodeInfoPtr nodeinfo) { @@ -1097,13 +1072,10 @@ esxDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid) { esxPrivate *priv = (esxPrivate *)conn->privateData; esxVI_String *propertyNameList = NULL; - esxVI_ObjectContent *virtualMachineList = NULL; esxVI_ObjectContent *virtualMachine = NULL; esxVI_VirtualMachinePowerState powerState; - int id_candidate = -1; - char *name_candidate = NULL; - unsigned char uuid_candidate[VIR_UUID_BUFLEN]; - char uuid_string[VIR_UUID_STRING_BUFLEN]; + int id = -1; + char *name = NULL; virDomainPtr domain = NULL; if (esxVI_EnsureSession(conn, priv->host) < 0) { @@ -1111,64 +1083,35 @@ esxDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid) } if (esxVI_String_AppendValueListToList(conn, &propertyNameList, - "configStatus\0" "name\0" - "runtime.powerState\0" - "config.uuid\0") < 0 || - esxVI_LookupObjectContentByType(conn, priv->host, priv->host->vmFolder, - "VirtualMachine", propertyNameList, - esxVI_Boolean_True, - &virtualMachineList) < 0) { + "runtime.powerState\0") < 0 || + esxVI_LookupVirtualMachineByUuid(conn, priv->host, uuid, + propertyNameList, &virtualMachine, + esxVI_Occurence_RequiredItem) < 0 || + esxVI_GetVirtualMachineIdentity(conn, virtualMachine, + &id, &name, NULL) < 0 || + esxVI_GetVirtualMachinePowerState(conn, virtualMachine, + &powerState) < 0) { goto failure; } - for (virtualMachine = virtualMachineList; virtualMachine != NULL; - virtualMachine = virtualMachine->_next) { - VIR_FREE(name_candidate); - - if (esxVI_GetVirtualMachineIdentity(conn, virtualMachine, - &id_candidate, &name_candidate, - uuid_candidate) < 0) { - goto failure; - } - - if (memcmp(uuid, uuid_candidate, - VIR_UUID_BUFLEN * sizeof(unsigned char)) != 0) { - continue; - } - - if (esxVI_GetVirtualMachinePowerState(conn, virtualMachine, - &powerState) < 0) { - goto failure; - } - - domain = virGetDomain(conn, name_candidate, uuid_candidate); - - if (domain == NULL) { - goto failure; - } - - /* Only running/suspended virtual machines have an ID != -1 */ - if (powerState != esxVI_VirtualMachinePowerState_PoweredOff) { - domain->id = id_candidate; - } else { - domain->id = -1; - } - - break; - } + domain = virGetDomain(conn, name, uuid); if (domain == NULL) { - virUUIDFormat(uuid, uuid_string); + goto failure; + } - ESX_ERROR(conn, VIR_ERR_NO_DOMAIN, "No domain with UUID '%s'", - uuid_string); + /* Only running/suspended virtual machines have an ID != -1 */ + if (powerState != esxVI_VirtualMachinePowerState_PoweredOff) { + domain->id = id; + } else { + domain->id = -1; } cleanup: esxVI_String_Free(&propertyNameList); - esxVI_ObjectContent_Free(&virtualMachineList); - VIR_FREE(name_candidate); + esxVI_ObjectContent_Free(&virtualMachine); + VIR_FREE(name); return domain; @@ -1262,89 +1205,6 @@ esxDomainLookupByName(virConnectPtr conn, const char *name) } -static int -esxDomainIsActive(virDomainPtr dom) -{ - esxPrivate *priv = (esxPrivate *)dom->conn->privateData; - esxVI_String *propertyNameList = NULL; - esxVI_ObjectContent *virtualMachineList = NULL; - esxVI_ObjectContent *virtualMachine = NULL; - esxVI_VirtualMachinePowerState powerState; - int id_candidate = -1; - char *name_candidate = NULL; - unsigned char uuid_candidate[VIR_UUID_BUFLEN]; - char uuid_string[VIR_UUID_STRING_BUFLEN]; - int ret = -1; - - if (esxVI_EnsureSession(dom->conn, priv->host) < 0) { - goto cleanup; - } - - if (esxVI_String_AppendValueListToList(dom->conn, &propertyNameList, - "configStatus\0" - "name\0" - "runtime.powerState\0" - "config.uuid\0") < 0 || - esxVI_LookupObjectContentByType(dom->conn, priv->host, priv->host->vmFolder, - "VirtualMachine", propertyNameList, - esxVI_Boolean_True, - &virtualMachineList) < 0) { - goto cleanup; - } - - for (virtualMachine = virtualMachineList; virtualMachine != NULL; - virtualMachine = virtualMachine->_next) { - VIR_FREE(name_candidate); - - if (esxVI_GetVirtualMachineIdentity(dom->conn, virtualMachine, - &id_candidate, &name_candidate, - uuid_candidate) < 0) { - goto cleanup; - } - - if (memcmp(dom->uuid, uuid_candidate, - VIR_UUID_BUFLEN * sizeof(unsigned char)) != 0) { - continue; - } - - if (esxVI_GetVirtualMachinePowerState(dom->conn, virtualMachine, - &powerState) < 0) { - goto cleanup; - } - - /* Only running/suspended virtual machines have an ID != -1 */ - if (powerState != esxVI_VirtualMachinePowerState_PoweredOff) { - ret = 1; - } else { - ret = 0; - } - - break; - } - - if (ret == -1) { - virUUIDFormat(dom->uuid, uuid_string); - - ESX_ERROR(dom->conn, VIR_ERR_NO_DOMAIN, "No domain with UUID '%s'", - uuid_string); - } - - cleanup: - esxVI_String_Free(&propertyNameList); - esxVI_ObjectContent_Free(&virtualMachineList); - VIR_FREE(name_candidate); - - return ret; -} - - -static int -esxDomainIsPersistent(virDomainPtr dom ATTRIBUTE_UNUSED) -{ - /* ESX has no concept of transient domains, so - * all of them are persistent */ - return 1; -} static int esxDomainSuspend(virDomainPtr domain) @@ -3355,6 +3215,87 @@ esxNodeGetFreeMemory(virConnectPtr conn) +static int +esxIsEncrypted(virConnectPtr conn) +{ + esxPrivate *priv = (esxPrivate *)conn->privateData; + + if (STRCASEEQ(priv->transport, "https")) { + return 1; + } else { + return 0; + } +} + + + +static int +esxIsSecure(virConnectPtr conn) +{ + esxPrivate *priv = (esxPrivate *)conn->privateData; + + if (STRCASEEQ(priv->transport, "https")) { + return 1; + } else { + return 0; + } +} + + + +static int +esxDomainIsActive(virDomainPtr domain) +{ + int result = 0; + esxPrivate *priv = (esxPrivate *)domain->conn->privateData; + esxVI_ObjectContent *virtualMachine = NULL; + esxVI_String *propertyNameList = NULL; + esxVI_VirtualMachinePowerState powerState; + + if (esxVI_EnsureSession(domain->conn, priv->host) < 0) { + goto failure; + } + + if (esxVI_String_AppendValueToList(domain->conn, &propertyNameList, + "runtime.powerState") < 0 || + esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host, + domain->uuid, propertyNameList, + &virtualMachine, + esxVI_Occurence_RequiredItem) < 0 || + esxVI_GetVirtualMachinePowerState(domain->conn, virtualMachine, + &powerState) < 0) { + goto failure; + } + + if (powerState != esxVI_VirtualMachinePowerState_PoweredOff) { + result = 1; + } else { + result = 0; + } + + cleanup: + esxVI_ObjectContent_Free(&virtualMachine); + esxVI_String_Free(&propertyNameList); + + return result; + + failure: + result = -1; + + goto cleanup; +} + + + +static int +esxDomainIsPersistent(virDomainPtr domain ATTRIBUTE_UNUSED) +{ + /* ESX has no concept of transient domains, so all of them are persistent */ + return 1; +} + + + static virDriver esxDriver = { VIR_DRV_ESX, "ESX", -- 1.6.0.4

On Sun, Dec 13, 2009 at 12:20:39AM +0100, Matthias Bolte wrote:
esxDomainLookupByUUID() and esxDomainIsActive() lookup a domain by asking ESX for all known domains and searching manually for the one with the matching UUID. This is inefficient. The VI API allows to lookup by UUID directly: FindByUuid().
* src/esx/esx_driver.c: change esxDomainLookupByUUID() and esxDomainIsActive() to use esxVI_LookupVirtualMachineByUuid(), also reorder some functions to keep them in sync with the driver struct --- src/esx/esx_driver.c | 261 +++++++++++++++++++------------------------------ 1 files changed, 101 insertions(+), 160 deletions(-)
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index 45da694..db379d7 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -507,30 +507,6 @@ esxClose(virConnectPtr conn) }
-static int -esxIsSecure(virConnectPtr conn) -{ - esxPrivate *priv = (esxPrivate *)conn->privateData; - - if (STRCASEEQ(priv->transport, "https")) { - return 1; - } else { - return 0; - } -} - - -static int -esxIsEncrypted(virConnectPtr conn) -{ - esxPrivate *priv = (esxPrivate *)conn->privateData; - - if (STRCASEEQ(priv->transport, "https")) { - return 1; - } else { - return 0; - } -}
static esxVI_Boolean esxSupportsVMotion(virConnectPtr conn) @@ -749,7 +725,6 @@ esxGetHostname(virConnectPtr conn)
- static int esxNodeGetInfo(virConnectPtr conn, virNodeInfoPtr nodeinfo) { @@ -1097,13 +1072,10 @@ esxDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid) { esxPrivate *priv = (esxPrivate *)conn->privateData; esxVI_String *propertyNameList = NULL; - esxVI_ObjectContent *virtualMachineList = NULL; esxVI_ObjectContent *virtualMachine = NULL; esxVI_VirtualMachinePowerState powerState; - int id_candidate = -1; - char *name_candidate = NULL; - unsigned char uuid_candidate[VIR_UUID_BUFLEN]; - char uuid_string[VIR_UUID_STRING_BUFLEN]; + int id = -1; + char *name = NULL; virDomainPtr domain = NULL;
if (esxVI_EnsureSession(conn, priv->host) < 0) { @@ -1111,64 +1083,35 @@ esxDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid) }
if (esxVI_String_AppendValueListToList(conn, &propertyNameList, - "configStatus\0" "name\0" - "runtime.powerState\0" - "config.uuid\0") < 0 || - esxVI_LookupObjectContentByType(conn, priv->host, priv->host->vmFolder, - "VirtualMachine", propertyNameList, - esxVI_Boolean_True, - &virtualMachineList) < 0) { + "runtime.powerState\0") < 0 || + esxVI_LookupVirtualMachineByUuid(conn, priv->host, uuid, + propertyNameList, &virtualMachine, + esxVI_Occurence_RequiredItem) < 0 || + esxVI_GetVirtualMachineIdentity(conn, virtualMachine, + &id, &name, NULL) < 0 || + esxVI_GetVirtualMachinePowerState(conn, virtualMachine, + &powerState) < 0) { goto failure; }
- for (virtualMachine = virtualMachineList; virtualMachine != NULL; - virtualMachine = virtualMachine->_next) { - VIR_FREE(name_candidate); - - if (esxVI_GetVirtualMachineIdentity(conn, virtualMachine, - &id_candidate, &name_candidate, - uuid_candidate) < 0) { - goto failure; - } - - if (memcmp(uuid, uuid_candidate, - VIR_UUID_BUFLEN * sizeof(unsigned char)) != 0) { - continue; - } - - if (esxVI_GetVirtualMachinePowerState(conn, virtualMachine, - &powerState) < 0) { - goto failure; - } - - domain = virGetDomain(conn, name_candidate, uuid_candidate); - - if (domain == NULL) { - goto failure; - } - - /* Only running/suspended virtual machines have an ID != -1 */ - if (powerState != esxVI_VirtualMachinePowerState_PoweredOff) { - domain->id = id_candidate; - } else { - domain->id = -1; - } - - break; - } + domain = virGetDomain(conn, name, uuid);
if (domain == NULL) { - virUUIDFormat(uuid, uuid_string); + goto failure; + }
- ESX_ERROR(conn, VIR_ERR_NO_DOMAIN, "No domain with UUID '%s'", - uuid_string); + /* Only running/suspended virtual machines have an ID != -1 */ + if (powerState != esxVI_VirtualMachinePowerState_PoweredOff) { + domain->id = id; + } else { + domain->id = -1; }
cleanup: esxVI_String_Free(&propertyNameList); - esxVI_ObjectContent_Free(&virtualMachineList); - VIR_FREE(name_candidate); + esxVI_ObjectContent_Free(&virtualMachine); + VIR_FREE(name);
return domain;
@@ -1262,89 +1205,6 @@ esxDomainLookupByName(virConnectPtr conn, const char *name) }
-static int -esxDomainIsActive(virDomainPtr dom) -{ - esxPrivate *priv = (esxPrivate *)dom->conn->privateData; - esxVI_String *propertyNameList = NULL; - esxVI_ObjectContent *virtualMachineList = NULL; - esxVI_ObjectContent *virtualMachine = NULL; - esxVI_VirtualMachinePowerState powerState; - int id_candidate = -1; - char *name_candidate = NULL; - unsigned char uuid_candidate[VIR_UUID_BUFLEN]; - char uuid_string[VIR_UUID_STRING_BUFLEN]; - int ret = -1; - - if (esxVI_EnsureSession(dom->conn, priv->host) < 0) { - goto cleanup; - } - - if (esxVI_String_AppendValueListToList(dom->conn, &propertyNameList, - "configStatus\0" - "name\0" - "runtime.powerState\0" - "config.uuid\0") < 0 || - esxVI_LookupObjectContentByType(dom->conn, priv->host, priv->host->vmFolder, - "VirtualMachine", propertyNameList, - esxVI_Boolean_True, - &virtualMachineList) < 0) { - goto cleanup; - } - - for (virtualMachine = virtualMachineList; virtualMachine != NULL; - virtualMachine = virtualMachine->_next) { - VIR_FREE(name_candidate); - - if (esxVI_GetVirtualMachineIdentity(dom->conn, virtualMachine, - &id_candidate, &name_candidate, - uuid_candidate) < 0) { - goto cleanup; - } - - if (memcmp(dom->uuid, uuid_candidate, - VIR_UUID_BUFLEN * sizeof(unsigned char)) != 0) { - continue; - } - - if (esxVI_GetVirtualMachinePowerState(dom->conn, virtualMachine, - &powerState) < 0) { - goto cleanup; - } - - /* Only running/suspended virtual machines have an ID != -1 */ - if (powerState != esxVI_VirtualMachinePowerState_PoweredOff) { - ret = 1; - } else { - ret = 0; - } - - break; - } - - if (ret == -1) { - virUUIDFormat(dom->uuid, uuid_string); - - ESX_ERROR(dom->conn, VIR_ERR_NO_DOMAIN, "No domain with UUID '%s'", - uuid_string); - } - - cleanup: - esxVI_String_Free(&propertyNameList); - esxVI_ObjectContent_Free(&virtualMachineList); - VIR_FREE(name_candidate); - - return ret; -} - - -static int -esxDomainIsPersistent(virDomainPtr dom ATTRIBUTE_UNUSED) -{ - /* ESX has no concept of transient domains, so - * all of them are persistent */ - return 1; -}
static int esxDomainSuspend(virDomainPtr domain) @@ -3355,6 +3215,87 @@ esxNodeGetFreeMemory(virConnectPtr conn)
+static int +esxIsEncrypted(virConnectPtr conn) +{ + esxPrivate *priv = (esxPrivate *)conn->privateData; + + if (STRCASEEQ(priv->transport, "https")) { + return 1; + } else { + return 0; + } +} + + + +static int +esxIsSecure(virConnectPtr conn) +{ + esxPrivate *priv = (esxPrivate *)conn->privateData; + + if (STRCASEEQ(priv->transport, "https")) { + return 1; + } else { + return 0; + } +} + + + +static int +esxDomainIsActive(virDomainPtr domain) +{ + int result = 0; + esxPrivate *priv = (esxPrivate *)domain->conn->privateData; + esxVI_ObjectContent *virtualMachine = NULL; + esxVI_String *propertyNameList = NULL; + esxVI_VirtualMachinePowerState powerState; + + if (esxVI_EnsureSession(domain->conn, priv->host) < 0) { + goto failure; + } + + if (esxVI_String_AppendValueToList(domain->conn, &propertyNameList, + "runtime.powerState") < 0 || + esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host, + domain->uuid, propertyNameList, + &virtualMachine, + esxVI_Occurence_RequiredItem) < 0 || + esxVI_GetVirtualMachinePowerState(domain->conn, virtualMachine, + &powerState) < 0) { + goto failure; + } + + if (powerState != esxVI_VirtualMachinePowerState_PoweredOff) { + result = 1; + } else { + result = 0; + } + + cleanup: + esxVI_ObjectContent_Free(&virtualMachine); + esxVI_String_Free(&propertyNameList); + + return result; + + failure: + result = -1; + + goto cleanup; +} + + + +static int +esxDomainIsPersistent(virDomainPtr domain ATTRIBUTE_UNUSED) +{ + /* ESX has no concept of transient domains, so all of them are persistent */ + return 1; +} + + + static virDriver esxDriver = { VIR_DRV_ESX, "ESX",
ACK, there is a bit more than just the change of lookup, e.g. the new IsActive and IsPersistent implementations, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

--- src/esx/esx_vi.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c index e934bd4..fd86cde 100644 --- a/src/esx/esx_vi.c +++ b/src/esx/esx_vi.c @@ -1828,7 +1828,7 @@ esxVI_LookupVirtualMachineByUuid(virConnectPtr conn, esxVI_Context *ctx, } else { virUUIDFormat(uuid, uuid_string); - ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + ESX_VI_ERROR(conn, VIR_ERR_NO_DOMAIN, "Could not find domain with UUID '%s'", uuid_string); goto failure; } -- 1.6.0.4

On Sun, Dec 13, 2009 at 12:20:40AM +0100, Matthias Bolte wrote:
--- src/esx/esx_vi.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c index e934bd4..fd86cde 100644 --- a/src/esx/esx_vi.c +++ b/src/esx/esx_vi.c @@ -1828,7 +1828,7 @@ esxVI_LookupVirtualMachineByUuid(virConnectPtr conn, esxVI_Context *ctx, } else { virUUIDFormat(uuid, uuid_string);
- ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + ESX_VI_ERROR(conn, VIR_ERR_NO_DOMAIN, "Could not find domain with UUID '%s'", uuid_string); goto failure; }
sure, ACK, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

--- src/esx/esx_vi.c | 2 +- src/esx/esx_vi_types.c | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c index fd86cde..21c405f 100644 --- a/src/esx/esx_vi.c +++ b/src/esx/esx_vi.c @@ -949,7 +949,7 @@ esxVI_List_CastFromAnyType(virConnectPtr conn, esxVI_AnyType *anyType, goto failure; } - for (childNode = anyType->_node->xmlChildrenNode; childNode != NULL; + for (childNode = anyType->_node->children; childNode != NULL; childNode = childNode->next) { if (childNode->type != XML_ELEMENT_NODE) { ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, diff --git a/src/esx/esx_vi_types.c b/src/esx/esx_vi_types.c index aa2f968..8c5b17b 100644 --- a/src/esx/esx_vi_types.c +++ b/src/esx/esx_vi_types.c @@ -229,7 +229,7 @@ return -1; \ } \ \ - for (childNode = node->xmlChildrenNode; childNode != NULL; \ + for (childNode = node->children; childNode != NULL; \ childNode = childNode->next) { \ if (childNode->type != XML_ELEMENT_NODE) { \ ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, \ @@ -272,8 +272,7 @@ return -1; \ } \ \ - string = (char *)xmlNodeListGetString(node->doc, \ - node->xmlChildrenNode, 1); \ + string = (char *)xmlNodeListGetString(node->doc, node->children, 1); \ \ if (string == NULL) { \ ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, \ @@ -639,7 +638,7 @@ esxVI_AnyType_Deserialize(virConnectPtr conn, xmlNodePtr node, } (*anyType)->value = - (char *)xmlNodeListGetString(node->doc, node->xmlChildrenNode, 1); + (char *)xmlNodeListGetString(node->doc, node->children, 1); if ((*anyType)->value == NULL) { (*anyType)->value = strdup(""); @@ -883,7 +882,7 @@ esxVI_String_Deserialize(virConnectPtr conn, xmlNodePtr node, } (*string)->value = - (char *)xmlNodeListGetString(node->doc, node->xmlChildrenNode, 1); + (char *)xmlNodeListGetString(node->doc, node->children, 1); if ((*string)->value == NULL) { (*string)->value = strdup(""); @@ -914,7 +913,7 @@ esxVI_String_DeserializeValue(virConnectPtr conn, xmlNodePtr node, return -1; } - *value = (char *)xmlNodeListGetString(node->doc, node->xmlChildrenNode, 1); + *value = (char *)xmlNodeListGetString(node->doc, node->children, 1); if (*value == NULL) { *value = strdup(""); @@ -1049,7 +1048,7 @@ esxVI_DateTime_Deserialize(virConnectPtr conn, xmlNodePtr node, } (*dateTime)->value = - (char *)xmlNodeListGetString(node->doc, node->xmlChildrenNode, 1); + (char *)xmlNodeListGetString(node->doc, node->children, 1); if ((*dateTime)->value == NULL) { ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, -- 1.6.0.4

On Sun, Dec 13, 2009 at 12:20:41AM +0100, Matthias Bolte wrote:
--- src/esx/esx_vi.c | 2 +- src/esx/esx_vi_types.c | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c index fd86cde..21c405f 100644 --- a/src/esx/esx_vi.c +++ b/src/esx/esx_vi.c @@ -949,7 +949,7 @@ esxVI_List_CastFromAnyType(virConnectPtr conn, esxVI_AnyType *anyType, goto failure; }
- for (childNode = anyType->_node->xmlChildrenNode; childNode != NULL; + for (childNode = anyType->_node->children; childNode != NULL; childNode = childNode->next) { if (childNode->type != XML_ELEMENT_NODE) { ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, diff --git a/src/esx/esx_vi_types.c b/src/esx/esx_vi_types.c index aa2f968..8c5b17b 100644 --- a/src/esx/esx_vi_types.c +++ b/src/esx/esx_vi_types.c @@ -229,7 +229,7 @@ return -1; \ } \ \ - for (childNode = node->xmlChildrenNode; childNode != NULL; \ + for (childNode = node->children; childNode != NULL; \ childNode = childNode->next) { \ if (childNode->type != XML_ELEMENT_NODE) { \ ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, \ @@ -272,8 +272,7 @@ return -1; \ } \ \ - string = (char *)xmlNodeListGetString(node->doc, \ - node->xmlChildrenNode, 1); \ + string = (char *)xmlNodeListGetString(node->doc, node->children, 1); \ \ if (string == NULL) { \ ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, \ @@ -639,7 +638,7 @@ esxVI_AnyType_Deserialize(virConnectPtr conn, xmlNodePtr node, }
(*anyType)->value = - (char *)xmlNodeListGetString(node->doc, node->xmlChildrenNode, 1); + (char *)xmlNodeListGetString(node->doc, node->children, 1);
if ((*anyType)->value == NULL) { (*anyType)->value = strdup(""); @@ -883,7 +882,7 @@ esxVI_String_Deserialize(virConnectPtr conn, xmlNodePtr node, }
(*string)->value = - (char *)xmlNodeListGetString(node->doc, node->xmlChildrenNode, 1); + (char *)xmlNodeListGetString(node->doc, node->children, 1);
if ((*string)->value == NULL) { (*string)->value = strdup(""); @@ -914,7 +913,7 @@ esxVI_String_DeserializeValue(virConnectPtr conn, xmlNodePtr node, return -1; }
- *value = (char *)xmlNodeListGetString(node->doc, node->xmlChildrenNode, 1); + *value = (char *)xmlNodeListGetString(node->doc, node->children, 1);
if (*value == NULL) { *value = strdup(""); @@ -1049,7 +1048,7 @@ esxVI_DateTime_Deserialize(virConnectPtr conn, xmlNodePtr node, }
(*dateTime)->value = - (char *)xmlNodeListGetString(node->doc, node->xmlChildrenNode, 1); + (char *)xmlNodeListGetString(node->doc, node->children, 1);
if ((*dateTime)->value == NULL) { ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
Well there is a compat macro, but right, I didn't spot that :-) Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

--- src/esx/esx_vi.c | 3 --- 1 files changed, 0 insertions(+), 3 deletions(-) diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c index 21c405f..cbc4613 100644 --- a/src/esx/esx_vi.c +++ b/src/esx/esx_vi.c @@ -22,9 +22,6 @@ #include <config.h> -#define __STDC_FORMAT_MACROS -#include <inttypes.h> - #include <libxml/parser.h> #include <libxml/xpathInternals.h> -- 1.6.0.4

If an ESX host is managed by a vCenter, it knows the IP address of the vCenter. Setting the vCenter query parameter to * allows to connect to the vCenter known to an ESX host without the need to specify its IP address or hostname explicitly. --- src/esx/esx_driver.c | 125 +++++++++++++++++++++++++++++++++++++++----------- 1 files changed, 98 insertions(+), 27 deletions(-) diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index db379d7..d7e1ab5 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -234,7 +234,7 @@ esxCapsInit(virConnectPtr conn) /* - * URI format: {esx|gsx}://[<user>@]<server>[:<port>][?transport={http|https}][&vcenter=<vcenter>][&no_verify={0|1}][&auto_answer={0|1}] + * URI format: {esx|gsx}://[<user>@]<server>[:<port>]/[<query parameter> ...] * * If no port is specified the default port is set dependent on the scheme and * transport parameter: @@ -243,10 +243,19 @@ esxCapsInit(virConnectPtr conn) * - gsx+http 8222 * - gsx+https 8333 * + * Optional query parameters: + * - transport={http|https} + * - vcenter={<vcenter>|*} + * - no_verify={0|1} + * - auto_answer={0|1} + * * If no transport parameter is specified https is used. * * The vcenter parameter is only necessary for migration, because the vCenter - * server is in charge to initiate a migration between two ESX hosts. + * 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 *, + * 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. * * If the no_verify parameter is set to 1, this disables libcurl client checks * of the server's certificate. The default value it 0. @@ -258,6 +267,7 @@ esxCapsInit(virConnectPtr conn) static virDrvOpenStatus esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) { + virDrvOpenStatus result = VIR_DRV_OPEN_SUCCESS; esxPrivate *priv = NULL; char hostIpAddress[NI_MAXHOST] = ""; char vCenterIpAddress[NI_MAXHOST] = ""; @@ -267,6 +277,9 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) int autoAnswer = 0; // boolean char *username = NULL; char *password = NULL; + esxVI_String *propertyNameList = NULL; + esxVI_ObjectContent *hostSystem = NULL; + esxVI_DynamicProperty *dynamicProperty = NULL; /* Decline if the URI is NULL or the scheme is neither 'esx' nor 'gsx' */ if (conn->uri == NULL || conn->uri->scheme == NULL || @@ -305,18 +318,6 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) priv->autoAnswer = esxVI_Boolean_True; } - /* Request credentials and login to host/vCenter */ - if (esxUtil_ResolveHostname(conn, conn->uri->server, hostIpAddress, - NI_MAXHOST) < 0) { - goto failure; - } - - if (vCenter != NULL && - esxUtil_ResolveHostname(conn, vCenter, vCenterIpAddress, - NI_MAXHOST) < 0) { - goto failure; - } - /* * Set the port dependent on the transport protocol if no port is * specified. This allows us to rely on the port parameter being @@ -340,6 +341,11 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) } /* Login to host */ + if (esxUtil_ResolveHostname(conn, conn->uri->server, hostIpAddress, + NI_MAXHOST) < 0) { + goto failure; + } + if (virAsprintf(&url, "%s://%s:%d/sdk", priv->transport, conn->uri->server, conn->uri->port) < 0) { virReportOOMError(conn); @@ -394,12 +400,77 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) } } - VIR_FREE(url); - VIR_FREE(password); - VIR_FREE(username); - /* Login to vCenter */ if (vCenter != NULL) { + VIR_FREE(url); + VIR_FREE(password); + VIR_FREE(username); + + /* If a vCenter is specified resolve the hostname */ + if (STRNEQ(vCenter, "*") && + esxUtil_ResolveHostname(conn, vCenter, vCenterIpAddress, + NI_MAXHOST) < 0) { + goto failure; + } + + /* Lookup the vCenter from the ESX host */ + if (esxVI_String_AppendValueToList + (conn, &propertyNameList, "summary.managementServerIp") < 0 || + esxVI_LookupHostSystemByIp(conn, priv->host, hostIpAddress, + propertyNameList, &hostSystem) < 0) { + goto failure; + } + + for (dynamicProperty = hostSystem->propSet; dynamicProperty != NULL; + dynamicProperty = dynamicProperty->_next) { + if (STREQ(dynamicProperty->name, + "summary.managementServerIp")) { + if (esxVI_AnyType_ExpectType(conn, dynamicProperty->val, + esxVI_Type_String) < 0) { + goto failure; + } + + /* Get the vCenter IP address or verify the specified one */ + if (STREQ(vCenter, "*")) { + VIR_FREE(vCenter); + + vCenter = strdup(dynamicProperty->val->string); + + if (vCenter == NULL) { + virReportOOMError(conn); + goto failure; + } + + if (virStrcpyStatic(vCenterIpAddress, + dynamicProperty->val->string) == NULL) { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "vCenter IP address %s too big for " + "destination", dynamicProperty->val->string); + goto failure; + } + } else if (STRNEQ(vCenterIpAddress, + dynamicProperty->val->string)) { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "This host is managed by a vCenter with IP " + "address %s, but a mismachting vCenter '%s' " + "(%s) has been specified", + dynamicProperty->val->string, vCenter, + vCenterIpAddress); + goto failure; + } + + break; + } else { + VIR_WARN("Unexpected '%s' property", dynamicProperty->name); + } + } + + if (STREQ(vCenter, "*")) { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "This host is not managed by a vCenter"); + goto failure; + } + if (virAsprintf(&url, "%s://%s/sdk", priv->transport, vCenter) < 0) { virReportOOMError(conn); @@ -440,11 +511,6 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) conn->uri->server); goto failure; } - - VIR_FREE(url); - VIR_FREE(vCenter); - VIR_FREE(password); - VIR_FREE(username); } conn->privateData = priv; @@ -456,14 +522,17 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) goto failure; } - return VIR_DRV_OPEN_SUCCESS; - - failure: + cleanup: VIR_FREE(url); VIR_FREE(vCenter); VIR_FREE(password); VIR_FREE(username); + esxVI_String_Free(&propertyNameList); + esxVI_ObjectContent_Free(&hostSystem); + return result; + + failure: if (priv != NULL) { esxVI_Context_Free(&priv->host); esxVI_Context_Free(&priv->vCenter); @@ -474,7 +543,9 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) VIR_FREE(priv); } - return VIR_DRV_OPEN_ERROR; + result = VIR_DRV_OPEN_ERROR; + + goto cleanup; } -- 1.6.0.4

On Sun, Dec 13, 2009 at 12:20:43AM +0100, Matthias Bolte wrote:
If an ESX host is managed by a vCenter, it knows the IP address of the vCenter. Setting the vCenter query parameter to * allows to connect to the vCenter known to an ESX host without the need to specify its IP address or hostname explicitly. --- src/esx/esx_driver.c | 125 +++++++++++++++++++++++++++++++++++++++----------- 1 files changed, 98 insertions(+), 27 deletions(-)
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index db379d7..d7e1ab5 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -234,7 +234,7 @@ esxCapsInit(virConnectPtr conn)
/* - * URI format: {esx|gsx}://[<user>@]<server>[:<port>][?transport={http|https}][&vcenter=<vcenter>][&no_verify={0|1}][&auto_answer={0|1}] + * URI format: {esx|gsx}://[<user>@]<server>[:<port>]/[<query parameter> ...] * * If no port is specified the default port is set dependent on the scheme and * transport parameter: @@ -243,10 +243,19 @@ esxCapsInit(virConnectPtr conn) * - gsx+http 8222 * - gsx+https 8333 * + * Optional query parameters: + * - transport={http|https} + * - vcenter={<vcenter>|*} + * - no_verify={0|1} + * - auto_answer={0|1} + * * If no transport parameter is specified https is used. * * The vcenter parameter is only necessary for migration, because the vCenter - * server is in charge to initiate a migration between two ESX hosts. + * 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 *, + * 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. * * If the no_verify parameter is set to 1, this disables libcurl client checks * of the server's certificate. The default value it 0. @@ -258,6 +267,7 @@ esxCapsInit(virConnectPtr conn) static virDrvOpenStatus esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) { + virDrvOpenStatus result = VIR_DRV_OPEN_SUCCESS; esxPrivate *priv = NULL; char hostIpAddress[NI_MAXHOST] = ""; char vCenterIpAddress[NI_MAXHOST] = ""; @@ -267,6 +277,9 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) int autoAnswer = 0; // boolean char *username = NULL; char *password = NULL; + esxVI_String *propertyNameList = NULL; + esxVI_ObjectContent *hostSystem = NULL; + esxVI_DynamicProperty *dynamicProperty = NULL;
/* Decline if the URI is NULL or the scheme is neither 'esx' nor 'gsx' */ if (conn->uri == NULL || conn->uri->scheme == NULL || @@ -305,18 +318,6 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) priv->autoAnswer = esxVI_Boolean_True; }
- /* Request credentials and login to host/vCenter */ - if (esxUtil_ResolveHostname(conn, conn->uri->server, hostIpAddress, - NI_MAXHOST) < 0) { - goto failure; - } - - if (vCenter != NULL && - esxUtil_ResolveHostname(conn, vCenter, vCenterIpAddress, - NI_MAXHOST) < 0) { - goto failure; - } - /* * Set the port dependent on the transport protocol if no port is * specified. This allows us to rely on the port parameter being @@ -340,6 +341,11 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) }
/* Login to host */ + if (esxUtil_ResolveHostname(conn, conn->uri->server, hostIpAddress, + NI_MAXHOST) < 0) { + goto failure; + } + if (virAsprintf(&url, "%s://%s:%d/sdk", priv->transport, conn->uri->server, conn->uri->port) < 0) { virReportOOMError(conn); @@ -394,12 +400,77 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) } }
- VIR_FREE(url); - VIR_FREE(password); - VIR_FREE(username); - /* Login to vCenter */ if (vCenter != NULL) { + VIR_FREE(url); + VIR_FREE(password); + VIR_FREE(username); + + /* If a vCenter is specified resolve the hostname */ + if (STRNEQ(vCenter, "*") && + esxUtil_ResolveHostname(conn, vCenter, vCenterIpAddress, + NI_MAXHOST) < 0) { + goto failure; + } + + /* Lookup the vCenter from the ESX host */ + if (esxVI_String_AppendValueToList + (conn, &propertyNameList, "summary.managementServerIp") < 0 || + esxVI_LookupHostSystemByIp(conn, priv->host, hostIpAddress, + propertyNameList, &hostSystem) < 0) { + goto failure; + } + + for (dynamicProperty = hostSystem->propSet; dynamicProperty != NULL; + dynamicProperty = dynamicProperty->_next) { + if (STREQ(dynamicProperty->name, + "summary.managementServerIp")) { + if (esxVI_AnyType_ExpectType(conn, dynamicProperty->val, + esxVI_Type_String) < 0) { + goto failure; + } + + /* Get the vCenter IP address or verify the specified one */ + if (STREQ(vCenter, "*")) { + VIR_FREE(vCenter); + + vCenter = strdup(dynamicProperty->val->string); + + if (vCenter == NULL) { + virReportOOMError(conn); + goto failure; + } + + if (virStrcpyStatic(vCenterIpAddress, + dynamicProperty->val->string) == NULL) { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "vCenter IP address %s too big for " + "destination", dynamicProperty->val->string); + goto failure; + } + } else if (STRNEQ(vCenterIpAddress, + dynamicProperty->val->string)) { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "This host is managed by a vCenter with IP " + "address %s, but a mismachting vCenter '%s' " + "(%s) has been specified", + dynamicProperty->val->string, vCenter, + vCenterIpAddress); + goto failure; + } + + break; + } else { + VIR_WARN("Unexpected '%s' property", dynamicProperty->name); + } + } + + if (STREQ(vCenter, "*")) { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "This host is not managed by a vCenter"); + goto failure; + } + if (virAsprintf(&url, "%s://%s/sdk", priv->transport, vCenter) < 0) { virReportOOMError(conn); @@ -440,11 +511,6 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) conn->uri->server); goto failure; } - - VIR_FREE(url); - VIR_FREE(vCenter); - VIR_FREE(password); - VIR_FREE(username); }
conn->privateData = priv; @@ -456,14 +522,17 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) goto failure; }
- return VIR_DRV_OPEN_SUCCESS; - - failure: + cleanup: VIR_FREE(url); VIR_FREE(vCenter); VIR_FREE(password); VIR_FREE(username); + esxVI_String_Free(&propertyNameList); + esxVI_ObjectContent_Free(&hostSystem);
+ return result; + + failure: if (priv != NULL) { esxVI_Context_Free(&priv->host); esxVI_Context_Free(&priv->vCenter); @@ -474,7 +543,9 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) VIR_FREE(priv); }
- return VIR_DRV_OPEN_ERROR; + result = VIR_DRV_OPEN_ERROR; + + goto cleanup; }
ACK, this should make it easier to set things up ! The doc update is nice, as well as the HTML update in the following patch Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

--- docs/drvesx.html.in | 52 ++++++++++++++++++++++++++++++++++++++++++++------ src/esx/README | 8 +++--- 2 files changed, 49 insertions(+), 11 deletions(-) diff --git a/docs/drvesx.html.in b/docs/drvesx.html.in index 362659c..b7909ff 100644 --- a/docs/drvesx.html.in +++ b/docs/drvesx.html.in @@ -15,7 +15,7 @@ installed on the ESX server. The driver uses version 2.5 of the remote, SOAP based <a href="http://www.vmware.com/support/developer/vc-sdk/visdk25pubs/ReferenceGuide/"> - VMware Virtual Infrastructure API</a> to communicate with the + VMware Virtual Infrastructure API</a> (VI API) to communicate with the ESX server, like the VMware Virtual Infrastructure Client does. Since version 4.0 this API is called <a href="http://www.vmware.com/support/developer/vc-sdk/visdk400pubs/ReferenceGuide/"> @@ -78,11 +78,12 @@ type://[username@]hostname[:port]/[?extraparameters] <code>vcenter</code> </td> <td> - Hostname of a VMware vCenter + Hostname of a VMware vCenter or <code>*</code> </td> <td> In order to perform a migration the driver needs to know the - VMware vCenter for the ESX server. + VMware vCenter for the ESX server. If set to <code>*</code>, + the driver connects to the vCenter known to the ESX server. </td> </tr> <tr> @@ -97,6 +98,20 @@ type://[username@]hostname[:port]/[?extraparameters] SSL certificate. The default value it 0. </td> </tr> + <tr> + <td> + <code>auto_answer</code> + </td> + <td> + <code>0</code> or <code>1</code> + </td> + <td> + If set to 1, the driver answers all + <a href="#questions">questions</a> with the default answer. + If set to 0, questions are reported as errors. The default + value it 0. + </td> + </tr> </table> @@ -120,6 +135,25 @@ type://[username@]hostname[:port]/[?extraparameters] </p> + <h2><a name="questions">Questions blocking tasks</a></h2> + <p> + Some methods of the VI API start tasks, for example + <code>PowerOnVM_Task()</code>. Such tasks may be blocked by questions + if the ESX server detects an issue with the domain that requires user + interaction. The ESX driver cannot prompt the user to answer a + question, libvirt doesn't have an API for something like this. + </p> + <p> + The VI API provides the <code>AnswerVM()</code> method to + programmatically answer a questions. So the driver has two options + how to handle such a situation: either answer the questions with the + default answer or report the question as an error and cancel the + blocked task if possible. The + <a href="#uriformat"><code>auto_answer</code></a> query parameter + controls the answering behavior. + </p> + + <h2><a name="xmlspecial">Specialties in the domain XML config</a></h2> <p> There are several specialties in the domain XML config for ESX domains. @@ -404,8 +438,12 @@ ethernet0.address = "00:50:56:25:48:C7" <h2><a name="migration">Migration</a></h2> <p> A migration cannot be initiated on an ESX server directly, a VMware - vCenter is necessary for this. The vCenter hostname has to be passed - to the driver via the <code>vcenter</code> query parameter. + vCenter is necessary for this. The <code>vcenter</code> query + parameter must be set either to the hostname or IP address of the + vCenter managing the ESX server or to <code>*</code>. Setting it + to <code>*</code> causes the driver to connect to the vCenter known to + the ESX server. If the ESX server is not managed by a vCenter an error + is reported. </p> <pre> esx://example.com/?vcenter=example-vcenter.com @@ -413,11 +451,11 @@ esx://example.com/?vcenter=example-vcenter.com <p> Here 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> involving vCenter + <code>example-dst.com</code> implicitly involving vCenter <code>example-vcenter.com</code> using <code>virsh</code>. </p> <pre> -$ virsh -c esx://example-src.com/?vcenter=example-vcenter.com migrate Fedora11 esx://example-dst.com/?vcenter=example-vcenter.com +$ virsh -c esx://example-src.com/?vcenter=* migrate Fedora11 esx://example-dst.com/?vcenter=* Enter username for example-src.com [root]: Enter root password for example-src.com: Enter username for example-vcenter.com [administrator]: diff --git a/src/esx/README b/src/esx/README index 3619054..51e49e3 100644 --- a/src/esx/README +++ b/src/esx/README @@ -18,8 +18,8 @@ Automatic question handling What is a question in the ESX context? -------------------------------------- -The VI API contains calls that start tasks, for example PowerOnVM_Task(). Such -tasks may be blocked by a question if the ESX host detects an issue with the +The VI API contains methods that start tasks, for example PowerOnVM_Task(). Such +tasks may be blocked by questions if the ESX host detects an issue with the virtual machine that requires user interaction. An example: If a virtual machine has a serial port that is realized via a file, @@ -29,8 +29,8 @@ Until this question is answered the power-on task is blocked and the virtual machine won't get powered on. The ESX driver cannot prompt the user to answer a question, libvirt doesn't -have an API for something like this. The VI API provides a AnswerVM() method to -programmatically answer such questions. A question comes together with a list +have an API for something like this. The VI API provides the AnswerVM() method +to programmatically answer such questions. A question comes together with a list of possible answers. One of this answers is marked as the default one. For all questions I've seen so far the default answer is always a non-destructive one. -- 1.6.0.4

On Sun, Dec 13, 2009 at 12:20:44AM +0100, Matthias Bolte wrote:
--- docs/drvesx.html.in | 52 ++++++++++++++++++++++++++++++++++++++++++++------ src/esx/README | 8 +++--- 2 files changed, 49 insertions(+), 11 deletions(-)
diff --git a/docs/drvesx.html.in b/docs/drvesx.html.in index 362659c..b7909ff 100644 --- a/docs/drvesx.html.in +++ b/docs/drvesx.html.in @@ -15,7 +15,7 @@ installed on the ESX server. The driver uses version 2.5 of the remote, SOAP based <a href="http://www.vmware.com/support/developer/vc-sdk/visdk25pubs/ReferenceGuide/"> - VMware Virtual Infrastructure API</a> to communicate with the + VMware Virtual Infrastructure API</a> (VI API) to communicate with the ESX server, like the VMware Virtual Infrastructure Client does. Since version 4.0 this API is called <a href="http://www.vmware.com/support/developer/vc-sdk/visdk400pubs/ReferenceGuide/"> @@ -78,11 +78,12 @@ type://[username@]hostname[:port]/[?extraparameters] <code>vcenter</code> </td> <td> - Hostname of a VMware vCenter + Hostname of a VMware vCenter or <code>*</code> </td> <td> In order to perform a migration the driver needs to know the - VMware vCenter for the ESX server. + VMware vCenter for the ESX server. If set to <code>*</code>, + the driver connects to the vCenter known to the ESX server. </td> </tr> <tr> @@ -97,6 +98,20 @@ type://[username@]hostname[:port]/[?extraparameters] SSL certificate. The default value it 0. </td> </tr> + <tr> + <td> + <code>auto_answer</code> + </td> + <td> + <code>0</code> or <code>1</code> + </td> + <td> + If set to 1, the driver answers all + <a href="#questions">questions</a> with the default answer. + If set to 0, questions are reported as errors. The default + value it 0. + </td> + </tr> </table>
@@ -120,6 +135,25 @@ type://[username@]hostname[:port]/[?extraparameters] </p>
+ <h2><a name="questions">Questions blocking tasks</a></h2> + <p> + Some methods of the VI API start tasks, for example + <code>PowerOnVM_Task()</code>. Such tasks may be blocked by questions + if the ESX server detects an issue with the domain that requires user + interaction. The ESX driver cannot prompt the user to answer a + question, libvirt doesn't have an API for something like this. + </p> + <p> + The VI API provides the <code>AnswerVM()</code> method to + programmatically answer a questions. So the driver has two options + how to handle such a situation: either answer the questions with the + default answer or report the question as an error and cancel the + blocked task if possible. The + <a href="#uriformat"><code>auto_answer</code></a> query parameter + controls the answering behavior. + </p> + + <h2><a name="xmlspecial">Specialties in the domain XML config</a></h2> <p> There are several specialties in the domain XML config for ESX domains. @@ -404,8 +438,12 @@ ethernet0.address = "00:50:56:25:48:C7" <h2><a name="migration">Migration</a></h2> <p> A migration cannot be initiated on an ESX server directly, a VMware - vCenter is necessary for this. The vCenter hostname has to be passed - to the driver via the <code>vcenter</code> query parameter. + vCenter is necessary for this. The <code>vcenter</code> query + parameter must be set either to the hostname or IP address of the + vCenter managing the ESX server or to <code>*</code>. Setting it + to <code>*</code> causes the driver to connect to the vCenter known to + the ESX server. If the ESX server is not managed by a vCenter an error + is reported. </p> <pre> esx://example.com/?vcenter=example-vcenter.com @@ -413,11 +451,11 @@ esx://example.com/?vcenter=example-vcenter.com <p> Here 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> involving vCenter + <code>example-dst.com</code> implicitly involving vCenter <code>example-vcenter.com</code> using <code>virsh</code>. </p> <pre> -$ virsh -c esx://example-src.com/?vcenter=example-vcenter.com migrate Fedora11 esx://example-dst.com/?vcenter=example-vcenter.com +$ virsh -c esx://example-src.com/?vcenter=* migrate Fedora11 esx://example-dst.com/?vcenter=* Enter username for example-src.com [root]: Enter root password for example-src.com: Enter username for example-vcenter.com [administrator]: diff --git a/src/esx/README b/src/esx/README index 3619054..51e49e3 100644 --- a/src/esx/README +++ b/src/esx/README @@ -18,8 +18,8 @@ Automatic question handling What is a question in the ESX context? --------------------------------------
-The VI API contains calls that start tasks, for example PowerOnVM_Task(). Such -tasks may be blocked by a question if the ESX host detects an issue with the +The VI API contains methods that start tasks, for example PowerOnVM_Task(). Such +tasks may be blocked by questions if the ESX host detects an issue with the virtual machine that requires user interaction.
An example: If a virtual machine has a serial port that is realized via a file, @@ -29,8 +29,8 @@ Until this question is answered the power-on task is blocked and the virtual machine won't get powered on.
The ESX driver cannot prompt the user to answer a question, libvirt doesn't -have an API for something like this. The VI API provides a AnswerVM() method to -programmatically answer such questions. A question comes together with a list +have an API for something like this. The VI API provides the AnswerVM() method +to programmatically answer such questions. A question comes together with a list of possible answers. One of this answers is marked as the default one. For all questions I've seen so far the default answer is always a non-destructive one.
ACK, thanks ! Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

--- src/esx/esx_driver.c | 20 ++++++++++---------- src/esx/esx_vi.c | 14 +++++++------- src/esx/esx_vi.h | 16 ++++++++-------- src/esx/esx_vi_methods.c | 2 +- src/esx/esx_vmx.c | 2 +- 5 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index d7e1ab5..ca8b4d3 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -1158,7 +1158,7 @@ esxDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid) "runtime.powerState\0") < 0 || esxVI_LookupVirtualMachineByUuid(conn, priv->host, uuid, propertyNameList, &virtualMachine, - esxVI_Occurence_RequiredItem) < 0 || + esxVI_Occurrence_RequiredItem) < 0 || esxVI_GetVirtualMachineIdentity(conn, virtualMachine, &id, &name, NULL) < 0 || esxVI_GetVirtualMachinePowerState(conn, virtualMachine, @@ -1415,7 +1415,7 @@ esxDomainShutdown(virDomainPtr domain) esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host, domain->uuid, propertyNameList, &virtualMachine, - esxVI_Occurence_RequiredItem) < 0 || + esxVI_Occurrence_RequiredItem) < 0 || esxVI_GetVirtualMachinePowerState(domain->conn, virtualMachine, &powerState) < 0) { goto failure; @@ -1464,7 +1464,7 @@ esxDomainReboot(virDomainPtr domain, unsigned int flags ATTRIBUTE_UNUSED) esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host, domain->uuid, propertyNameList, &virtualMachine, - esxVI_Occurence_RequiredItem) < 0 || + esxVI_Occurrence_RequiredItem) < 0 || esxVI_GetVirtualMachinePowerState(domain->conn, virtualMachine, &powerState) < 0) { goto failure; @@ -1587,7 +1587,7 @@ esxDomainGetMaxMemory(virDomainPtr domain) esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host, domain->uuid, propertyNameList, &virtualMachine, - esxVI_Occurence_RequiredItem) < 0) { + esxVI_Occurrence_RequiredItem) < 0) { goto failure; } @@ -1771,7 +1771,7 @@ esxDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info) esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host, domain->uuid, propertyNameList, &virtualMachine, - esxVI_Occurence_RequiredItem) < 0) { + esxVI_Occurrence_RequiredItem) < 0) { goto failure; } @@ -2159,7 +2159,7 @@ esxDomainDumpXML(virDomainPtr domain, int flags) esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host, domain->uuid, propertyNameList, &virtualMachine, - esxVI_Occurence_RequiredItem) < 0) { + esxVI_Occurrence_RequiredItem) < 0) { goto failure; } @@ -2497,7 +2497,7 @@ esxDomainDefineXML(virConnectPtr conn, const char *xml ATTRIBUTE_UNUSED) /* Check if an existing domain should be edited */ if (esxVI_LookupVirtualMachineByUuid(conn, priv->host, def->uuid, NULL, &virtualMachine, - esxVI_Occurence_OptionalItem) < 0) { + esxVI_Occurrence_OptionalItem) < 0) { goto failure; } @@ -2686,7 +2686,7 @@ esxDomainUndefine(virDomainPtr domain) esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host, domain->uuid, propertyNameList, &virtualMachine, - esxVI_Occurence_RequiredItem) < 0 || + esxVI_Occurrence_RequiredItem) < 0 || esxVI_GetVirtualMachinePowerState(domain->conn, virtualMachine, &powerState) < 0) { goto failure; @@ -2794,7 +2794,7 @@ esxDomainGetSchedulerParameters(virDomainPtr domain, esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host, domain->uuid, propertyNameList, &virtualMachine, - esxVI_Occurence_RequiredItem) < 0) { + esxVI_Occurrence_RequiredItem) < 0) { goto failure; } @@ -3332,7 +3332,7 @@ esxDomainIsActive(virDomainPtr domain) esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host, domain->uuid, propertyNameList, &virtualMachine, - esxVI_Occurence_RequiredItem) < 0 || + esxVI_Occurrence_RequiredItem) < 0 || esxVI_GetVirtualMachinePowerState(domain->conn, virtualMachine, &powerState) < 0) { goto failure; diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c index cbc4613..e039a5d 100644 --- a/src/esx/esx_vi.c +++ b/src/esx/esx_vi.c @@ -1803,7 +1803,7 @@ esxVI_LookupVirtualMachineByUuid(virConnectPtr conn, esxVI_Context *ctx, const unsigned char *uuid, esxVI_String *propertyNameList, esxVI_ObjectContent **virtualMachine, - esxVI_Occurence occurence) + esxVI_Occurrence occurrence) { int result = 0; esxVI_ManagedObjectReference *managedObjectReference = NULL; @@ -1820,7 +1820,7 @@ esxVI_LookupVirtualMachineByUuid(virConnectPtr conn, esxVI_Context *ctx, } if (managedObjectReference == NULL) { - if (occurence == esxVI_Occurence_OptionalItem) { + if (occurrence == esxVI_Occurrence_OptionalItem) { return 0; } else { virUUIDFormat(uuid, uuid_string); @@ -1870,7 +1870,7 @@ esxVI_LookupVirtualMachineByUuidAndPrepareForTask esxVI_LookupVirtualMachineByUuid(conn, ctx, uuid, completePropertyNameList, virtualMachine, - esxVI_Occurence_RequiredItem) < 0 || + esxVI_Occurrence_RequiredItem) < 0 || esxVI_GetVirtualMachineQuestionInfo(conn, *virtualMachine, &questionInfo) < 0 || esxVI_LookupPendingTaskInfoListByVirtualMachine @@ -1909,7 +1909,7 @@ int esxVI_LookupDatastoreByName(virConnectPtr conn, esxVI_Context *ctx, const char *name, esxVI_String *propertyNameList, esxVI_ObjectContent **datastore, - esxVI_Occurence occurence) + esxVI_Occurrence occurrence) { int result = 0; esxVI_String *completePropertyNameList = NULL; @@ -1943,7 +1943,7 @@ esxVI_LookupDatastoreByName(virConnectPtr conn, esxVI_Context *ctx, } if (datastoreList == NULL) { - if (occurence == esxVI_Occurence_OptionalItem) { + if (occurrence == esxVI_Occurrence_OptionalItem) { goto cleanup; } else { ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, @@ -2038,7 +2038,7 @@ esxVI_LookupDatastoreByName(virConnectPtr conn, esxVI_Context *ctx, } } - if (occurence != esxVI_Occurence_OptionalItem) { + if (occurrence != esxVI_Occurrence_OptionalItem) { if (numInaccessibleDatastores > 0) { ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Could not find datastore '%s', maybe it's " @@ -2196,7 +2196,7 @@ esxVI_LookupAndHandleVirtualMachineQuestion(virConnectPtr conn, "runtime.question") < 0 || esxVI_LookupVirtualMachineByUuid(conn, ctx, uuid, propertyNameList, &virtualMachine, - esxVI_Occurence_RequiredItem) < 0 || + esxVI_Occurrence_RequiredItem) < 0 || esxVI_GetVirtualMachineQuestionInfo(conn, virtualMachine, &questionInfo) < 0) { goto failure; diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h index a10d874..c2054c8 100644 --- a/src/esx/esx_vi.h +++ b/src/esx/esx_vi.h @@ -33,7 +33,7 @@ typedef enum _esxVI_APIVersion esxVI_APIVersion; typedef enum _esxVI_ProductVersion esxVI_ProductVersion; -typedef enum _esxVI_Occurence esxVI_Occurence; +typedef enum _esxVI_Occurrence esxVI_Occurrence; typedef struct _esxVI_Context esxVI_Context; typedef struct _esxVI_Response esxVI_Response; typedef struct _esxVI_Enumeration esxVI_Enumeration; @@ -58,11 +58,11 @@ enum _esxVI_ProductVersion { esxVI_ProductVersion_VPX40 }; -enum _esxVI_Occurence { - esxVI_Occurence_Undefined = 0, - esxVI_Occurence_RequiredItem, - esxVI_Occurence_OptionalItem, - esxVI_Occurence_List +enum _esxVI_Occurrence { + esxVI_Occurrence_Undefined = 0, + esxVI_Occurrence_RequiredItem, + esxVI_Occurrence_OptionalItem, + esxVI_Occurrence_List }; @@ -254,7 +254,7 @@ int esxVI_LookupVirtualMachineByUuid(virConnectPtr conn, esxVI_Context *ctx, const unsigned char *uuid, esxVI_String *propertyNameList, esxVI_ObjectContent **virtualMachine, - esxVI_Occurence occurence); + esxVI_Occurrence occurrence); int esxVI_LookupVirtualMachineByUuidAndPrepareForTask (virConnectPtr conn, esxVI_Context *ctx, const unsigned char *uuid, @@ -265,7 +265,7 @@ int esxVI_LookupDatastoreByName(virConnectPtr conn, esxVI_Context *ctx, const char *name, esxVI_String *propertyNameList, esxVI_ObjectContent **datastore, - esxVI_Occurence occurence); + esxVI_Occurrence occurrence); int esxVI_LookupTaskInfoByTask(virConnectPtr conn, esxVI_Context *ctx, esxVI_ManagedObjectReference *task, diff --git a/src/esx/esx_vi_methods.c b/src/esx/esx_vi_methods.c index d18e56b..6f9f3a8 100644 --- a/src/esx/esx_vi_methods.c +++ b/src/esx/esx_vi_methods.c @@ -1149,7 +1149,7 @@ esxVI_FindByUuid(virConnectPtr conn, esxVI_Context *ctx, request = virBufferContentAndReset(&buffer); - /* FIXME: Use esxVI_Occurence instead of expectList */ + /* FIXME: Use esxVI_Occurrence instead of expectList */ if (esxVI_Context_Execute(conn, ctx, request, ESX_VI__SOAP__RESPONSE_XPATH("FindByUuid"), &response, esxVI_Boolean_True) < 0) { diff --git a/src/esx/esx_vmx.c b/src/esx/esx_vmx.c index f5b4544..aaf14c2 100644 --- a/src/esx/esx_vmx.c +++ b/src/esx/esx_vmx.c @@ -608,7 +608,7 @@ esxVMX_AbsolutePathToDatastoreRelatedPath(virConnectPtr conn, if (ctx != NULL) { if (esxVI_LookupDatastoreByName(conn, ctx, preliminaryDatastoreName, NULL, &datastore, - esxVI_Occurence_OptionalItem) < 0) { + esxVI_Occurrence_OptionalItem) < 0) { goto failure; } -- 1.6.0.4

On Sun, Dec 13, 2009 at 12:20:45AM +0100, Matthias Bolte wrote:
--- src/esx/esx_driver.c | 20 ++++++++++---------- src/esx/esx_vi.c | 14 +++++++------- src/esx/esx_vi.h | 16 ++++++++-------- src/esx/esx_vi_methods.c | 2 +- src/esx/esx_vmx.c | 2 +- 5 files changed, 27 insertions(+), 27 deletions(-)
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index d7e1ab5..ca8b4d3 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -1158,7 +1158,7 @@ esxDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid) "runtime.powerState\0") < 0 || esxVI_LookupVirtualMachineByUuid(conn, priv->host, uuid, propertyNameList, &virtualMachine, - esxVI_Occurence_RequiredItem) < 0 || + esxVI_Occurrence_RequiredItem) < 0 || esxVI_GetVirtualMachineIdentity(conn, virtualMachine, &id, &name, NULL) < 0 || esxVI_GetVirtualMachinePowerState(conn, virtualMachine, @@ -1415,7 +1415,7 @@ esxDomainShutdown(virDomainPtr domain) esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host, domain->uuid, propertyNameList, &virtualMachine, - esxVI_Occurence_RequiredItem) < 0 || + esxVI_Occurrence_RequiredItem) < 0 || esxVI_GetVirtualMachinePowerState(domain->conn, virtualMachine, &powerState) < 0) { goto failure; @@ -1464,7 +1464,7 @@ esxDomainReboot(virDomainPtr domain, unsigned int flags ATTRIBUTE_UNUSED) esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host, domain->uuid, propertyNameList, &virtualMachine, - esxVI_Occurence_RequiredItem) < 0 || + esxVI_Occurrence_RequiredItem) < 0 || esxVI_GetVirtualMachinePowerState(domain->conn, virtualMachine, &powerState) < 0) { goto failure; @@ -1587,7 +1587,7 @@ esxDomainGetMaxMemory(virDomainPtr domain) esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host, domain->uuid, propertyNameList, &virtualMachine, - esxVI_Occurence_RequiredItem) < 0) { + esxVI_Occurrence_RequiredItem) < 0) { goto failure; }
@@ -1771,7 +1771,7 @@ esxDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info) esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host, domain->uuid, propertyNameList, &virtualMachine, - esxVI_Occurence_RequiredItem) < 0) { + esxVI_Occurrence_RequiredItem) < 0) { goto failure; }
@@ -2159,7 +2159,7 @@ esxDomainDumpXML(virDomainPtr domain, int flags) esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host, domain->uuid, propertyNameList, &virtualMachine, - esxVI_Occurence_RequiredItem) < 0) { + esxVI_Occurrence_RequiredItem) < 0) { goto failure; }
@@ -2497,7 +2497,7 @@ esxDomainDefineXML(virConnectPtr conn, const char *xml ATTRIBUTE_UNUSED) /* Check if an existing domain should be edited */ if (esxVI_LookupVirtualMachineByUuid(conn, priv->host, def->uuid, NULL, &virtualMachine, - esxVI_Occurence_OptionalItem) < 0) { + esxVI_Occurrence_OptionalItem) < 0) { goto failure; }
@@ -2686,7 +2686,7 @@ esxDomainUndefine(virDomainPtr domain) esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host, domain->uuid, propertyNameList, &virtualMachine, - esxVI_Occurence_RequiredItem) < 0 || + esxVI_Occurrence_RequiredItem) < 0 || esxVI_GetVirtualMachinePowerState(domain->conn, virtualMachine, &powerState) < 0) { goto failure; @@ -2794,7 +2794,7 @@ esxDomainGetSchedulerParameters(virDomainPtr domain, esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host, domain->uuid, propertyNameList, &virtualMachine, - esxVI_Occurence_RequiredItem) < 0) { + esxVI_Occurrence_RequiredItem) < 0) { goto failure; }
@@ -3332,7 +3332,7 @@ esxDomainIsActive(virDomainPtr domain) esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host, domain->uuid, propertyNameList, &virtualMachine, - esxVI_Occurence_RequiredItem) < 0 || + esxVI_Occurrence_RequiredItem) < 0 || esxVI_GetVirtualMachinePowerState(domain->conn, virtualMachine, &powerState) < 0) { goto failure; diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c index cbc4613..e039a5d 100644 --- a/src/esx/esx_vi.c +++ b/src/esx/esx_vi.c @@ -1803,7 +1803,7 @@ esxVI_LookupVirtualMachineByUuid(virConnectPtr conn, esxVI_Context *ctx, const unsigned char *uuid, esxVI_String *propertyNameList, esxVI_ObjectContent **virtualMachine, - esxVI_Occurence occurence) + esxVI_Occurrence occurrence) { int result = 0; esxVI_ManagedObjectReference *managedObjectReference = NULL; @@ -1820,7 +1820,7 @@ esxVI_LookupVirtualMachineByUuid(virConnectPtr conn, esxVI_Context *ctx, }
if (managedObjectReference == NULL) { - if (occurence == esxVI_Occurence_OptionalItem) { + if (occurrence == esxVI_Occurrence_OptionalItem) { return 0; } else { virUUIDFormat(uuid, uuid_string); @@ -1870,7 +1870,7 @@ esxVI_LookupVirtualMachineByUuidAndPrepareForTask esxVI_LookupVirtualMachineByUuid(conn, ctx, uuid, completePropertyNameList, virtualMachine, - esxVI_Occurence_RequiredItem) < 0 || + esxVI_Occurrence_RequiredItem) < 0 || esxVI_GetVirtualMachineQuestionInfo(conn, *virtualMachine, &questionInfo) < 0 || esxVI_LookupPendingTaskInfoListByVirtualMachine @@ -1909,7 +1909,7 @@ int esxVI_LookupDatastoreByName(virConnectPtr conn, esxVI_Context *ctx, const char *name, esxVI_String *propertyNameList, esxVI_ObjectContent **datastore, - esxVI_Occurence occurence) + esxVI_Occurrence occurrence) { int result = 0; esxVI_String *completePropertyNameList = NULL; @@ -1943,7 +1943,7 @@ esxVI_LookupDatastoreByName(virConnectPtr conn, esxVI_Context *ctx, }
if (datastoreList == NULL) { - if (occurence == esxVI_Occurence_OptionalItem) { + if (occurrence == esxVI_Occurrence_OptionalItem) { goto cleanup; } else { ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, @@ -2038,7 +2038,7 @@ esxVI_LookupDatastoreByName(virConnectPtr conn, esxVI_Context *ctx, } }
- if (occurence != esxVI_Occurence_OptionalItem) { + if (occurrence != esxVI_Occurrence_OptionalItem) { if (numInaccessibleDatastores > 0) { ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Could not find datastore '%s', maybe it's " @@ -2196,7 +2196,7 @@ esxVI_LookupAndHandleVirtualMachineQuestion(virConnectPtr conn, "runtime.question") < 0 || esxVI_LookupVirtualMachineByUuid(conn, ctx, uuid, propertyNameList, &virtualMachine, - esxVI_Occurence_RequiredItem) < 0 || + esxVI_Occurrence_RequiredItem) < 0 || esxVI_GetVirtualMachineQuestionInfo(conn, virtualMachine, &questionInfo) < 0) { goto failure; diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h index a10d874..c2054c8 100644 --- a/src/esx/esx_vi.h +++ b/src/esx/esx_vi.h @@ -33,7 +33,7 @@
typedef enum _esxVI_APIVersion esxVI_APIVersion; typedef enum _esxVI_ProductVersion esxVI_ProductVersion; -typedef enum _esxVI_Occurence esxVI_Occurence; +typedef enum _esxVI_Occurrence esxVI_Occurrence; typedef struct _esxVI_Context esxVI_Context; typedef struct _esxVI_Response esxVI_Response; typedef struct _esxVI_Enumeration esxVI_Enumeration; @@ -58,11 +58,11 @@ enum _esxVI_ProductVersion { esxVI_ProductVersion_VPX40 };
-enum _esxVI_Occurence { - esxVI_Occurence_Undefined = 0, - esxVI_Occurence_RequiredItem, - esxVI_Occurence_OptionalItem, - esxVI_Occurence_List +enum _esxVI_Occurrence { + esxVI_Occurrence_Undefined = 0, + esxVI_Occurrence_RequiredItem, + esxVI_Occurrence_OptionalItem, + esxVI_Occurrence_List };
@@ -254,7 +254,7 @@ int esxVI_LookupVirtualMachineByUuid(virConnectPtr conn, esxVI_Context *ctx, const unsigned char *uuid, esxVI_String *propertyNameList, esxVI_ObjectContent **virtualMachine, - esxVI_Occurence occurence); + esxVI_Occurrence occurrence);
int esxVI_LookupVirtualMachineByUuidAndPrepareForTask (virConnectPtr conn, esxVI_Context *ctx, const unsigned char *uuid, @@ -265,7 +265,7 @@ int esxVI_LookupDatastoreByName(virConnectPtr conn, esxVI_Context *ctx, const char *name, esxVI_String *propertyNameList, esxVI_ObjectContent **datastore, - esxVI_Occurence occurence); + esxVI_Occurrence occurrence);
int esxVI_LookupTaskInfoByTask(virConnectPtr conn, esxVI_Context *ctx, esxVI_ManagedObjectReference *task, diff --git a/src/esx/esx_vi_methods.c b/src/esx/esx_vi_methods.c index d18e56b..6f9f3a8 100644 --- a/src/esx/esx_vi_methods.c +++ b/src/esx/esx_vi_methods.c @@ -1149,7 +1149,7 @@ esxVI_FindByUuid(virConnectPtr conn, esxVI_Context *ctx,
request = virBufferContentAndReset(&buffer);
- /* FIXME: Use esxVI_Occurence instead of expectList */ + /* FIXME: Use esxVI_Occurrence instead of expectList */ if (esxVI_Context_Execute(conn, ctx, request, ESX_VI__SOAP__RESPONSE_XPATH("FindByUuid"), &response, esxVI_Boolean_True) < 0) { diff --git a/src/esx/esx_vmx.c b/src/esx/esx_vmx.c index f5b4544..aaf14c2 100644 --- a/src/esx/esx_vmx.c +++ b/src/esx/esx_vmx.c @@ -608,7 +608,7 @@ esxVMX_AbsolutePathToDatastoreRelatedPath(virConnectPtr conn, if (ctx != NULL) { if (esxVI_LookupDatastoreByName(conn, ctx, preliminaryDatastoreName, NULL, &datastore, - esxVI_Occurence_OptionalItem) < 0) { + esxVI_Occurrence_OptionalItem) < 0) { goto failure; }
-- 1.6.0.4
Trivial, ACK, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

Also move XPath expression composition into esxVI_Context_Execute(). --- src/esx/esx_vi.c | 155 +++++++++++++++++++++++++++++----------------- src/esx/esx_vi.h | 8 +- src/esx/esx_vi_methods.c | 80 ++++++++++-------------- 3 files changed, 133 insertions(+), 110 deletions(-) diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c index e039a5d..64bf649 100644 --- a/src/esx/esx_vi.c +++ b/src/esx/esx_vi.c @@ -514,7 +514,7 @@ esxVI_Context_DownloadFile(virConnectPtr conn, esxVI_Context *ctx, goto failure; } else if (responseCode != 200) { ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, - "HTTP response code %d while trying to download '%s'", + "HTTP response code %d for download from '%s'", responseCode, url); goto failure; } @@ -560,7 +560,7 @@ esxVI_Context_UploadFile(virConnectPtr conn, esxVI_Context *ctx, return -1; } else if (responseCode != 200 && responseCode != 201) { ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, - "HTTP response code %d while trying to upload to '%s'", + "HTTP response code %d for upload to '%s'", responseCode, url); return -1; } @@ -570,11 +570,15 @@ esxVI_Context_UploadFile(virConnectPtr conn, esxVI_Context *ctx, int esxVI_Context_Execute(virConnectPtr conn, esxVI_Context *ctx, - const char *request, const char *xpathExpression, - esxVI_Response **response, esxVI_Boolean expectList) + const char *methodName, const char *request, + esxVI_Response **response, esxVI_Occurrence occurrence) { + int result = 0; virBuffer buffer = VIR_BUFFER_INITIALIZER; esxVI_Fault *fault = NULL; + char *xpathExpression = NULL; + xmlXPathContextPtr xpathContext = NULL; + xmlNodePtr responseNode = NULL; if (request == NULL || response == NULL || *response != NULL) { ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument"); @@ -608,108 +612,146 @@ esxVI_Context_Execute(virConnectPtr conn, esxVI_Context *ctx, (*response)->content = virBufferContentAndReset(&buffer); - if ((*response)->responseCode == 500 || - (xpathExpression != NULL && (*response)->responseCode == 200)) { + if ((*response)->responseCode == 500 || (*response)->responseCode == 200) { (*response)->document = xmlReadDoc(BAD_CAST (*response)->content, "", NULL, XML_PARSE_NONET); if ((*response)->document == NULL) { ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, - "Could not parse XML response"); + "Response for call to '%s' could not be parsed", + methodName); goto failure; } if (xmlDocGetRootElement((*response)->document) == NULL) { ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, - "XML response is an empty document"); + "Response for call to '%s' is an empty XML document", + methodName); goto failure; } - (*response)->xpathContext = xmlXPathNewContext((*response)->document); + xpathContext = xmlXPathNewContext((*response)->document); - if ((*response)->xpathContext == NULL) { + if (xpathContext == NULL) { ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Could not create XPath context"); goto failure; } - xmlXPathRegisterNs((*response)->xpathContext, BAD_CAST "soapenv", + xmlXPathRegisterNs(xpathContext, BAD_CAST "soapenv", BAD_CAST "http://schemas.xmlsoap.org/soap/envelope/"); - xmlXPathRegisterNs((*response)->xpathContext, BAD_CAST "vim", - BAD_CAST "urn:vim25"); + xmlXPathRegisterNs(xpathContext, BAD_CAST "vim", BAD_CAST "urn:vim25"); if ((*response)->responseCode == 500) { (*response)->node = virXPathNode(conn, "/soapenv:Envelope/soapenv:Body/soapenv:Fault", - (*response)->xpathContext); + xpathContext); if ((*response)->node == NULL) { ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, - "HTTP response code %d. VI Fault is unknown, " - "XPath evaluation failed", - (int)(*response)->responseCode); + "HTTP response code %d for call to '%s'. " + "Fault is unknown, XPath evaluation failed", + (*response)->responseCode, methodName); goto failure; } if (esxVI_Fault_Deserialize(conn, (*response)->node, &fault) < 0) { ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, - "HTTP response code %d. VI Fault is unknown, " - "deserialization failed", - (int)(*response)->responseCode); + "HTTP response code %d for call to '%s'. " + "Fault is unknown, deserialization failed", + (*response)->responseCode, methodName); goto failure; } ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, - "HTTP response code %d. VI Fault: %s - %s", - (int)(*response)->responseCode, - fault->faultcode, fault->faultstring); - + "HTTP response code %d for call to '%s'. " + "Fault: %s - %s", (*response)->responseCode, + methodName, fault->faultcode, fault->faultstring); goto failure; - } else if (expectList == esxVI_Boolean_True) { - xmlNodePtr *nodeSet = NULL; - int nodeSet_size; + } else { + if (virAsprintf(&xpathExpression, + "/soapenv:Envelope/soapenv:Body/vim:%sResponse", + methodName) < 0) { + virReportOOMError(conn); + goto failure; + } - nodeSet_size = virXPathNodeSet(conn, xpathExpression, - (*response)->xpathContext, - &nodeSet); + responseNode = virXPathNode(conn, xpathExpression, xpathContext); - if (nodeSet_size < 0) { + if (responseNode == NULL) { ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, - "XPath evaluation of '%s' failed", - xpathExpression); + "XPath evaluation of response for call to '%s' " + "failed", methodName); goto failure; - } else if (nodeSet_size == 0) { - (*response)->node = NULL; - } else { - (*response)->node = nodeSet[0]; } - VIR_FREE(nodeSet); - } else { - (*response)->node = virXPathNode(conn, xpathExpression, - (*response)->xpathContext); + xpathContext->node = responseNode; + (*response)->node = virXPathNode(conn, "./vim:returnval", + xpathContext); - if ((*response)->node == NULL) { + switch (occurrence) { + case esxVI_Occurrence_RequiredItem: + if ((*response)->node == NULL) { + ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Call to '%s' returned an empty result, " + "expecting a non-empty result", methodName); + goto failure; + } + + break; + + case esxVI_Occurrence_OptionalItem: + if ((*response)->node != NULL && + (*response)->node->next != NULL) { + ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Call to '%s' returned a list, expecting " + "exactly one item", methodName); + goto failure; + } + + break; + + case esxVI_Occurrence_List: + /* Any amount of items is valid */ + break; + + case esxVI_Occurrence_None: + if ((*response)->node != NULL) { + ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Call to '%s' returned something, expecting " + "an empty result", methodName); + goto failure; + } + + break; + + default: ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, - "XPath evaluation of '%s' failed", - xpathExpression); + "Invalid argument (occurrence)"); goto failure; } } - } else if ((*response)->responseCode != 200) { + } else { ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, - "HTTP response code %d", (*response)->responseCode); + "HTTP response code %d for call to '%s'", + (*response)->responseCode, methodName); goto failure; } - return 0; + cleanup: + VIR_FREE(xpathExpression); + xmlXPathFreeContext(xpathContext); + + return result; failure: virBufferFreeAndReset(&buffer); esxVI_Response_Free(response); esxVI_Fault_Free(&fault); - return -1; + result = -1; + + goto cleanup; } @@ -726,8 +768,6 @@ ESX_VI__TEMPLATE__FREE(Response, { VIR_FREE(item->content); - xmlXPathFreeContext(item->xpathContext); - if (item->document != NULL) { xmlFreeDoc(item->document); } @@ -2229,24 +2269,23 @@ esxVI_StartVirtualMachineTask(virConnectPtr conn, esxVI_Context *ctx, esxVI_ManagedObjectReference **task) { int result = 0; - char *xpathExpression = NULL; + char *methodName = NULL; esxVI_Response *response = NULL; - if (virAsprintf(&xpathExpression, - ESX_VI__SOAP__RESPONSE_XPATH("%s_Task"), name) < 0) { + if (virAsprintf(&methodName, "%s_Task", name) < 0) { virReportOOMError(conn); goto failure; } - if (esxVI_Context_Execute(conn, ctx, request, xpathExpression, &response, - esxVI_Boolean_False) < 0 || + if (esxVI_Context_Execute(conn, ctx, methodName, request, &response, + esxVI_Occurrence_RequiredItem) < 0 || esxVI_ManagedObjectReference_Deserialize(conn, response->node, task, "Task") < 0) { goto failure; } cleanup: - VIR_FREE(xpathExpression); + VIR_FREE(methodName); esxVI_Response_Free(&response); return result; @@ -2349,8 +2388,8 @@ esxVI_SimpleVirtualMachineMethod(virConnectPtr conn, esxVI_Context *ctx, request = virBufferContentAndReset(&buffer); - if (esxVI_Context_Execute(conn, ctx, request, NULL, &response, - esxVI_Boolean_False) < 0) { + if (esxVI_Context_Execute(conn, ctx, name, request, &response, + esxVI_Occurrence_None) < 0) { goto failure; } diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h index c2054c8..840a3c3 100644 --- a/src/esx/esx_vi.h +++ b/src/esx/esx_vi.h @@ -62,7 +62,8 @@ enum _esxVI_Occurrence { esxVI_Occurrence_Undefined = 0, esxVI_Occurrence_RequiredItem, esxVI_Occurrence_OptionalItem, - esxVI_Occurrence_List + esxVI_Occurrence_List, + esxVI_Occurrence_None }; @@ -100,8 +101,8 @@ int esxVI_Context_DownloadFile(virConnectPtr conn, esxVI_Context *ctx, 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); + const char *methodName, const char *request, + esxVI_Response **response, esxVI_Occurrence occurrence); @@ -113,7 +114,6 @@ struct _esxVI_Response { int responseCode; /* required */ char *content; /* required */ xmlDocPtr document; /* optional */ - xmlXPathContextPtr xpathContext; /* optional */ xmlNodePtr node; /* optional, list */ }; diff --git a/src/esx/esx_vi_methods.c b/src/esx/esx_vi_methods.c index 6f9f3a8..be21112 100644 --- a/src/esx/esx_vi_methods.c +++ b/src/esx/esx_vi_methods.c @@ -49,9 +49,6 @@ "</soapenv:Body>" \ "</soapenv:Envelope>" -#define ESX_VI__SOAP__RESPONSE_XPATH(_type) \ - "/soapenv:Envelope/soapenv:Body/vim:"_type"Response/vim:returnval" - /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * @@ -79,9 +76,8 @@ esxVI_RetrieveServiceContent(virConnectPtr conn, esxVI_Context *ctx, return -1; } - if (esxVI_Context_Execute(conn, ctx, request, - ESX_VI__SOAP__RESPONSE_XPATH("RetrieveServiceContent"), - &response, esxVI_Boolean_False) < 0 || + if (esxVI_Context_Execute(conn, ctx, "RetrieveServiceContent", request, + &response, esxVI_Occurrence_RequiredItem) < 0 || esxVI_ServiceContent_Deserialize(conn, response->node, serviceContent) < 0) { goto failure; @@ -144,9 +140,8 @@ esxVI_Login(virConnectPtr conn, esxVI_Context *ctx, request = virBufferContentAndReset(&buffer); - if (esxVI_Context_Execute(conn, ctx, request, - ESX_VI__SOAP__RESPONSE_XPATH("Login"), - &response, esxVI_Boolean_False) < 0 || + if (esxVI_Context_Execute(conn, ctx, "Login", request, &response, + esxVI_Occurrence_RequiredItem) < 0 || esxVI_UserSession_Deserialize(conn, response->node, userSession) < 0) { goto failure; } @@ -200,8 +195,8 @@ esxVI_Logout(virConnectPtr conn, esxVI_Context *ctx) request = virBufferContentAndReset(&buffer); - if (esxVI_Context_Execute(conn, ctx, request, NULL, &response, - esxVI_Boolean_False) < 0) { + if (esxVI_Context_Execute(conn, ctx, "Logout", request, &response, + esxVI_Occurrence_None) < 0) { goto failure; } @@ -265,9 +260,8 @@ esxVI_SessionIsActive(virConnectPtr conn, esxVI_Context *ctx, request = virBufferContentAndReset(&buffer); - if (esxVI_Context_Execute(conn, ctx, request, - ESX_VI__SOAP__RESPONSE_XPATH("SessionIsActive"), - &response, esxVI_Boolean_False) < 0 || + if (esxVI_Context_Execute(conn, ctx, "SessionIsActive", request, + &response, esxVI_Occurrence_RequiredItem) < 0 || esxVI_Boolean_Deserialize(conn, response->node, active) < 0) { goto failure; } @@ -331,9 +325,8 @@ esxVI_RetrieveProperties(virConnectPtr conn, esxVI_Context *ctx, request = virBufferContentAndReset(&buffer); - if (esxVI_Context_Execute(conn, ctx, request, - ESX_VI__SOAP__RESPONSE_XPATH("RetrieveProperties"), - &response, esxVI_Boolean_True) < 0 || + if (esxVI_Context_Execute(conn, ctx, "RetrieveProperties", request, + &response, esxVI_Occurrence_List) < 0 || esxVI_ObjectContent_DeserializeList(conn, response->node, objectContentList) < 0) { goto failure; @@ -608,8 +601,8 @@ esxVI_CancelTask(virConnectPtr conn, esxVI_Context *ctx, request = virBufferContentAndReset(&buffer); - if (esxVI_Context_Execute(conn, ctx, request, NULL, &response, - esxVI_Boolean_False) < 0) { + if (esxVI_Context_Execute(conn, ctx, "UnregisterVM", request, &response, + esxVI_Occurrence_None) < 0) { goto failure; } @@ -659,8 +652,8 @@ esxVI_UnregisterVM(virConnectPtr conn, esxVI_Context *ctx, request = virBufferContentAndReset(&buffer); - if (esxVI_Context_Execute(conn, ctx, request, NULL, &response, - esxVI_Boolean_False) < 0) { + if (esxVI_Context_Execute(conn, ctx, "AnswerVM", request, &response, + esxVI_Occurrence_None) < 0) { goto failure; } @@ -781,9 +774,8 @@ esxVI_CreateFilter(virConnectPtr conn, esxVI_Context *ctx, request = virBufferContentAndReset(&buffer); - if (esxVI_Context_Execute(conn, ctx, request, - ESX_VI__SOAP__RESPONSE_XPATH("CreateFilter"), - &response, esxVI_Boolean_False) < 0 || + if (esxVI_Context_Execute(conn, ctx, "CreateFilter", request, &response, + esxVI_Occurrence_RequiredItem) < 0 || esxVI_ManagedObjectReference_Deserialize(conn, response->node, propertyFilter, "PropertyFilter") < 0) { @@ -839,8 +831,8 @@ esxVI_DestroyPropertyFilter(virConnectPtr conn, esxVI_Context *ctx, request = virBufferContentAndReset(&buffer); - if (esxVI_Context_Execute(conn, ctx, request, NULL, &response, - esxVI_Boolean_False) < 0) { + if (esxVI_Context_Execute(conn, ctx, "DestroyPropertyFilter", request, + &response, esxVI_Occurrence_None) < 0) { goto failure; } @@ -901,9 +893,8 @@ esxVI_WaitForUpdates(virConnectPtr conn, esxVI_Context *ctx, request = virBufferContentAndReset(&buffer); - if (esxVI_Context_Execute(conn, ctx, request, - ESX_VI__SOAP__RESPONSE_XPATH("WaitForUpdates"), - &response, esxVI_Boolean_False) < 0 || + if (esxVI_Context_Execute(conn, ctx, "WaitForUpdates", request, + &response, esxVI_Occurrence_RequiredItem) < 0 || esxVI_UpdateSet_Deserialize(conn, response->node, updateSet) < 0) { goto failure; } @@ -1003,9 +994,8 @@ esxVI_ValidateMigration(virConnectPtr conn, esxVI_Context *ctx, request = virBufferContentAndReset(&buffer); - if (esxVI_Context_Execute(conn, ctx, request, - ESX_VI__SOAP__RESPONSE_XPATH("ValidateMigration"), - &response, esxVI_Boolean_True) < 0 || + if (esxVI_Context_Execute(conn, ctx, "ValidateMigration", request, + &response, esxVI_Occurrence_List) < 0 || esxVI_Event_DeserializeList(conn, response->node, eventList) < 0) { goto failure; } @@ -1073,9 +1063,8 @@ esxVI_FindByIp(virConnectPtr conn, esxVI_Context *ctx, request = virBufferContentAndReset(&buffer); - if (esxVI_Context_Execute(conn, ctx, request, - ESX_VI__SOAP__RESPONSE_XPATH("FindByIp"), - &response, esxVI_Boolean_False) < 0 || + if (esxVI_Context_Execute(conn, ctx, "FindByIp", request, &response, + esxVI_Occurrence_OptionalItem) < 0 || esxVI_ManagedObjectReference_Deserialize (conn, response->node, managedObjectReference, vmSearch == esxVI_Boolean_True ? "VirtualMachine" @@ -1149,10 +1138,8 @@ esxVI_FindByUuid(virConnectPtr conn, esxVI_Context *ctx, request = virBufferContentAndReset(&buffer); - /* FIXME: Use esxVI_Occurrence instead of expectList */ - if (esxVI_Context_Execute(conn, ctx, request, - ESX_VI__SOAP__RESPONSE_XPATH("FindByUuid"), - &response, esxVI_Boolean_True) < 0) { + if (esxVI_Context_Execute(conn, ctx, "FindByUuid", request, &response, + esxVI_Occurrence_OptionalItem) < 0) { goto failure; } @@ -1233,9 +1220,8 @@ esxVI_QueryAvailablePerfMetric(virConnectPtr conn, esxVI_Context *ctx, request = virBufferContentAndReset(&buffer); - if (esxVI_Context_Execute(conn, ctx, request, - ESX_VI__SOAP__RESPONSE_XPATH("QueryAvailablePerfMetric"), - &response, esxVI_Boolean_True) < 0 || + if (esxVI_Context_Execute(conn, ctx, "QueryAvailablePerfMetric", request, + &response, esxVI_Occurrence_List) < 0 || esxVI_PerfMetricId_DeserializeList(conn, response->node, perfMetricIdList) < 0) { goto failure; @@ -1298,9 +1284,8 @@ esxVI_QueryPerfCounter(virConnectPtr conn, esxVI_Context *ctx, request = virBufferContentAndReset(&buffer); - if (esxVI_Context_Execute(conn, ctx, request, - ESX_VI__SOAP__RESPONSE_XPATH("QueryPerfCounter"), - &response, esxVI_Boolean_True) < 0 || + if (esxVI_Context_Execute(conn, ctx, "QueryPerfCounter", request, + &response, esxVI_Occurrence_List) < 0 || esxVI_PerfCounterInfo_DeserializeList(conn, response->node, perfCounterInfoList) < 0) { goto failure; @@ -1363,9 +1348,8 @@ esxVI_QueryPerf(virConnectPtr conn, esxVI_Context *ctx, request = virBufferContentAndReset(&buffer); - if (esxVI_Context_Execute(conn, ctx, request, - ESX_VI__SOAP__RESPONSE_XPATH("QueryPerf"), - &response, esxVI_Boolean_True) < 0 || + if (esxVI_Context_Execute(conn, ctx, "QueryPerf", request, &response, + esxVI_Occurrence_List) < 0 || esxVI_PerfEntityMetric_DeserializeList(conn, response->node, perfEntityMetricList) < 0) { goto failure; -- 1.6.0.4

On Sun, Dec 13, 2009 at 12:20:46AM +0100, Matthias Bolte wrote:
Also move XPath expression composition into esxVI_Context_Execute(). --- src/esx/esx_vi.c | 155 +++++++++++++++++++++++++++++----------------- src/esx/esx_vi.h | 8 +- src/esx/esx_vi_methods.c | 80 ++++++++++-------------- 3 files changed, 133 insertions(+), 110 deletions(-)
ACK, this makes the caller code slighly simpler, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

--- src/esx/esx_driver.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index ca8b4d3..221d29d 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -293,7 +293,7 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) return VIR_DRV_OPEN_DECLINED; } - if (conn->uri->path != NULL) { + if (conn->uri->path != NULL && STRNEQ(conn->uri->path, "/")) { VIR_WARN("Ignoring unexpected path '%s' in URI", conn->uri->path); } -- 1.6.0.4

Undefining a virtual machine on an ESX server leaves a orphan on the vCenter behind. So undefine a virtual machine on a vCenter if available to fix this problem. --- src/esx/esx_driver.c | 16 +++++++++++----- 1 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index 221d29d..98b8e91 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -2673,19 +2673,25 @@ esxDomainUndefine(virDomainPtr domain) { int result = 0; esxPrivate *priv = (esxPrivate *)domain->conn->privateData; + esxVI_Context *ctx = NULL; esxVI_ObjectContent *virtualMachine = NULL; esxVI_String *propertyNameList = NULL; esxVI_VirtualMachinePowerState powerState; - if (esxVI_EnsureSession(domain->conn, priv->host) < 0) { + if (priv->vCenter != NULL) { + ctx = priv->vCenter; + } else { + ctx = priv->host; + } + + if (esxVI_EnsureSession(domain->conn, ctx) < 0) { goto failure; } if (esxVI_String_AppendValueToList(domain->conn, &propertyNameList, "runtime.powerState") < 0 || - esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host, - domain->uuid, propertyNameList, - &virtualMachine, + esxVI_LookupVirtualMachineByUuid(domain->conn, ctx, domain->uuid, + propertyNameList, &virtualMachine, esxVI_Occurrence_RequiredItem) < 0 || esxVI_GetVirtualMachinePowerState(domain->conn, virtualMachine, &powerState) < 0) { @@ -2699,7 +2705,7 @@ esxDomainUndefine(virDomainPtr domain) goto failure; } - if (esxVI_UnregisterVM(domain->conn, priv->host, virtualMachine->obj) < 0) { + if (esxVI_UnregisterVM(domain->conn, ctx, virtualMachine->obj) < 0) { goto failure; } -- 1.6.0.4

If a virtual machine is destroyed on a ESX server then immediately undefining this virtual machine on a vCenter may fail, because the vCenter has not been informed about the status change yet. Therefore, destroy a virtual machine on a vCenter if available, so the vCenter is up-to-date when the virtual machine should be undefined. --- src/esx/esx_driver.c | 20 +++++++++++++------- 1 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index 98b8e91..7792291 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -1499,21 +1499,28 @@ esxDomainDestroy(virDomainPtr domain) { int result = 0; esxPrivate *priv = (esxPrivate *)domain->conn->privateData; + esxVI_Context *ctx = NULL; esxVI_ObjectContent *virtualMachine = NULL; esxVI_String *propertyNameList = NULL; esxVI_VirtualMachinePowerState powerState; esxVI_ManagedObjectReference *task = NULL; esxVI_TaskInfoState taskInfoState; - if (esxVI_EnsureSession(domain->conn, priv->host) < 0) { + if (priv->vCenter != NULL) { + ctx = priv->vCenter; + } else { + ctx = priv->host; + } + + if (esxVI_EnsureSession(domain->conn, ctx) < 0) { goto failure; } if (esxVI_String_AppendValueToList(domain->conn, &propertyNameList, "runtime.powerState") < 0 || esxVI_LookupVirtualMachineByUuidAndPrepareForTask - (domain->conn, priv->host, domain->uuid, propertyNameList, - &virtualMachine, priv->autoAnswer) < 0 || + (domain->conn, ctx, domain->uuid, propertyNameList, &virtualMachine, + priv->autoAnswer) < 0 || esxVI_GetVirtualMachinePowerState(domain->conn, virtualMachine, &powerState) < 0) { goto failure; @@ -1525,11 +1532,10 @@ esxDomainDestroy(virDomainPtr domain) goto failure; } - if (esxVI_PowerOffVM_Task(domain->conn, priv->host, virtualMachine->obj, + if (esxVI_PowerOffVM_Task(domain->conn, ctx, virtualMachine->obj, &task) < 0 || - esxVI_WaitForTaskCompletion(domain->conn, priv->host, task, - domain->uuid, priv->autoAnswer, - &taskInfoState) < 0) { + esxVI_WaitForTaskCompletion(domain->conn, ctx, task, domain->uuid, + priv->autoAnswer, &taskInfoState) < 0) { goto failure; } -- 1.6.0.4

On Sun, Dec 13, 2009 at 12:20:49AM +0100, Matthias Bolte wrote:
If a virtual machine is destroyed on a ESX server then immediately undefining this virtual machine on a vCenter may fail, because the vCenter has not been informed about the status change yet. Therefore, destroy a virtual machine on a vCenter if available, so the vCenter is up-to-date when the virtual machine should be undefined. --- src/esx/esx_driver.c | 20 +++++++++++++------- 1 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index 98b8e91..7792291 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -1499,21 +1499,28 @@ esxDomainDestroy(virDomainPtr domain) { int result = 0; esxPrivate *priv = (esxPrivate *)domain->conn->privateData; + esxVI_Context *ctx = NULL; esxVI_ObjectContent *virtualMachine = NULL; esxVI_String *propertyNameList = NULL; esxVI_VirtualMachinePowerState powerState; esxVI_ManagedObjectReference *task = NULL; esxVI_TaskInfoState taskInfoState;
- if (esxVI_EnsureSession(domain->conn, priv->host) < 0) { + if (priv->vCenter != NULL) { + ctx = priv->vCenter; + } else { + ctx = priv->host; + } + + if (esxVI_EnsureSession(domain->conn, ctx) < 0) { goto failure; }
if (esxVI_String_AppendValueToList(domain->conn, &propertyNameList, "runtime.powerState") < 0 || esxVI_LookupVirtualMachineByUuidAndPrepareForTask - (domain->conn, priv->host, domain->uuid, propertyNameList, - &virtualMachine, priv->autoAnswer) < 0 || + (domain->conn, ctx, domain->uuid, propertyNameList, &virtualMachine, + priv->autoAnswer) < 0 || esxVI_GetVirtualMachinePowerState(domain->conn, virtualMachine, &powerState) < 0) { goto failure; @@ -1525,11 +1532,10 @@ esxDomainDestroy(virDomainPtr domain) goto failure; }
- if (esxVI_PowerOffVM_Task(domain->conn, priv->host, virtualMachine->obj, + if (esxVI_PowerOffVM_Task(domain->conn, ctx, virtualMachine->obj, &task) < 0 || - esxVI_WaitForTaskCompletion(domain->conn, priv->host, task, - domain->uuid, priv->autoAnswer, - &taskInfoState) < 0) { + esxVI_WaitForTaskCompletion(domain->conn, ctx, task, domain->uuid, + priv->autoAnswer, &taskInfoState) < 0) { goto failure; }
Okay, similar, c.f. my question on previous patch :-) ACK Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

--- src/esx/README | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/src/esx/README b/src/esx/README index 51e49e3..7254332 100644 --- a/src/esx/README +++ b/src/esx/README @@ -3,10 +3,12 @@ Some links to relevant documentation ==================================== -VI API reference: http://www.vmware.com/support/developer/vc-sdk/visdk25pubs/ReferenceGuide/ +VI/vSphere API: http://www.vmware.com/support/developer/vc-sdk/visdk25pubs/ReferenceGuide/ + http://www.vmware.com/support/developer/vc-sdk/visdk400pubs/ReferenceGuide/ VMX config: http://www.sanbarrow.com/vmx.html CPUID: http://www.sandpile.org/ia32/cpuid.htm Memory model: http://www.vmware.com/pdf/esx3_memory.pdf + http://www.vmware.com/pdf/usenix_resource_mgmt.pdf -- 1.6.0.4

On Sun, Dec 13, 2009 at 12:20:50AM +0100, Matthias Bolte wrote:
--- src/esx/README | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/src/esx/README b/src/esx/README index 51e49e3..7254332 100644 --- a/src/esx/README +++ b/src/esx/README @@ -3,10 +3,12 @@ Some links to relevant documentation ====================================
-VI API reference: http://www.vmware.com/support/developer/vc-sdk/visdk25pubs/ReferenceGuide/ +VI/vSphere API: http://www.vmware.com/support/developer/vc-sdk/visdk25pubs/ReferenceGuide/ + http://www.vmware.com/support/developer/vc-sdk/visdk400pubs/ReferenceGuide/ VMX config: http://www.sanbarrow.com/vmx.html CPUID: http://www.sandpile.org/ia32/cpuid.htm Memory model: http://www.vmware.com/pdf/esx3_memory.pdf + http://www.vmware.com/pdf/usenix_resource_mgmt.pdf
ACK, thanks a lot ! Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

On Sun, Dec 13, 2009 at 12:20:37AM +0100, Matthias Bolte wrote:
Automatic question handling is the most important part of this series, see src/esx/README for more details.
Matthias Bolte (13): esx: Add automatic question handling esx: Improve domain lookup by UUID esx: Use more suitable error code in esxVI_LookupVirtualMachineByUuid() esx: Replace libxml1 'xmlChildrenNode' with libxml2 'children' esx: Removed unused inttypes.h include esx: Extend vCenter query parameter esx: Extend documentation about 'vcenter' and add some about 'auto_answer' esx: Fix occurence typo esx: Use occurrence enum to specify expected result of a SOAP call esx: Don't warn about '/' paths esx: Undefine virtual machine on a vCenter if available esx: Destroy virtual machine on a vCenter if available esx: Add more links to external documentation
Okay, ACK for the whole serie, thanks ! Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

2009/12/17 Daniel Veillard <veillard@redhat.com>:
On Sun, Dec 13, 2009 at 12:20:37AM +0100, Matthias Bolte wrote:
Automatic question handling is the most important part of this series, see src/esx/README for more details.
Matthias Bolte (13): esx: Add automatic question handling esx: Improve domain lookup by UUID esx: Use more suitable error code in esxVI_LookupVirtualMachineByUuid() esx: Replace libxml1 'xmlChildrenNode' with libxml2 'children' esx: Removed unused inttypes.h include esx: Extend vCenter query parameter esx: Extend documentation about 'vcenter' and add some about 'auto_answer' esx: Fix occurence typo esx: Use occurrence enum to specify expected result of a SOAP call esx: Don't warn about '/' paths esx: Undefine virtual machine on a vCenter if available esx: Destroy virtual machine on a vCenter if available esx: Add more links to external documentation
Okay, ACK for the whole serie,
thanks !
Daniel
Okay, pushed. Matthias
participants (2)
-
Daniel Veillard
-
Matthias Bolte