[libvirt] [PATCH] esx: Add domain snapshot support

Matthias Bolte matthias.bolte at googlemail.com
Wed Apr 7 10:00:01 UTC 2010


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.
---
 bootstrap.conf                 |    2 +
 src/esx/esx_driver.c           |  468 +++++++++++++++++++++++++++++++++++++---
 src/esx/esx_vi.c               |  290 +++++++++++++++++++++++++
 src/esx/esx_vi.h               |   27 +++
 src/esx/esx_vi_generator.input |   12 +
 src/esx/esx_vi_generator.py    |   25 ++-
 src/esx/esx_vi_methods.c       |   86 ++++++++
 src/esx/esx_vi_methods.h       |   14 ++
 src/esx/esx_vi_types.c         |   99 +++++++++
 src/esx/esx_vi_types.h         |   12 +
 10 files changed, 990 insertions(+), 45 deletions(-)

diff --git a/bootstrap.conf b/bootstrap.conf
index ac2f8e6..ca9332d 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -52,9 +52,11 @@ stpcpy
 strchrnul
 strndup
 strerror
+strptime
 strsep
 sys_stat
 time_r
+timegm
 useless-if-before-free
 vasprintf
 verify
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index eb06555..5272654 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -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,418 @@ 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 failure;
+    }
+
+    if (esxVI_LookupRootSnapshotTreeList(priv->host, domain->uuid,
+                                         &rootSnapshotTreeList) < 0 ||
+        esxVI_GetSnapshotTreeByName(rootSnapshotTreeList, name, &snapshotTree,
+                                    &snapshotTreeParent,
+                                    esxVI_Occurrence_RequiredItem) < 0) {
+        goto failure;
+    }
+
+    snapshot = virGetDomainSnapshot(domain, name);
+
+  cleanup:
+    esxVI_VirtualMachineSnapshotTree_Free(&rootSnapshotTreeList);
+
+    return snapshot;
+
+  failure:
+    snapshot = NULL;
+
+    goto cleanup;
+}
+
+
+
+static int
+esxDomainHasCurrentSnapshot(virDomainPtr domain,
+                            unsigned int flags ATTRIBUTE_UNUSED)
+{
+    int result = 0;
+    esxPrivate *priv = domain->conn->privateData;
+    esxVI_VirtualMachineSnapshotTree *currentSnapshotTree = NULL;
+
+    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 ATTRIBUTE_UNUSED)
+{
+
+    virDomainSnapshotPtr snapshot = NULL;
+    esxPrivate *priv = domain->conn->privateData;
+    esxVI_VirtualMachineSnapshotTree *currentSnapshotTree = NULL;
+
+    if (esxVI_EnsureSession(priv->host) < 0) {
+        goto failure;
+    }
+
+    if (esxVI_LookupCurrentSnapshotTree(priv->host, domain->uuid,
+                                        &currentSnapshotTree,
+                                        esxVI_Occurrence_RequiredItem) < 0) {
+        goto failure;
+    }
+
+    snapshot = virGetDomainSnapshot(domain, currentSnapshotTree->name);
+
+  cleanup:
+    esxVI_VirtualMachineSnapshotTree_Free(&currentSnapshotTree);
+
+    return snapshot;
+
+  failure:
+    snapshot = NULL;
+
+    goto cleanup;
+}
+
+
+
+static int
+esxDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
+                          unsigned int flags ATTRIBUTE_UNUSED)
+{
+    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 (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 +3786,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 */
 };
 
 
diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c
index c37dfa1..eb5371d 100644
--- a/src/esx/esx_vi.c
+++ b/src/esx/esx_vi.c
@@ -1719,6 +1719,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,
    esxVI_ManagedObjectReference **resourcePool)
@@ -2336,6 +2482,150 @@ 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,
    esxVI_VirtualMachineQuestionInfo *questionInfo,
diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h
index 9b65e85..a8d4cc3 100644
--- a/src/esx/esx_vi.h
+++ b/src/esx/esx_vi.h
@@ -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,
diff --git a/src/esx/esx_vi_generator.input b/src/esx/esx_vi_generator.input
index 06dddbf..9c545eb 100644
--- a/src/esx/esx_vi_generator.input
+++ b/src/esx/esx_vi_generator.input
@@ -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
diff --git a/src/esx/esx_vi_generator.py b/src/esx/esx_vi_generator.py
index 5ca6138..b933d5b 100755
--- a/src/esx/esx_vi_generator.py
+++ b/src/esx/esx_vi_generator.py
@@ -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
diff --git a/src/esx/esx_vi_methods.c b/src/esx/esx_vi_methods.c
index 3e095c7..b2b3e8d 100644
--- a/src/esx/esx_vi_methods.c
+++ b/src/esx/esx_vi_methods.c
@@ -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,
diff --git a/src/esx/esx_vi_methods.h b/src/esx/esx_vi_methods.h
index 40bff51..9ff8b4b 100644
--- a/src/esx/esx_vi_methods.h
+++ b/src/esx/esx_vi_methods.h
@@ -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,
diff --git a/src/esx/esx_vi_types.c b/src/esx/esx_vi_types.c
index a69ea44..40d8b9b 100644
--- a/src/esx/esx_vi_types.c
+++ b/src/esx/esx_vi_types.c
@@ -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,72 @@ 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: 2010-04-05T12:13:55.316789+02:00 */
+    tmp = strptime(value, "%Y-%m-%dT%H:%M:%S", &tm);
+
+    if (tmp == NULL || *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;
+    }
+
+    sign = *tmp;
+
+    if ((sign != '+' && sign != '-') ||
+        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;
+    }
+
+    /*
+     * xsd:dateTime represents local time relative to the 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 +1416,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;
+    }
+}
diff --git a/src/esx/esx_vi_types.h b/src/esx/esx_vi_types.h
index d3c7115..4bedca9 100644
--- a/src/esx/esx_vi_types.h
+++ b/src/esx/esx_vi_types.h
@@ -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__ */
-- 
1.6.3.3




More information about the libvir-list mailing list