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