]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
esx: Add domain snapshot support
authorMatthias Bolte <matthias.bolte@googlemail.com>
Wed, 7 Apr 2010 09:23:53 +0000 (11:23 +0200)
committerMatthias Bolte <matthias.bolte@googlemail.com>
Thu, 8 Apr 2010 19:54:43 +0000 (21:54 +0200)
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.

bootstrap.conf
src/esx/esx_driver.c
src/esx/esx_vi.c
src/esx/esx_vi.h
src/esx/esx_vi_generator.input
src/esx/esx_vi_generator.py
src/esx/esx_vi_methods.c
src/esx/esx_vi_methods.h
src/esx/esx_vi_types.c
src/esx/esx_vi_types.h
tests/esxutilstest.c

index ac2f8e69d36b6f35eab9ca8439075d1986d489e3..ca9332da1da1cc3f35c09981cf70021cc7f26bab 100644 (file)
@@ -52,9 +52,11 @@ stpcpy
 strchrnul
 strndup
 strerror
+strptime
 strsep
 sys_stat
 time_r
+timegm
 useless-if-before-free
 vasprintf
 verify
index aed4a626a11f68685a5f823c67d2deedba13883d..4ed98909a6cfb922ff11319478aa5dacdca7789d 100644 (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 */
 };
 
 
index c37dfa10f99f7f41953262be8fbe8d0b98c4e197..1a71558c4704161f472e0ef2c87a100afc1d0f6d 100644 (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;
 
index 9b65e85ad86cde7963bcb88c2de46299ddda7e18..a8d4cc36700e7edc59e13e8e4988dab9557bd827 100644 (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,
index 06dddbf2a42ff6ce894245b55f522eff0f10705f..9c545ebc6d6c6d663b0ac922bb1ec3fb39169632 100644 (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
index 5ca61380b1b7b9133cd7ac7fa8ce9fcd1b491cd1..b933d5bdfa654644b3ac77fc54fd49ae89945bb0 100755 (executable)
@@ -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
index 3e095c70bfee16524c8abe1b963613b16857517e..b2b3e8d4a7c254566161de014815c589068e9042 100644 (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,
index 40bff511b464f6ae30c693812eb63e993aa9b28c..9ff8b4b4121eb7926999e39dadff9c8fe4a4cd8d 100644 (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,
index a69ea447abb4a54bb04664725805207b3b4a47e3..ed4674b3b2f257a9297ef703051663984ce553ca 100644 (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;
+    }
+}
index d3c7115b472e41fa56fd68b9779e983d266fd554..4bedca9ca16aa7014a758cd2d31899b472b4a58a 100644 (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__ */
index 10f6a3c1d829c611a28864413e429607090a3e84..2a13282cd435aa43a22913c4e00049e5e06fcc06 100644 (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;
 }