From 2a151699f133d89373aba8849fdcf9a7df8afc54 Mon Sep 17 00:00:00 2001 From: Matthias Bolte Date: Mon, 6 Dec 2010 13:53:36 +0100 Subject: [PATCH] esx: Improve error reporting for failed tasks Instead of just reporting that a task failed get the localized message from the TaskInfo error and include it in the reported error message. Implement minimal deserialization support for the MethodFault type in order to obtain the actual fault type. For example, this changes the reported error message when trying to create a volume with zero size from Could not create volume to Could not create volume: InvalidArgument - A specified parameter was not correct. Not perfect yet, but better than before. --- src/esx/esx_driver.c | 118 ++++++++++++++++++++++++--------- src/esx/esx_storage_driver.c | 8 ++- src/esx/esx_vi.c | 53 +++++++++++++-- src/esx/esx_vi.h | 3 +- src/esx/esx_vi_generator.input | 8 ++- src/esx/esx_vi_generator.py | 2 + src/esx/esx_vi_types.c | 51 +++++++++++++- src/esx/esx_vi_types.h | 25 +++++++ 8 files changed, 227 insertions(+), 41 deletions(-) diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index 8ea6219f86..03a7be30df 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -1706,6 +1706,7 @@ esxDomainSuspend(virDomainPtr domain) esxVI_VirtualMachinePowerState powerState; esxVI_ManagedObjectReference *task = NULL; esxVI_TaskInfoState taskInfoState; + char *taskInfoErrorMessage = NULL; if (esxVI_EnsureSession(priv->primary) < 0) { return -1; @@ -1729,12 +1730,14 @@ esxDomainSuspend(virDomainPtr domain) if (esxVI_SuspendVM_Task(priv->primary, virtualMachine->obj, &task) < 0 || esxVI_WaitForTaskCompletion(priv->primary, task, domain->uuid, esxVI_Occurrence_RequiredItem, - priv->autoAnswer, &taskInfoState) < 0) { + priv->autoAnswer, &taskInfoState, + &taskInfoErrorMessage) < 0) { goto cleanup; } if (taskInfoState != esxVI_TaskInfoState_Success) { - ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not suspend domain")); + ESX_ERROR(VIR_ERR_INTERNAL_ERROR, _("Could not suspend domain: %s"), + taskInfoErrorMessage); goto cleanup; } @@ -1744,6 +1747,7 @@ esxDomainSuspend(virDomainPtr domain) esxVI_ObjectContent_Free(&virtualMachine); esxVI_String_Free(&propertyNameList); esxVI_ManagedObjectReference_Free(&task); + VIR_FREE(taskInfoErrorMessage); return result; } @@ -1760,6 +1764,7 @@ esxDomainResume(virDomainPtr domain) esxVI_VirtualMachinePowerState powerState; esxVI_ManagedObjectReference *task = NULL; esxVI_TaskInfoState taskInfoState; + char *taskInfoErrorMessage = NULL; if (esxVI_EnsureSession(priv->primary) < 0) { return -1; @@ -1783,12 +1788,14 @@ esxDomainResume(virDomainPtr domain) &task) < 0 || esxVI_WaitForTaskCompletion(priv->primary, task, domain->uuid, esxVI_Occurrence_RequiredItem, - priv->autoAnswer, &taskInfoState) < 0) { + priv->autoAnswer, &taskInfoState, + &taskInfoErrorMessage) < 0) { goto cleanup; } if (taskInfoState != esxVI_TaskInfoState_Success) { - ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not resume domain")); + ESX_ERROR(VIR_ERR_INTERNAL_ERROR, _("Could not resume domain: %s"), + taskInfoErrorMessage); goto cleanup; } @@ -1798,6 +1805,7 @@ esxDomainResume(virDomainPtr domain) esxVI_ObjectContent_Free(&virtualMachine); esxVI_String_Free(&propertyNameList); esxVI_ManagedObjectReference_Free(&task); + VIR_FREE(taskInfoErrorMessage); return result; } @@ -1901,6 +1909,7 @@ esxDomainDestroy(virDomainPtr domain) esxVI_VirtualMachinePowerState powerState; esxVI_ManagedObjectReference *task = NULL; esxVI_TaskInfoState taskInfoState; + char *taskInfoErrorMessage = NULL; if (priv->vCenter != NULL) { ctx = priv->vCenter; @@ -1930,12 +1939,14 @@ esxDomainDestroy(virDomainPtr domain) if (esxVI_PowerOffVM_Task(ctx, virtualMachine->obj, &task) < 0 || esxVI_WaitForTaskCompletion(ctx, task, domain->uuid, esxVI_Occurrence_RequiredItem, - priv->autoAnswer, &taskInfoState) < 0) { + priv->autoAnswer, &taskInfoState, + &taskInfoErrorMessage) < 0) { goto cleanup; } if (taskInfoState != esxVI_TaskInfoState_Success) { - ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not destroy domain")); + ESX_ERROR(VIR_ERR_INTERNAL_ERROR, _("Could not destroy domain: %s"), + taskInfoErrorMessage); goto cleanup; } @@ -1946,6 +1957,7 @@ esxDomainDestroy(virDomainPtr domain) esxVI_ObjectContent_Free(&virtualMachine); esxVI_String_Free(&propertyNameList); esxVI_ManagedObjectReference_Free(&task); + VIR_FREE(taskInfoErrorMessage); return result; } @@ -2028,6 +2040,7 @@ esxDomainSetMaxMemory(virDomainPtr domain, unsigned long memory) esxVI_VirtualMachineConfigSpec *spec = NULL; esxVI_ManagedObjectReference *task = NULL; esxVI_TaskInfoState taskInfoState; + char *taskInfoErrorMessage = NULL; if (esxVI_EnsureSession(priv->primary) < 0) { return -1; @@ -2048,13 +2061,15 @@ esxDomainSetMaxMemory(virDomainPtr domain, unsigned long memory) &task) < 0 || esxVI_WaitForTaskCompletion(priv->primary, task, domain->uuid, esxVI_Occurrence_RequiredItem, - priv->autoAnswer, &taskInfoState) < 0) { + priv->autoAnswer, &taskInfoState, + &taskInfoErrorMessage) < 0) { goto cleanup; } if (taskInfoState != esxVI_TaskInfoState_Success) { ESX_ERROR(VIR_ERR_INTERNAL_ERROR, - _("Could not set max-memory to %lu kilobytes"), memory); + _("Could not set max-memory to %lu kilobytes: %s"), memory, + taskInfoErrorMessage); goto cleanup; } @@ -2064,6 +2079,7 @@ esxDomainSetMaxMemory(virDomainPtr domain, unsigned long memory) esxVI_ObjectContent_Free(&virtualMachine); esxVI_VirtualMachineConfigSpec_Free(&spec); esxVI_ManagedObjectReference_Free(&task); + VIR_FREE(taskInfoErrorMessage); return result; } @@ -2079,6 +2095,7 @@ esxDomainSetMemory(virDomainPtr domain, unsigned long memory) esxVI_VirtualMachineConfigSpec *spec = NULL; esxVI_ManagedObjectReference *task = NULL; esxVI_TaskInfoState taskInfoState; + char *taskInfoErrorMessage = NULL; if (esxVI_EnsureSession(priv->primary) < 0) { return -1; @@ -2100,13 +2117,15 @@ esxDomainSetMemory(virDomainPtr domain, unsigned long memory) &task) < 0 || esxVI_WaitForTaskCompletion(priv->primary, task, domain->uuid, esxVI_Occurrence_RequiredItem, - priv->autoAnswer, &taskInfoState) < 0) { + priv->autoAnswer, &taskInfoState, + &taskInfoErrorMessage) < 0) { goto cleanup; } if (taskInfoState != esxVI_TaskInfoState_Success) { ESX_ERROR(VIR_ERR_INTERNAL_ERROR, - _("Could not set memory to %lu kilobytes"), memory); + _("Could not set memory to %lu kilobytes: %s"), memory, + taskInfoErrorMessage); goto cleanup; } @@ -2116,6 +2135,7 @@ esxDomainSetMemory(virDomainPtr domain, unsigned long memory) esxVI_ObjectContent_Free(&virtualMachine); esxVI_VirtualMachineConfigSpec_Free(&spec); esxVI_ManagedObjectReference_Free(&task); + VIR_FREE(taskInfoErrorMessage); return result; } @@ -2394,6 +2414,7 @@ esxDomainSetVcpusFlags(virDomainPtr domain, unsigned int nvcpus, esxVI_VirtualMachineConfigSpec *spec = NULL; esxVI_ManagedObjectReference *task = NULL; esxVI_TaskInfoState taskInfoState; + char *taskInfoErrorMessage = NULL; if (flags != VIR_DOMAIN_VCPU_LIVE) { ESX_ERROR(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags); @@ -2438,13 +2459,15 @@ esxDomainSetVcpusFlags(virDomainPtr domain, unsigned int nvcpus, &task) < 0 || esxVI_WaitForTaskCompletion(priv->primary, task, domain->uuid, esxVI_Occurrence_RequiredItem, - priv->autoAnswer, &taskInfoState) < 0) { + priv->autoAnswer, &taskInfoState, + &taskInfoErrorMessage) < 0) { goto cleanup; } if (taskInfoState != esxVI_TaskInfoState_Success) { ESX_ERROR(VIR_ERR_INTERNAL_ERROR, - _("Could not set number of virtual CPUs to %d"), nvcpus); + _("Could not set number of virtual CPUs to %d: %s"), nvcpus, + taskInfoErrorMessage); goto cleanup; } @@ -2454,6 +2477,7 @@ esxDomainSetVcpusFlags(virDomainPtr domain, unsigned int nvcpus, esxVI_ObjectContent_Free(&virtualMachine); esxVI_VirtualMachineConfigSpec_Free(&spec); esxVI_ManagedObjectReference_Free(&task); + VIR_FREE(taskInfoErrorMessage); return result; } @@ -2828,6 +2852,7 @@ esxDomainCreateWithFlags(virDomainPtr domain, unsigned int flags) int id = -1; esxVI_ManagedObjectReference *task = NULL; esxVI_TaskInfoState taskInfoState; + char *taskInfoErrorMessage = NULL; virCheckFlags(0, -1); @@ -2855,12 +2880,14 @@ esxDomainCreateWithFlags(virDomainPtr domain, unsigned int flags) &task) < 0 || esxVI_WaitForTaskCompletion(priv->primary, task, domain->uuid, esxVI_Occurrence_RequiredItem, - priv->autoAnswer, &taskInfoState) < 0) { + priv->autoAnswer, &taskInfoState, + &taskInfoErrorMessage) < 0) { goto cleanup; } if (taskInfoState != esxVI_TaskInfoState_Success) { - ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not start domain")); + ESX_ERROR(VIR_ERR_INTERNAL_ERROR, _("Could not start domain: %s"), + taskInfoErrorMessage); goto cleanup; } @@ -2871,6 +2898,7 @@ esxDomainCreateWithFlags(virDomainPtr domain, unsigned int flags) esxVI_ObjectContent_Free(&virtualMachine); esxVI_String_Free(&propertyNameList); esxVI_ManagedObjectReference_Free(&task); + VIR_FREE(taskInfoErrorMessage); return result; } @@ -2907,6 +2935,7 @@ esxDomainDefineXML(virConnectPtr conn, const char *xml) esxVI_ManagedObjectReference *resourcePool = NULL; esxVI_ManagedObjectReference *task = NULL; esxVI_TaskInfoState taskInfoState; + char *taskInfoErrorMessage = NULL; virDomainPtr domain = NULL; if (esxVI_EnsureSession(priv->primary) < 0) { @@ -3066,12 +3095,14 @@ esxDomainDefineXML(virConnectPtr conn, const char *xml) &task) < 0 || esxVI_WaitForTaskCompletion(priv->primary, task, def->uuid, esxVI_Occurrence_OptionalItem, - priv->autoAnswer, &taskInfoState) < 0) { + priv->autoAnswer, &taskInfoState, + &taskInfoErrorMessage) < 0) { goto cleanup; } if (taskInfoState != esxVI_TaskInfoState_Success) { - ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not define domain")); + ESX_ERROR(VIR_ERR_INTERNAL_ERROR, _("Could not define domain: %s"), + taskInfoErrorMessage); goto cleanup; } @@ -3100,6 +3131,7 @@ esxDomainDefineXML(virConnectPtr conn, const char *xml) esxVI_ObjectContent_Free(&hostSystem); esxVI_ManagedObjectReference_Free(&resourcePool); esxVI_ManagedObjectReference_Free(&task); + VIR_FREE(taskInfoErrorMessage); return domain; } @@ -3340,6 +3372,7 @@ esxDomainSetSchedulerParameters(virDomainPtr domain, esxVI_SharesInfo *sharesInfo = NULL; esxVI_ManagedObjectReference *task = NULL; esxVI_TaskInfoState taskInfoState; + char *taskInfoErrorMessage = NULL; int i; if (esxVI_EnsureSession(priv->primary) < 0) { @@ -3434,13 +3467,15 @@ esxDomainSetSchedulerParameters(virDomainPtr domain, &task) < 0 || esxVI_WaitForTaskCompletion(priv->primary, task, domain->uuid, esxVI_Occurrence_RequiredItem, - priv->autoAnswer, &taskInfoState) < 0) { + priv->autoAnswer, &taskInfoState, + &taskInfoErrorMessage) < 0) { goto cleanup; } if (taskInfoState != esxVI_TaskInfoState_Success) { - ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", - _("Could not change scheduler parameters")); + ESX_ERROR(VIR_ERR_INTERNAL_ERROR, + _("Could not change scheduler parameters: %s"), + taskInfoErrorMessage); goto cleanup; } @@ -3450,6 +3485,7 @@ esxDomainSetSchedulerParameters(virDomainPtr domain, esxVI_ObjectContent_Free(&virtualMachine); esxVI_VirtualMachineConfigSpec_Free(&spec); esxVI_ManagedObjectReference_Free(&task); + VIR_FREE(taskInfoErrorMessage); return result; } @@ -3504,6 +3540,7 @@ esxDomainMigratePerform(virDomainPtr domain, esxVI_Event *eventList = NULL; esxVI_ManagedObjectReference *task = NULL; esxVI_TaskInfoState taskInfoState; + char *taskInfoErrorMessage = NULL; if (priv->vCenter == NULL) { ESX_ERROR(VIR_ERR_INVALID_ARG, "%s", @@ -3601,14 +3638,16 @@ esxDomainMigratePerform(virDomainPtr domain, &task) < 0 || esxVI_WaitForTaskCompletion(priv->vCenter, task, domain->uuid, esxVI_Occurrence_RequiredItem, - priv->autoAnswer, &taskInfoState) < 0) { + priv->autoAnswer, &taskInfoState, + &taskInfoErrorMessage) < 0) { goto cleanup; } if (taskInfoState != esxVI_TaskInfoState_Success) { - ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", + ESX_ERROR(VIR_ERR_INTERNAL_ERROR, _("Could not migrate domain, migration task finished with " - "an error")); + "an error: %s"), + taskInfoErrorMessage); goto cleanup; } @@ -3619,6 +3658,7 @@ esxDomainMigratePerform(virDomainPtr domain, esxVI_ObjectContent_Free(&virtualMachine); esxVI_Event_Free(&eventList); esxVI_ManagedObjectReference_Free(&task); + VIR_FREE(taskInfoErrorMessage); return result; } @@ -3783,6 +3823,7 @@ esxDomainSnapshotCreateXML(virDomainPtr domain, const char *xmlDesc, esxVI_VirtualMachineSnapshotTree *snapshotTreeParent = NULL; esxVI_ManagedObjectReference *task = NULL; esxVI_TaskInfoState taskInfoState; + char *taskInfoErrorMessage = NULL; virDomainSnapshotPtr snapshot = NULL; virCheckFlags(0, NULL); @@ -3820,12 +3861,14 @@ esxDomainSnapshotCreateXML(virDomainPtr domain, const char *xmlDesc, esxVI_Boolean_False, &task) < 0 || esxVI_WaitForTaskCompletion(priv->primary, task, domain->uuid, esxVI_Occurrence_RequiredItem, - priv->autoAnswer, &taskInfoState) < 0) { + priv->autoAnswer, &taskInfoState, + &taskInfoErrorMessage) < 0) { goto cleanup; } if (taskInfoState != esxVI_TaskInfoState_Success) { - ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not create snapshot")); + ESX_ERROR(VIR_ERR_INTERNAL_ERROR, _("Could not create snapshot: %s"), + taskInfoErrorMessage); goto cleanup; } @@ -3836,6 +3879,7 @@ esxDomainSnapshotCreateXML(virDomainPtr domain, const char *xmlDesc, esxVI_ObjectContent_Free(&virtualMachine); esxVI_VirtualMachineSnapshotTree_Free(&rootSnapshotList); esxVI_ManagedObjectReference_Free(&task); + VIR_FREE(taskInfoErrorMessage); return snapshot; } @@ -4058,6 +4102,7 @@ esxDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, unsigned int flags) esxVI_VirtualMachineSnapshotTree *snapshotTreeParent = NULL; esxVI_ManagedObjectReference *task = NULL; esxVI_TaskInfoState taskInfoState; + char *taskInfoErrorMessage = NULL; virCheckFlags(0, -1); @@ -4077,13 +4122,15 @@ esxDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, unsigned int flags) &task) < 0 || esxVI_WaitForTaskCompletion(priv->primary, task, snapshot->domain->uuid, esxVI_Occurrence_RequiredItem, - priv->autoAnswer, &taskInfoState) < 0) { + priv->autoAnswer, &taskInfoState, + &taskInfoErrorMessage) < 0) { goto cleanup; } if (taskInfoState != esxVI_TaskInfoState_Success) { ESX_ERROR(VIR_ERR_INTERNAL_ERROR, - _("Could not revert to snapshot '%s'"), snapshot->name); + _("Could not revert to snapshot '%s': %s"), snapshot->name, + taskInfoErrorMessage); goto cleanup; } @@ -4092,6 +4139,7 @@ esxDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, unsigned int flags) cleanup: esxVI_VirtualMachineSnapshotTree_Free(&rootSnapshotList); esxVI_ManagedObjectReference_Free(&task); + VIR_FREE(taskInfoErrorMessage); return result; } @@ -4109,6 +4157,7 @@ esxDomainSnapshotDelete(virDomainSnapshotPtr snapshot, unsigned int flags) esxVI_Boolean removeChildren = esxVI_Boolean_False; esxVI_ManagedObjectReference *task = NULL; esxVI_TaskInfoState taskInfoState; + char *taskInfoErrorMessage = NULL; virCheckFlags(VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN, -1); @@ -4132,13 +4181,15 @@ esxDomainSnapshotDelete(virDomainSnapshotPtr snapshot, unsigned int flags) removeChildren, &task) < 0 || esxVI_WaitForTaskCompletion(priv->primary, task, snapshot->domain->uuid, esxVI_Occurrence_RequiredItem, - priv->autoAnswer, &taskInfoState) < 0) { + priv->autoAnswer, &taskInfoState, + &taskInfoErrorMessage) < 0) { goto cleanup; } if (taskInfoState != esxVI_TaskInfoState_Success) { ESX_ERROR(VIR_ERR_INTERNAL_ERROR, - _("Could not delete snapshot '%s'"), snapshot->name); + _("Could not delete snapshot '%s': %s"), snapshot->name, + taskInfoErrorMessage); goto cleanup; } @@ -4147,6 +4198,7 @@ esxDomainSnapshotDelete(virDomainSnapshotPtr snapshot, unsigned int flags) cleanup: esxVI_VirtualMachineSnapshotTree_Free(&rootSnapshotList); esxVI_ManagedObjectReference_Free(&task); + VIR_FREE(taskInfoErrorMessage); return result; } @@ -4163,6 +4215,7 @@ esxDomainSetMemoryParameters(virDomainPtr domain, virMemoryParameterPtr params, esxVI_VirtualMachineConfigSpec *spec = NULL; esxVI_ManagedObjectReference *task = NULL; esxVI_TaskInfoState taskInfoState; + char *taskInfoErrorMessage = NULL; int i; virCheckFlags(0, -1); @@ -4199,13 +4252,15 @@ esxDomainSetMemoryParameters(virDomainPtr domain, virMemoryParameterPtr params, &task) < 0 || esxVI_WaitForTaskCompletion(priv->primary, task, domain->uuid, esxVI_Occurrence_RequiredItem, - priv->autoAnswer, &taskInfoState) < 0) { + priv->autoAnswer, &taskInfoState, + &taskInfoErrorMessage) < 0) { goto cleanup; } if (taskInfoState != esxVI_TaskInfoState_Success) { - ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", - _("Could not change memory parameters")); + ESX_ERROR(VIR_ERR_INTERNAL_ERROR, + _("Could not change memory parameters: %s"), + taskInfoErrorMessage); goto cleanup; } @@ -4215,6 +4270,7 @@ esxDomainSetMemoryParameters(virDomainPtr domain, virMemoryParameterPtr params, esxVI_ObjectContent_Free(&virtualMachine); esxVI_VirtualMachineConfigSpec_Free(&spec); esxVI_ManagedObjectReference_Free(&task); + VIR_FREE(taskInfoErrorMessage); return result; } diff --git a/src/esx/esx_storage_driver.c b/src/esx/esx_storage_driver.c index 72e0d7a5cd..83b53fbbd2 100644 --- a/src/esx/esx_storage_driver.c +++ b/src/esx/esx_storage_driver.c @@ -926,6 +926,7 @@ esxStorageVolumeCreateXML(virStoragePoolPtr pool, const char *xmldesc, esxVI_FileBackedVirtualDiskSpec *virtualDiskSpec = NULL; esxVI_ManagedObjectReference *task = NULL; esxVI_TaskInfoState taskInfoState; + char *taskInfoErrorMessage = NULL; char *uuid_string = NULL; char *key = NULL; @@ -1092,12 +1093,14 @@ esxStorageVolumeCreateXML(virStoragePoolPtr pool, const char *xmldesc, esxVI_VirtualDiskSpec_DynamicCast(virtualDiskSpec), &task) < 0 || esxVI_WaitForTaskCompletion(priv->primary, task, NULL, esxVI_Occurrence_None, - priv->autoAnswer, &taskInfoState) < 0) { + priv->autoAnswer, &taskInfoState, + &taskInfoErrorMessage) < 0) { goto cleanup; } if (taskInfoState != esxVI_TaskInfoState_Success) { - ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not create volume")); + ESX_ERROR(VIR_ERR_INTERNAL_ERROR, _("Could not create volume: %s"), + taskInfoErrorMessage); goto cleanup; } @@ -1151,6 +1154,7 @@ esxStorageVolumeCreateXML(virStoragePoolPtr pool, const char *xmldesc, esxVI_FileInfo_Free(&fileInfo); esxVI_FileBackedVirtualDiskSpec_Free(&virtualDiskSpec); esxVI_ManagedObjectReference_Free(&task); + VIR_FREE(taskInfoErrorMessage); VIR_FREE(uuid_string); VIR_FREE(key); diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c index 9c966504b7..74a2a422ec 100644 --- a/src/esx/esx_vi.c +++ b/src/esx/esx_vi.c @@ -3009,6 +3009,7 @@ esxVI_LookupFileInfoByDatastorePath(esxVI_Context *ctx, esxVI_FloppyImageFileQuery *floppyImageFileQuery = NULL; esxVI_ManagedObjectReference *task = NULL; esxVI_TaskInfoState taskInfoState; + char *taskInfoErrorMessage = NULL; esxVI_TaskInfo *taskInfo = NULL; esxVI_HostDatastoreBrowserSearchResults *searchResults = NULL; @@ -3128,13 +3129,15 @@ esxVI_LookupFileInfoByDatastorePath(esxVI_Context *ctx, datastorePathWithoutFileName, searchSpec, &task) < 0 || esxVI_WaitForTaskCompletion(ctx, task, NULL, esxVI_Occurrence_None, - esxVI_Boolean_False, &taskInfoState) < 0) { + esxVI_Boolean_False, &taskInfoState, + &taskInfoErrorMessage) < 0) { goto cleanup; } if (taskInfoState != esxVI_TaskInfoState_Success) { ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, - _("Could not serach in datastore '%s'"), datastoreName); + _("Could not search in datastore '%s': %s"), + datastoreName, taskInfoErrorMessage); goto cleanup; } @@ -3179,6 +3182,7 @@ esxVI_LookupFileInfoByDatastorePath(esxVI_Context *ctx, esxVI_ManagedObjectReference_Free(&hostDatastoreBrowser); esxVI_HostDatastoreBrowserSearchSpec_Free(&searchSpec); esxVI_ManagedObjectReference_Free(&task); + VIR_FREE(taskInfoErrorMessage); esxVI_TaskInfo_Free(&taskInfo); esxVI_HostDatastoreBrowserSearchResults_Free(&searchResults); @@ -3203,6 +3207,7 @@ esxVI_LookupDatastoreContentByDatastoreName char *datastorePath = NULL; esxVI_ManagedObjectReference *task = NULL; esxVI_TaskInfoState taskInfoState; + char *taskInfoErrorMessage = NULL; esxVI_TaskInfo *taskInfo = NULL; if (searchResultsList == NULL || *searchResultsList != NULL) { @@ -3269,13 +3274,15 @@ esxVI_LookupDatastoreContentByDatastoreName datastorePath, searchSpec, &task) < 0 || esxVI_WaitForTaskCompletion(ctx, task, NULL, esxVI_Occurrence_None, - esxVI_Boolean_False, &taskInfoState) < 0) { + esxVI_Boolean_False, &taskInfoState, + &taskInfoErrorMessage) < 0) { goto cleanup; } if (taskInfoState != esxVI_TaskInfoState_Success) { ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, - _("Could not serach in datastore '%s'"), datastoreName); + _("Could not serach in datastore '%s': %s"), + datastoreName, taskInfoErrorMessage); goto cleanup; } @@ -3294,6 +3301,7 @@ esxVI_LookupDatastoreContentByDatastoreName esxVI_HostDatastoreBrowserSearchSpec_Free(&searchSpec); VIR_FREE(datastorePath); esxVI_ManagedObjectReference_Free(&task); + VIR_FREE(taskInfoErrorMessage); esxVI_TaskInfo_Free(&taskInfo); return result; @@ -3472,7 +3480,8 @@ esxVI_WaitForTaskCompletion(esxVI_Context *ctx, const unsigned char *virtualMachineUuid, esxVI_Occurrence virtualMachineOccurrence, esxVI_Boolean autoAnswer, - esxVI_TaskInfoState *finalState) + esxVI_TaskInfoState *finalState, + char **errorMessage) { int result = -1; esxVI_ObjectSpec *objectSpec = NULL; @@ -3489,6 +3498,11 @@ esxVI_WaitForTaskCompletion(esxVI_Context *ctx, esxVI_Boolean blocked = esxVI_Boolean_Undefined; esxVI_TaskInfo *taskInfo = NULL; + if (errorMessage == NULL || *errorMessage != NULL) { + ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); + return -1; + } + version = strdup(""); if (version == NULL) { @@ -3609,6 +3623,35 @@ esxVI_WaitForTaskCompletion(esxVI_Context *ctx, goto cleanup; } + if (*finalState != esxVI_TaskInfoState_Success) { + if (esxVI_LookupTaskInfoByTask(ctx, task, &taskInfo)) { + goto cleanup; + } + + if (taskInfo->error == NULL) { + *errorMessage = strdup(_("Unknown error")); + + if (*errorMessage == NULL) { + virReportOOMError(); + goto cleanup; + } + } else if (taskInfo->error->localizedMessage == NULL) { + *errorMessage = strdup(taskInfo->error->fault->_actualType); + + if (*errorMessage == NULL) { + virReportOOMError(); + goto cleanup; + } + } else { + if (virAsprintf(errorMessage, "%s - %s", + taskInfo->error->fault->_actualType, + taskInfo->error->localizedMessage) < 0) { + virReportOOMError(); + goto cleanup; + } + } + } + result = 0; cleanup: diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h index 26779ad074..20e6fb50f6 100644 --- a/src/esx/esx_vi.h +++ b/src/esx/esx_vi.h @@ -429,7 +429,8 @@ int esxVI_WaitForTaskCompletion(esxVI_Context *ctx, const unsigned char *virtualMachineUuid, esxVI_Occurrence virtualMachineOccurrence, esxVI_Boolean autoAnswer, - esxVI_TaskInfoState *finalState); + esxVI_TaskInfoState *finalState, + char **errorMessage); int esxVI_ParseHostCpuIdInfo(esxVI_ParsedHostCpuIdInfo *parsedHostCpuIdInfo, esxVI_HostCpuIdInfo *hostCpuIdInfo); diff --git a/src/esx/esx_vi_generator.input b/src/esx/esx_vi_generator.input index 2ee513a2f1..991ce8a92f 100644 --- a/src/esx/esx_vi_generator.input +++ b/src/esx/esx_vi_generator.input @@ -311,6 +311,12 @@ object LocalDatastoreInfo extends DatastoreInfo end +object LocalizedMethodFault + MethodFault fault r + String localizedMessage o +end + + object NasDatastoreInfo extends DatastoreInfo HostNasVolume nas o end @@ -494,7 +500,7 @@ object TaskInfo TaskInfoState state r Boolean cancelled r Boolean cancelable r - LocalizedMethodFault error i + LocalizedMethodFault error o AnyType result o Int progress o TaskReason reason i diff --git a/src/esx/esx_vi_generator.py b/src/esx/esx_vi_generator.py index 459337975b..4a8a9dc72e 100755 --- a/src/esx/esx_vi_generator.py +++ b/src/esx/esx_vi_generator.py @@ -1139,6 +1139,7 @@ predefined_objects = ["AnyType", "Long", "String", "DateTime", + "MethodFault", "ManagedObjectReference"] @@ -1172,6 +1173,7 @@ additional_object_features = { "DatastoreHostMount" : Object.FEATURE__DE removed_object_features = { "DynamicProperty" : Object.FEATURE__SERIALIZE, + "LocalizedMethodFault" : Object.FEATURE__SERIALIZE, "ObjectContent" : Object.FEATURE__SERIALIZE, "ObjectUpdate" : Object.FEATURE__SERIALIZE, "PropertyChange" : Object.FEATURE__SERIALIZE, diff --git a/src/esx/esx_vi_types.c b/src/esx/esx_vi_types.c index ad45483b45..a70e1e05a1 100644 --- a/src/esx/esx_vi_types.c +++ b/src/esx/esx_vi_types.c @@ -701,6 +701,9 @@ esxVI_Type_ToString(esxVI_Type type) case esxVI_Type_Fault: return "Fault"; + case esxVI_Type_MethodFault: + return "MethodFault"; + case esxVI_Type_ManagedObjectReference: return "ManagedObjectReference"; @@ -741,6 +744,8 @@ esxVI_Type_FromString(const char *type) return esxVI_Type_DateTime; } else if (STREQ(type, "Fault")) { return esxVI_Type_Fault; + } else if (STREQ(type, "MethodFault")) { + return esxVI_Type_MethodFault; } else if (STREQ(type, "ManagedObjectReference")) { return esxVI_Type_ManagedObjectReference; } else if (STREQ(type, "Datacenter")) { @@ -751,7 +756,6 @@ esxVI_Type_FromString(const char *type) return esxVI_Type_HostSystem; } - #include "esx_vi_types.generated.typefromstring" else { @@ -1446,6 +1450,51 @@ ESX_VI__TEMPLATE__DESERIALIZE(Fault, +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * VI Type: MethodFault + */ + +/* esxVI_MethodFault_Alloc */ +ESX_VI__TEMPLATE__ALLOC(MethodFault); + +/* esxVI_MethodFault_Free */ +ESX_VI__TEMPLATE__FREE(MethodFault, +{ + VIR_FREE(item->_actualType); +}) + +int +esxVI_MethodFault_Deserialize(xmlNodePtr node, esxVI_MethodFault **methodFault) +{ + if (methodFault == NULL || *methodFault != NULL) { + ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); + return -1; + } + + if (esxVI_MethodFault_Alloc(methodFault) < 0) { + return -1; + } + + (*methodFault)->_actualType = + (char *)xmlGetNsProp(node, BAD_CAST "type", + BAD_CAST "http://www.w3.org/2001/XMLSchema-instance"); + + if ((*methodFault)->_actualType == NULL) { + ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", + _("MethodFault is missing 'type' property")); + goto failure; + } + + return 0; + + failure: + esxVI_MethodFault_Free(methodFault); + + return -1; +} + + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VI Type: ManagedObjectReference */ diff --git a/src/esx/esx_vi_types.h b/src/esx/esx_vi_types.h index 901eda0357..64bf2dc27e 100644 --- a/src/esx/esx_vi_types.h +++ b/src/esx/esx_vi_types.h @@ -48,6 +48,7 @@ typedef struct _esxVI_DateTime esxVI_DateTime; */ typedef struct _esxVI_Fault esxVI_Fault; +typedef struct _esxVI_MethodFault esxVI_MethodFault; typedef struct _esxVI_ManagedObjectReference esxVI_ManagedObjectReference; typedef struct _esxVI_Datacenter esxVI_Datacenter; typedef struct _esxVI_ComputeResource esxVI_ComputeResource; @@ -71,6 +72,7 @@ enum _esxVI_Type { esxVI_Type_Long, esxVI_Type_DateTime, esxVI_Type_Fault, + esxVI_Type_MethodFault, esxVI_Type_ManagedObjectReference, esxVI_Type_Datacenter, esxVI_Type_ComputeResource, @@ -278,6 +280,29 @@ int esxVI_Fault_Deserialize(xmlNodePtr node, esxVI_Fault **fault); +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * VI Type: MethodFault + */ + +/* + * FIXME: This is just a minimal implementation of the MethodFault type. + * A complete implementation would require to implement dozens of + * extending types too. + */ +struct _esxVI_MethodFault { + esxVI_MethodFault *_unused; /* optional */ + esxVI_Type _type; /* required */ + + char *_actualType; /* required */ +}; + +int esxVI_MethodFault_Alloc(esxVI_MethodFault **methodfault); +void esxVI_MethodFault_Free(esxVI_MethodFault **methodFault); +int esxVI_MethodFault_Deserialize(xmlNodePtr node, + esxVI_MethodFault **methodFault); + + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VI Type: ManagedObjectReference */