strchrnul
strndup
strerror
+strptime
strsep
sys_stat
time_r
+timegm
useless-if-before-free
vasprintf
verify
esxVI_Logout(priv->host) < 0) {
result = -1;
}
+
esxVI_Context_Free(&priv->host);
if (priv->vCenter != NULL) {
esxVI_Logout(priv->vCenter) < 0) {
result = -1;
}
+
esxVI_Context_Free(&priv->vCenter);
}
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) {
count = -1;
goto cleanup;
-
}
+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",
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 */
};
+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,
+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,
return result;
failure:
- if (possibleAnswers == NULL) {
- possibleAnswers = virBufferContentAndReset(&buffer);
- }
+ virBufferFreeAndReset(&buffer);
result = -1;
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);
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,
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
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)
"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 }
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
+/* 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,
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,
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,
{
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;
+}
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
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;
+ }
+}
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);
# include "esx_vi_types.generated.h"
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Enum: VirtualMachinePowerState (Additions)
+ */
+
+int esxVI_VirtualMachinePowerState_ConvertToLibvirt
+ (esxVI_VirtualMachinePowerState powerState);
+
#endif /* __ESX_VI_TYPES_H__ */
# include "testutils.h"
# include "util.h"
# include "esx/esx_util.h"
+# include "esx/esx_vi_types.h"
static char *progname;
+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)
{
DO_TEST(IndexToDiskName);
DO_TEST(DiskNameToIndex);
DO_TEST(ParseDatastoreRelatedPath);
+ DO_TEST(ConvertDateTimeToCalendarTime);
return result == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}