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

esx: Add automatic question handling

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
上级 1c5c6333
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.
......@@ -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;
}
......
......@@ -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);
......
......@@ -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);
......
......@@ -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)
......@@ -1478,6 +1479,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,
......@@ -1826,6 +1854,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,
......@@ -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,
......@@ -2133,9 +2373,110 @@ 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;
......
......@@ -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__ */
......@@ -576,6 +576,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)
......@@ -625,6 +680,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,
......
......@@ -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,
......
......@@ -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,
......@@ -1339,6 +1345,76 @@ esxVI_ManagedObjectReference_CastFromAnyType
expectedType);
}
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,
......@@ -2426,6 +2502,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
*
......@@ -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,
{
......@@ -2462,6 +2576,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);
});
......@@ -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,
......@@ -1064,6 +1077,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
*
......@@ -1087,12 +1126,40 @@ 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);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* 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__ */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册