[libvirt] [PATCH] esx: Improve error reporting for failed tasks
by Matthias Bolte
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 8ea6219..03a7be3 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 72e0d7a..83b53fb 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 9c96650..74a2a42 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 26779ad..20e6fb5 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 2ee513a..991ce8a 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 4593379..4a8a9dc 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 ad45483..a70e1e0 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 {
@@ -1447,6 +1451,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 901eda0..64bf2dc 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,
@@ -279,6 +281,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
*/
--
1.7.0.4
14 years, 6 months
[libvirt] [PATCH] command: plug memory leak
by Eric Blake
* src/util/command.c (virCommandFree): Free data from
virCommandSetInputBuffer.
---
src/util/command.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/src/util/command.c b/src/util/command.c
index 089e0bd..5e2b19a 100644
--- a/src/util/command.c
+++ b/src/util/command.c
@@ -1198,6 +1198,7 @@ virCommandFree(virCommandPtr cmd)
}
}
+ VIR_FREE(cmd->inbuf);
VIR_FORCE_CLOSE(cmd->outfd);
VIR_FORCE_CLOSE(cmd->errfd);
--
1.7.3.2
14 years, 6 months
[libvirt] [v2] qemu: Set domain def as updated and transient if changes
by Osier Yang
As qemu driver doesn't allow to make changes on persistent
domain configuration via "attach/detach/update device",
and all the changes made on the running domain configuration
should not be persistent across next boot (without the need
of restarting libvirtd), so:
1) Set the running domain def as transient, and restore
the domain configuration to original configuration when
shutdown.
2) Set the running domain def as updated, and reset it as
not updated when shutdown.
Also for "live VCPU set", it doesn't change the persistent
domain configuration, so, we also set the running domain
def as updated and transient, and restore the original def
when shutdown.
* src/qemu/qemu_driver.c
---
src/qemu/qemu_driver.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 47 insertions(+), 0 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 19ce9a6..a3d87eb 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4429,11 +4429,18 @@ retry:
VIR_FREE(priv->vcpupids);
priv->nvcpupids = 0;
+ /* Restore original domain def, so that changes on running domain def
+ * will not be persistent across next boot.
+ */
if (vm->newDef) {
virDomainDefFree(vm->def);
vm->def = vm->newDef;
vm->def->id = -1;
vm->newDef = NULL;
+
+ /* Now set domain def as not updated */
+ if (vm->updated)
+ vm->updated = 0;
}
if (orig_err) {
@@ -6473,7 +6480,17 @@ qemudDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
break;
case VIR_DOMAIN_VCPU_LIVE:
+ if (virDomainObjSetDefTransient(driver->caps, vm) < 0) {
+ VIR_ERROR("Unable to set domain %s's running config as transient",
+ vm->def->name);
+
+ goto endjob;
+ }
+
ret = qemudDomainHotplugVcpus(vm, nvcpus);
+
+ if (ret == 0)
+ vm->updated = 1;
break;
case VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG:
@@ -8819,6 +8836,13 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
goto endjob;
}
+ if (virDomainObjSetDefTransient(driver->caps, vm) < 0) {
+ VIR_ERROR("Unable to set domain %s's running config as transient",
+ vm->def->name);
+
+ goto endjob;
+ }
+
dev = virDomainDeviceDefParse(driver->caps, vm->def, xml,
VIR_DOMAIN_XML_INACTIVE);
if (dev == NULL)
@@ -8916,6 +8940,9 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
goto endjob;
}
+ if (ret == 0)
+ vm->updated = 1;
+
if (!ret && virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
ret = -1;
@@ -9066,6 +9093,13 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom,
goto endjob;
}
+ if (virDomainObjSetDefTransient(driver->caps, vm) < 0) {
+ VIR_ERROR("Unable to set domain %s's running config as transient",
+ vm->def->name);
+
+ goto endjob;
+ }
+
dev = virDomainDeviceDefParse(driver->caps, vm->def, xml,
VIR_DOMAIN_XML_INACTIVE);
if (dev == NULL)
@@ -9126,6 +9160,9 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom,
break;
}
+ if (ret == 0)
+ vm->updated = 1;
+
if (!ret && virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
ret = -1;
@@ -9786,6 +9823,13 @@ static int qemudDomainDetachDevice(virDomainPtr dom,
goto endjob;
}
+ if (virDomainObjSetDefTransient(driver->caps, vm) < 0) {
+ VIR_ERROR("Unable to set domain %s's running config as transient",
+ vm->def->name);
+
+ goto endjob;
+ }
+
dev = virDomainDeviceDefParse(driver->caps, vm->def, xml,
VIR_DOMAIN_XML_INACTIVE);
if (dev == NULL)
@@ -9828,6 +9872,9 @@ static int qemudDomainDetachDevice(virDomainPtr dom,
"%s", _("This type of device cannot be hot unplugged"));
}
+ if (ret == 0)
+ vm->updated = 1;
+
if (!ret && virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
ret = -1;
--
1.7.3.2
14 years, 6 months
[libvirt] [PATCH v6 0/4] Support of auto-dump on watchdog event in libvirtd
by Hu Tao
This patch series adds a new watchdog action `dump' which lets libvirtd
can do auto-dump when receiving a watchdog event from qemu guest.
In order to make the function work, there must be a watchdog device
added to guest, and guest must have a watchdog daemon running, for
example, /etc/init.d/watchdog start or auto-started on boot.
Changes:
v6:
- remove struct qemud_worker and qemud_server.job, qemud_server.nworkers,
qemud_server.nactiveworkers, qemud_server.workers.
v5:
- qemu_driver is passed into threadpool as opaque parameter rather than
visit the global qemu_driver in worker function
- same situation as above of server in libvirtd.c
- also list auto_dump_path in src/qemu/libvirtd_qemu.aug and
src/qemu/test_libvirtd_qemu.aug
- check return value of qemuDomainObjEndJob for safety
v4:
- updated threadpool to follow libvirt naming style, use appropriate
internals APIs, and hide the struct definitions from the header
(by Daniel)
- fix an error that qemuDomainObjBeginJobWithDriver() get lost in
qemuDomainCoreDump()
- use thread pool in libvirtd (qemud worker)
v3:
- let default auto-dump dir be /var/lib/libvirt/qemu/dump
Hu Tao (4):
threadpool impl
Add a new function doCoreDump
Add a watchdog action `dump'
Using threadpool API to manage qemud worker
cfg.mk | 1 +
daemon/libvirtd.c | 187 +++++---------------------------
daemon/libvirtd.h | 16 +---
src/Makefile.am | 1 +
src/conf/domain_conf.c | 1 +
src/conf/domain_conf.h | 1 +
src/libvirt_private.syms | 6 +
src/qemu/libvirtd_qemu.aug | 1 +
src/qemu/qemu.conf | 5 +
src/qemu/qemu_conf.c | 16 +++-
src/qemu/qemu_conf.h | 5 +
src/qemu/qemu_driver.c | 228 ++++++++++++++++++++++++++++----------
src/qemu/test_libvirtd_qemu.aug | 2 +
src/util/threadpool.c | 231 +++++++++++++++++++++++++++++++++++++++
src/util/threadpool.h | 48 ++++++++
15 files changed, 517 insertions(+), 232 deletions(-)
create mode 100644 src/util/threadpool.c
create mode 100644 src/util/threadpool.h
--
1.7.3
--
Thanks,
Hu Tao
14 years, 6 months
[libvirt] [PATCH 0/8] Initial integration of lock managers
by Daniel P. Berrange
This patch series is the bare minimum framework required to integrate
with external lock managers. This is a fleshing out of the original
proposal in
http://www.redhat.com/archives/libvir-list/2010-September/msg00167.html
What's in this series
* Major refactor of the security drivers to simplify code
and clarify interaction with lock maanger
* Low level internal lock manager plugin API for locking
objects and their resources
* High level internal lock manager API for locking virtual
machines and their disks
* Simple 'no op' plugin impl to stub out all the code
* Re-ordering of QEMU startup to add a handshake between
libvirtd & the child process, immediately prior to exec().
This allows acquiring locks in the child, before the
parent libvirtd process then re-labels disks
* The public API header for 3rd parties to implement
new lock manager plugins against
* Some basic documentation
What's not in this series
* A standard 'fcntl' based plugin
* Enhanced migration process to transfer lock state
* Hooks to re-validate the lock at time of VM resume
14 years, 6 months
[libvirt] [PATCH] spec: do not start libvirt-guests if that service is off
by Dan Kenigsberg
starting a service during rpm installation is impolite. It is even worse if done
during upgrade, for a service that was explicitly turned off.
---
libvirt.spec.in | 8 +++++---
1 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/libvirt.spec.in b/libvirt.spec.in
index 48453d7..e0cab78 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -700,9 +700,11 @@ fi
/sbin/ldconfig
/sbin/chkconfig --add libvirt-guests
if [ $1 -ge 1 ]; then
- # this doesn't do anything but allowing for libvirt-guests to be
- # stopped on the first shutdown
- /sbin/service libvirt-guests start > /dev/null 2>&1 || true
+ if /sbin/chkconfig --list libvirt-guests | /bin/grep -q :on ; then
+ # this doesn't do anything but allowing for libvirt-guests to be
+ # stopped on the first shutdown
+ /sbin/service libvirt-guests start > /dev/null 2>&1 || true
+ fi
fi
%postun client -p /sbin/ldconfig
--
1.7.3.2
14 years, 6 months
[libvirt] [PATCH] add network disk support
by MORITA Kazutaka
This patch adds network disk support to libvirt/QEMU. The currently
supported protcols are nbd, rbd, and sheepdog. The XML syntax is like
this:
<disk type="network" device="disk">
<driver name="qemu" type="raw" />
<source protocol='rbd|sheepdog|nbd' name="...some image identifier...">
<host name="mon1.example.org" port="6000">
<host name="mon2.example.org" port="6000">
<host name="mon3.example.org" port="6000">
</source>
<target dev="vda" bus="virtio" />
</disk>
Signed-off-by: MORITA Kazutaka <morita.kazutaka(a)lab.ntt.co.jp>
---
This patch addresses the discussion on
https://www.redhat.com/archives/libvir-list/2010-November/msg00759.html
Josh mentioned that the monitor hostnames of RBD can be set through
the environment variables, but I couldn't find any documentations
about it, so the monitors are not set in this patch. I hope someone
who is familiar with RBD implements it.
I appreciate any feedback.
Thanks,
Kazutaka
docs/schemas/domain.rng | 31 +++++++++
src/conf/domain_conf.c | 68 +++++++++++++++++--
src/conf/domain_conf.h | 20 ++++++
src/qemu/qemu_conf.c | 169 +++++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 279 insertions(+), 9 deletions(-)
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index fb44335..81f4004 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -612,6 +612,37 @@
<ref name="diskspec"/>
</interleave>
</group>
+ <group>
+ <attribute name="type">
+ <value>network</value>
+ </attribute>
+ <interleave>
+ <optional>
+ <element name="source">
+ <attribute name="protocol">
+ <choice>
+ <value>nbd</value>
+ <value>rbd</value>
+ <value>sheepdog</value>
+ </choice>
+ </attribute>
+ <attribute name="name"/>
+ <zeroOrMore>
+ <element name="host">
+ <attribute name="name">
+ <ref name="genericName"/>
+ </attribute>
+ <attribute name="port">
+ <ref name="unsignedInt"/>
+ </attribute>
+ </element>
+ </zeroOrMore>
+ <empty/>
+ </element>
+ </optional>
+ <ref name="diskspec"/>
+ </interleave>
+ </group>
<ref name="diskspec"/>
</choice>
</element>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 3f14cee..b9dbc61 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -113,7 +113,8 @@ VIR_ENUM_IMPL(virDomainDeviceAddress, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST,
VIR_ENUM_IMPL(virDomainDisk, VIR_DOMAIN_DISK_TYPE_LAST,
"block",
"file",
- "dir")
+ "dir",
+ "network")
VIR_ENUM_IMPL(virDomainDiskDevice, VIR_DOMAIN_DISK_DEVICE_LAST,
"disk",
@@ -142,6 +143,11 @@ VIR_ENUM_IMPL(virDomainDiskErrorPolicy, VIR_DOMAIN_DISK_ERROR_POLICY_LAST,
"ignore",
"enospace")
+VIR_ENUM_IMPL(virDomainDiskProtocol, VIR_DOMAIN_DISK_PROTOCOL_LAST,
+ "nbd",
+ "rbd",
+ "sheepdog")
+
VIR_ENUM_IMPL(virDomainController, VIR_DOMAIN_CONTROLLER_TYPE_LAST,
"ide",
"fdc",
@@ -508,6 +514,7 @@ void virDomainDiskDefFree(virDomainDiskDefPtr def)
VIR_FREE(def->serial);
VIR_FREE(def->src);
+ VIR_FREE(def->hosts);
VIR_FREE(def->dst);
VIR_FREE(def->driverName);
VIR_FREE(def->driverType);
@@ -1574,13 +1581,15 @@ virDomainDiskDefParseXML(virCapsPtr caps,
xmlNodePtr node,
int flags) {
virDomainDiskDefPtr def;
- xmlNodePtr cur;
+ xmlNodePtr cur, host;
char *type = NULL;
char *device = NULL;
char *driverName = NULL;
char *driverType = NULL;
char *source = NULL;
char *target = NULL;
+ char *protocol = NULL;
+ virDomainDiskHostDefPtr hosts = NULL;
char *bus = NULL;
char *cachetag = NULL;
char *error_policy = NULL;
@@ -1607,7 +1616,7 @@ virDomainDiskDefParseXML(virCapsPtr caps,
cur = node->children;
while (cur != NULL) {
if (cur->type == XML_ELEMENT_NODE) {
- if ((source == NULL) &&
+ if ((source == NULL && hosts == NULL) &&
(xmlStrEqual(cur->name, BAD_CAST "source"))) {
switch (def->type) {
@@ -1620,6 +1629,30 @@ virDomainDiskDefParseXML(virCapsPtr caps,
case VIR_DOMAIN_DISK_TYPE_DIR:
source = virXMLPropString(cur, "dir");
break;
+ case VIR_DOMAIN_DISK_TYPE_NETWORK:
+ protocol = virXMLPropString(cur, "protocol");
+ if (protocol == NULL) {
+ virDomainReportError(VIR_ERR_XML_ERROR,
+ "%s", _("missing protocol type"));
+ break;
+ }
+ def->protocol = virDomainDiskProtocolTypeFromString(protocol);
+ source = virXMLPropString(cur, "name");
+ host = cur->children;
+ while (host != NULL) {
+ if (host->type == XML_ELEMENT_NODE &&
+ xmlStrEqual(host->name, BAD_CAST "host")) {
+ if (VIR_REALLOC_N(hosts, def->nhosts + 1) < 0) {
+ virReportOOMError();
+ goto error;
+ }
+ hosts[def->nhosts].name = virXMLPropString(host, "name");
+ hosts[def->nhosts].port = virXMLPropString(host, "port");
+ def->nhosts++;
+ }
+ host = host->next;
+ }
+ break;
default:
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
_("unexpected disk type %s"),
@@ -1685,7 +1718,7 @@ virDomainDiskDefParseXML(virCapsPtr caps,
/* Only CDROM and Floppy devices are allowed missing source path
* to indicate no media present */
- if (source == NULL &&
+ if (source == NULL && hosts == NULL &&
def->device != VIR_DOMAIN_DISK_DEVICE_CDROM &&
def->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
virDomainReportError(VIR_ERR_NO_SOURCE,
@@ -1791,6 +1824,8 @@ virDomainDiskDefParseXML(virCapsPtr caps,
source = NULL;
def->dst = target;
target = NULL;
+ def->hosts = hosts;
+ hosts = NULL;
def->driverName = driverName;
driverName = NULL;
def->driverType = driverType;
@@ -1819,6 +1854,8 @@ cleanup:
VIR_FREE(type);
VIR_FREE(target);
VIR_FREE(source);
+ VIR_FREE(hosts);
+ VIR_FREE(protocol);
VIR_FREE(device);
VIR_FREE(driverType);
VIR_FREE(driverName);
@@ -5887,7 +5924,7 @@ virDomainDiskDefFormat(virBufferPtr buf,
virBufferVSprintf(buf, "/>\n");
}
- if (def->src) {
+ if (def->src || def->nhosts > 0) {
switch (def->type) {
case VIR_DOMAIN_DISK_TYPE_FILE:
virBufferEscapeString(buf, " <source file='%s'/>\n",
@@ -5901,6 +5938,27 @@ virDomainDiskDefFormat(virBufferPtr buf,
virBufferEscapeString(buf, " <source dir='%s'/>\n",
def->src);
break;
+ case VIR_DOMAIN_DISK_TYPE_NETWORK:
+ virBufferVSprintf(buf, " <source protocol='%s'",
+ virDomainDiskProtocolTypeToString(def->protocol));
+ if (def->src) {
+ virBufferEscapeString(buf, " name='%s'", def->src);
+ }
+ if (def->nhosts == 0) {
+ virBufferVSprintf(buf, "/>\n");
+ } else {
+ int i;
+
+ virBufferVSprintf(buf, ">\n");
+ for (i = 0; i < def->nhosts; i++) {
+ virBufferEscapeString(buf, " <host name='%s'",
+ def->hosts[i].name);
+ virBufferEscapeString(buf, " port='%s'/>\n",
+ def->hosts[i].port);
+ }
+ virBufferVSprintf(buf, " </source>\n");
+ }
+ break;
default:
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
_("unexpected disk type %s"),
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 899b19f..6c97289 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -120,6 +120,7 @@ enum virDomainDiskType {
VIR_DOMAIN_DISK_TYPE_BLOCK,
VIR_DOMAIN_DISK_TYPE_FILE,
VIR_DOMAIN_DISK_TYPE_DIR,
+ VIR_DOMAIN_DISK_TYPE_NETWORK,
VIR_DOMAIN_DISK_TYPE_LAST
};
@@ -164,6 +165,21 @@ enum virDomainDiskErrorPolicy {
VIR_DOMAIN_DISK_ERROR_POLICY_LAST
};
+enum virDomainDiskProtocol {
+ VIR_DOMAIN_DISK_PROTOCOL_NBD,
+ VIR_DOMAIN_DISK_PROTOCOL_RBD,
+ VIR_DOMAIN_DISK_PROTOCOL_SHEEPDOG,
+
+ VIR_DOMAIN_DISK_PROTOCOL_LAST
+};
+
+typedef struct _virDomainDiskHostDef virDomainDiskHostDef;
+typedef virDomainDiskHostDef *virDomainDiskHostDefPtr;
+struct _virDomainDiskHostDef {
+ char *name;
+ char *port;
+};
+
/* Stores the virtual disk configuration */
typedef struct _virDomainDiskDef virDomainDiskDef;
typedef virDomainDiskDef *virDomainDiskDefPtr;
@@ -173,6 +189,9 @@ struct _virDomainDiskDef {
int bus;
char *src;
char *dst;
+ int protocol;
+ int nhosts;
+ virDomainDiskHostDefPtr hosts;
char *driverName;
char *driverType;
char *serial;
@@ -1237,6 +1256,7 @@ VIR_ENUM_DECL(virDomainDiskDevice)
VIR_ENUM_DECL(virDomainDiskBus)
VIR_ENUM_DECL(virDomainDiskCache)
VIR_ENUM_DECL(virDomainDiskErrorPolicy)
+VIR_ENUM_DECL(virDomainDiskProtocol)
VIR_ENUM_DECL(virDomainController)
VIR_ENUM_DECL(virDomainControllerModel)
VIR_ENUM_DECL(virDomainFS)
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 35caccc..63abd75 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -2714,7 +2714,7 @@ qemuBuildDriveStr(virDomainDiskDefPtr disk,
break;
}
- if (disk->src) {
+ if (disk->src || disk->nhosts > 0) {
if (disk->type == VIR_DOMAIN_DISK_TYPE_DIR) {
/* QEMU only supports magic FAT format for now */
if (disk->driverType &&
@@ -2733,6 +2733,24 @@ qemuBuildDriveStr(virDomainDiskDefPtr disk,
virBufferVSprintf(&opt, "file=fat:floppy:%s,", disk->src);
else
virBufferVSprintf(&opt, "file=fat:%s,", disk->src);
+ } else if (disk->type == VIR_DOMAIN_DISK_TYPE_NETWORK) {
+ switch (disk->protocol) {
+ case VIR_DOMAIN_DISK_PROTOCOL_NBD:
+ virBufferVSprintf(&opt, "file=nbd:%s:%s,",
+ disk->hosts->name, disk->hosts->port);
+ break;
+ case VIR_DOMAIN_DISK_PROTOCOL_RBD:
+ virBufferVSprintf(&opt, "file=rbd:%s,", disk->src);
+ break;
+ case VIR_DOMAIN_DISK_PROTOCOL_SHEEPDOG:
+ if (disk->nhosts > 0)
+ virBufferVSprintf(&opt, "file=sheepdog:%s:%s:%s,",
+ disk->hosts->name, disk->hosts->port,
+ disk->src);
+ else
+ virBufferVSprintf(&opt, "file=sheepdog:%s,", disk->src);
+ break;
+ }
} else {
virBufferVSprintf(&opt, "file=%s,", disk->src);
}
@@ -4722,6 +4740,24 @@ int qemudBuildCommandLine(virConnectPtr conn,
snprintf(file, PATH_MAX, "fat:floppy:%s", disk->src);
else
snprintf(file, PATH_MAX, "fat:%s", disk->src);
+ } else if (disk->type == VIR_DOMAIN_DISK_TYPE_NETWORK) {
+ switch (disk->protocol) {
+ case VIR_DOMAIN_DISK_PROTOCOL_NBD:
+ snprintf(file, PATH_MAX, "nbd:%s:%s,",
+ disk->hosts->name, disk->hosts->port);
+ break;
+ case VIR_DOMAIN_DISK_PROTOCOL_RBD:
+ snprintf(file, PATH_MAX, "rbd:%s,", disk->src);
+ break;
+ case VIR_DOMAIN_DISK_PROTOCOL_SHEEPDOG:
+ if (disk->nhosts > 0)
+ snprintf(file, PATH_MAX, "sheepdog:%s:%s:%s,",
+ disk->hosts->name, disk->hosts->port,
+ disk->src);
+ else
+ snprintf(file, PATH_MAX, "sheepdog:%s,", disk->src);
+ break;
+ }
} else {
snprintf(file, PATH_MAX, "%s", disk->src);
}
@@ -5794,7 +5830,67 @@ qemuParseCommandLineDisk(virCapsPtr caps,
values[i] = NULL;
if (STRPREFIX(def->src, "/dev/"))
def->type = VIR_DOMAIN_DISK_TYPE_BLOCK;
- else
+ else if (STRPREFIX(def->src, "nbd:")) {
+ char *host, *port;
+
+ def->type = VIR_DOMAIN_DISK_TYPE_NETWORK;
+ host = def->src + strlen("nbd:");
+ port = strchr(host, ':');
+ if (!port) {
+ def = NULL;
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot parse nbd filename '%s'"), def->src);
+ goto cleanup;
+ }
+ *port++ = '\0';
+ if (VIR_ALLOC(def->hosts) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ def->nhosts = 1;
+ def->hosts->name = strdup(host);
+ def->hosts->port = strdup(port);
+
+ VIR_FREE(def->src);
+ def->src = NULL;
+ } else if (STRPREFIX(def->src, "rbd:")) {
+ char *p = def->src;
+
+ def->type = VIR_DOMAIN_DISK_TYPE_NETWORK;
+ def->src = strdup(p + strlen("rbd:"));
+
+ VIR_FREE(p);
+ } else if (STRPREFIX(def->src, "sheepdog:")) {
+ char *p = def->src;
+ char *port, *vdi;
+
+ def->type = VIR_DOMAIN_DISK_TYPE_NETWORK;
+ def->src = strdup(p + strlen("sheepdog:"));
+
+ /* def->src must be [vdiname] or [host]:[port]:[vdiname] */
+ port = strchr(def->src, ':');
+ if (port) {
+ *port++ = '\0';
+ vdi = strchr(port, ':');
+ if (!vdi) {
+ def = NULL;
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot parse sheepdog filename '%s'"), p);
+ goto cleanup;
+ }
+ *vdi++ = '\0';
+ if (VIR_ALLOC(def->hosts) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ def->nhosts = 1;
+ def->hosts->name = def->src;
+ def->hosts->port = strdup(port);
+ def->src = strdup(vdi);
+ }
+
+ VIR_FREE(p);
+ } else
def->type = VIR_DOMAIN_DISK_TYPE_FILE;
} else {
def->type = VIR_DOMAIN_DISK_TYPE_FILE;
@@ -6731,7 +6827,19 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
if (STRPREFIX(val, "/dev/"))
disk->type = VIR_DOMAIN_DISK_TYPE_BLOCK;
- else
+ else if (STRPREFIX(val, "nbd:")) {
+ disk->type = VIR_DOMAIN_DISK_TYPE_NETWORK;
+ disk->protocol = VIR_DOMAIN_DISK_PROTOCOL_NBD;
+ val += strlen("nbd:");
+ } else if (STRPREFIX(val, "rbd:")) {
+ disk->type = VIR_DOMAIN_DISK_TYPE_NETWORK;
+ disk->protocol = VIR_DOMAIN_DISK_PROTOCOL_RBD;
+ val += strlen("rbd:");
+ } else if (STRPREFIX(val, "sheepdog:")) {
+ disk->type = VIR_DOMAIN_DISK_TYPE_NETWORK;
+ disk->protocol = VIR_DOMAIN_DISK_PROTOCOL_SHEEPDOG;
+ val += strlen("sheepdog:");
+ } else
disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
if (STREQ(arg, "-cdrom")) {
disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
@@ -6751,7 +6859,60 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
disk->dst = strdup(arg + 1);
}
disk->src = strdup(val);
- if (!disk->src ||
+
+ if (disk->type == VIR_DOMAIN_DISK_TYPE_NETWORK) {
+ char *host, *port;
+
+ switch (disk->protocol) {
+ case VIR_DOMAIN_DISK_PROTOCOL_NBD:
+ host = disk->src;
+ port = strchr(host, ':');
+ if (!port) {
+ def = NULL;
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot parse nbd filename '%s'"), disk->src);
+ goto error;
+ }
+ *port++ = '\0';
+ if (VIR_ALLOC(disk->hosts) < 0) {
+ virReportOOMError();
+ goto error;
+ }
+ disk->nhosts = 1;
+ disk->hosts->name = host;
+ disk->hosts->port = strdup(port);
+ disk->src = NULL;
+ break;
+ case VIR_DOMAIN_DISK_PROTOCOL_RBD:
+ break;
+ case VIR_DOMAIN_DISK_PROTOCOL_SHEEPDOG:
+ /* disk->src must be [vdiname] or [host]:[port]:[vdiname] */
+ port = strchr(disk->src, ':');
+ if (port) {
+ char *vdi;
+
+ *port++ = '\0';
+ vdi = strchr(port, ':');
+ if (!vdi) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot parse sheepdog filename '%s'"), val);
+ goto error;
+ }
+ *vdi++ = '\0';
+ if (VIR_ALLOC(disk->hosts) < 0) {
+ virReportOOMError();
+ goto error;
+ }
+ disk->nhosts = 1;
+ disk->hosts->name = disk->src;
+ disk->hosts->port = strdup(port);
+ disk->src = strdup(vdi);
+ }
+ break;
+ }
+ }
+
+ if (!(disk->src || disk->nhosts > 0) ||
!disk->dst) {
virDomainDiskDefFree(disk);
goto no_memory;
--
1.7.1
14 years, 6 months
[libvirt] [PATCH] correct the signal's name
by Wen Congyang
The signal's name is wrong...
Signed-off-by: Wen Congyang <wency(a)cn.fujitsu.com>
---
tools/console.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/tools/console.c b/tools/console.c
index c2971cf..e126320 100644
--- a/tools/console.c
+++ b/tools/console.c
@@ -365,10 +365,10 @@ int vshRunConsole(virDomainPtr dom, const char *devname)
}
/* Restore original signal handlers */
- signal(SIGQUIT, old_sigpipe);
- signal(SIGQUIT, old_sighup);
- signal(SIGQUIT, old_sigint);
- signal(SIGQUIT, old_sigterm);
+ signal(SIGPIPE, old_sigpipe);
+ signal(SIGHUP, old_sighup);
+ signal(SIGINT, old_sigint);
+ signal(SIGTERM, old_sigterm);
signal(SIGQUIT, old_sigquit);
resettty:
--
1.7.1
14 years, 6 months