esx: Add domain snapshot support

Fix invalid code generating in esx_vi_generator.py regarding deep copy
types that contain enum properties.

Add strptime and timegm to bootstrap.conf. Both are used to convert a
xsd:dateTime to calendar time.

Add a testcase of the xsd:dateTime conversion.
This commit is contained in:
Matthias Bolte 2010-04-07 11:23:53 +02:00
parent 1787fdff57
commit 1aaa909116
11 changed files with 1089 additions and 48 deletions

View File

@ -52,9 +52,11 @@ stpcpy
strchrnul
strndup
strerror
strptime
strsep
sys_stat
time_r
timegm
useless-if-before-free
vasprintf
verify

View File

@ -563,6 +563,7 @@ esxClose(virConnectPtr conn)
esxVI_Logout(priv->host) < 0) {
result = -1;
}
esxVI_Context_Free(&priv->host);
if (priv->vCenter != NULL) {
@ -570,6 +571,7 @@ esxClose(virConnectPtr conn)
esxVI_Logout(priv->vCenter) < 0) {
result = -1;
}
esxVI_Context_Free(&priv->vCenter);
}
@ -1742,23 +1744,8 @@ esxDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
goto failure;
}
switch (powerState) {
case esxVI_VirtualMachinePowerState_PoweredOff:
info->state = VIR_DOMAIN_SHUTOFF;
break;
case esxVI_VirtualMachinePowerState_PoweredOn:
info->state = VIR_DOMAIN_RUNNING;
break;
case esxVI_VirtualMachinePowerState_Suspended:
info->state = VIR_DOMAIN_PAUSED;
break;
default:
info->state = VIR_DOMAIN_NOSTATE;
break;
}
info->state = esxVI_VirtualMachinePowerState_ConvertToLibvirt
(powerState);
} else if (STREQ(dynamicProperty->name, "config.hardware.memoryMB")) {
if (esxVI_AnyType_ExpectType(dynamicProperty->val,
esxVI_Type_Int) < 0) {
@ -2329,7 +2316,6 @@ esxListDefinedDomains(virConnectPtr conn, char **const names, int maxnames)
count = -1;
goto cleanup;
}
@ -3308,6 +3294,425 @@ esxDomainIsPersistent(virDomainPtr domain ATTRIBUTE_UNUSED)
static virDomainSnapshotPtr
esxDomainSnapshotCreateXML(virDomainPtr domain, const char *xmlDesc,
unsigned int flags ATTRIBUTE_UNUSED)
{
esxPrivate *priv = domain->conn->privateData;
virDomainSnapshotDefPtr def = NULL;
esxVI_ObjectContent *virtualMachine = NULL;
esxVI_VirtualMachineSnapshotTree *rootSnapshotList = NULL;
esxVI_VirtualMachineSnapshotTree *snapshotTree = NULL;
esxVI_VirtualMachineSnapshotTree *snapshotTreeParent = NULL;
esxVI_ManagedObjectReference *task = NULL;
esxVI_TaskInfoState taskInfoState;
virDomainSnapshotPtr snapshot = NULL;
if (esxVI_EnsureSession(priv->host) < 0) {
goto failure;
}
def = virDomainSnapshotDefParseString(xmlDesc, 1);
if (def == NULL) {
goto failure;
}
if (esxVI_LookupVirtualMachineByUuidAndPrepareForTask
(priv->host, domain->uuid, NULL, &virtualMachine,
priv->autoAnswer) < 0 ||
esxVI_LookupRootSnapshotTreeList(priv->host, domain->uuid,
&rootSnapshotList) < 0 ||
esxVI_GetSnapshotTreeByName(rootSnapshotList, def->name,
&snapshotTree, &snapshotTreeParent,
esxVI_Occurrence_OptionalItem) < 0) {
goto failure;
}
if (snapshotTree != NULL) {
ESX_ERROR(VIR_ERR_OPERATION_INVALID,
_("Snapshot '%s' already exists"), def->name);
goto failure;
}
if (esxVI_CreateSnapshot_Task(priv->host, virtualMachine->obj,
def->name, def->description,
esxVI_Boolean_True,
esxVI_Boolean_False, &task) < 0 ||
esxVI_WaitForTaskCompletion(priv->host, task, domain->uuid,
priv->autoAnswer, &taskInfoState) < 0) {
goto failure;
}
if (taskInfoState != esxVI_TaskInfoState_Success) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not create snapshot"));
goto failure;
}
snapshot = virGetDomainSnapshot(domain, def->name);
cleanup:
virDomainSnapshotDefFree(def);
esxVI_ObjectContent_Free(&virtualMachine);
esxVI_VirtualMachineSnapshotTree_Free(&rootSnapshotList);
esxVI_ManagedObjectReference_Free(&task);
return snapshot;
failure:
domain = NULL;
goto cleanup;
}
static char *
esxDomainSnapshotDumpXML(virDomainSnapshotPtr snapshot,
unsigned int flags ATTRIBUTE_UNUSED)
{
esxPrivate *priv = snapshot->domain->conn->privateData;
esxVI_VirtualMachineSnapshotTree *rootSnapshotList = NULL;
esxVI_VirtualMachineSnapshotTree *snapshotTree = NULL;
esxVI_VirtualMachineSnapshotTree *snapshotTreeParent = NULL;
virDomainSnapshotDef def;
char uuid_string[VIR_UUID_STRING_BUFLEN] = "";
char *xml = NULL;
memset(&def, 0, sizeof (virDomainSnapshotDef));
if (esxVI_EnsureSession(priv->host) < 0) {
goto failure;
}
if (esxVI_LookupRootSnapshotTreeList(priv->host, snapshot->domain->uuid,
&rootSnapshotList) < 0 ||
esxVI_GetSnapshotTreeByName(rootSnapshotList, snapshot->name,
&snapshotTree, &snapshotTreeParent,
esxVI_Occurrence_RequiredItem) < 0) {
goto failure;
}
def.name = snapshot->name;
def.description = snapshotTree->description;
def.parent = snapshotTreeParent != NULL ? snapshotTreeParent->name : NULL;
if (esxVI_DateTime_ConvertToCalendarTime(snapshotTree->createTime,
&def.creationTime) < 0) {
goto failure;
}
def.state = esxVI_VirtualMachinePowerState_ConvertToLibvirt
(snapshotTree->state);
virUUIDFormat(snapshot->domain->uuid, uuid_string);
xml = virDomainSnapshotDefFormat(uuid_string, &def, 0);
cleanup:
esxVI_VirtualMachineSnapshotTree_Free(&rootSnapshotList);
return xml;
failure:
VIR_FREE(xml);
goto cleanup;
}
static int
esxDomainSnapshotNum(virDomainPtr domain, unsigned int flags ATTRIBUTE_UNUSED)
{
int result = 0;
esxPrivate *priv = domain->conn->privateData;
esxVI_VirtualMachineSnapshotTree *rootSnapshotTreeList = NULL;
if (esxVI_EnsureSession(priv->host) < 0) {
goto failure;
}
if (esxVI_LookupRootSnapshotTreeList(priv->host, domain->uuid,
&rootSnapshotTreeList) < 0) {
goto failure;
}
result = esxVI_GetNumberOfSnapshotTrees(rootSnapshotTreeList);
cleanup:
esxVI_VirtualMachineSnapshotTree_Free(&rootSnapshotTreeList);
return result;
failure:
result = -1;
goto cleanup;
}
static int
esxDomainSnapshotListNames(virDomainPtr domain, char **names, int nameslen,
unsigned int flags ATTRIBUTE_UNUSED)
{
int result = 0;
esxPrivate *priv = domain->conn->privateData;
esxVI_VirtualMachineSnapshotTree *rootSnapshotTreeList = NULL;
if (names == NULL || nameslen < 0) {
ESX_ERROR(VIR_ERR_INVALID_ARG, "%s", _("Invalid argument"));
return -1;
}
if (nameslen == 0) {
return 0;
}
if (esxVI_EnsureSession(priv->host) < 0) {
goto failure;
}
if (esxVI_LookupRootSnapshotTreeList(priv->host, domain->uuid,
&rootSnapshotTreeList) < 0) {
goto failure;
}
result = esxVI_GetSnapshotTreeNames(rootSnapshotTreeList, names, nameslen);
cleanup:
esxVI_VirtualMachineSnapshotTree_Free(&rootSnapshotTreeList);
return result;
failure:
result = -1;
goto cleanup;
}
static virDomainSnapshotPtr
esxDomainSnapshotLookupByName(virDomainPtr domain, const char *name,
unsigned int flags ATTRIBUTE_UNUSED)
{
esxPrivate *priv = domain->conn->privateData;
esxVI_VirtualMachineSnapshotTree *rootSnapshotTreeList = NULL;
esxVI_VirtualMachineSnapshotTree *snapshotTree = NULL;
esxVI_VirtualMachineSnapshotTree *snapshotTreeParent = NULL;
virDomainSnapshotPtr snapshot = NULL;
if (esxVI_EnsureSession(priv->host) < 0) {
goto cleanup;
}
if (esxVI_LookupRootSnapshotTreeList(priv->host, domain->uuid,
&rootSnapshotTreeList) < 0 ||
esxVI_GetSnapshotTreeByName(rootSnapshotTreeList, name, &snapshotTree,
&snapshotTreeParent,
esxVI_Occurrence_RequiredItem) < 0) {
goto cleanup;
}
snapshot = virGetDomainSnapshot(domain, name);
cleanup:
esxVI_VirtualMachineSnapshotTree_Free(&rootSnapshotTreeList);
return snapshot;
}
static int
esxDomainHasCurrentSnapshot(virDomainPtr domain, unsigned int flags)
{
int result = 0;
esxPrivate *priv = domain->conn->privateData;
esxVI_VirtualMachineSnapshotTree *currentSnapshotTree = NULL;
if (flags != 0) {
ESX_ERROR(VIR_ERR_INVALID_ARG,
_("Unsupported flags (0x%x) passed to %s"),
flags, __FUNCTION__);
return -1;
}
if (esxVI_EnsureSession(priv->host) < 0) {
goto failure;
}
if (esxVI_LookupCurrentSnapshotTree(priv->host, domain->uuid,
&currentSnapshotTree,
esxVI_Occurrence_OptionalItem) < 0) {
goto failure;
}
if (currentSnapshotTree != NULL) {
result = 1;
}
cleanup:
esxVI_VirtualMachineSnapshotTree_Free(&currentSnapshotTree);
return result;
failure:
result = -1;
goto cleanup;
}
static virDomainSnapshotPtr
esxDomainSnapshotCurrent(virDomainPtr domain, unsigned int flags)
{
virDomainSnapshotPtr snapshot = NULL;
esxPrivate *priv = domain->conn->privateData;
esxVI_VirtualMachineSnapshotTree *currentSnapshotTree = NULL;
if (flags != 0) {
ESX_ERROR(VIR_ERR_INVALID_ARG,
_("Unsupported flags (0x%x) passed to %s"),
flags, __FUNCTION__);
return NULL;
}
if (esxVI_EnsureSession(priv->host) < 0) {
goto cleanup;
}
if (esxVI_LookupCurrentSnapshotTree(priv->host, domain->uuid,
&currentSnapshotTree,
esxVI_Occurrence_RequiredItem) < 0) {
goto cleanup;
}
snapshot = virGetDomainSnapshot(domain, currentSnapshotTree->name);
cleanup:
esxVI_VirtualMachineSnapshotTree_Free(&currentSnapshotTree);
return snapshot;
}
static int
esxDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, unsigned int flags)
{
int result = 0;
esxPrivate *priv = snapshot->domain->conn->privateData;
esxVI_VirtualMachineSnapshotTree *rootSnapshotList = NULL;
esxVI_VirtualMachineSnapshotTree *snapshotTree = NULL;
esxVI_VirtualMachineSnapshotTree *snapshotTreeParent = NULL;
esxVI_ManagedObjectReference *task = NULL;
esxVI_TaskInfoState taskInfoState;
if (flags != 0) {
ESX_ERROR(VIR_ERR_INVALID_ARG,
_("Unsupported flags (0x%x) passed to %s"),
flags, __FUNCTION__);
return -1;
}
if (esxVI_EnsureSession(priv->host) < 0) {
goto failure;
}
if (esxVI_LookupRootSnapshotTreeList(priv->host, snapshot->domain->uuid,
&rootSnapshotList) < 0 ||
esxVI_GetSnapshotTreeByName(rootSnapshotList, snapshot->name,
&snapshotTree, &snapshotTreeParent,
esxVI_Occurrence_RequiredItem) < 0) {
goto failure;
}
if (esxVI_RevertToSnapshot_Task(priv->host, snapshotTree->snapshot, NULL,
&task) < 0 ||
esxVI_WaitForTaskCompletion(priv->host, task, snapshot->domain->uuid,
priv->autoAnswer, &taskInfoState) < 0) {
goto failure;
}
if (taskInfoState != esxVI_TaskInfoState_Success) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Could not revert to snapshot '%s'"), snapshot->name);
goto failure;
}
cleanup:
esxVI_VirtualMachineSnapshotTree_Free(&rootSnapshotList);
esxVI_ManagedObjectReference_Free(&task);
return result;
failure:
result = -1;
goto cleanup;
}
static int
esxDomainSnapshotDelete(virDomainSnapshotPtr snapshot, unsigned int flags)
{
int result = 0;
esxPrivate *priv = snapshot->domain->conn->privateData;
esxVI_VirtualMachineSnapshotTree *rootSnapshotList = NULL;
esxVI_VirtualMachineSnapshotTree *snapshotTree = NULL;
esxVI_VirtualMachineSnapshotTree *snapshotTreeParent = NULL;
esxVI_Boolean removeChildren = esxVI_Boolean_False;
esxVI_ManagedObjectReference *task = NULL;
esxVI_TaskInfoState taskInfoState;
if (esxVI_EnsureSession(priv->host) < 0) {
goto failure;
}
if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN) {
removeChildren = esxVI_Boolean_True;
}
if (esxVI_LookupRootSnapshotTreeList(priv->host, snapshot->domain->uuid,
&rootSnapshotList) < 0 ||
esxVI_GetSnapshotTreeByName(rootSnapshotList, snapshot->name,
&snapshotTree, &snapshotTreeParent,
esxVI_Occurrence_RequiredItem) < 0) {
goto failure;
}
if (esxVI_RemoveSnapshot_Task(priv->host, snapshotTree->snapshot,
removeChildren, &task) < 0 ||
esxVI_WaitForTaskCompletion(priv->host, task, snapshot->domain->uuid,
priv->autoAnswer, &taskInfoState) < 0) {
goto failure;
}
if (taskInfoState != esxVI_TaskInfoState_Success) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Could not delete snapshot '%s'"), snapshot->name);
goto failure;
}
cleanup:
esxVI_VirtualMachineSnapshotTree_Free(&rootSnapshotList);
esxVI_ManagedObjectReference_Free(&task);
return result;
failure:
result = -1;
goto cleanup;
}
static virDriver esxDriver = {
VIR_DRV_ESX,
"ESX",
@ -3388,23 +3793,23 @@ static virDriver esxDriver = {
esxDomainIsPersistent, /* domainIsPersistent */
NULL, /* cpuCompare */
NULL, /* cpuBaseline */
NULL, /* domainGetJobInfo */
NULL, /* domainAbortJob */
NULL, /* domainMigrateSetMaxDowntime */
NULL, /* domainEventRegisterAny */
NULL, /* domainEventDeregisterAny */
NULL, /* domainManagedSave */
NULL, /* domainHasManagedSaveImage */
NULL, /* domainManagedSaveRemove */
NULL, /* domainSnapshotCreateXML */
NULL, /* domainSnapshotDumpXML */
NULL, /* domainSnapshotNum */
NULL, /* domainSnapshotListNames */
NULL, /* domainSnapshotLookupByName */
NULL, /* domainHasCurrentSnapshot */
NULL, /* domainSnapshotCurrent */
NULL, /* domainRevertToSnapshot */
NULL, /* domainSnapshotDelete */
NULL, /* domainGetJobInfo */
NULL, /* domainAbortJob */
NULL, /* domainMigrateSetMaxDowntime */
NULL, /* domainEventRegisterAny */
NULL, /* domainEventDeregisterAny */
NULL, /* domainManagedSave */
NULL, /* domainHasManagedSaveImage */
NULL, /* domainManagedSaveRemove */
esxDomainSnapshotCreateXML, /* domainSnapshotCreateXML */
esxDomainSnapshotDumpXML, /* domainSnapshotDumpXML */
esxDomainSnapshotNum, /* domainSnapshotNum */
esxDomainSnapshotListNames, /* domainSnapshotListNames */
esxDomainSnapshotLookupByName, /* domainSnapshotLookupByName */
esxDomainHasCurrentSnapshot, /* domainHasCurrentSnapshot */
esxDomainSnapshotCurrent, /* domainSnapshotCurrent */
esxDomainRevertToSnapshot, /* domainRevertToSnapshot */
esxDomainSnapshotDelete, /* domainSnapshotDelete */
};

View File

@ -1718,6 +1718,152 @@ esxVI_GetVirtualMachineIdentity(esxVI_ObjectContent *virtualMachine,
int
esxVI_GetNumberOfSnapshotTrees
(esxVI_VirtualMachineSnapshotTree *snapshotTreeList)
{
int count = 0;
esxVI_VirtualMachineSnapshotTree *snapshotTree;
for (snapshotTree = snapshotTreeList; snapshotTree != NULL;
snapshotTree = snapshotTree->_next) {
count += 1 + esxVI_GetNumberOfSnapshotTrees
(snapshotTree->childSnapshotList);
}
return count;
}
int
esxVI_GetSnapshotTreeNames(esxVI_VirtualMachineSnapshotTree *snapshotTreeList,
char **names, int nameslen)
{
int count = 0;
int result;
int i;
esxVI_VirtualMachineSnapshotTree *snapshotTree;
for (snapshotTree = snapshotTreeList;
snapshotTree != NULL && count < nameslen;
snapshotTree = snapshotTree->_next) {
names[count] = strdup(snapshotTree->name);
if (names[count] == NULL) {
virReportOOMError();
goto failure;
}
count++;
if (count >= nameslen) {
break;
}
result = esxVI_GetSnapshotTreeNames(snapshotTree->childSnapshotList,
names + count, nameslen - count);
if (result < 0) {
goto failure;
}
count += result;
}
return count;
failure:
for (i = 0; i < count; ++i) {
VIR_FREE(names[i]);
}
return -1;
}
int
esxVI_GetSnapshotTreeByName
(esxVI_VirtualMachineSnapshotTree *snapshotTreeList, const char *name,
esxVI_VirtualMachineSnapshotTree **snapshotTree,
esxVI_VirtualMachineSnapshotTree **snapshotTreeParent,
esxVI_Occurrence occurrence)
{
esxVI_VirtualMachineSnapshotTree *candidate;
if (snapshotTree == NULL || *snapshotTree != NULL ||
snapshotTreeParent == NULL || *snapshotTreeParent != NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
return -1;
}
for (candidate = snapshotTreeList; candidate != NULL;
candidate = candidate->_next) {
if (STREQ(candidate->name, name)) {
*snapshotTree = candidate;
*snapshotTreeParent = NULL;
return 1;
}
if (esxVI_GetSnapshotTreeByName(candidate->childSnapshotList, name,
snapshotTree, snapshotTreeParent,
occurrence) > 0) {
if (*snapshotTreeParent == NULL) {
*snapshotTreeParent = candidate;
}
return 1;
}
}
if (occurrence == esxVI_Occurrence_OptionalItem) {
return 0;
} else {
ESX_VI_ERROR(VIR_ERR_NO_DOMAIN_SNAPSHOT,
_("Could not find snapshot with name '%s'"), name);
return -1;
}
}
int
esxVI_GetSnapshotTreeBySnapshot
(esxVI_VirtualMachineSnapshotTree *snapshotTreeList,
esxVI_ManagedObjectReference *snapshot,
esxVI_VirtualMachineSnapshotTree **snapshotTree)
{
esxVI_VirtualMachineSnapshotTree *candidate;
if (snapshotTree == NULL || *snapshotTree != NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
return -1;
}
for (candidate = snapshotTreeList; candidate != NULL;
candidate = candidate->_next) {
if (STREQ(candidate->snapshot->value, snapshot->value)) {
*snapshotTree = candidate;
return 0;
}
if (esxVI_GetSnapshotTreeBySnapshot(candidate->childSnapshotList,
snapshot, snapshotTree) >= 0) {
return 0;
}
}
ESX_VI_ERROR(VIR_ERR_NO_DOMAIN_SNAPSHOT,
_("Could not find domain snapshot with internal name '%s'"),
snapshot->value);
return -1;
}
int
esxVI_LookupResourcePoolByHostSystem
(esxVI_Context *ctx, esxVI_ObjectContent *hostSystem,
@ -2335,6 +2481,149 @@ esxVI_LookupAndHandleVirtualMachineQuestion(esxVI_Context *ctx,
int
esxVI_LookupRootSnapshotTreeList
(esxVI_Context *ctx, const unsigned char *virtualMachineUuid,
esxVI_VirtualMachineSnapshotTree **rootSnapshotTreeList)
{
int result = 0;
esxVI_String *propertyNameList = NULL;
esxVI_ObjectContent *virtualMachine = NULL;
esxVI_DynamicProperty *dynamicProperty = NULL;
if (rootSnapshotTreeList == NULL || *rootSnapshotTreeList != NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
return -1;
}
if (esxVI_String_AppendValueToList(&propertyNameList,
"snapshot.rootSnapshotList") < 0 ||
esxVI_LookupVirtualMachineByUuid(ctx, virtualMachineUuid,
propertyNameList, &virtualMachine,
esxVI_Occurrence_RequiredItem) < 0) {
goto failure;
}
for (dynamicProperty = virtualMachine->propSet; dynamicProperty != NULL;
dynamicProperty = dynamicProperty->_next) {
if (STREQ(dynamicProperty->name, "snapshot.rootSnapshotList")) {
if (esxVI_VirtualMachineSnapshotTree_CastListFromAnyType
(dynamicProperty->val, rootSnapshotTreeList) < 0) {
goto failure;
}
break;
} else {
VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
}
}
if (*rootSnapshotTreeList == NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not lookup root snapshot list"));
goto failure;
}
cleanup:
esxVI_String_Free(&propertyNameList);
esxVI_ObjectContent_Free(&virtualMachine);
return result;
failure:
esxVI_VirtualMachineSnapshotTree_Free(rootSnapshotTreeList);
result = -1;
goto cleanup;
}
int
esxVI_LookupCurrentSnapshotTree
(esxVI_Context *ctx, const unsigned char *virtualMachineUuid,
esxVI_VirtualMachineSnapshotTree **currentSnapshotTree,
esxVI_Occurrence occurrence)
{
int result = 0;
esxVI_String *propertyNameList = NULL;
esxVI_ObjectContent *virtualMachine = NULL;
esxVI_DynamicProperty *dynamicProperty = NULL;
esxVI_ManagedObjectReference *currentSnapshot = NULL;
esxVI_VirtualMachineSnapshotTree *rootSnapshotTreeList = NULL;
esxVI_VirtualMachineSnapshotTree *snapshotTree = NULL;
if (currentSnapshotTree == NULL || *currentSnapshotTree != NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
return -1;
}
if (esxVI_String_AppendValueListToList(&propertyNameList,
"snapshot.currentSnapshot\0"
"snapshot.rootSnapshotList\0") < 0 ||
esxVI_LookupVirtualMachineByUuid(ctx, virtualMachineUuid,
propertyNameList, &virtualMachine,
esxVI_Occurrence_RequiredItem) < 0) {
goto failure;
}
for (dynamicProperty = virtualMachine->propSet; dynamicProperty != NULL;
dynamicProperty = dynamicProperty->_next) {
if (STREQ(dynamicProperty->name, "snapshot.currentSnapshot")) {
if (esxVI_ManagedObjectReference_CastFromAnyType
(dynamicProperty->val, &currentSnapshot) < 0) {
goto failure;
}
} else if (STREQ(dynamicProperty->name, "snapshot.rootSnapshotList")) {
if (esxVI_VirtualMachineSnapshotTree_CastListFromAnyType
(dynamicProperty->val, &rootSnapshotTreeList) < 0) {
goto failure;
}
} else {
VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
}
}
if (currentSnapshot == NULL) {
if (occurrence == esxVI_Occurrence_OptionalItem) {
return 0;
} else {
ESX_VI_ERROR(VIR_ERR_NO_DOMAIN_SNAPSHOT, "%s",
_("Domain has no current snapshot"));
goto failure;
}
}
if (rootSnapshotTreeList == NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not lookup root snapshot list"));
goto failure;
}
if (esxVI_GetSnapshotTreeBySnapshot(rootSnapshotTreeList, currentSnapshot,
&snapshotTree) < 0 ||
esxVI_VirtualMachineSnapshotTree_DeepCopy(currentSnapshotTree,
snapshotTree) < 0) {
goto failure;
}
cleanup:
esxVI_String_Free(&propertyNameList);
esxVI_ObjectContent_Free(&virtualMachine);
esxVI_ManagedObjectReference_Free(&currentSnapshot);
esxVI_VirtualMachineSnapshotTree_Free(&rootSnapshotTreeList);
return result;
failure:
result = -1;
goto cleanup;
}
int
esxVI_HandleVirtualMachineQuestion
(esxVI_Context *ctx, esxVI_ManagedObjectReference *virtualMachine,
@ -2422,9 +2711,7 @@ esxVI_HandleVirtualMachineQuestion
return result;
failure:
if (possibleAnswers == NULL) {
possibleAnswers = virBufferContentAndReset(&buffer);
}
virBufferFreeAndReset(&buffer);
result = -1;

View File

@ -233,6 +233,24 @@ int esxVI_LookupNumberOfDomainsByPowerState
int esxVI_GetVirtualMachineIdentity(esxVI_ObjectContent *virtualMachine,
int *id, char **name, unsigned char *uuid);
int esxVI_GetNumberOfSnapshotTrees
(esxVI_VirtualMachineSnapshotTree *snapshotTreeList);
int esxVI_GetSnapshotTreeNames
(esxVI_VirtualMachineSnapshotTree *snapshotTreeList, char **names,
int nameslen);
int esxVI_GetSnapshotTreeByName
(esxVI_VirtualMachineSnapshotTree *snapshotTreeList, const char *name,
esxVI_VirtualMachineSnapshotTree **snapshotTree,
esxVI_VirtualMachineSnapshotTree **snapshotTreeParent,
esxVI_Occurrence occurrence);
int esxVI_GetSnapshotTreeBySnapshot
(esxVI_VirtualMachineSnapshotTree *snapshotTreeList,
esxVI_ManagedObjectReference *snapshot,
esxVI_VirtualMachineSnapshotTree **snapshotTree);
int esxVI_LookupResourcePoolByHostSystem
(esxVI_Context *ctx, esxVI_ObjectContent *hostSystem,
esxVI_ManagedObjectReference **resourcePool);
@ -274,6 +292,15 @@ int esxVI_LookupAndHandleVirtualMachineQuestion(esxVI_Context *ctx,
const unsigned char *uuid,
esxVI_Boolean autoAnswer);
int esxVI_LookupRootSnapshotTreeList
(esxVI_Context *ctx, const unsigned char *virtualMachineUuid,
esxVI_VirtualMachineSnapshotTree **rootSnapshotTreeList);
int esxVI_LookupCurrentSnapshotTree
(esxVI_Context *ctx, const unsigned char *virtualMachineUuid,
esxVI_VirtualMachineSnapshotTree **currentSnapshotTree,
esxVI_Occurrence occurrence);
int esxVI_HandleVirtualMachineQuestion
(esxVI_Context *ctx,
esxVI_ManagedObjectReference *virtualMachine,

View File

@ -424,3 +424,15 @@ object VirtualMachineQuestionInfo
ChoiceOption choice r
VirtualMachineMessage message i
end
object VirtualMachineSnapshotTree
ManagedObjectReference snapshot r
ManagedObjectReference vm r
String name r
String description r
DateTime createTime r
VirtualMachinePowerState state r
Boolean quiesced r
VirtualMachineSnapshotTree childSnapshotList ol
end

View File

@ -95,6 +95,8 @@ class Property:
return " ESX_VI__TEMPLATE__PROPERTY__DEEP_COPY_LIST(%s, %s)\n" % (self.type, self.name)
elif self.type == "String":
return " ESX_VI__TEMPLATE__PROPERTY__DEEP_COPY_VALUE(String, %s)\n" % self.name
elif self.is_enum():
return " (*dest)->%s = src->%s;\n" % (self.name, self.name)
else:
return " ESX_VI__TEMPLATE__PROPERTY__DEEP_COPY(%s, %s)\n" % (self.type, self.name)
@ -841,17 +843,19 @@ additional_object_features = { "Event" : Object.FEATURE__LI
"SharesInfo" : Object.FEATURE__ANY_TYPE,
"TaskInfo" : Object.FEATURE__ANY_TYPE | Object.FEATURE__LIST,
"UserSession" : Object.FEATURE__ANY_TYPE,
"VirtualMachineQuestionInfo" : Object.FEATURE__ANY_TYPE }
"VirtualMachineQuestionInfo" : Object.FEATURE__ANY_TYPE,
"VirtualMachineSnapshotTree" : Object.FEATURE__DEEP_COPY | Object.FEATURE__ANY_TYPE }
removed_object_features = { "DynamicProperty" : Object.FEATURE__SERIALIZE,
"ObjectContent" : Object.FEATURE__SERIALIZE,
"ObjectUpdate" : Object.FEATURE__SERIALIZE,
"PropertyChange" : Object.FEATURE__SERIALIZE,
"PropertyFilterUpdate" : Object.FEATURE__SERIALIZE,
"TaskInfo" : Object.FEATURE__SERIALIZE,
"UpdateSet" : Object.FEATURE__SERIALIZE,
"VirtualMachineConfigInfo" : Object.FEATURE__SERIALIZE }
removed_object_features = { "DynamicProperty" : Object.FEATURE__SERIALIZE,
"ObjectContent" : Object.FEATURE__SERIALIZE,
"ObjectUpdate" : Object.FEATURE__SERIALIZE,
"PropertyChange" : Object.FEATURE__SERIALIZE,
"PropertyFilterUpdate" : Object.FEATURE__SERIALIZE,
"TaskInfo" : Object.FEATURE__SERIALIZE,
"UpdateSet" : Object.FEATURE__SERIALIZE,
"VirtualMachineConfigInfo" : Object.FEATURE__SERIALIZE,
"VirtualMachineSnapshotTree" : Object.FEATURE__SERIALIZE }
@ -948,7 +952,8 @@ for obj in objects_by_name.values():
if obj.features & Object.FEATURE__DEEP_COPY:
for property in obj.properties:
if property.occurrence != Property.OCCURRENCE__IGNORED and \
property.type not in predefined_objects:
property.type not in predefined_objects and \
property.type in objects_by_name:
objects_by_name[property.type].features |= Object.FEATURE__DEEP_COPY
# detect extended_by relation

View File

@ -491,6 +491,92 @@ ESX_VI__METHOD(RegisterVM_Task,
/* esxVI_CreateSnapshot_Task */
ESX_VI__METHOD(CreateSnapshot_Task,
(esxVI_Context *ctx,
esxVI_ManagedObjectReference *virtualMachine,
const char *name, const char *description,
esxVI_Boolean memory, esxVI_Boolean quiesce,
esxVI_ManagedObjectReference **task),
RequiredItem,
{
ESX_VI__METHOD__PARAMETER__CHECK_OUTPUT(task)
},
{
ESX_VI__METHOD__PARAMETER__REQUIRE_THIS(virtualMachine)
ESX_VI__METHOD__PARAMETER__REQUIRE(name)
ESX_VI__METHOD__PARAMETER__REQUIRE(memory)
ESX_VI__METHOD__PARAMETER__REQUIRE(quiesce)
},
{
ESX_VI__METHOD__PARAMETER__SERIALIZE_THIS(ManagedObjectReference,
virtualMachine)
ESX_VI__METHOD__PARAMETER__SERIALIZE_VALUE(String, name)
ESX_VI__METHOD__PARAMETER__SERIALIZE_VALUE(String, description)
ESX_VI__METHOD__PARAMETER__SERIALIZE(Boolean, memory)
ESX_VI__METHOD__PARAMETER__SERIALIZE(Boolean, quiesce)
},
{
if (esxVI_ManagedObjectReference_Deserialize(response->node, task) < 0) {
goto failure;
}
})
/* esxVI_RevertToSnapshot_Task */
ESX_VI__METHOD(RevertToSnapshot_Task,
(esxVI_Context *ctx,
esxVI_ManagedObjectReference *virtualMachineSnapshot,
esxVI_ManagedObjectReference *host,
esxVI_ManagedObjectReference **task),
RequiredItem,
{
ESX_VI__METHOD__PARAMETER__CHECK_OUTPUT(task)
},
{
ESX_VI__METHOD__PARAMETER__REQUIRE_THIS(virtualMachineSnapshot)
},
{
ESX_VI__METHOD__PARAMETER__SERIALIZE_THIS(ManagedObjectReference,
virtualMachineSnapshot)
ESX_VI__METHOD__PARAMETER__SERIALIZE(ManagedObjectReference, host)
},
{
if (esxVI_ManagedObjectReference_Deserialize(response->node, task) < 0) {
goto failure;
}
})
/* esxVI_RemoveSnapshot_Task */
ESX_VI__METHOD(RemoveSnapshot_Task,
(esxVI_Context *ctx,
esxVI_ManagedObjectReference *virtualMachineSnapshot,
esxVI_Boolean removeChildren,
esxVI_ManagedObjectReference **task),
RequiredItem,
{
ESX_VI__METHOD__PARAMETER__CHECK_OUTPUT(task)
},
{
ESX_VI__METHOD__PARAMETER__REQUIRE_THIS(virtualMachineSnapshot)
ESX_VI__METHOD__PARAMETER__REQUIRE(removeChildren)
},
{
ESX_VI__METHOD__PARAMETER__SERIALIZE_THIS(ManagedObjectReference,
virtualMachineSnapshot)
ESX_VI__METHOD__PARAMETER__SERIALIZE(Boolean, removeChildren)
},
{
if (esxVI_ManagedObjectReference_Deserialize(response->node, task) < 0) {
goto failure;
}
})
/* esxVI_CancelTask */
ESX_VI__METHOD(CancelTask,
(esxVI_Context *ctx,

View File

@ -80,6 +80,20 @@ int esxVI_RegisterVM_Task(esxVI_Context *ctx,
esxVI_ManagedObjectReference *host,
esxVI_ManagedObjectReference **task);
int esxVI_CreateSnapshot_Task(esxVI_Context *ctx,
esxVI_ManagedObjectReference *virtualMachine,
const char *name, const char *description,
esxVI_Boolean memory, esxVI_Boolean quiesce,
esxVI_ManagedObjectReference **task);
int esxVI_RevertToSnapshot_Task
(esxVI_Context *ctx, esxVI_ManagedObjectReference *virtualMachineSnapshot,
esxVI_ManagedObjectReference *host, esxVI_ManagedObjectReference **task);
int esxVI_RemoveSnapshot_Task
(esxVI_Context *ctx, esxVI_ManagedObjectReference *virtualMachineSnapshot,
esxVI_Boolean removeChildren, esxVI_ManagedObjectReference **task);
int esxVI_CancelTask(esxVI_Context *ctx, esxVI_ManagedObjectReference *task);
int esxVI_UnregisterVM(esxVI_Context *ctx,

View File

@ -1177,6 +1177,12 @@ ESX_VI__TEMPLATE__VALIDATE(DateTime,
ESX_VI__TEMPLATE__PROPERTY__REQUIRE(value);
})
/* esxVI_DateTime_DeepCopy */
ESX_VI__TEMPLATE__DEEP_COPY(DateTime,
{
ESX_VI__TEMPLATE__PROPERTY__DEEP_COPY_VALUE(String, value)
})
/* esxVI_DateTime_Serialize */
ESX_VI__TEMPLATE__SERIALIZE(DateTime,
{
@ -1213,6 +1219,104 @@ esxVI_DateTime_Deserialize(xmlNodePtr node, esxVI_DateTime **dateTime)
return -1;
}
int
esxVI_DateTime_ConvertToCalendarTime(esxVI_DateTime *dateTime,
time_t *secondsSinceEpoch)
{
char value[64] = "";
char *tmp;
struct tm tm;
int milliseconds;
char sign;
int tz_hours;
int tz_minutes;
int tz_offset = 0;
if (dateTime == NULL || secondsSinceEpoch == NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
return -1;
}
if (virStrcpyStatic(value, dateTime->value) == NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("xsd:dateTime value '%s' too long for destination"),
dateTime->value);
return -1;
}
/*
* expected format: [-]CCYY-MM-DDTHH:MM:SS[.ssssss][((+|-)HH:MM|Z)]
* typical example: 2010-04-05T12:13:55.316789+02:00
*
* see http://www.w3.org/TR/xmlschema-2/#dateTime
*
* map negative years to 0, since the base for time_t is the year 1970.
*/
if (*value == '-') {
*secondsSinceEpoch = 0;
return 0;
}
tmp = strptime(value, "%Y-%m-%dT%H:%M:%S", &tm);
if (tmp == NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("xsd:dateTime value '%s' has unexpected format"),
dateTime->value);
return -1;
}
if (*tmp != '\0') {
/* skip .ssssss part if present */
if (*tmp == '.' &&
virStrToLong_i(tmp + 1, &tmp, 10, &milliseconds) < 0) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("xsd:dateTime value '%s' has unexpected format"),
dateTime->value);
return -1;
}
/* parse timezone offset if present. if missing assume UTC */
if (*tmp == '+' || *tmp == '-') {
sign = *tmp;
if (virStrToLong_i(tmp + 1, &tmp, 10, &tz_hours) < 0 ||
*tmp != ':' ||
virStrToLong_i(tmp + 1, NULL, 10, &tz_minutes) < 0) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("xsd:dateTime value '%s' has unexpected format"),
dateTime->value);
return -1;
}
tz_offset = tz_hours * 60 * 60 + tz_minutes * 60;
if (sign == '-') {
tz_offset = -tz_offset;
}
} else if (STREQ(tmp, "Z")) {
/* Z refers to UTC. tz_offset is already initialized to zero */
} else {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("xsd:dateTime value '%s' has unexpected format"),
dateTime->value);
return -1;
}
}
/*
* xsd:dateTime represents local time relative to the optional timezone
* given as offset. pretend the local time is in UTC and use timegm in
* order to avoid interference with the timezone to this computer.
* apply timezone correction afterwards, because it's simpler than
* handling all the possible over- and underflows when trying to apply
* it to the tm struct.
*/
*secondsSinceEpoch = timegm(&tm) - tz_offset;
return 0;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
@ -1344,4 +1448,31 @@ esxVI_ManagedObjectReference_Deserialize
return -1;
}
#include "esx_vi_types.generated.c"
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* VI Enum: VirtualMachinePowerState (Additions)
*/
int
esxVI_VirtualMachinePowerState_ConvertToLibvirt
(esxVI_VirtualMachinePowerState powerState)
{
switch (powerState) {
case esxVI_VirtualMachinePowerState_PoweredOff:
return VIR_DOMAIN_SHUTOFF;
case esxVI_VirtualMachinePowerState_PoweredOn:
return VIR_DOMAIN_RUNNING;
case esxVI_VirtualMachinePowerState_Suspended:
return VIR_DOMAIN_PAUSED;
default:
return VIR_DOMAIN_NOSTATE;
}
}

View File

@ -230,9 +230,12 @@ struct _esxVI_DateTime {
int esxVI_DateTime_Alloc(esxVI_DateTime **dateTime);
void esxVI_DateTime_Free(esxVI_DateTime **dateTime);
int esxVI_DateTime_Validate(esxVI_DateTime *dateTime);
int esxVI_DateTime_DeepCopy(esxVI_DateTime **dest, esxVI_DateTime *src);
int esxVI_DateTime_Serialize(esxVI_DateTime *dateTime, const char *element,
virBufferPtr output);
int esxVI_DateTime_Deserialize(xmlNodePtr node, esxVI_DateTime **dateTime);
int esxVI_DateTime_ConvertToCalendarTime(esxVI_DateTime *dateTime,
time_t *secondsSinceEpoch);
@ -295,4 +298,13 @@ int esxVI_ManagedObjectReference_Deserialize
# include "esx_vi_types.generated.h"
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* VI Enum: VirtualMachinePowerState (Additions)
*/
int esxVI_VirtualMachinePowerState_ConvertToLibvirt
(esxVI_VirtualMachinePowerState powerState);
#endif /* __ESX_VI_TYPES_H__ */

View File

@ -11,6 +11,7 @@
# include "testutils.h"
# include "util.h"
# include "esx/esx_util.h"
# include "esx/esx_vi_types.h"
static char *progname;
@ -164,6 +165,64 @@ testParseDatastoreRelatedPath(const void *data ATTRIBUTE_UNUSED)
struct testDateTime {
const char *dateTime;
time_t calendarTime;
};
static struct testDateTime times[] = {
/* different timezones */
{ "2010-04-08T05:45:11-07:00", 1270730711 },
{ "2010-04-08T07:45:11-05:00", 1270730711 },
{ "2010-04-08T12:45:11+00:00", 1270730711 },
{ "2010-04-08T14:45:11+02:00", 1270730711 },
{ "2010-04-08T22:15:11+09:30", 1270730711 },
{ "2010-04-09T01:30:11+12:45", 1270730711 },
/* optional parts */
{ "2010-04-08T12:45:11Z", 1270730711 },
{ "2010-04-08T12:45:11", 1270730711 },
{ "-2010-04-08T14:45:11+02:00", 0 },
{ "2010-04-08T14:45:11.529576+02:00", 1270730711 },
/* borders */
{ "1970-01-01T00:00:00+00:00", 0 },
{ "2038-01-19T03:14:07+00:00", 2147483647 },
/* random */
{ "1999-08-02T01:19:55+02:00", 933549595 },
{ "2004-03-07T23:23:55+02:00", 1078694635 },
{ "1984-10-27T14:33:45+02:00", 467728425 },
{ "1970-01-12T16:11:04+02:00", 1001464 },
{ "2014-07-20T13:35:38+02:00", 1405856138 },
{ "2032-06-24T17:04:49+02:00", 1971702289 },
};
static int
testConvertDateTimeToCalendarTime(const void *data ATTRIBUTE_UNUSED)
{
int i;
esxVI_DateTime dateTime;
time_t calendarTime;
for (i = 0; i < ARRAY_CARDINALITY(times); ++i) {
dateTime.value = (char *)times[i].dateTime;
if (esxVI_DateTime_ConvertToCalendarTime(&dateTime,
&calendarTime) < 0) {
return -1;
}
if (times[i].calendarTime != calendarTime) {
return -1;
}
}
return 0;
}
static int
mymain(int argc, char **argv)
{
@ -194,6 +253,7 @@ mymain(int argc, char **argv)
DO_TEST(IndexToDiskName);
DO_TEST(DiskNameToIndex);
DO_TEST(ParseDatastoreRelatedPath);
DO_TEST(ConvertDateTimeToCalendarTime);
return result == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}