mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 17:34:18 +03:00
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:
parent
1787fdff57
commit
1aaa909116
@ -52,9 +52,11 @@ stpcpy
|
||||
strchrnul
|
||||
strndup
|
||||
strerror
|
||||
strptime
|
||||
strsep
|
||||
sys_stat
|
||||
time_r
|
||||
timegm
|
||||
useless-if-before-free
|
||||
vasprintf
|
||||
verify
|
||||
|
@ -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,
|
||||
¤tSnapshotTree,
|
||||
esxVI_Occurrence_OptionalItem) < 0) {
|
||||
goto failure;
|
||||
}
|
||||
|
||||
if (currentSnapshotTree != NULL) {
|
||||
result = 1;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
esxVI_VirtualMachineSnapshotTree_Free(¤tSnapshotTree);
|
||||
|
||||
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,
|
||||
¤tSnapshotTree,
|
||||
esxVI_Occurrence_RequiredItem) < 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
snapshot = virGetDomainSnapshot(domain, currentSnapshotTree->name);
|
||||
|
||||
cleanup:
|
||||
esxVI_VirtualMachineSnapshotTree_Free(¤tSnapshotTree);
|
||||
|
||||
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 */
|
||||
};
|
||||
|
||||
|
||||
|
293
src/esx/esx_vi.c
293
src/esx/esx_vi.c
@ -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, ¤tSnapshot) < 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(¤tSnapshot);
|
||||
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;
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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__ */
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user