[libvirt] VMware ESX driver progress

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

the development was hindered by our testing cluster being offline
since 2 weeks due to server room cooling system maintenance. But I
finally got a basic version of dump-XML done, that fills all fields of
the virDomainDef that the VMX file contains data for.

Changes since first announcement:

- Move code into esx subdirectory
- Add esxNodeGetInfo()
- Fix esxDomainGetInfo() to report the correct value for memory
- Add memory and max-memory getter/setters
- Add CPU scheduler getter/setters
- Validate a migration before trying to perform it
- Replace esxUtil_Strdup() with strdup() and remove
esxUtil_MigrateStringFromLibXML()
- Add esxVI_EnsureSession() to handle expiring sessions
- Separate VI client code into multiple files and generate most of the
type handling code with macros
- Add esxDomainDumpXML() based on esxVMX_ParseConfig()

The ESX driver isn't complete yet, currently it supports:

- domain lookup by ID, UUID and name
- domain listing
- domain info retrieval
- domain suspend and resume
- domain start and destroy
- domain reboot and shutdown, if the VMware tools are installed inside
the domain
- domain migration with previous validation
- domain memory configuration
- domain CPU amount and scheduler configuration
- domain XML-dump
- domain XML-from-native (VMX)
- node info retrieval
- node hostname retrieval

The next milestone is creating/defining a new domain from a domain XML
config, but this will not be finished until feature freeze for 0.7.0
on friday.

Regards,
  Matthias
diff --git a/configure.in b/configure.in
index 634e812..552587c 100644
--- a/configure.in
+++ b/configure.in
@@ -193,6 +193,8 @@ AC_ARG_WITH([lxc],
 [  --with-lxc              add Linux Container support (on)],[],[with_lxc=yes])
 AC_ARG_WITH([one],
 [  --with-one              add ONE support (on)],[],[with_one=check])
+AC_ARG_WITH([esx],
+[  --with-esx              add ESX support (on)],[],[with_esx=yes])
 AC_ARG_WITH([test],
 [  --with-test             add test driver support (on)],[],[with_test=yes])
 AC_ARG_WITH([remote],
@@ -317,6 +319,11 @@ if test "$with_one" = "yes" ; then
 fi
 AM_CONDITIONAL([WITH_ONE],[test "$with_one" = "yes"])
 
+if test "$with_esx" = "yes" ; then
+    AC_DEFINE_UNQUOTED([WITH_ESX], 1, [whether ESX driver is enabled])
+fi
+AM_CONDITIONAL([WITH_ESX], [test "$with_esx" = "yes"])
+
 if test "$with_test" = "yes" ; then
     AC_DEFINE_UNQUOTED([WITH_TEST], 1, [whether Test driver is enabled])
 fi
@@ -1084,6 +1091,26 @@ AM_CONDITIONAL([WITH_STORAGE_DISK], [test "$with_storage_disk" = "yes"])
 AC_SUBST([LIBPARTED_CFLAGS])
 AC_SUBST([LIBPARTED_LIBS])
 
+dnl
+dnl check for libcurl
+dnl
+
+LIBCURL_CFLAGS=""
+LIBCURL_LIBS=""
+LIBCURL_REQUIRED="7.18.0"
+LIBCURL_FOUND="no"
+
+if test "$with_esx" = "yes" ; then
+  PKG_CHECK_MODULES(LIBCURL, libcurl >= $LIBCURL_REQUIRED, [LIBCURL_FOUND=yes], [LIBCURL_FOUND=no])
+
+  if test "$LIBCURL_FOUND" = "no"; then
+    AC_MSG_CHECKING(for libcurl libraries >= $LIBCURL_REQUIRED)
+    AC_MSG_ERROR([libcurl >= $LIBCURL_REQUIRED is required for the ESX driver])
+  fi
+fi
+
+AC_SUBST([LIBCURL_CFLAGS])
+AC_SUBST([LIBCURL_LIBS])
 
 dnl
 dnl check for python
@@ -1492,6 +1519,7 @@ AC_MSG_NOTICE([  OpenVZ: $with_openvz])
 AC_MSG_NOTICE([    VBox: $with_vbox])
 AC_MSG_NOTICE([     LXC: $with_lxc])
 AC_MSG_NOTICE([     ONE: $with_one])
+AC_MSG_NOTICE([     ESX: $with_esx])
 AC_MSG_NOTICE([    Test: $with_test])
 AC_MSG_NOTICE([  Remote: $with_remote])
 AC_MSG_NOTICE([ Network: $with_network])
@@ -1519,6 +1547,11 @@ AC_MSG_NOTICE([  dlopen: $DRIVER_MODULES_CFLAGS $DRIVER_MODULES_LIBS])
 else
 AC_MSG_NOTICE([  dlopen: no])
 fi
+if test "$with_esx" = "yes" ; then
+AC_MSG_NOTICE([ libcurl: $LIBCURL_CFLAGS $LIBCURL_LIBS])
+else
+AC_MSG_NOTICE([ libcurl: no])
+fi
 AC_MSG_NOTICE([])
 AC_MSG_NOTICE([Libraries])
 AC_MSG_NOTICE([])
diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
index 1092896..672572f 100644
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -65,6 +65,7 @@ typedef enum {
     VIR_FROM_VBOX,    /* Error from VirtualBox driver */
     VIR_FROM_INTERFACE, /* Error when operating on an interface */
     VIR_FROM_ONE,     /* Error from OpenNebula driver */
+    VIR_FROM_ESX,      /* Error from ESX driver */
 } virErrorDomain;
 
 
diff --git a/src/Makefile.am b/src/Makefile.am
index 9b662ae..ff83966 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -156,6 +156,14 @@ ONE_DRIVER_SOURCES =					\
 		./opennebula/one_client.c		\
 		./opennebula/one_client.h
 
+ESX_DRIVER_SOURCES =								\
+		esx/esx_driver.c esx/esx_driver.h			\
+		esx/esx_util.c esx/esx_util.h				\
+		esx/esx_vi.c esx/esx_vi.h					\
+		esx/esx_vi_methods.c esx/esx_vi_methods.h	\
+		esx/esx_vi_types.c esx/esx_vi_types.h		\
+		esx/esx_vmx.c esx/esx_vmx.h
+
 NETWORK_DRIVER_SOURCES =					\
 		network_driver.h network_driver.c
 
@@ -375,6 +383,21 @@ endif
 
 
 
+if WITH_ESX
+if WITH_DRIVER_MODULES
+mod_LTLIBRARIES += libvirt_driver_esx.la
+else
+noinst_LTLIBRARIES += libvirt_driver_esx.la
+libvirt_la_LIBADD += libvirt_driver_esx.la
+endif
+libvirt_driver_esx_la_CFLAGS = $(LIBCURL_CFLAGS)
+libvirt_driver_esx_la_LDFLAGS = $(LIBCURL_LIBS)
+if WITH_DRIVER_MODULES
+libvirt_driver_esx_la_LDFLAGS += -module -avoid-version
+endif
+libvirt_driver_esx_la_SOURCES = $(ESX_DRIVER_SOURCES)
+endif
+
 if WITH_NETWORK
 if WITH_DRIVER_MODULES
 mod_LTLIBRARIES += libvirt_driver_network.la
@@ -475,6 +498,7 @@ EXTRA_DIST +=							\
 		$(ONE_DRIVER_SOURCES)				\
 		$(OPENVZ_DRIVER_SOURCES)			\
 		$(VBOX_DRIVER_SOURCES)				\
+		$(ESX_DRIVER_SOURCES)				\
 		$(NETWORK_DRIVER_SOURCES)			\
 		$(STORAGE_DRIVER_SOURCES)			\
 		$(STORAGE_DRIVER_FS_SOURCES)			\
diff --git a/src/driver.h b/src/driver.h
index 2502c63..2d94444 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -22,6 +22,7 @@ typedef enum {
     VIR_DRV_UML = 7,
     VIR_DRV_VBOX = 8,
     VIR_DRV_ONE = 9,
+    VIR_DRV_ESX = 10,
 } virDrvNo;
 
 
diff --git a/src/libvirt.c b/src/libvirt.c
index f4a7fa7..46d3702 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -58,6 +58,9 @@
 #ifdef WITH_VBOX
 #include "vbox/vbox_driver.h"
 #endif
+#ifdef WITH_ESX
+#include "esx/esx_driver.h"
+#endif
 #endif
 
 #define VIR_FROM_THIS VIR_FROM_NONE
@@ -308,6 +311,7 @@ virInitialize(void)
     virDriverLoadModule("xen");
     virDriverLoadModule("openvz");
     virDriverLoadModule("vbox");
+    virDriverLoadModule("esx");
     virDriverLoadModule("remote");
 #else
 #ifdef WITH_TEST
@@ -322,6 +326,9 @@ virInitialize(void)
 #ifdef WITH_VBOX
     if (vboxRegister() == -1) return -1;
 #endif
+#ifdef WITH_ESX
+    if (esxRegister() == -1) return -1;
+#endif
 #ifdef WITH_REMOTE
     if (remoteRegister () == -1) return -1;
 #endif
@@ -905,6 +912,10 @@ virGetVersion(unsigned long *libVer, const char *type,
         if (STRCASEEQ(type, "ONE"))
             *typeVer = LIBVIR_VERSION_NUMBER;
 #endif
+#if WITH_ESX
+        if (STRCASEEQ(type, "ESX"))
+            *typeVer = LIBVIR_VERSION_NUMBER;
+#endif
 #if WITH_REMOTE
         if (STRCASEEQ(type, "Remote"))
             *typeVer = remoteVersion();
diff --git a/src/virterror.c b/src/virterror.c
index d284fb8..587db72 100644
--- a/src/virterror.c
+++ b/src/virterror.c
@@ -163,6 +163,9 @@ static const char *virErrorDomainName(virErrorDomain domain) {
         case VIR_FROM_ONE:
             dom = "ONE ";
             break;
+        case VIR_FROM_ESX:
+            dom = "ESX ";
+            break;
     }
     return(dom);
 }
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
new file mode 100644
index 0000000..aa73e46
--- /dev/null
+++ b/src/esx/esx_driver.c
@@ -0,0 +1,2861 @@
+
+/*
+ * esx_driver.c: core driver methods for managing VMware ESX hosts
+ *
+ * Copyright (C) 2009 Matthias Bolte <matthias.bolte@xxxxxxxxxxxxxx>
+ * Copyright (C) 2009 Maximilian Wilhelm <max@xxxxxxxxxxx>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ */
+
+/*
+ * Some links to relevant documentation:
+ *
+ * - Memory model:        http://www.vmware.com/pdf/esx3_memory.pdf
+ * - VI API reference:    http://www.vmware.com/support/developer/vc-sdk/visdk25pubs/ReferenceGuide/
+ * - VMX-file parameters: http://www.sanbarrow.com/vmx.html
+ */
+
+#include <config.h>
+
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+
+#include <netdb.h>
+
+#include "internal.h"
+#include "virterror_internal.h"
+#include "domain_conf.h"
+#include "util.h"
+#include "memory.h"
+#include "logging.h"
+#include "uuid.h"
+#include "esx_driver.h"
+#include "esx_vi.h"
+#include "esx_vi_methods.h"
+#include "esx_util.h"
+#include "esx_vmx.h"
+
+#define VIR_FROM_THIS VIR_FROM_ESX
+
+#define ESX_ERROR(conn, code, fmt...)                                         \
+    virReportErrorHelper(conn, VIR_FROM_ESX, code, __FILE__, __FUNCTION__,    \
+                         __LINE__, fmt)
+
+static int esxDomainGetMaxVcpus(virDomainPtr domain);
+
+typedef struct _esxPrivate {
+    esxVI_Context *host;
+    esxVI_Context *vcenter;
+    int phantom; // boolean
+    char *transport;
+    int32_t nvcpus_max;
+    esxVI_Boolean supports_vmotion;
+    int32_t usedCpuTimeCounterId;
+} esxPrivate;
+
+
+
+/*
+ * URI format: esx://[<user>@]<server>[?transport={http|https}][&vcenter=<vcenter>]
+ *             esx:///phantom
+ */
+static virDrvOpenStatus
+esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED)
+{
+    esxPrivate *priv = NULL;
+    char dummy_string[NI_MAXHOST] = "";
+    char *url = NULL;
+    char *vcenter = NULL;
+    char *username = NULL;
+    char *password = NULL;
+    int phantom = 0;
+
+    /* Decline if the URI is NULL or the scheme is not 'esx' */
+    if (conn->uri == NULL || conn->uri->scheme == NULL ||
+        STRNEQ(conn->uri->scheme, "esx")) {
+        return VIR_DRV_OPEN_DECLINED;
+    }
+
+    /* Check for 'esx:///phantom' URI */
+    if (conn->uri->server == NULL && conn->uri->path != NULL &&
+        STREQ(conn->uri->path, "/phantom")) {
+        phantom = 1;
+    }
+
+    if (! phantom) {
+        /* Decline non-phantom URIs without server part, or missing auth */
+        if (conn->uri->server == NULL || auth == NULL || auth->cb == NULL) {
+            return VIR_DRV_OPEN_DECLINED;
+        }
+
+        if (conn->uri->path != NULL) {
+            VIR_WARN("Ignoring unexpected path '%s' in URI", conn->uri->path);
+        }
+    }
+
+    /* Allocate per-connection private data */
+    if (VIR_ALLOC(priv) < 0) {
+        virReportOOMError(conn);
+        goto failure;
+    }
+
+    priv->phantom = phantom;
+    priv->nvcpus_max = -1;
+    priv->supports_vmotion = esxVI_Boolean_Undefined;
+    priv->usedCpuTimeCounterId = -1;
+
+    /* Request credentials and login to non-phantom host/vCenter */
+    if (! phantom) {
+        if (esxUtil_ParseQuery(conn, &priv->transport, &vcenter) < 0) {
+            goto failure;
+        }
+
+        if (esxUtil_ResolveHostname(conn, conn->uri->server, dummy_string,
+                                    NI_MAXHOST) < 0) {
+            goto failure;
+        }
+
+        if (vcenter != NULL &&
+            esxUtil_ResolveHostname(conn, vcenter, dummy_string,
+                                    NI_MAXHOST) < 0) {
+            goto failure;
+        }
+
+        if (virAsprintf(&url, "%s://%s/sdk", priv->transport,
+                        conn->uri->server) < 0) {
+            virReportOOMError(conn);
+            goto failure;
+        }
+
+        if (conn->uri->user != NULL) {
+            username = strdup(conn->uri->user);
+
+            if (username == NULL) {
+                virReportOOMError(conn);
+                goto failure;
+            }
+        } else {
+            username = esxUtil_RequestUsername(auth, "root", conn->uri->server);
+
+            if (username == NULL) {
+                ESX_ERROR(conn, VIR_ERR_AUTH_FAILED, "Username request failed");
+                goto failure;
+            }
+        }
+
+        if (esxVI_Context_Alloc(conn, &priv->host) < 0) {
+            goto failure;
+        }
+
+        password = esxUtil_RequestPassword(auth, username, conn->uri->server);
+
+        if (password == NULL) {
+            ESX_ERROR(conn, VIR_ERR_AUTH_FAILED, "Password request failed");
+            goto failure;
+        }
+
+        if (esxVI_Context_Connect(conn, priv->host, url, username,
+                                  password) < 0) {
+            goto failure;
+        }
+
+        VIR_FREE(url);
+        VIR_FREE(password);
+        VIR_FREE(username);
+
+        if (vcenter != NULL) {
+            if (virAsprintf(&url, "%s://%s/sdk", priv->transport,
+                            vcenter) < 0) {
+                virReportOOMError(conn);
+                goto failure;
+            }
+
+            if (esxVI_Context_Alloc(conn, &priv->vcenter) < 0) {
+                goto failure;
+            }
+
+            username = esxUtil_RequestUsername(auth, "administrator", vcenter);
+
+            if (username == NULL) {
+                ESX_ERROR(conn, VIR_ERR_AUTH_FAILED,
+                          "Username request failed");
+                goto failure;
+            }
+
+            password = esxUtil_RequestPassword(auth, username, vcenter);
+
+            if (password == NULL) {
+                ESX_ERROR(conn, VIR_ERR_AUTH_FAILED,
+                          "Password request failed");
+                goto failure;
+            }
+
+            if (esxVI_Context_Connect(conn, priv->vcenter, url, username,
+                                      password) < 0) {
+                goto failure;
+            }
+
+            VIR_FREE(url);
+            VIR_FREE(password);
+            VIR_FREE(username);
+        }
+
+        VIR_FREE(vcenter);
+    }
+
+    conn->privateData = priv;
+
+    return VIR_DRV_OPEN_SUCCESS;
+
+  failure:
+    VIR_FREE(url);
+    VIR_FREE(vcenter);
+    VIR_FREE(password);
+    VIR_FREE(username);
+
+    if (priv != NULL) {
+        esxVI_Context_Free(&priv->host);
+        esxVI_Context_Free(&priv->vcenter);
+
+        VIR_FREE(priv);
+    }
+
+    return VIR_DRV_OPEN_ERROR;
+}
+
+
+
+static int
+esxClose(virConnectPtr conn)
+{
+    esxPrivate *priv = (esxPrivate *)conn->privateData;
+
+    if (! priv->phantom) {
+        esxVI_EnsureSession(conn, priv->host);
+
+        esxVI_Logout(conn, priv->host);
+        esxVI_Context_Free(&priv->host);
+
+        if (priv->vcenter != NULL) {
+            esxVI_EnsureSession(conn, priv->vcenter);
+
+            esxVI_Logout(conn, priv->vcenter);
+            esxVI_Context_Free(&priv->vcenter);
+        }
+    }
+
+    VIR_FREE(priv->transport);
+    VIR_FREE(priv);
+
+    conn->privateData = NULL;
+
+    return 0;
+}
+
+
+
+static esxVI_Boolean
+esxSupportsVMotion(virConnectPtr conn)
+{
+    esxPrivate *priv = (esxPrivate *)conn->privateData;
+    esxVI_String *propertyNameList = NULL;
+    esxVI_ObjectContent *hostSystem = NULL;
+    esxVI_DynamicProperty *dynamicProperty = NULL;
+
+    if (priv->phantom) {
+        ESX_ERROR(conn, VIR_ERR_OPERATION_INVALID,
+                  "Not possible with a phantom connection");
+        goto failure;
+    }
+
+    if (priv->supports_vmotion != esxVI_Boolean_Undefined) {
+        return priv->supports_vmotion;
+    }
+
+    if (esxVI_EnsureSession(conn, priv->host) < 0) {
+        goto failure;
+    }
+
+    if (esxVI_String_AppendValueToList(conn, &propertyNameList,
+                                       "capability.vmotionSupported") < 0 ||
+        esxVI_GetObjectContent(conn, priv->host, priv->host->hostFolder,
+                               "HostSystem", propertyNameList,
+                               esxVI_Boolean_True, &hostSystem) < 0) {
+        goto failure;
+    }
+
+    if (hostSystem == NULL) {
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                  "Could not retrieve the HostSystem object");
+        goto failure;
+    }
+
+    for (dynamicProperty = hostSystem->propSet; dynamicProperty != NULL;
+         dynamicProperty = dynamicProperty->_next) {
+        if (STREQ(dynamicProperty->name, "capability.vmotionSupported")) {
+            if (esxVI_AnyType_ExpectType(conn, dynamicProperty->val,
+                                         esxVI_Type_Boolean) < 0) {
+                goto failure;
+            }
+
+            priv->supports_vmotion = dynamicProperty->val->boolean;
+            break;
+        } else {
+            VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
+        }
+    }
+
+  cleanup:
+    esxVI_String_Free(&propertyNameList);
+    esxVI_ObjectContent_Free(&hostSystem);
+
+    return priv->supports_vmotion;
+
+  failure:
+    priv->supports_vmotion = esxVI_Boolean_Undefined;
+
+    goto cleanup;
+}
+
+
+
+static int
+esxSupportsFeature(virConnectPtr conn, int feature)
+{
+    esxPrivate *priv = (esxPrivate *)conn->privateData;
+    esxVI_Boolean supports_vmotion = esxVI_Boolean_Undefined;
+
+    if (priv->phantom) {
+        ESX_ERROR(conn, VIR_ERR_OPERATION_INVALID,
+                  "Not possible with a phantom connection");
+        return -1;
+    }
+
+    switch (feature) {
+      case VIR_DRV_FEATURE_MIGRATION_V1:
+        supports_vmotion = esxSupportsVMotion(conn);
+
+        if (supports_vmotion == esxVI_Boolean_Undefined) {
+            return -1;
+        }
+
+        /*
+         * Migration is only possible via a Virtual Center and if VMotion is
+         * enabled
+         */
+        return priv->vcenter != NULL &&
+               supports_vmotion == esxVI_Boolean_True ? 1 : 0;
+
+      default:
+        return 0;
+    }
+}
+
+
+
+static const char *
+esxGetType(virConnectPtr conn ATTRIBUTE_UNUSED)
+{
+    return "ESX";
+}
+
+
+
+static int
+esxGetVersion(virConnectPtr conn, unsigned long *version)
+{
+    esxPrivate *priv = (esxPrivate *)conn->privateData;
+    char *temp;
+    unsigned int major, minor, release;
+
+    if (priv->phantom) {
+        ESX_ERROR(conn, VIR_ERR_OPERATION_INVALID,
+                  "Not possible with a phantom connection");
+        return -1;
+    }
+
+    temp = (char *)priv->host->service->about->version;
+
+    /* Expecting 'major.minor.release' format */
+    if (virStrToLong_ui(temp, &temp, 10, &major) < 0 || temp == NULL ||
+        *temp != '.') {
+        goto failure;
+    }
+
+    if (virStrToLong_ui(temp + 1, &temp, 10, &minor) < 0 || temp == NULL ||
+        *temp != '.') {
+        goto failure;
+    }
+
+    if (virStrToLong_ui(temp + 1, NULL, 10, &release) < 0) {
+        goto failure;
+    }
+
+    *version = 1000000 * major + 1000 * minor + release;
+
+    return 0;
+
+  failure:
+    ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+              "Expecting version to match 'major.minor.release', but got '%s'",
+              priv->host->service->about->version);
+
+    return -1;
+}
+
+
+
+static char *
+esxGetHostname(virConnectPtr conn)
+{
+    esxPrivate *priv = (esxPrivate *)conn->privateData;
+    esxVI_String *propertyNameList = NULL;
+    esxVI_ObjectContent *hostSystem = NULL;
+    esxVI_DynamicProperty *dynamicProperty = NULL;
+    const char *hostName = NULL;
+    const char *domainName = NULL;
+    char *complete = NULL;
+
+    if (priv->phantom) {
+        ESX_ERROR(conn, VIR_ERR_OPERATION_INVALID,
+                  "Not possible with a phantom connection");
+        goto failure;
+    }
+
+    if (esxVI_EnsureSession(conn, priv->host) < 0) {
+        goto failure;
+    }
+
+    if (esxVI_String_AppendValueListToList
+          (conn, &propertyNameList,
+           "config.network.dnsConfig.hostName\0"
+           "config.network.dnsConfig.domainName\0") < 0 ||
+        esxVI_GetObjectContent(conn, priv->host, priv->host->hostFolder,
+                               "HostSystem", propertyNameList,
+                               esxVI_Boolean_True, &hostSystem) < 0) {
+        goto failure;
+    }
+
+    if (hostSystem == NULL) {
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                  "Could not retrieve the HostSystem object");
+        goto failure;
+    }
+
+    for (dynamicProperty = hostSystem->propSet; dynamicProperty != NULL;
+         dynamicProperty = dynamicProperty->_next) {
+        if (STREQ(dynamicProperty->name,
+                  "config.network.dnsConfig.hostName")) {
+            if (esxVI_AnyType_ExpectType(conn, dynamicProperty->val,
+                                         esxVI_Type_String) < 0) {
+                goto failure;
+            }
+
+            hostName = dynamicProperty->val->string;
+        } else if (STREQ(dynamicProperty->name,
+                         "config.network.dnsConfig.domainName")) {
+            if (esxVI_AnyType_ExpectType(conn, dynamicProperty->val,
+                                         esxVI_Type_String) < 0) {
+                goto failure;
+            }
+
+            domainName = dynamicProperty->val->string;
+        } else {
+            VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
+        }
+    }
+
+    if (hostName == NULL || strlen (hostName) < 1) {
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                  "Missing or empty 'hostName' property");
+        goto failure;
+    }
+
+    if (domainName == NULL || strlen (domainName) < 1) {
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                  "Missing or empty 'domainName' property");
+        goto failure;
+    }
+
+    if (virAsprintf(&complete, "%s.%s", hostName, domainName) < 0) {
+        virReportOOMError(conn);
+        goto failure;
+    }
+
+  cleanup:
+    esxVI_String_Free(&propertyNameList);
+    esxVI_ObjectContent_Free(&hostSystem);
+
+    return complete;
+
+  failure:
+    VIR_FREE(complete);
+
+    goto cleanup;
+}
+
+
+
+
+static int
+esxNodeGetInfo(virConnectPtr conn, virNodeInfoPtr nodeinfo)
+{
+    int result = 0;
+    esxPrivate *priv = (esxPrivate *)conn->privateData;
+    esxVI_String *propertyNameList = NULL;
+    esxVI_ObjectContent *hostSystem = NULL;
+    esxVI_DynamicProperty *dynamicProperty = NULL;
+    int64_t cpuInfo_hz = 0;
+    int16_t cpuInfo_numCpuCores = 0;
+    int16_t cpuInfo_numCpuPackages = 0;
+    int16_t cpuInfo_numCpuThreads = 0;
+    int64_t memorySize = 0;
+    int32_t numaInfo_numNodes = 0;
+    char *ptr = NULL;
+
+    memset (nodeinfo, 0, sizeof (virNodeInfo));
+
+    if (priv->phantom) {
+        ESX_ERROR(conn, VIR_ERR_OPERATION_INVALID,
+                  "Not possible with a phantom connection");
+        goto failure;
+    }
+
+    if (esxVI_EnsureSession(conn, priv->host) < 0) {
+        goto failure;
+    }
+
+    if (esxVI_String_AppendValueListToList(conn, &propertyNameList,
+                                           "hardware.cpuInfo.hz\0"
+                                           "hardware.cpuInfo.numCpuCores\0"
+                                           "hardware.cpuInfo.numCpuPackages\0"
+                                           "hardware.cpuInfo.numCpuThreads\0"
+                                           "hardware.memorySize\0"
+                                           "hardware.numaInfo.numNodes\0"
+                                           "summary.hardware.cpuModel\0") < 0 ||
+        esxVI_GetObjectContent(conn, priv->host, priv->host->hostFolder,
+                               "HostSystem", propertyNameList,
+                               esxVI_Boolean_True, &hostSystem) < 0) {
+        goto failure;
+    }
+
+    if (hostSystem == NULL) {
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                  "Could not retrieve the HostSystem object");
+        goto failure;
+    }
+
+    for (dynamicProperty = hostSystem->propSet; dynamicProperty != NULL;
+         dynamicProperty = dynamicProperty->_next) {
+        if (STREQ(dynamicProperty->name, "hardware.cpuInfo.hz")) {
+            if (esxVI_AnyType_ExpectType(conn, dynamicProperty->val,
+                                         esxVI_Type_Long) < 0) {
+                goto failure;
+            }
+
+            cpuInfo_hz = dynamicProperty->val->int64;
+        } else if (STREQ(dynamicProperty->name,
+                         "hardware.cpuInfo.numCpuCores")) {
+            if (esxVI_AnyType_ExpectType(conn, dynamicProperty->val,
+                                         esxVI_Type_Short) < 0) {
+                goto failure;
+            }
+
+            cpuInfo_numCpuCores = dynamicProperty->val->int16;
+        } else if (STREQ(dynamicProperty->name,
+                         "hardware.cpuInfo.numCpuPackages")) {
+            if (esxVI_AnyType_ExpectType(conn, dynamicProperty->val,
+                                         esxVI_Type_Short) < 0) {
+                goto failure;
+            }
+
+            cpuInfo_numCpuPackages = dynamicProperty->val->int16;
+        } else if (STREQ(dynamicProperty->name,
+                         "hardware.cpuInfo.numCpuThreads")) {
+            if (esxVI_AnyType_ExpectType(conn, dynamicProperty->val,
+                                         esxVI_Type_Short) < 0) {
+                goto failure;
+            }
+
+            cpuInfo_numCpuThreads = dynamicProperty->val->int16;
+        } else if (STREQ(dynamicProperty->name, "hardware.memorySize")) {
+            if (esxVI_AnyType_ExpectType(conn, dynamicProperty->val,
+                                         esxVI_Type_Long) < 0) {
+                goto failure;
+            }
+
+            memorySize = dynamicProperty->val->int64;
+        } else if (STREQ(dynamicProperty->name,
+                         "hardware.numaInfo.numNodes")) {
+            if (esxVI_AnyType_ExpectType(conn, dynamicProperty->val,
+                                         esxVI_Type_Int) < 0) {
+                goto failure;
+            }
+
+            numaInfo_numNodes = dynamicProperty->val->int32;
+        } else if (STREQ(dynamicProperty->name,
+                         "summary.hardware.cpuModel")) {
+            if (esxVI_AnyType_ExpectType(conn, dynamicProperty->val,
+                                         esxVI_Type_String) < 0) {
+                goto failure;
+            }
+
+            ptr = dynamicProperty->val->string;
+
+            /* Strip the string to fit more relevant information in 32 chars */
+            while (*ptr != '\0') {
+                if (STRPREFIX (ptr, "  ")) {
+                    memmove(ptr, ptr + 1, strlen (ptr + 1) + 1);
+                    continue;
+                } else if (STRPREFIX (ptr, "(R)")) {
+                    memmove(ptr, ptr + 3, strlen (ptr + 3) + 1);
+                    continue;
+                }
+
+                ++ptr;
+            }
+
+            strncpy (nodeinfo->model, dynamicProperty->val->string,
+                     sizeof (nodeinfo->model) - 1);
+            nodeinfo->model[sizeof (nodeinfo->model) - 1] = '\0';
+        } else {
+            VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
+        }
+    }
+
+    nodeinfo->memory = memorySize / 1024; /* Scale from bytes to kilobytes */
+    nodeinfo->cpus = cpuInfo_numCpuCores;
+    nodeinfo->mhz = cpuInfo_hz / (1024 * 1024); /* Scale from hz to mhz */
+    nodeinfo->nodes = numaInfo_numNodes;
+    nodeinfo->sockets = cpuInfo_numCpuPackages;
+    nodeinfo->cores = cpuInfo_numCpuPackages > 0
+                        ? cpuInfo_numCpuCores / cpuInfo_numCpuPackages
+                        : 0;
+    nodeinfo->threads = cpuInfo_numCpuCores > 0
+                          ? cpuInfo_numCpuThreads / cpuInfo_numCpuCores
+                          : 0;
+
+  cleanup:
+    esxVI_String_Free(&propertyNameList);
+    esxVI_ObjectContent_Free(&hostSystem);
+
+    return result;
+
+  failure:
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+static int
+esxListDomains(virConnectPtr conn, int *ids, int maxids)
+{
+    esxPrivate *priv = (esxPrivate *)conn->privateData;
+    esxVI_ObjectContent *virtualMachineList = NULL;
+    esxVI_ObjectContent *virtualMachine = NULL;
+    esxVI_String *propertyNameList = NULL;
+    esxVI_VirtualMachinePowerState powerState;
+    int count = 0;
+
+    if (priv->phantom) {
+        ESX_ERROR(conn, VIR_ERR_OPERATION_INVALID,
+                  "Not possible with a phantom connection");
+        goto failure;
+    }
+
+    if (ids == NULL || maxids < 0) {
+        goto failure;
+    }
+
+    if (maxids == 0) {
+        return 0;
+    }
+
+    if (esxVI_EnsureSession(conn, priv->host) < 0) {
+        goto failure;
+    }
+
+    if (esxVI_String_AppendValueToList(conn, &propertyNameList,
+                                       "runtime.powerState") < 0 ||
+        esxVI_GetObjectContent(conn, priv->host, priv->host->vmFolder,
+                               "VirtualMachine", propertyNameList,
+                               esxVI_Boolean_True, &virtualMachineList) < 0) {
+        goto failure;
+    }
+
+    for (virtualMachine = virtualMachineList; virtualMachine != NULL;
+         virtualMachine = virtualMachine->_next) {
+        if (esxVI_GetVirtualMachinePowerState(conn, virtualMachine,
+                                              &powerState) < 0) {
+            goto failure;
+        }
+
+        if (powerState != esxVI_VirtualMachinePowerState_PoweredOn) {
+            continue;
+        }
+
+        if (esxUtil_ParseVirtualMachineIDString(virtualMachine->obj->value,
+                                                &ids[count]) < 0 ||
+            ids[count] <= 0) {
+            ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                      "Failed to parse positive integer from '%s'",
+                      virtualMachine->obj->value);
+            goto failure;
+        }
+
+        count++;
+
+        if (count >= maxids) {
+            break;
+        }
+    }
+
+  cleanup:
+    esxVI_String_Free(&propertyNameList);
+    esxVI_ObjectContent_Free(&virtualMachineList);
+
+    return count;
+
+  failure:
+    count = -1;
+
+    goto cleanup;
+}
+
+
+
+static int
+esxNumberOfDomains(virConnectPtr conn)
+{
+    esxPrivate *priv = (esxPrivate *)conn->privateData;
+
+    if (priv->phantom) {
+        ESX_ERROR(conn, VIR_ERR_OPERATION_INVALID,
+                  "Not possible with a phantom connection");
+        return -1;
+    }
+
+    if (esxVI_EnsureSession(conn, priv->host) < 0) {
+        return -1;
+    }
+
+    return esxVI_GetNumberOfDomainsByPowerState
+             (conn, priv->host, esxVI_VirtualMachinePowerState_PoweredOn,
+              esxVI_Boolean_False);
+}
+
+
+
+static virDomainPtr
+esxDomainLookupByID(virConnectPtr conn, int id)
+{
+    esxPrivate *priv = (esxPrivate *)conn->privateData;
+    esxVI_String *propertyNameList = NULL;
+    esxVI_ObjectContent *virtualMachineList = NULL;
+    esxVI_ObjectContent *virtualMachine = NULL;
+    esxVI_VirtualMachinePowerState powerState;
+    int id_ = -1;
+    char *name_ = NULL;
+    unsigned char uuid_[VIR_UUID_BUFLEN];
+    virDomainPtr domain = NULL;
+
+    if (priv->phantom) {
+        ESX_ERROR(conn, VIR_ERR_OPERATION_INVALID,
+                  "Not possible with a phantom connection");
+        goto failure;
+    }
+
+    if (esxVI_EnsureSession(conn, priv->host) < 0) {
+        goto failure;
+    }
+
+    if (esxVI_String_AppendValueListToList(conn, &propertyNameList,
+                                           "name\0"
+                                           "runtime.powerState\0"
+                                           "summary.config.uuid\0") < 0 ||
+        esxVI_GetObjectContent(conn, priv->host, priv->host->vmFolder,
+                               "VirtualMachine", propertyNameList,
+                               esxVI_Boolean_True, &virtualMachineList) < 0) {
+        goto failure;
+    }
+
+    for (virtualMachine = virtualMachineList; virtualMachine != NULL;
+         virtualMachine = virtualMachine->_next) {
+        if (esxVI_GetVirtualMachinePowerState(conn, virtualMachine,
+                                              &powerState) < 0) {
+            goto failure;
+        }
+
+        /* Only running/suspended domains have an ID != -1 */
+        if (powerState == esxVI_VirtualMachinePowerState_PoweredOff) {
+            continue;
+        }
+
+        VIR_FREE(name_);
+
+        if (esxVI_GetVirtualMachineIdentity(conn, virtualMachine, &id_,
+                                            &name_, uuid_) < 0) {
+            goto failure;
+        }
+
+        if (id_ != id) {
+            continue;
+        }
+
+        domain = virGetDomain(conn, name_, uuid_);
+
+        if (domain == NULL) {
+            goto failure;
+        }
+
+        domain->id = id;
+
+        break;
+    }
+
+    if (domain == NULL) {
+        ESX_ERROR(conn, VIR_ERR_NO_DOMAIN, "No domain with ID %d", id);
+    }
+
+  cleanup:
+    esxVI_String_Free(&propertyNameList);
+    esxVI_ObjectContent_Free(&virtualMachineList);
+    VIR_FREE(name_);
+
+    return domain;
+
+  failure:
+    domain = NULL;
+
+    goto cleanup;
+}
+
+
+
+static virDomainPtr
+esxDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
+{
+    esxPrivate *priv = (esxPrivate *)conn->privateData;
+    esxVI_String *propertyNameList = NULL;
+    esxVI_ObjectContent *virtualMachineList = NULL;
+    esxVI_ObjectContent *virtualMachine = NULL;
+    esxVI_VirtualMachinePowerState powerState;
+    int id_ = -1;
+    char *name_ = NULL;
+    unsigned char uuid_[VIR_UUID_BUFLEN];
+    char uuid_string[VIR_UUID_STRING_BUFLEN];
+    virDomainPtr domain = NULL;
+
+    if (priv->phantom) {
+        ESX_ERROR(conn, VIR_ERR_OPERATION_INVALID,
+                  "Not possible with a phantom connection");
+        goto failure;
+    }
+
+    if (esxVI_EnsureSession(conn, priv->host) < 0) {
+        goto failure;
+    }
+
+    if (esxVI_String_AppendValueListToList(conn, &propertyNameList,
+                                           "name\0"
+                                           "runtime.powerState\0"
+                                           "summary.config.uuid\0") < 0 ||
+        esxVI_GetObjectContent(conn, priv->host, priv->host->vmFolder,
+                               "VirtualMachine", propertyNameList,
+                               esxVI_Boolean_True, &virtualMachineList) < 0) {
+        goto failure;
+    }
+
+    for (virtualMachine = virtualMachineList; virtualMachine != NULL;
+         virtualMachine = virtualMachine->_next) {
+        VIR_FREE(name_);
+
+        if (esxVI_GetVirtualMachineIdentity(conn, virtualMachine, &id_,
+                                            &name_, uuid_) < 0) {
+            goto failure;
+        }
+
+        if (memcmp(uuid, uuid_,
+                   VIR_UUID_BUFLEN * sizeof (unsigned char)) != 0) {
+            continue;
+        }
+
+        domain = virGetDomain(conn, name_, uuid);
+
+        if (domain == NULL) {
+            goto failure;
+        }
+
+        if (esxVI_GetVirtualMachinePowerState(conn, virtualMachine,
+                                              &powerState) < 0) {
+            goto failure;
+        }
+
+        /* Only running/suspended virtual machines have an ID != -1 */
+        if (powerState != esxVI_VirtualMachinePowerState_PoweredOff) {
+            domain->id = id_;
+        } else {
+            domain->id = -1;
+        }
+
+        break;
+    }
+
+    if (domain == NULL) {
+        virUUIDFormat(uuid, uuid_string);
+
+        ESX_ERROR(conn, VIR_ERR_NO_DOMAIN, "No domain with UUID '%s'",
+                  uuid_string);
+    }
+
+  cleanup:
+    esxVI_String_Free(&propertyNameList);
+    esxVI_ObjectContent_Free(&virtualMachineList);
+    VIR_FREE(name_);
+
+    return domain;
+
+  failure:
+    domain = NULL;
+
+    goto cleanup;
+}
+
+
+
+static virDomainPtr
+esxDomainLookupByName(virConnectPtr conn, const char *name)
+{
+    esxPrivate *priv = (esxPrivate *)conn->privateData;
+    esxVI_String *propertyNameList = NULL;
+    esxVI_ObjectContent *virtualMachineList = NULL;
+    esxVI_ObjectContent *virtualMachine = NULL;
+    esxVI_VirtualMachinePowerState powerState;
+    int id_ = -1;
+    char *name_ = NULL;
+    unsigned char uuid_[VIR_UUID_BUFLEN];
+    virDomainPtr domain = NULL;
+
+    if (priv->phantom) {
+        ESX_ERROR(conn, VIR_ERR_OPERATION_INVALID,
+                  "Not possible with a phantom connection");
+        goto failure;
+    }
+
+    if (esxVI_EnsureSession(conn, priv->host) < 0) {
+        goto failure;
+    }
+
+    if (esxVI_String_AppendValueListToList(conn, &propertyNameList,
+                                           "name\0"
+                                           "runtime.powerState\0"
+                                           "summary.config.uuid\0") < 0 ||
+        esxVI_GetObjectContent(conn, priv->host, priv->host->vmFolder,
+                               "VirtualMachine", propertyNameList,
+                               esxVI_Boolean_True, &virtualMachineList) < 0) {
+        goto failure;
+    }
+
+    for (virtualMachine = virtualMachineList; virtualMachine != NULL;
+         virtualMachine = virtualMachine->_next) {
+        VIR_FREE(name_);
+
+        if (esxVI_GetVirtualMachineIdentity(conn, virtualMachine, &id_,
+                                            &name_, uuid_) < 0) {
+            goto failure;
+        }
+
+        if (STRNEQ(name_, name)) {
+            continue;
+        }
+
+        domain = virGetDomain(conn, name, uuid_);
+
+        if (domain == NULL) {
+            goto failure;
+        }
+
+        if (esxVI_GetVirtualMachinePowerState(conn, virtualMachine,
+                                              &powerState) < 0) {
+            goto failure;
+        }
+
+        /* Only running/suspended virtual machines have an ID != -1 */
+        if (powerState != esxVI_VirtualMachinePowerState_PoweredOff) {
+            domain->id = id_;
+        } else {
+            domain->id = -1;
+        }
+
+        break;
+    }
+
+    if (domain == NULL) {
+        ESX_ERROR(conn, VIR_ERR_NO_DOMAIN, "No domain with name '%s'", name);
+    }
+
+  cleanup:
+    esxVI_String_Free(&propertyNameList);
+    esxVI_ObjectContent_Free(&virtualMachineList);
+    VIR_FREE(name_);
+
+    return domain;
+
+  failure:
+    domain = NULL;
+
+    goto cleanup;
+}
+
+
+
+static int
+esxDomainSuspend(virDomainPtr domain)
+{
+    int result = 0;
+    esxPrivate *priv = (esxPrivate *)domain->conn->privateData;
+    esxVI_ObjectContent *virtualMachine = NULL;
+    esxVI_String *propertyNameList = NULL;
+    esxVI_VirtualMachinePowerState powerState;
+    esxVI_ManagedObjectReference *task = NULL;
+    esxVI_TaskInfoState taskInfoState;
+
+    if (priv->phantom) {
+        ESX_ERROR(domain->conn, VIR_ERR_OPERATION_INVALID,
+                  "Not possible with a phantom connection");
+        goto failure;
+    }
+
+    if (esxVI_EnsureSession(domain->conn, priv->host) < 0) {
+        goto failure;
+    }
+
+    if (esxVI_String_AppendValueToList(domain->conn, &propertyNameList,
+                                       "runtime.powerState") < 0 ||
+        esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host,
+                                         domain->uuid, propertyNameList,
+                                         &virtualMachine) < 0 ||
+        esxVI_GetVirtualMachinePowerState(domain->conn, virtualMachine,
+                                          &powerState) < 0) {
+        goto failure;
+    }
+
+    if (powerState != esxVI_VirtualMachinePowerState_PoweredOn) {
+        ESX_ERROR(domain->conn, VIR_ERR_OPERATION_INVALID,
+                  "Domain is not powered on");
+        goto failure;
+    }
+
+    if (esxVI_SuspendVM_Task(domain->conn, priv->host, virtualMachine->obj,
+                             &task) < 0 ||
+        esxVI_WaitForTaskCompletion(domain->conn, priv->host, task,
+                                    &taskInfoState) < 0) {
+        goto failure;
+    }
+
+    if (taskInfoState != esxVI_TaskInfoState_Success) {
+        ESX_ERROR(domain->conn, VIR_ERR_INTERNAL_ERROR,
+                  "Could not suspend domain");
+        goto failure;
+    }
+
+  cleanup:
+    esxVI_ObjectContent_Free(&virtualMachine);
+    esxVI_String_Free(&propertyNameList);
+    esxVI_ManagedObjectReference_Free(&task);
+
+    return result;
+
+  failure:
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+static int
+esxDomainResume(virDomainPtr domain)
+{
+    int result = 0;
+    esxPrivate *priv = (esxPrivate *)domain->conn->privateData;
+    esxVI_ObjectContent *virtualMachine = NULL;
+    esxVI_String *propertyNameList = NULL;
+    esxVI_VirtualMachinePowerState powerState;
+    esxVI_ManagedObjectReference *task = NULL;
+    esxVI_TaskInfoState taskInfoState;
+
+    if (priv->phantom) {
+        ESX_ERROR(domain->conn, VIR_ERR_OPERATION_INVALID,
+                  "Not possible with a phantom connection");
+        goto failure;
+    }
+
+    if (esxVI_EnsureSession(domain->conn, priv->host) < 0) {
+        goto failure;
+    }
+
+    if (esxVI_String_AppendValueToList(domain->conn, &propertyNameList,
+                                       "runtime.powerState") < 0 ||
+        esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host,
+                                         domain->uuid, propertyNameList,
+                                         &virtualMachine) < 0 ||
+        esxVI_GetVirtualMachinePowerState(domain->conn, virtualMachine,
+                                          &powerState) < 0) {
+        goto failure;
+    }
+
+    if (powerState != esxVI_VirtualMachinePowerState_Suspended) {
+        ESX_ERROR(domain->conn, VIR_ERR_OPERATION_INVALID,
+                  "Domain is not suspended");
+        goto failure;
+    }
+
+    if (esxVI_PowerOnVM_Task(domain->conn, priv->host, virtualMachine->obj,
+                             &task) < 0 ||
+        esxVI_WaitForTaskCompletion(domain->conn, priv->host, task,
+                                    &taskInfoState) < 0) {
+        goto failure;
+    }
+
+    if (taskInfoState != esxVI_TaskInfoState_Success) {
+        ESX_ERROR(domain->conn, VIR_ERR_INTERNAL_ERROR,
+                  "Could not resume domain");
+        goto failure;
+    }
+
+  cleanup:
+    esxVI_ObjectContent_Free(&virtualMachine);
+    esxVI_String_Free(&propertyNameList);
+    esxVI_ManagedObjectReference_Free(&task);
+
+    return result;
+
+  failure:
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+static int
+esxDomainShutdown(virDomainPtr domain)
+{
+    int result = 0;
+    esxPrivate *priv = (esxPrivate *)domain->conn->privateData;
+    esxVI_ObjectContent *virtualMachine = NULL;
+    esxVI_String *propertyNameList = NULL;
+    esxVI_VirtualMachinePowerState powerState;
+
+    if (priv->phantom) {
+        ESX_ERROR(domain->conn, VIR_ERR_OPERATION_INVALID,
+                  "Not possible with a phantom connection");
+        goto failure;
+    }
+
+    if (esxVI_EnsureSession(domain->conn, priv->host) < 0) {
+        goto failure;
+    }
+
+    if (esxVI_String_AppendValueToList(domain->conn, &propertyNameList,
+                                       "runtime.powerState") < 0 ||
+        esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host,
+                                         domain->uuid, propertyNameList,
+                                         &virtualMachine) < 0 ||
+        esxVI_GetVirtualMachinePowerState(domain->conn, virtualMachine,
+                                          &powerState) < 0) {
+        goto failure;
+    }
+
+    if (powerState != esxVI_VirtualMachinePowerState_PoweredOn) {
+        ESX_ERROR(domain->conn, VIR_ERR_OPERATION_INVALID,
+                  "Domain is not powered on");
+        goto failure;
+    }
+
+    if (esxVI_ShutdownGuest(domain->conn, priv->host,
+                            virtualMachine->obj) < 0) {
+        goto failure;
+    }
+
+  cleanup:
+    esxVI_ObjectContent_Free(&virtualMachine);
+    esxVI_String_Free(&propertyNameList);
+
+    return result;
+
+  failure:
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+static int
+esxDomainReboot(virDomainPtr domain, unsigned int flags ATTRIBUTE_UNUSED)
+{
+    int result = 0;
+    esxPrivate *priv = (esxPrivate *)domain->conn->privateData;
+    esxVI_ObjectContent *virtualMachine = NULL;
+    esxVI_String *propertyNameList = NULL;
+    esxVI_VirtualMachinePowerState powerState;
+
+    if (priv->phantom) {
+        ESX_ERROR(domain->conn, VIR_ERR_OPERATION_INVALID,
+                  "Not possible with a phantom connection");
+        goto failure;
+    }
+
+    if (esxVI_EnsureSession(domain->conn, priv->host) < 0) {
+        goto failure;
+    }
+
+    if (esxVI_String_AppendValueToList(domain->conn, &propertyNameList,
+                                       "runtime.powerState") < 0 ||
+        esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host,
+                                         domain->uuid, propertyNameList,
+                                         &virtualMachine) < 0 ||
+        esxVI_GetVirtualMachinePowerState(domain->conn, virtualMachine,
+                                          &powerState) < 0) {
+        goto failure;
+    }
+
+    if (powerState != esxVI_VirtualMachinePowerState_PoweredOn) {
+        ESX_ERROR(domain->conn, VIR_ERR_OPERATION_INVALID,
+                  "Domain is not powered on");
+        goto failure;
+    }
+
+    if (esxVI_RebootGuest(domain->conn, priv->host, virtualMachine->obj) < 0) {
+        goto failure;
+    }
+
+  cleanup:
+    esxVI_ObjectContent_Free(&virtualMachine);
+    esxVI_String_Free(&propertyNameList);
+
+    return result;
+
+  failure:
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+static int
+esxDomainDestroy(virDomainPtr domain)
+{
+    int result = 0;
+    esxPrivate *priv = (esxPrivate *)domain->conn->privateData;
+    esxVI_ObjectContent *virtualMachine = NULL;
+    esxVI_String *propertyNameList = NULL;
+    esxVI_VirtualMachinePowerState powerState;
+    esxVI_ManagedObjectReference *task = NULL;
+    esxVI_TaskInfoState taskInfoState;
+
+    if (priv->phantom) {
+        ESX_ERROR(domain->conn, VIR_ERR_OPERATION_INVALID,
+                  "Not possible with a phantom connection");
+        goto failure;
+    }
+
+    if (esxVI_EnsureSession(domain->conn, priv->host) < 0) {
+        goto failure;
+    }
+
+    if (esxVI_String_AppendValueToList(domain->conn, &propertyNameList,
+                                       "runtime.powerState") < 0 ||
+        esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host,
+                                         domain->uuid, propertyNameList,
+                                         &virtualMachine) < 0 ||
+        esxVI_GetVirtualMachinePowerState(domain->conn, virtualMachine,
+                                          &powerState) < 0) {
+        goto failure;
+    }
+
+    if (powerState != esxVI_VirtualMachinePowerState_PoweredOn) {
+        ESX_ERROR(domain->conn, VIR_ERR_OPERATION_INVALID,
+                  "Domain is not powered on");
+        goto failure;
+    }
+
+    if (esxVI_PowerOffVM_Task(domain->conn, priv->host, virtualMachine->obj,
+                              &task) < 0 ||
+        esxVI_WaitForTaskCompletion(domain->conn, priv->host, task,
+                                    &taskInfoState) < 0) {
+        goto failure;
+    }
+
+    if (taskInfoState != esxVI_TaskInfoState_Success) {
+        ESX_ERROR(domain->conn, VIR_ERR_INTERNAL_ERROR,
+                  "Could not destory domain");
+        goto failure;
+    }
+
+  cleanup:
+    esxVI_ObjectContent_Free(&virtualMachine);
+    esxVI_String_Free(&propertyNameList);
+    esxVI_ManagedObjectReference_Free(&task);
+
+    return result;
+
+  failure:
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+static char *
+esxDomainGetOSType(virDomainPtr dom ATTRIBUTE_UNUSED)
+{
+    return strdup("hvm");
+}
+
+
+
+static unsigned long
+esxDomainGetMaxMemory(virDomainPtr domain)
+{
+    esxPrivate *priv = (esxPrivate *)domain->conn->privateData;
+    esxVI_String *propertyNameList = NULL;
+    esxVI_ObjectContent *virtualMachine = NULL;
+    esxVI_DynamicProperty *dynamicProperty = NULL;
+    unsigned long memoryMB = 0;
+
+    if (priv->phantom) {
+        ESX_ERROR(domain->conn, VIR_ERR_OPERATION_INVALID,
+                  "Not possible with a phantom connection");
+        goto failure;
+    }
+
+    if (esxVI_EnsureSession(domain->conn, priv->host) < 0) {
+        goto failure;
+    }
+
+    if (esxVI_String_AppendValueToList(domain->conn, &propertyNameList,
+                                       "config.hardware.memoryMB") < 0 ||
+        esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host,
+                                         domain->uuid, propertyNameList,
+                                         &virtualMachine) < 0) {
+        goto failure;
+    }
+
+    for (dynamicProperty = virtualMachine->propSet; dynamicProperty != NULL;
+         dynamicProperty = dynamicProperty->_next) {
+        if (STREQ(dynamicProperty->name, "config.hardware.memoryMB")) {
+            if (esxVI_AnyType_ExpectType(domain->conn, dynamicProperty->val,
+                                         esxVI_Type_Int) < 0) {
+                goto failure;
+            }
+
+            if (dynamicProperty->val->int32 < 0) {
+                ESX_ERROR(domain->conn, VIR_ERR_INTERNAL_ERROR,
+                          "Got invalid memory size %d",
+                          dynamicProperty->val->int32);
+            } else {
+                memoryMB = dynamicProperty->val->int32;
+            }
+
+            break;
+        } else {
+            VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
+        }
+    }
+
+  cleanup:
+    esxVI_String_Free(&propertyNameList);
+    esxVI_ObjectContent_Free(&virtualMachine);
+
+    return memoryMB * 1024; /* Scale from megabyte to kilobyte */
+
+  failure:
+    memoryMB = 0;
+
+    goto cleanup;
+}
+
+
+
+static int
+esxDomainSetMaxMemory(virDomainPtr domain, unsigned long memory)
+{
+    int result = 0;
+    esxPrivate *priv = (esxPrivate *)domain->conn->privateData;
+    esxVI_ObjectContent *virtualMachine = NULL;
+    esxVI_VirtualMachineConfigSpec *spec = NULL;
+    esxVI_ManagedObjectReference *task = NULL;
+    esxVI_TaskInfoState taskInfoState;
+
+    if (priv->phantom) {
+        ESX_ERROR(domain->conn, VIR_ERR_OPERATION_INVALID,
+                  "Not possible with a phantom connection");
+        goto failure;
+    }
+
+    if (esxVI_EnsureSession(domain->conn, priv->host) < 0) {
+        goto failure;
+    }
+
+    if (esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host,
+                                         domain->uuid, NULL,
+                                         &virtualMachine) < 0 ||
+        esxVI_VirtualMachineConfigSpec_Alloc(domain->conn, &spec) < 0 ||
+        esxVI_Long_Alloc(domain->conn, &spec->memoryMB) < 0) {
+        goto failure;
+    }
+
+    spec->memoryMB->value =
+      memory / 1024; /* Scale from kilobytes to megabytes */
+
+    if (esxVI_ReconfigVM_Task(domain->conn, priv->host, virtualMachine->obj,
+                              spec, &task) < 0 ||
+        esxVI_WaitForTaskCompletion(domain->conn, priv->host, task,
+                                    &taskInfoState) < 0) {
+        goto failure;
+    }
+
+    if (taskInfoState != esxVI_TaskInfoState_Success) {
+        ESX_ERROR(domain->conn, VIR_ERR_INTERNAL_ERROR,
+                  "Could not set max-memory to %lu kilobytes", memory);
+        goto failure;
+    }
+
+  cleanup:
+    esxVI_ObjectContent_Free(&virtualMachine);
+    esxVI_VirtualMachineConfigSpec_Free(&spec);
+    esxVI_ManagedObjectReference_Free(&task);
+
+    return result;
+
+  failure:
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+static int
+esxDomainSetMemory(virDomainPtr domain, unsigned long memory)
+{
+    int result = 0;
+    esxPrivate *priv = (esxPrivate *)domain->conn->privateData;
+    esxVI_ObjectContent *virtualMachine = NULL;
+    esxVI_VirtualMachineConfigSpec *spec = NULL;
+    esxVI_ManagedObjectReference *task = NULL;
+    esxVI_TaskInfoState taskInfoState;
+
+    if (priv->phantom) {
+        ESX_ERROR(domain->conn, VIR_ERR_OPERATION_INVALID,
+                  "Not possible with a phantom connection");
+        goto failure;
+    }
+
+    if (esxVI_EnsureSession(domain->conn, priv->host) < 0) {
+        goto failure;
+    }
+
+    if (esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host,
+                                         domain->uuid, NULL,
+                                         &virtualMachine) < 0 ||
+        esxVI_VirtualMachineConfigSpec_Alloc(domain->conn, &spec) < 0 ||
+        esxVI_ResourceAllocationInfo_Alloc(domain->conn,
+                                           &spec->memoryAllocation) < 0 ||
+        esxVI_Long_Alloc(domain->conn, &spec->memoryAllocation->limit) < 0) {
+        goto failure;
+    }
+
+    spec->memoryAllocation->limit->value =
+      memory / 1024; /* Scale from kilobytes to megabytes */
+
+    if (esxVI_ReconfigVM_Task(domain->conn, priv->host, virtualMachine->obj,
+                              spec, &task) < 0 ||
+        esxVI_WaitForTaskCompletion(domain->conn, priv->host, task,
+                                    &taskInfoState) < 0) {
+        goto failure;
+    }
+
+    if (taskInfoState != esxVI_TaskInfoState_Success) {
+        ESX_ERROR(domain->conn, VIR_ERR_INTERNAL_ERROR,
+                  "Could not set memory to %lu kilobytes", memory);
+        goto failure;
+    }
+
+  cleanup:
+    esxVI_ObjectContent_Free(&virtualMachine);
+    esxVI_VirtualMachineConfigSpec_Free(&spec);
+    esxVI_ManagedObjectReference_Free(&task);
+
+    return result;
+
+  failure:
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+static int
+esxDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
+{
+    int result = 0;
+    esxPrivate *priv = (esxPrivate *)domain->conn->privateData;
+    esxVI_String *propertyNameList = NULL;
+    esxVI_ObjectContent *virtualMachine = NULL;
+    esxVI_DynamicProperty *dynamicProperty = NULL;
+    esxVI_VirtualMachinePowerState powerState;
+    int64_t memory_limit = -1;
+    esxVI_PerfMetricId *perfMetricId = NULL;
+    esxVI_PerfMetricId *perfMetricIdList = NULL;
+    esxVI_Int *counterId = NULL;
+    esxVI_Int *counterIdList = NULL;
+    esxVI_PerfCounterInfo *perfCounterInfo = NULL;
+    esxVI_PerfCounterInfo *perfCounterInfoList = NULL;
+    esxVI_PerfQuerySpec *querySpec = NULL;
+    esxVI_PerfEntityMetric *perfEntityMetric = NULL;
+    esxVI_PerfEntityMetric *perfEntityMetricList = NULL;
+    esxVI_PerfMetricIntSeries *perfMetricIntSeries = NULL;
+    esxVI_Long *value = NULL;
+
+    if (priv->phantom) {
+        ESX_ERROR(domain->conn, VIR_ERR_OPERATION_INVALID,
+                  "Not possible with a phantom connection");
+        goto failure;
+    }
+
+    if (esxVI_EnsureSession(domain->conn, priv->host) < 0) {
+        goto failure;
+    }
+
+    if (esxVI_String_AppendValueListToList(domain->conn, &propertyNameList,
+                                           "runtime.powerState\0"
+                                           "config.hardware.memoryMB\0"
+                                           "config.hardware.numCPU\0"
+                                           "config.memoryAllocation.limit\0") < 0 ||
+        esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host,
+                                         domain->uuid, propertyNameList,
+                                         &virtualMachine) < 0) {
+        goto failure;
+    }
+
+    info->state = VIR_DOMAIN_NOSTATE;
+    info->maxMem = 0;
+    info->memory = 0;
+    info->nrVirtCpu = 0;
+    info->cpuTime = 0; /* FIXME */
+
+    for (dynamicProperty = virtualMachine->propSet; dynamicProperty != NULL;
+         dynamicProperty = dynamicProperty->_next) {
+        if (STREQ(dynamicProperty->name, "runtime.powerState")) {
+            if (esxVI_VirtualMachinePowerState_CastFromAnyType
+                  (domain->conn, dynamicProperty->val, &powerState) < 0) {
+                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;
+            }
+        } else if (STREQ(dynamicProperty->name, "config.hardware.memoryMB")) {
+            if (esxVI_AnyType_ExpectType(domain->conn, dynamicProperty->val,
+                                         esxVI_Type_Int) < 0) {
+                goto failure;
+            }
+
+            info->maxMem = dynamicProperty->val->int32 * 1024; /* Scale from megabyte to kilobyte */
+        } else if (STREQ(dynamicProperty->name, "config.hardware.numCPU")) {
+            if (esxVI_AnyType_ExpectType(domain->conn, dynamicProperty->val,
+                                         esxVI_Type_Int) < 0) {
+                goto failure;
+            }
+
+            info->nrVirtCpu = dynamicProperty->val->int32;
+        } else if (STREQ(dynamicProperty->name,
+                         "config.memoryAllocation.limit")) {
+            if (esxVI_AnyType_ExpectType(domain->conn, dynamicProperty->val,
+                                         esxVI_Type_Long) < 0) {
+                goto failure;
+            }
+
+            memory_limit = dynamicProperty->val->int64;
+
+            if (memory_limit > 0) {
+                memory_limit *= 1024; /* Scale from megabyte to kilobyte */
+            }
+        } else {
+            VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
+        }
+    }
+
+    /* memory_limit < 0 means no memory limit is set */
+    info->memory = memory_limit < 0 ? info->maxMem : memory_limit;
+
+    /* Verify the cached 'used CPU time' performance counter ID */
+    if (info->state == VIR_DOMAIN_RUNNING && priv->usedCpuTimeCounterId >= 0) {
+        if (esxVI_Int_Alloc(domain->conn, &counterId) < 0) {
+            goto failure;
+        }
+
+        counterId->value = priv->usedCpuTimeCounterId;
+
+        if (esxVI_Int_AppendToList(domain->conn, &counterIdList,
+                                   counterId) < 0) {
+            goto failure;
+        }
+
+        if (esxVI_QueryPerfCounter(domain->conn, priv->host, counterIdList,
+                                   &perfCounterInfo) < 0) {
+            goto failure;
+        }
+
+        if (STRNEQ(perfCounterInfo->groupInfo->key, "cpu") ||
+            STRNEQ(perfCounterInfo->nameInfo->key, "used") ||
+            STRNEQ(perfCounterInfo->unitInfo->key, "millisecond")) {
+            VIR_DEBUG("Cached usedCpuTimeCounterId %d is invalid",
+                      priv->usedCpuTimeCounterId);
+
+            priv->usedCpuTimeCounterId = -1;
+        }
+
+        esxVI_Int_Free(&counterIdList);
+        esxVI_PerfCounterInfo_Free(&perfCounterInfo);
+    }
+
+    /*
+     * Query the PerformanceManager for the 'used CPU time' performance
+     * counter ID and cache it, if it's not already cached.
+     */
+    if (info->state == VIR_DOMAIN_RUNNING && priv->usedCpuTimeCounterId < 0) {
+        if (esxVI_QueryAvailablePerfMetric(domain->conn, priv->host,
+                                           virtualMachine->obj, NULL, NULL,
+                                           NULL, &perfMetricIdList) < 0) {
+            goto failure;
+        }
+
+        for (perfMetricId = perfMetricIdList; perfMetricId != NULL;
+             perfMetricId = perfMetricId->_next) {
+            VIR_DEBUG("perfMetricId counterId %d, instance '%s'",
+                      perfMetricId->counterId->value, perfMetricId->instance);
+
+            counterId = NULL;
+
+            if (esxVI_Int_DeepCopy(domain->conn, &counterId,
+                                   perfMetricId->counterId) < 0 ||
+                esxVI_Int_AppendToList(domain->conn, &counterIdList,
+                                       counterId) < 0) {
+                goto failure;
+            }
+        }
+
+        if (esxVI_QueryPerfCounter(domain->conn, priv->host, counterIdList,
+                                   &perfCounterInfoList) < 0) {
+            goto failure;
+        }
+
+        for (perfCounterInfo = perfCounterInfoList; perfCounterInfo != NULL;
+             perfCounterInfo = perfCounterInfo->_next) {
+            VIR_DEBUG("perfCounterInfo key %d, nameInfo '%s', groupInfo '%s', "
+                      "unitInfo '%s', rollupType %d, statsType %d",
+                      perfCounterInfo->key->value,
+                      perfCounterInfo->nameInfo->key,
+                      perfCounterInfo->groupInfo->key,
+                      perfCounterInfo->unitInfo->key,
+                      perfCounterInfo->rollupType,
+                      perfCounterInfo->statsType);
+
+            if (STREQ(perfCounterInfo->groupInfo->key, "cpu") &&
+                STREQ(perfCounterInfo->nameInfo->key, "used") &&
+                STREQ(perfCounterInfo->unitInfo->key, "millisecond")) {
+                priv->usedCpuTimeCounterId = perfCounterInfo->key->value;
+                break;
+            }
+        }
+
+        if (priv->usedCpuTimeCounterId < 0) {
+            VIR_WARN0("Could not find 'used CPU time' performance counter");
+        }
+    }
+
+    /*
+     * Query the PerformanceManager for the 'used CPU time' performance
+     * counter value.
+     */
+    if (info->state == VIR_DOMAIN_RUNNING && priv->usedCpuTimeCounterId >= 0) {
+        VIR_DEBUG("usedCpuTimeCounterId %d BEGIN", priv->usedCpuTimeCounterId);
+
+        if (esxVI_PerfQuerySpec_Alloc(domain->conn, &querySpec) < 0 ||
+            esxVI_Int_Alloc(domain->conn, &querySpec->maxSample) < 0 ||
+            esxVI_PerfMetricId_Alloc(domain->conn, &querySpec->metricId) < 0 ||
+            esxVI_Int_Alloc(domain->conn,
+                            &querySpec->metricId->counterId) < 0) {
+            goto failure;
+        }
+
+        querySpec->entity = virtualMachine->obj;
+        querySpec->maxSample->value = 1;
+        querySpec->metricId->counterId->value = priv->usedCpuTimeCounterId;
+        querySpec->metricId->instance = (char *)"";
+        querySpec->format = (char *)"normal";
+
+
+        if (esxVI_QueryPerf(domain->conn, priv->host, querySpec,
+                            &perfEntityMetricList) < 0) {
+            querySpec->entity = NULL;
+            querySpec->metricId->instance = NULL;
+            querySpec->format = NULL;
+            goto failure;
+        }
+
+        for (perfEntityMetric = perfEntityMetricList; perfEntityMetric != NULL;
+             perfEntityMetric = perfEntityMetric->_next) {
+            VIR_DEBUG0("perfEntityMetric ...");
+
+            for (perfMetricIntSeries = perfEntityMetric->value;
+                 perfMetricIntSeries != NULL;
+                 perfMetricIntSeries = perfMetricIntSeries->_next) {
+                VIR_DEBUG0("perfMetricIntSeries ...");
+
+                for (value = perfMetricIntSeries->value;
+                     value != NULL;
+                     value = value->_next) {
+                    VIR_DEBUG("value %"PRIi64, value->value);
+                }
+            }
+        }
+
+        querySpec->entity = NULL;
+        querySpec->metricId->instance = NULL;
+        querySpec->format = NULL;
+
+        VIR_DEBUG("usedCpuTimeCounterId %d END", priv->usedCpuTimeCounterId);
+    }
+
+  cleanup:
+    esxVI_String_Free(&propertyNameList);
+    esxVI_ObjectContent_Free(&virtualMachine);
+    esxVI_PerfMetricId_Free(&perfMetricIdList);
+    esxVI_Int_Free(&counterIdList);
+    esxVI_PerfCounterInfo_Free(&perfCounterInfoList);
+    esxVI_PerfQuerySpec_Free(&querySpec);
+    esxVI_PerfEntityMetric_Free(&perfEntityMetricList);
+
+    return result;
+
+  failure:
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+static int
+esxDomainSetVcpus(virDomainPtr domain, unsigned int nvcpus)
+{
+    int result = 0;
+    esxPrivate *priv = (esxPrivate *)domain->conn->privateData;
+    int nvcpus_max;
+    esxVI_ObjectContent *virtualMachine = NULL;
+    esxVI_VirtualMachineConfigSpec *spec = NULL;
+    esxVI_ManagedObjectReference *task = NULL;
+    esxVI_TaskInfoState taskInfoState;
+
+    if (priv->phantom) {
+        ESX_ERROR(domain->conn, VIR_ERR_OPERATION_INVALID,
+                  "Not possible with a phantom connection");
+        goto failure;
+    }
+
+    if (nvcpus < 1) {
+        ESX_ERROR(domain->conn, VIR_ERR_INVALID_ARG,
+                  "Requested number of virtual CPUs must al least be 1");
+        goto failure;
+    }
+
+    if (esxVI_EnsureSession(domain->conn, priv->host) < 0) {
+        goto failure;
+    }
+
+    nvcpus_max = esxDomainGetMaxVcpus(domain);
+
+    if (nvcpus_max < 0) {
+        goto failure;
+    }
+
+    if (nvcpus > nvcpus_max) {
+        ESX_ERROR(domain->conn, VIR_ERR_INVALID_ARG,
+                  "Requested number of virtual CPUs is greater than max "
+                  "allowable number of virtual CPUs for the domain: %d > %d",
+                  nvcpus, nvcpus_max);
+        goto failure;
+    }
+
+    if (esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host,
+                                         domain->uuid, NULL,
+                                         &virtualMachine) < 0 ||
+        esxVI_VirtualMachineConfigSpec_Alloc(domain->conn, &spec) < 0 ||
+        esxVI_Int_Alloc(domain->conn, &spec->numCPUs) < 0) {
+        goto failure;
+    }
+
+    spec->numCPUs->value = nvcpus;
+
+    if (esxVI_ReconfigVM_Task(domain->conn, priv->host, virtualMachine->obj,
+                              spec, &task) < 0 ||
+        esxVI_WaitForTaskCompletion(domain->conn, priv->host, task,
+                                    &taskInfoState) < 0) {
+        goto failure;
+    }
+
+    if (taskInfoState != esxVI_TaskInfoState_Success) {
+        ESX_ERROR(domain->conn, VIR_ERR_INTERNAL_ERROR,
+                  "Could not set number of virtual CPUs to %d", nvcpus);
+        goto failure;
+    }
+
+  cleanup:
+    esxVI_ObjectContent_Free(&virtualMachine);
+    esxVI_VirtualMachineConfigSpec_Free(&spec);
+    esxVI_ManagedObjectReference_Free(&task);
+
+    return result;
+
+  failure:
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+static int
+esxDomainGetMaxVcpus(virDomainPtr domain)
+{
+    esxPrivate *priv = (esxPrivate *)domain->conn->privateData;
+    esxVI_String *propertyNameList = NULL;
+    esxVI_ObjectContent *hostSystem = NULL;
+    esxVI_DynamicProperty *dynamicProperty = NULL;
+
+    if (priv->phantom) {
+        ESX_ERROR(domain->conn, VIR_ERR_OPERATION_INVALID,
+                  "Not possible with a phantom connection");
+        goto failure;
+    }
+
+    if (priv->nvcpus_max > 0) {
+        return priv->nvcpus_max;
+    }
+
+    if (esxVI_EnsureSession(domain->conn, priv->host) < 0) {
+        goto failure;
+    }
+
+    if (esxVI_String_AppendValueToList(domain->conn, &propertyNameList,
+                                       "capability.maxSupportedVcpus") < 0 ||
+        esxVI_GetObjectContent(domain->conn, priv->host,
+                               priv->host->hostFolder, "HostSystem",
+                               propertyNameList, esxVI_Boolean_True,
+                               &hostSystem) < 0) {
+        goto failure;
+    }
+
+    if (hostSystem == NULL) {
+        ESX_ERROR(domain->conn, VIR_ERR_INTERNAL_ERROR,
+                  "Could not retrieve the HostSystem object");
+        goto failure;
+    }
+
+    for (dynamicProperty = hostSystem->propSet; dynamicProperty != NULL;
+         dynamicProperty = dynamicProperty->_next) {
+        if (STREQ(dynamicProperty->name, "capability.maxSupportedVcpus")) {
+            if (esxVI_AnyType_ExpectType(domain->conn, dynamicProperty->val,
+                                         esxVI_Type_Int) < 0) {
+                goto failure;
+            }
+
+            priv->nvcpus_max = dynamicProperty->val->int32;
+            break;
+        } else {
+            VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
+        }
+    }
+
+  cleanup:
+    esxVI_String_Free(&propertyNameList);
+    esxVI_ObjectContent_Free(&hostSystem);
+
+    return priv->nvcpus_max;
+
+  failure:
+    priv->nvcpus_max = -1;
+
+    goto cleanup;
+}
+
+
+
+static char *
+esxDomainDumpXML(virDomainPtr domain, int flags)
+{
+    esxPrivate *priv = (esxPrivate *)domain->conn->privateData;
+    esxVI_String *propertyNameList = NULL;
+    esxVI_ObjectContent *virtualMachine = NULL;
+    esxVI_DynamicProperty *dynamicProperty = NULL;
+    const char *vmPathName = NULL;
+    char *datastoreName = NULL;
+    char *vmxPath = NULL;
+    char *url = NULL;
+    char *vmx = NULL;
+    virDomainDefPtr def = NULL;
+    char *xml = NULL;
+
+    if (priv->phantom) {
+        ESX_ERROR(domain->conn, VIR_ERR_OPERATION_INVALID,
+                  "Not possible with a phantom connection");
+        return NULL;
+    }
+
+    if (esxVI_EnsureSession(domain->conn, priv->host) < 0) {
+        goto failure;
+    }
+
+    if (esxVI_String_AppendValueToList(domain->conn, &propertyNameList,
+                                       "config.files.vmPathName") < 0 ||
+        esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host,
+                                         domain->uuid, propertyNameList,
+                                         &virtualMachine) < 0) {
+        goto failure;
+    }
+
+    for (dynamicProperty = virtualMachine->propSet; dynamicProperty != NULL;
+         dynamicProperty = dynamicProperty->_next) {
+        if (STREQ(dynamicProperty->name, "config.files.vmPathName")) {
+            if (esxVI_AnyType_ExpectType(domain->conn, dynamicProperty->val,
+                                         esxVI_Type_String) < 0) {
+                goto failure;
+            }
+
+            vmPathName = dynamicProperty->val->string;
+            break;
+        }
+    }
+
+    /* expected format: "[<datastoreName>] <vmxPath>" */
+    if (sscanf(vmPathName, "[%a[^]%]] %as", &datastoreName, &vmxPath) != 2) {
+        ESX_ERROR(domain->conn, VIR_ERR_OPERATION_INVALID,
+                  "'config.files.vmPathName' property '%s' doesn't have "
+                  "expected format '[<datastore>] <vmx>'", vmPathName);
+        goto failure;
+    }
+
+    if (virAsprintf(&url, "%s://%s/folder/%s?dcPath=%s&dsName=%s",
+                    priv->transport, domain->conn->uri->server,
+                    vmxPath, priv->host->datacenter->value,
+                    datastoreName) < 0) {
+        virReportOOMError(domain->conn);
+        goto failure;
+    }
+
+    if (esxVI_Context_Download(domain->conn, priv->host, url, &vmx) < 0) {
+        goto failure;
+    }
+
+    def = esxVMX_ParseConfig(domain->conn, vmx);
+
+    if (def != NULL) {
+        xml = virDomainDefFormat(domain->conn, def, flags);
+    }
+
+  cleanup:
+    VIR_FREE(datastoreName);
+    VIR_FREE(vmxPath);
+    VIR_FREE(url);
+    VIR_FREE(vmx);
+
+    return xml;
+
+  failure:
+    VIR_FREE(xml);
+
+    goto cleanup;
+}
+
+
+
+static char *
+esxDomainXMLFromNative(virConnectPtr conn, const char *nativeFormat,
+                       const char *nativeConfig,
+                       unsigned int flags ATTRIBUTE_UNUSED)
+{
+    virDomainDefPtr def = NULL;
+    char *xml = NULL;
+
+    if (STRNEQ(nativeFormat, "vmware-vmx")) {
+        ESX_ERROR(conn, VIR_ERR_INVALID_ARG,
+                  "Unsupported config format '%s'", nativeFormat);
+        goto cleanup;
+    }
+
+    def = esxVMX_ParseConfig(conn, nativeConfig);
+
+    if (def != NULL) {
+        xml = virDomainDefFormat(conn, def, VIR_DOMAIN_XML_INACTIVE);
+    }
+
+cleanup:
+    virDomainDefFree(def);
+
+    return xml;
+}
+
+
+
+static int
+esxListDefinedDomains(virConnectPtr conn, char **const names, int maxnames)
+{
+    esxPrivate *priv = (esxPrivate *)conn->privateData;
+    esxVI_String *propertyNameList = NULL;
+    esxVI_ObjectContent *virtualMachineList = NULL;
+    esxVI_ObjectContent *virtualMachine = NULL;
+    esxVI_DynamicProperty *dynamicProperty = NULL;
+    esxVI_VirtualMachinePowerState powerState;
+    int count = 0;
+
+    if (priv->phantom) {
+        ESX_ERROR(conn, VIR_ERR_OPERATION_INVALID,
+                  "Not possible with a phantom connection");
+        goto failure;
+    }
+
+    if (names == NULL || maxnames < 0) {
+        goto failure;
+    }
+
+    if (maxnames == 0) {
+        return 0;
+    }
+
+    if (esxVI_EnsureSession(conn, priv->host) < 0) {
+        goto failure;
+    }
+
+    if (esxVI_String_AppendValueListToList(conn, &propertyNameList,
+                                           "name\0"
+                                           "runtime.powerState\0") < 0 ||
+        esxVI_GetObjectContent(conn, priv->host, priv->host->vmFolder,
+                               "VirtualMachine", propertyNameList,
+                               esxVI_Boolean_True, &virtualMachineList) < 0) {
+        goto failure;
+    }
+
+    for (virtualMachine = virtualMachineList; virtualMachine != NULL;
+         virtualMachine = virtualMachine->_next) {
+        if (esxVI_GetVirtualMachinePowerState(conn, virtualMachine,
+                                              &powerState) < 0) {
+            goto failure;
+        }
+
+        if (powerState == esxVI_VirtualMachinePowerState_PoweredOn) {
+            continue;
+        }
+
+        for (dynamicProperty = virtualMachine->propSet;
+             dynamicProperty != NULL;
+             dynamicProperty = dynamicProperty->_next) {
+            if (STREQ(dynamicProperty->name, "name")) {
+                if (esxVI_AnyType_ExpectType(conn, dynamicProperty->val,
+                                             esxVI_Type_String) < 0) {
+                    goto failure;
+                }
+
+                names[count] = strdup(dynamicProperty->val->string);
+
+                if (names[count] == NULL) {
+                    virReportOOMError(conn);
+                    goto failure;
+                }
+
+                count++;
+                break;
+            }
+        }
+
+        if (count >= maxnames) {
+            break;
+        }
+    }
+
+  cleanup:
+    esxVI_String_Free(&propertyNameList);
+    esxVI_ObjectContent_Free(&virtualMachineList);
+
+    return count;
+
+  failure:
+    count = -1;
+
+    goto cleanup;
+
+}
+
+
+
+static int
+esxNumberOfDefinedDomains(virConnectPtr conn)
+{
+    esxPrivate *priv = (esxPrivate *)conn->privateData;
+
+    if (priv->phantom) {
+        ESX_ERROR(conn, VIR_ERR_OPERATION_INVALID,
+                  "Not possible with a phantom connection");
+        return -1;
+    }
+
+    if (esxVI_EnsureSession(conn, priv->host) < 0) {
+        return -1;
+    }
+
+    return esxVI_GetNumberOfDomainsByPowerState
+             (conn, priv->host, esxVI_VirtualMachinePowerState_PoweredOn,
+              esxVI_Boolean_True);
+}
+
+
+
+static int
+esxDomainCreate(virDomainPtr domain)
+{
+    int result = 0;
+    esxPrivate *priv = (esxPrivate *)domain->conn->privateData;
+    esxVI_ObjectContent *virtualMachine = NULL;
+    esxVI_String *propertyNameList = NULL;
+    esxVI_VirtualMachinePowerState powerState;
+    esxVI_ManagedObjectReference *task = NULL;
+    esxVI_TaskInfoState taskInfoState;
+
+    if (priv->phantom) {
+        ESX_ERROR(domain->conn, VIR_ERR_OPERATION_INVALID,
+                  "Not possible with a phantom connection");
+        goto failure;
+    }
+
+    if (esxVI_EnsureSession(domain->conn, priv->host) < 0) {
+        goto failure;
+    }
+
+    if (esxVI_String_AppendValueToList(domain->conn, &propertyNameList,
+                                       "runtime.powerState") < 0 ||
+        esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host,
+                                         domain->uuid, propertyNameList,
+                                         &virtualMachine) < 0 ||
+        esxVI_GetVirtualMachinePowerState(domain->conn, virtualMachine,
+                                          &powerState) < 0) {
+        goto failure;
+    }
+
+    if (powerState != esxVI_VirtualMachinePowerState_PoweredOff) {
+        ESX_ERROR(domain->conn, VIR_ERR_OPERATION_INVALID,
+                  "Domain is not powered off");
+        goto failure;
+    }
+
+    if (esxVI_PowerOnVM_Task(domain->conn, priv->host, virtualMachine->obj,
+                             &task) < 0 ||
+        esxVI_WaitForTaskCompletion(domain->conn, priv->host, task,
+                                    &taskInfoState) < 0) {
+        goto failure;
+    }
+
+    if (taskInfoState != esxVI_TaskInfoState_Success) {
+        ESX_ERROR(domain->conn, VIR_ERR_INTERNAL_ERROR,
+                  "Could not start domain");
+        goto failure;
+    }
+
+  cleanup:
+    esxVI_ObjectContent_Free(&virtualMachine);
+    esxVI_String_Free(&propertyNameList);
+    esxVI_ManagedObjectReference_Free(&task);
+
+    return result;
+
+  failure:
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+static char *
+esxDomainGetSchedulerType(virDomainPtr domain, int *nparams)
+{
+    char *type = strdup("allocation");
+
+    if (type == NULL) {
+        virReportOOMError(domain->conn);
+    }
+
+    *nparams = 3; /* reservation, limit, shares */
+
+    return type;
+}
+
+
+
+static int
+esxDomainGetSchedulerParameters(virDomainPtr domain,
+                                virSchedParameterPtr params, int *nparams)
+{
+    int result = 0;
+    esxPrivate *priv = (esxPrivate *)domain->conn->privateData;
+    esxVI_String *propertyNameList = NULL;
+    esxVI_ObjectContent *virtualMachine = NULL;
+    esxVI_DynamicProperty *dynamicProperty = NULL;
+    esxVI_SharesInfo *sharesInfo = NULL;
+    unsigned int mask = 0;
+    int i = 0;
+
+    if (priv->phantom) {
+        ESX_ERROR(domain->conn, VIR_ERR_OPERATION_INVALID,
+                  "Not possible with a phantom connection");
+        goto failure;
+    }
+
+    if (*nparams < 3) {
+        ESX_ERROR(domain->conn, VIR_ERR_INVALID_ARG,
+                  "Parameter array must have space for 3 items");
+        goto failure;
+    }
+
+    if (esxVI_EnsureSession(domain->conn, priv->host) < 0) {
+        goto failure;
+    }
+
+    if (esxVI_String_AppendValueListToList(domain->conn, &propertyNameList,
+                                           "config.cpuAllocation.reservation\0"
+                                           "config.cpuAllocation.limit\0"
+                                           "config.cpuAllocation.shares\0") < 0 ||
+        esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host,
+                                         domain->uuid, propertyNameList,
+                                         &virtualMachine) < 0) {
+        goto failure;
+    }
+
+    for (dynamicProperty = virtualMachine->propSet;
+         dynamicProperty != NULL && mask != 7 && i < 3;
+         dynamicProperty = dynamicProperty->_next) {
+        if (STREQ(dynamicProperty->name, "config.cpuAllocation.reservation") &&
+            !(mask & (1 << 0))) {
+            snprintf (params[i].field, VIR_DOMAIN_SCHED_FIELD_LENGTH, "%s",
+                      "reservation");
+
+            params[i].type = VIR_DOMAIN_SCHED_FIELD_LLONG;
+
+            if (esxVI_AnyType_ExpectType(domain->conn, dynamicProperty->val,
+                                         esxVI_Type_Long) < 0) {
+                goto failure;
+            }
+
+            params[i].value.l = dynamicProperty->val->int64;
+            mask |= 1 << 0;
+            ++i;
+        } else if (STREQ(dynamicProperty->name,
+                         "config.cpuAllocation.limit") &&
+                   !(mask & (1 << 1))) {
+            snprintf (params[i].field, VIR_DOMAIN_SCHED_FIELD_LENGTH, "%s",
+                      "limit");
+
+            params[i].type = VIR_DOMAIN_SCHED_FIELD_LLONG;
+
+            if (esxVI_AnyType_ExpectType(domain->conn, dynamicProperty->val,
+                                         esxVI_Type_Long) < 0) {
+                goto failure;
+            }
+
+            params[i].value.l = dynamicProperty->val->int64;
+            mask |= 1 << 1;
+            ++i;
+        } else if (STREQ(dynamicProperty->name,
+                         "config.cpuAllocation.shares") &&
+                   !(mask & (1 << 2))) {
+            snprintf (params[i].field, VIR_DOMAIN_SCHED_FIELD_LENGTH, "%s",
+                      "shares");
+
+            params[i].type = VIR_DOMAIN_SCHED_FIELD_INT;
+
+            if (esxVI_SharesInfo_CastFromAnyType(domain->conn,
+                                                 dynamicProperty->val,
+                                                 &sharesInfo) < 0) {
+                goto failure;
+            }
+
+            switch (sharesInfo->level) {
+              case esxVI_SharesLevel_Custom:
+                params[i].value.i = sharesInfo->shares->value;
+                break;
+
+              case esxVI_SharesLevel_Low:
+                params[i].value.i = -1;
+                break;
+
+              case esxVI_SharesLevel_Normal:
+                params[i].value.i = -2;
+                break;
+
+              case esxVI_SharesLevel_High:
+                params[i].value.i = -3;
+                break;
+
+              default:
+                ESX_ERROR(domain->conn, VIR_ERR_INTERNAL_ERROR,
+                          "Shares level has unknown value %"PRIi32,
+                          sharesInfo->level);
+                goto failure;
+            }
+
+            esxVI_SharesInfo_Free(&sharesInfo);
+
+            mask |= 1 << 2;
+            ++i;
+        } else {
+            VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
+        }
+    }
+
+    *nparams = i;
+
+  cleanup:
+    esxVI_String_Free(&propertyNameList);
+    esxVI_ObjectContent_Free(&virtualMachine);
+
+    return result;
+
+  failure:
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+static int
+esxDomainSetSchedulerParameters(virDomainPtr domain,
+                                virSchedParameterPtr params, int nparams)
+{
+    int result = 0;
+    esxPrivate *priv = (esxPrivate *)domain->conn->privateData;
+    esxVI_ObjectContent *virtualMachine = NULL;
+    esxVI_VirtualMachineConfigSpec *spec = NULL;
+    esxVI_SharesInfo *sharesInfo = NULL;
+    esxVI_ManagedObjectReference *task = NULL;
+    esxVI_TaskInfoState taskInfoState;
+    int i;
+    int32_t value;
+
+    if (priv->phantom) {
+        ESX_ERROR(domain->conn, VIR_ERR_OPERATION_INVALID,
+                  "Not possible with a phantom connection");
+        goto failure;
+    }
+
+    if (esxVI_EnsureSession(domain->conn, priv->host) < 0) {
+        goto failure;
+    }
+
+    if (esxVI_LookupVirtualMachineByUuid(domain->conn, priv->host,
+                                         domain->uuid, NULL,
+                                         &virtualMachine) < 0 ||
+        esxVI_VirtualMachineConfigSpec_Alloc(domain->conn, &spec) < 0 ||
+        esxVI_ResourceAllocationInfo_Alloc(domain->conn,
+                                           &spec->cpuAllocation) < 0) {
+        goto failure;
+    }
+
+    for (i = 0; i < nparams; ++i) {
+        if (STREQ (params[i].field, "reservation") &&
+            params[i].type == VIR_DOMAIN_SCHED_FIELD_LLONG) {
+            if (esxVI_Long_Alloc(domain->conn,
+                                 &spec->cpuAllocation->reservation) < 0) {
+                goto failure;
+            }
+
+            if (params[i].value.l < 0) {
+                ESX_ERROR(domain->conn, VIR_ERR_INVALID_ARG,
+                          "Could not set reservation to %lld MHz, expecting "
+                          "positive value", params[i].value.l);
+                goto failure;
+            }
+
+            spec->cpuAllocation->reservation->value = params[i].value.l;
+        } else if (STREQ (params[i].field, "limit") &&
+                   params[i].type == VIR_DOMAIN_SCHED_FIELD_LLONG) {
+            if (esxVI_Long_Alloc(domain->conn,
+                                 &spec->cpuAllocation->limit) < 0) {
+                goto failure;
+            }
+
+            if (params[i].value.l < -1) {
+                ESX_ERROR(domain->conn, VIR_ERR_INVALID_ARG,
+                          "Could not set limit to %lld MHz, expecting "
+                          "positive value or -1 (unlimited)",
+                          params[i].value.l);
+                goto failure;
+            }
+
+            spec->cpuAllocation->limit->value = params[i].value.l;
+        } else if (STREQ (params[i].field, "shares") &&
+                   (params[i].type == VIR_DOMAIN_SCHED_FIELD_INT ||
+                    params[i].type == VIR_DOMAIN_SCHED_FIELD_LLONG)) {
+            if (params[i].type == VIR_DOMAIN_SCHED_FIELD_LLONG) {
+                /*
+                 * Allow VIR_DOMAIN_SCHED_FIELD_LLONG here even if the expected
+                 * data type is VIR_DOMAIN_SCHED_FIELD_INT, because virsh is
+                 * using VIR_DOMAIN_SCHED_FIELD_LLONG only.
+                 */
+                if (params[i].value.l < INT32_MIN ||
+                    params[i].value.l > INT32_MAX) {
+                    ESX_ERROR(domain->conn, VIR_ERR_INVALID_ARG,
+                              "Could not set shares to %lld, expecting 32bit "
+                              "integer value", params[i].value.l);
+                    goto failure;
+                }
+
+                value = params[i].value.l;
+            } else {
+                value = params[i].value.i;
+            }
+
+            if (esxVI_SharesInfo_Alloc(domain->conn, &sharesInfo) < 0 ||
+                esxVI_Int_Alloc(domain->conn, &sharesInfo->shares) < 0) {
+                goto failure;
+            }
+
+            spec->cpuAllocation->shares = sharesInfo;
+
+            if (value >= 0) {
+                spec->cpuAllocation->shares->level = esxVI_SharesLevel_Custom;
+                spec->cpuAllocation->shares->shares->value = value;
+            } else {
+                switch (value) {
+                  case -1:
+                    spec->cpuAllocation->shares->level = esxVI_SharesLevel_Low;
+                    spec->cpuAllocation->shares->shares->value = -1;
+                    break;
+
+                  case -2:
+                    spec->cpuAllocation->shares->level =
+                      esxVI_SharesLevel_Normal;
+                    spec->cpuAllocation->shares->shares->value = -1;
+                    break;
+
+                  case -3:
+                    spec->cpuAllocation->shares->level =
+                      esxVI_SharesLevel_High;
+                    spec->cpuAllocation->shares->shares->value = -1;
+                    break;
+
+                  default:
+                    ESX_ERROR(domain->conn, VIR_ERR_INVALID_ARG,
+                              "Could not set shares to %d, expecting positive "
+                              "value or -1 (low), -2 (normal) or -3 (high)",
+                              params[i].value.i);
+                    goto failure;
+                }
+            }
+        } else {
+            ESX_ERROR(domain->conn, VIR_ERR_INVALID_ARG,
+                      "Unknown field '%s'", params[i].field);
+            goto failure;
+        }
+    }
+
+    if (esxVI_ReconfigVM_Task(domain->conn, priv->host, virtualMachine->obj,
+                              spec, &task) < 0 ||
+        esxVI_WaitForTaskCompletion(domain->conn, priv->host, task,
+                                    &taskInfoState) < 0) {
+        goto failure;
+    }
+
+    if (taskInfoState != esxVI_TaskInfoState_Success) {
+        ESX_ERROR(domain->conn, VIR_ERR_INTERNAL_ERROR,
+                  "Could not change scheduler parameters");
+        goto failure;
+    }
+
+  cleanup:
+    esxVI_ObjectContent_Free(&virtualMachine);
+    esxVI_VirtualMachineConfigSpec_Free(&spec);
+    esxVI_ManagedObjectReference_Free(&task);
+
+    return result;
+
+  failure:
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+static int
+esxDomainMigratePrepare(virConnectPtr dconn,
+                        char **cookie ATTRIBUTE_UNUSED,
+                        int *cookielen ATTRIBUTE_UNUSED,
+                        const char *uri_in, char **uri_out,
+                        unsigned long flags ATTRIBUTE_UNUSED,
+                        const char *dname ATTRIBUTE_UNUSED,
+                        unsigned long resource ATTRIBUTE_UNUSED)
+{
+    int result = 0;
+    char *transport = NULL;
+
+    if (uri_in == NULL) {
+        if (esxUtil_ParseQuery(dconn, &transport, NULL) < 0) {
+            return -1;
+        }
+
+        if (virAsprintf(uri_out, "%s://%s/sdk", transport,
+                        dconn->uri->server) < 0) {
+            virReportOOMError(dconn);
+            goto failure;
+        }
+    }
+
+  cleanup:
+    VIR_FREE(transport);
+
+    return result;
+
+  failure:
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+static int
+esxDomainMigratePerform(virDomainPtr domain,
+                        const char *cookie ATTRIBUTE_UNUSED,
+                        int cookielen ATTRIBUTE_UNUSED,
+                        const char *uri,
+                        unsigned long flags ATTRIBUTE_UNUSED,
+                        const char *dname,
+                        unsigned long bandwidth ATTRIBUTE_UNUSED)
+{
+    int result = 0;
+    esxPrivate *priv = (esxPrivate *)domain->conn->privateData;
+    xmlURIPtr xmlUri = NULL;
+    char host_ip_string[NI_MAXHOST] = "";
+    esxVI_ObjectContent *virtualMachine = NULL;
+    esxVI_String *propertyNameList = NULL;
+    esxVI_ObjectContent *hostSystem = NULL;
+    esxVI_DynamicProperty *dynamicProperty = NULL;
+    esxVI_ManagedObjectReference *managedObjectReference = NULL;
+    esxVI_ObjectContent *computeResource = NULL;
+    esxVI_ManagedObjectReference *resourcePool = NULL;
+    esxVI_Event *eventList = NULL;
+    esxVI_ManagedObjectReference *task = NULL;
+    esxVI_TaskInfoState taskInfoState;
+
+    if (priv->phantom) {
+        ESX_ERROR(domain->conn, VIR_ERR_OPERATION_INVALID,
+                  "Not possible with a phantom connection");
+        goto failure;
+    }
+
+    if (priv->vcenter == NULL) {
+        ESX_ERROR(domain->conn, VIR_ERR_INVALID_ARG,
+                  "Migration not possible without a Virtual Center");
+        goto failure;
+    }
+
+    if (dname != NULL) {
+        ESX_ERROR(domain->conn, VIR_ERR_INVALID_ARG,
+                  "Renaming domains on migration not supported");
+        goto failure;
+    }
+
+    if (esxVI_EnsureSession(domain->conn, priv->vcenter) < 0) {
+        goto failure;
+    }
+
+    /* Parse the destination URI and resolve the hostname */
+    xmlUri = xmlParseURI(uri);
+
+    if (xmlUri == NULL) {
+        virReportOOMError(domain->conn);
+        goto failure;
+    }
+
+    if (esxUtil_ResolveHostname(domain->conn, xmlUri->server, host_ip_string,
+                                NI_MAXHOST) < 0) {
+        goto failure;
+    }
+
+    /* Lookup VirtualMachine, HostSystem and ResourcePool */
+    if (esxVI_LookupVirtualMachineByUuid(domain->conn, priv->vcenter,
+                                         domain->uuid, NULL,
+                                         &virtualMachine) < 0) {
+        goto failure;
+    }
+
+    if (esxVI_String_AppendValueToList(domain->conn, &propertyNameList,
+                                       "parent") < 0 ||
+        esxVI_LookupHostSystemByIp(domain->conn, priv->vcenter,
+                                   host_ip_string, propertyNameList,
+                                   &hostSystem) < 0) {
+        goto failure;
+    }
+
+    for (dynamicProperty = hostSystem->propSet; dynamicProperty != NULL;
+         dynamicProperty = dynamicProperty->_next) {
+        if (STREQ(dynamicProperty->name, "parent")) {
+            if (esxVI_ManagedObjectReference_CastFromAnyType
+                  (domain->conn, dynamicProperty->val, &managedObjectReference,
+                   "ComputeResource") < 0) {
+                goto failure;
+            }
+
+            break;
+        } else {
+            VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
+        }
+    }
+
+    if (managedObjectReference == NULL) {
+        ESX_ERROR(domain->conn, VIR_ERR_INTERNAL_ERROR,
+                  "Could not retrieve compute resource of host system");
+        goto failure;
+    }
+
+    esxVI_String_Free(&propertyNameList);
+
+    if (esxVI_String_AppendValueToList(domain->conn, &propertyNameList,
+                                       "resourcePool") < 0 ||
+        esxVI_GetObjectContent(domain->conn, priv->vcenter,
+                               managedObjectReference, "ComputeResource",
+                               propertyNameList, esxVI_Boolean_False,
+                               &computeResource) < 0) {
+        goto failure;
+    }
+
+    if (computeResource == NULL) {
+        ESX_ERROR(domain->conn, VIR_ERR_INTERNAL_ERROR,
+                  "Could not retrieve compute resource of host system");
+        goto failure;
+    }
+
+    for (dynamicProperty = computeResource->propSet; dynamicProperty != NULL;
+         dynamicProperty = dynamicProperty->_next) {
+        if (STREQ(dynamicProperty->name, "resourcePool")) {
+            if (esxVI_ManagedObjectReference_CastFromAnyType
+                  (domain->conn, dynamicProperty->val, &resourcePool,
+                   "ResourcePool") < 0) {
+                goto failure;
+            }
+
+            break;
+        } else {
+            VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
+        }
+    }
+
+    if (resourcePool == NULL) {
+        ESX_ERROR(domain->conn, VIR_ERR_INTERNAL_ERROR,
+                  "Could not retrieve resource pool of compute resource of "
+                  "host system");
+        goto failure;
+    }
+
+    /* Validate the purposed migration */
+    if (esxVI_ValidateMigration(domain->conn, priv->vcenter,
+                                virtualMachine->obj,
+                                esxVI_VirtualMachinePowerState_Undefined,
+                                NULL, resourcePool, hostSystem->obj,
+                                &eventList) < 0) {
+        goto failure;
+    }
+
+    if (eventList != NULL) {
+        /*
+         * FIXME: Need to report the complete list of events. Limit reporting
+         *        to the first event for now.
+         */
+        if (eventList->fullFormattedMessage != NULL) {
+            ESX_ERROR(domain->conn, VIR_ERR_INTERNAL_ERROR,
+                      "Could not migrate domain, validation reported a "
+                      "problem: %s", eventList->fullFormattedMessage);
+        } else {
+            ESX_ERROR(domain->conn, VIR_ERR_INTERNAL_ERROR,
+                      "Could not migrate domain, validation reported a "
+                      "problem");
+        }
+
+        goto failure;
+    }
+
+    /* Perform the purposed migration */
+    if (esxVI_MigrateVM_Task(domain->conn, priv->vcenter, virtualMachine->obj,
+                             resourcePool, hostSystem->obj, &task) < 0 ||
+        esxVI_WaitForTaskCompletion(domain->conn, priv->vcenter, task,
+                                    &taskInfoState) < 0) {
+        goto failure;
+    }
+
+    if (taskInfoState != esxVI_TaskInfoState_Success) {
+        ESX_ERROR(domain->conn, VIR_ERR_INTERNAL_ERROR,
+                  "Could not migrate domain, migration task finished with "
+                  "an error");
+        goto failure;
+    }
+
+  cleanup:
+    xmlFreeURI(xmlUri);
+    esxVI_ObjectContent_Free(&virtualMachine);
+    esxVI_String_Free(&propertyNameList);
+    esxVI_ObjectContent_Free(&hostSystem);
+    esxVI_ManagedObjectReference_Free(&managedObjectReference);
+    esxVI_ObjectContent_Free(&computeResource);
+    esxVI_ManagedObjectReference_Free(&resourcePool);
+    esxVI_Event_Free(&eventList);
+    esxVI_ManagedObjectReference_Free(&task);
+
+    return result;
+
+  failure:
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+static virDomainPtr
+esxDomainMigrateFinish(virConnectPtr dconn, const char *dname,
+                       const char *cookie ATTRIBUTE_UNUSED,
+                       int cookielen ATTRIBUTE_UNUSED,
+                       const char *uri ATTRIBUTE_UNUSED,
+                       unsigned long flags ATTRIBUTE_UNUSED)
+{
+    return esxDomainLookupByName(dconn, dname);
+}
+
+
+
+static virDriver esxDriver = {
+    VIR_DRV_ESX,
+    "ESX",
+    esxOpen,                         /* open */
+    esxClose,                        /* close */
+    esxSupportsFeature,              /* supports_feature */
+    esxGetType,                      /* type */
+    esxGetVersion,                   /* version */
+    esxGetHostname,                  /* hostname */
+    NULL,                            /* getMaxVcpus */
+    esxNodeGetInfo,                  /* nodeGetInfo */
+    NULL,                            /* getCapabilities */
+    esxListDomains,                  /* listDomains */
+    esxNumberOfDomains,              /* numOfDomains */
+    NULL,                            /* domainCreateXML */
+    esxDomainLookupByID,             /* domainLookupByID */
+    esxDomainLookupByUUID,           /* domainLookupByUUID */
+    esxDomainLookupByName,           /* domainLookupByName */
+    esxDomainSuspend,                /* domainSuspend */
+    esxDomainResume,                 /* domainResume */
+    esxDomainShutdown,               /* domainShutdown */
+    esxDomainReboot,                 /* domainReboot */
+    esxDomainDestroy,                /* domainDestroy */
+    esxDomainGetOSType,              /* domainGetOSType */
+    esxDomainGetMaxMemory,           /* domainGetMaxMemory */
+    esxDomainSetMaxMemory,           /* domainSetMaxMemory */
+    esxDomainSetMemory,              /* domainSetMemory */
+    esxDomainGetInfo,                /* domainGetInfo */
+    NULL,                            /* domainSave */
+    NULL,                            /* domainRestore */
+    NULL,                            /* domainCoreDump */
+    esxDomainSetVcpus,               /* domainSetVcpus */
+    NULL,                            /* domainPinVcpu */
+    NULL,                            /* domainGetVcpus */
+    esxDomainGetMaxVcpus,            /* domainGetMaxVcpus */
+    NULL,                            /* domainGetSecurityLabel */
+    NULL,                            /* nodeGetSecurityModel */
+    esxDomainDumpXML,                /* domainDumpXML */
+    esxDomainXMLFromNative,          /* domainXmlFromNative */
+    NULL,                            /* domainXmlToNative */
+    esxListDefinedDomains,           /* listDefinedDomains */
+    esxNumberOfDefinedDomains,       /* numOfDefinedDomains */
+    esxDomainCreate,                 /* domainCreate */
+    NULL,                            /* domainDefineXML */
+    NULL,                            /* domainUndefine */
+    NULL,                            /* domainAttachDevice */
+    NULL,                            /* domainDetachDevice */
+    NULL,                            /* domainGetAutostart */
+    NULL,                            /* domainSetAutostart */
+    esxDomainGetSchedulerType,       /* domainGetSchedulerType */
+    esxDomainGetSchedulerParameters, /* domainGetSchedulerParameters */
+    esxDomainSetSchedulerParameters, /* domainSetSchedulerParameters */
+    esxDomainMigratePrepare,         /* domainMigratePrepare */
+    esxDomainMigratePerform,         /* domainMigratePerform */
+    esxDomainMigrateFinish,          /* domainMigrateFinish */
+    NULL,                            /* domainBlockStats */
+    NULL,                            /* domainInterfaceStats */
+    NULL,                            /* domainBlockPeek */
+    NULL,                            /* domainMemoryPeek */
+    NULL,                            /* nodeGetCellsFreeMemory */
+    NULL,                            /* nodeGetFreeMemory */
+    NULL,                            /* domainEventRegister */
+    NULL,                            /* domainEventDeregister */
+    NULL,                            /* domainMigratePrepare2 */
+    NULL,                            /* domainMigrateFinish2 */
+    NULL,                            /* nodeDeviceDettach */
+    NULL,                            /* nodeDeviceReAttach */
+    NULL,                            /* nodeDeviceReset */
+};
+
+
+
+int
+esxRegister(void)
+{
+    virRegisterDriver(&esxDriver);
+
+    return 0;
+}
diff --git a/src/esx/esx_driver.h b/src/esx/esx_driver.h
new file mode 100644
index 0000000..85f4b32
--- /dev/null
+++ b/src/esx/esx_driver.h
@@ -0,0 +1,29 @@
+
+/*
+ * esx_driver.h: core driver methods for managing VMware ESX hosts
+ *
+ * Copyright (C) 2009 Matthias Bolte <matthias.bolte@xxxxxxxxxxxxxx>
+ * Copyright (C) 2009 Maximilian Wilhelm <max@xxxxxxxxxxx>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ */
+
+#ifndef __ESX_DRIVER_H__
+#define __ESX_DRIVER_H__
+
+int esxRegister(void);
+
+#endif /* __ESX_DRIVER_H__ */
diff --git a/src/esx/esx_util.c b/src/esx/esx_util.c
new file mode 100644
index 0000000..bd931bf
--- /dev/null
+++ b/src/esx/esx_util.c
@@ -0,0 +1,488 @@
+
+/*
+ * esx_util.c: utility methods for the VMware ESX driver
+ *
+ * Copyright (C) 2009 Matthias Bolte <matthias.bolte@xxxxxxxxxxxxxx>
+ * Copyright (C) 2009 Maximilian Wilhelm <max@xxxxxxxxxxx>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ */
+
+#include <config.h>
+
+#include <netdb.h>
+
+#include "internal.h"
+#include "virterror_internal.h"
+#include "datatypes.h"
+#include "qparams.h"
+#include "util.h"
+#include "memory.h"
+#include "logging.h"
+#include "uuid.h"
+#include "esx_util.h"
+
+#define VIR_FROM_THIS VIR_FROM_ESX
+
+#define ESX_ERROR(conn, code, fmt...)                                         \
+    virReportErrorHelper (conn, VIR_FROM_ESX, code, __FILE__, __FUNCTION__,   \
+                          __LINE__, fmt)
+
+
+
+char *
+esxUtil_RequestUsername(virConnectAuthPtr auth, const char *default_username,
+                        const char *server)
+{
+    unsigned int ncred;
+    virConnectCredential cred;
+    char *prompt = NULL;
+
+    memset(&cred, 0, sizeof(virConnectCredential));
+
+    if (virAsprintf(&prompt, "Enter username for %s [%s]", server,
+                    default_username) < 0) {
+        return NULL;
+    }
+
+    for (ncred = 0; ncred < auth->ncredtype; ncred++) {
+        if (auth->credtype[ncred] != VIR_CRED_AUTHNAME) {
+            continue;
+        }
+
+        cred.type = VIR_CRED_AUTHNAME;
+        cred.prompt = prompt;
+        cred.challenge = NULL;
+        cred.defresult = default_username;
+        cred.result = NULL;
+        cred.resultlen = 0;
+
+        if ((*(auth->cb))(&cred, 1, auth->cbdata) < 0) {
+            VIR_FREE(cred.result);
+        }
+
+        break;
+    }
+
+    VIR_FREE(prompt);
+
+    return cred.result;
+}
+
+
+
+char *
+esxUtil_RequestPassword(virConnectAuthPtr auth, const char *username,
+                        const char *server)
+{
+    unsigned int ncred;
+    virConnectCredential cred;
+    char *prompt;
+
+    memset(&cred, 0, sizeof(virConnectCredential));
+
+    if (virAsprintf(&prompt, "Enter %s password for %s", username,
+                    server) < 0) {
+        return NULL;
+    }
+
+    for (ncred = 0; ncred < auth->ncredtype; ncred++) {
+        if (auth->credtype[ncred] != VIR_CRED_PASSPHRASE &&
+            auth->credtype[ncred] != VIR_CRED_NOECHOPROMPT) {
+            continue;
+        }
+
+        cred.type = auth->credtype[ncred];
+        cred.prompt = prompt;
+        cred.challenge = NULL;
+        cred.defresult = NULL;
+        cred.result = NULL;
+        cred.resultlen = 0;
+
+        if ((*(auth->cb))(&cred, 1, auth->cbdata) < 0) {
+            VIR_FREE(cred.result);
+        }
+
+        break;
+    }
+
+    VIR_FREE(prompt);
+
+    return cred.result;
+}
+
+
+
+int
+esxUtil_ParseQuery(virConnectPtr conn, char **transport, char **vcenter)
+{
+    int result = 0;
+    int i;
+    struct qparam_set *queryParamSet = NULL;
+    struct qparam *queryParam = NULL;
+
+    if (transport != NULL) {
+        *transport = NULL;
+    }
+
+    if (vcenter != NULL) {
+        *vcenter = NULL;
+    }
+
+#ifdef HAVE_XMLURI_QUERY_RAW
+    queryParamSet = qparam_query_parse(conn->uri->query_raw);
+#else
+    queryParamSet = qparam_query_parse(conn->uri->query);
+#endif
+
+    if (queryParamSet == NULL) {
+        goto failure;
+    }
+
+    for (i = 0; i < queryParamSet->n; i++) {
+        queryParam = &queryParamSet->p[i];
+
+        if (STRCASEEQ(queryParam->name, "transport") && transport != NULL) {
+            *transport = strdup(queryParam->value);
+
+            if (*transport == NULL) {
+                virReportOOMError(conn);
+                goto failure;
+            }
+
+            if (STRNEQ(*transport, "http") && STRNEQ(*transport, "https")) {
+                ESX_ERROR(conn, VIR_ERR_INVALID_ARG,
+                          "Query parameter 'transport' has unexpected value "
+                          "'%s' (should be http|https)", *transport);
+                goto failure;
+            }
+        } else if (STRCASEEQ(queryParam->name, "vcenter") && vcenter != NULL) {
+            *vcenter = strdup(queryParam->value);
+
+            if (*vcenter == NULL) {
+                virReportOOMError(conn);
+                goto failure;
+            }
+        } else {
+            VIR_WARN("Ignoring unexpected query parameter '%s'",
+                     queryParam->name);
+        }
+    }
+
+    if (transport != NULL && *transport == NULL) {
+        *transport = strdup("https");
+
+        if (*transport == NULL) {
+            virReportOOMError(conn);
+            goto failure;
+        }
+    }
+
+  cleanup:
+    if (queryParamSet != NULL) {
+        free_qparam_set(queryParamSet);
+    }
+
+    return result;
+
+  failure:
+    if (transport != NULL) {
+        VIR_FREE(*transport);
+    }
+
+    if (vcenter != NULL) {
+        VIR_FREE(*vcenter);
+    }
+
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+int
+esxUtil_ParseVirtualMachineIDString(const char *id_string, int *id)
+{
+    /* Try to parse an integer from the complete string. */
+    if (virStrToLong_i(id_string, NULL, 10, id) == 0) {
+        return 0;
+    }
+
+    /*
+     * If that fails try to parse an integer from the string tail
+     * assuming the naming scheme Virtual Center seems to use.
+     */
+    if (STRPREFIX(id_string, "vm-")) {
+        if (virStrToLong_i(id_string + 3, NULL, 10, id) == 0) {
+            return 0;
+        }
+    }
+
+    return -1;
+}
+
+
+
+int
+esxUtil_ResolveHostname(virConnectPtr conn, const char *hostname,
+                        char *ip_address, size_t ip_address_length)
+{
+    struct addrinfo hints;
+    struct addrinfo *result = NULL;
+    int errcode;
+
+    memset(&hints, 0, sizeof (struct addrinfo));
+
+    hints.ai_flags = AI_ADDRCONFIG;
+    hints.ai_family = AF_INET;
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_protocol = 0;
+
+    errcode = getaddrinfo(hostname, NULL, &hints, &result);
+
+    if (errcode != 0) {
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                  "IP address lookup for host '%s' failed: %s", hostname,
+                  gai_strerror(errcode));
+        return -1;
+    }
+
+    if (result == NULL) {
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                  "No IP address for host '%s' found: %s", hostname,
+                  gai_strerror(errcode));
+        return -1;
+    }
+
+    errcode = getnameinfo(result->ai_addr, result->ai_addrlen, ip_address,
+                          ip_address_length, NULL, 0, NI_NUMERICHOST);
+
+    if (errcode != 0) {
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                  "Formating IP address for host '%s' failed: %s", hostname,
+                  gai_strerror(errcode));
+        freeaddrinfo(result);
+        return -1;
+    }
+
+    freeaddrinfo(result);
+
+    return 0;
+}
+
+
+
+int
+esxUtil_GetConfigString(virConnectPtr conn, virConfPtr conf, const char *name,
+                        char **string, int optional)
+{
+    virConfValuePtr value;
+
+    *string = NULL;
+    value = virConfGetValue(conf, name);
+
+    if (value == NULL) {
+        if (optional) {
+            return 0;
+        }
+
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                  "Missing essential config entry '%s'", name);
+        return -1;
+    }
+
+    if (value->type != VIR_CONF_STRING) {
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                  "Config entry '%s' must be a string", name);
+        return -1;
+    }
+
+    if (value->str == NULL) {
+        if (optional) {
+            return 0;
+        }
+
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                  "Missing essential config entry '%s'", name);
+        return -1;
+    }
+
+    *string = strdup(value->str);
+
+    if (*string == NULL) {
+        virReportOOMError(conn);
+        return -1;
+    }
+
+    return 0;
+}
+
+
+
+int
+esxUtil_GetConfigUUID(virConnectPtr conn, virConfPtr conf, const char *name,
+                      unsigned char *uuid, int optional)
+{
+    virConfValuePtr value;
+
+    value = virConfGetValue(conf, name);
+
+    if (value == NULL) {
+        if (optional) {
+            return 0;
+        } else {
+            ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                      "Missing essential config entry '%s'", name);
+            return -1;
+        }
+    }
+
+    if (value->type != VIR_CONF_STRING) {
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                  "Config entry '%s' must be a string", name);
+        return -1;
+    }
+
+    if (value->str == NULL) {
+        if (optional) {
+            return 0;
+        } else {
+            ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                      "Missing essential config entry '%s'", name);
+            return -1;
+        }
+    }
+
+    virUUIDParse(value->str, uuid);
+
+    return 0;
+}
+
+
+
+int
+esxUtil_GetConfigLong(virConnectPtr conn, virConfPtr conf, const char *name,
+                      long long *number, long long default_, int optional)
+{
+    virConfValuePtr value;
+
+    *number = default_;
+    value = virConfGetValue(conf, name);
+
+    if (value == NULL) {
+        if (optional) {
+            return 0;
+        } else {
+            ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                      "Missing essential config entry '%s'", name);
+            return -1;
+        }
+    }
+
+    if (value->type == VIR_CONF_STRING) {
+        if (value->str == NULL) {
+            if (optional) {
+                return 0;
+            } else {
+                ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                          "Missing essential config entry '%s'", name);
+                return -1;
+            }
+        }
+
+        if (STREQ(value->str, "unlimited")) {
+            *number = -1;
+        } else if (virStrToLong_ll(value->str, NULL, 10, number) < 0) {
+            ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                      "Config entry '%s' must represent an integer value",
+                      name);
+            return -1;
+        }
+    } else {
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                  "Config entry '%s' must be a string", name);
+        return -1;
+    }
+
+    return 0;
+}
+
+
+
+int
+esxUtil_GetConfigBoolean(virConnectPtr conn, virConfPtr conf,
+                         const char *name, int *boolean, int default_,
+                         int optional)
+{
+    virConfValuePtr value;
+
+    *boolean = default_;
+    value = virConfGetValue(conf, name);
+
+    if (value == NULL) {
+        if (optional) {
+            return 0;
+        } else {
+            ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                      "Missing essential config entry '%s'", name);
+            return -1;
+        }
+    }
+
+    if (value->type == VIR_CONF_STRING) {
+        if (value->str == NULL) {
+            if (optional) {
+                return 0;
+            } else {
+                ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                          "Missing essential config entry '%s'", name);
+                return -1;
+            }
+        }
+
+        if (STRCASEEQ(value->str, "true")) {
+            *boolean = 1;
+        } else if (STRCASEEQ(value->str, "false")) {
+            *boolean = 0;
+        } else {
+            ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                      "Config entry '%s' must represent a boolean value "
+                      "(true|false)", name);
+            return -1;
+        }
+    } else {
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                  "Config entry '%s' must be a string", name);
+        return -1;
+    }
+
+    return 0;
+}
+
+
+
+int
+esxUtil_EqualSuffix(const char *string, const char* suffix)
+{
+    int difference = (int)strlen(string) - (int)strlen(suffix);
+
+    if (difference < 0) {
+        return -1;
+    } else {
+        return STRCASEEQ(string + difference, suffix);
+    }
+}
diff --git a/src/esx/esx_util.h b/src/esx/esx_util.h
new file mode 100644
index 0000000..f746231
--- /dev/null
+++ b/src/esx/esx_util.h
@@ -0,0 +1,60 @@
+
+/*
+ * esx_util.h: utility methods for the VMware ESX driver
+ *
+ * Copyright (C) 2009 Matthias Bolte <matthias.bolte@xxxxxxxxxxxxxx>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ */
+
+#ifndef __ESX_UTIL_H__
+#define __ESX_UTIL_H__
+
+#include <libxml/tree.h>
+
+#include "internal.h"
+#include "conf.h"
+
+char *esxUtil_RequestUsername(virConnectAuthPtr auth,
+                              const char *default_username,
+                              const char *server);
+
+char *esxUtil_RequestPassword(virConnectAuthPtr auth, const char *username,
+                              const char *server);
+
+int esxUtil_ParseQuery(virConnectPtr conn, char **transport, char **vcenter);
+
+int esxUtil_ParseVirtualMachineIDString(const char *id_string, int *id);
+
+int esxUtil_ResolveHostname(virConnectPtr conn, const char *hostname,
+                            char *ip_address, size_t ip_address_length);
+
+int esxUtil_GetConfigString(virConnectPtr conn, virConfPtr conf,
+                            const char *name, char **string, int optional);
+
+int esxUtil_GetConfigUUID(virConnectPtr conn, virConfPtr conf, const char *name,
+                          unsigned char *uuid, int optional);
+
+int esxUtil_GetConfigLong(virConnectPtr conn, virConfPtr conf, const char *name,
+                          long long *number, long long default_, int optional);
+
+int esxUtil_GetConfigBoolean(virConnectPtr conn, virConfPtr conf,
+                             const char *name, int *boolean, int default_,
+                             int optional);
+
+int esxUtil_EqualSuffix(const char *string, const char* suffix);
+
+#endif /* __ESX_UTIL_H__ */
diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c
new file mode 100644
index 0000000..4b083c6
--- /dev/null
+++ b/src/esx/esx_vi.c
@@ -0,0 +1,1868 @@
+
+/*
+ * esx_vi.c: client for the VMware VI API 2.5 to manage ESX hosts
+ *
+ * Copyright (C) 2009 Matthias Bolte <matthias.bolte@xxxxxxxxxxxxxx>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ */
+
+#include <config.h>
+
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+
+#include <libxml/parser.h>
+#include <libxml/xpathInternals.h>
+
+#include "buf.h"
+#include "memory.h"
+#include "logging.h"
+#include "util.h"
+#include "uuid.h"
+#include "virterror_internal.h"
+#include "esx_vi.h"
+#include "esx_vi_methods.h"
+#include "esx_util.h"
+
+#define VIR_FROM_THIS VIR_FROM_ESX
+
+#define ESX_VI_ERROR(conn, code, fmt...)                                      \
+    virReportErrorHelper(conn, VIR_FROM_ESX, code, __FILE__, __FUNCTION__,    \
+                         __LINE__, fmt)
+
+#define ESX_VI__SOAP__REQUEST_HEADER                                          \
+    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"                            \
+    "<soapenv:Envelope "                                                      \
+      "xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"; "          \
+      "xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\"; "          \
+      "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"; "              \
+      "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\";>"                       \
+    "<soapenv:Body>"
+
+#define ESX_VI__SOAP__REQUEST_FOOTER                                          \
+    "</soapenv:Body>"                                                         \
+    "</soapenv:Envelope>"
+
+#define ESX_VI__SOAP__RESPONSE_XPATH(_type)                                   \
+    ((char *)"/soapenv:Envelope/soapenv:Body/"                                \
+               "vim:"_type"Response/vim:returnval")
+
+#define ESV_VI__XML_TAG__OPEN(_buffer, _element, _type)                       \
+    do {                                                                      \
+        virBufferAddLit(_buffer, "<");                                        \
+        virBufferAdd(_buffer, _element, -1);                                  \
+        virBufferAddLit(_buffer, " xmlns=\"urn:vim25\" xsi:type=\"");         \
+        virBufferAdd(_buffer, _type, -1);                                     \
+        virBufferAddLit(_buffer, "\">");                                      \
+    } while (0)
+
+#define ESV_VI__XML_TAG__CLOSE(_buffer, _element)                             \
+    do {                                                                      \
+        virBufferAddLit(_buffer, "</");                                       \
+        virBufferAdd(_buffer, _element, -1);                                  \
+        virBufferAddLit(_buffer, ">");                                        \
+    } while (0)
+
+#define ESX_VI__TEMPLATE__ALLOC(_type)                                        \
+    int                                                                       \
+    esxVI_##_type##_Alloc(virConnectPtr conn, esxVI_##_type **ptrptr)         \
+    {                                                                         \
+        return esxVI_Alloc(conn, (void **)ptrptr, sizeof (esxVI_##_type));    \
+    }
+
+#define ESX_VI__TEMPLATE__FREE(_type, _body)                                  \
+    void                                                                      \
+    esxVI_##_type##_Free(esxVI_##_type **ptrptr)                              \
+    {                                                                         \
+        esxVI_##_type *item = NULL;                                           \
+                                                                              \
+        if (ptrptr == NULL || *ptrptr == NULL) {                              \
+            return;                                                           \
+        }                                                                     \
+                                                                              \
+        item = *ptrptr;                                                       \
+                                                                              \
+        _body                                                                 \
+                                                                              \
+        VIR_FREE(*ptrptr);                                                    \
+    }
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Context
+ */
+
+/* esxVI_Context_Alloc */
+ESX_VI__TEMPLATE__ALLOC(Context);
+
+/* esxVI_Context_Free */
+ESX_VI__TEMPLATE__FREE(Context,
+{
+    VIR_FREE(item->url);
+
+    if (item->curl_handle != NULL) {
+        curl_easy_cleanup(item->curl_handle);
+    }
+
+    if (item->curl_headers != NULL) {
+        curl_slist_free_all(item->curl_headers);
+    }
+
+    virMutexDestroy(&item->curl_lock);
+
+    VIR_FREE(item->username);
+    VIR_FREE(item->password);
+    esxVI_ServiceContent_Free(&item->service);
+    esxVI_UserSession_Free(&item->session);
+    esxVI_ManagedObjectReference_Free(&item->datacenter);
+    esxVI_ManagedObjectReference_Free(&item->vmFolder);
+    esxVI_ManagedObjectReference_Free(&item->hostFolder);
+    esxVI_SelectionSpec_Free(&item->fullTraversalSpecList);
+});
+
+static size_t
+_esxVI_CURL_WriteBuffer(char *data, size_t size, size_t nmemb, void *buffer)
+{
+    if (buffer != NULL) {
+        virBufferAdd((virBufferPtr) buffer, data, size * nmemb);
+
+        return size * nmemb;
+    }
+
+    return 0;
+}
+
+#define ESX_VI__CURL__ENABLE_DEBUG_OUTPUT 0
+
+#if ESX_VI__CURL__ENABLE_DEBUG_OUTPUT
+static int
+_esxVI_CURL_Debug(CURL *curl ATTRIBUTE_UNUSED, curl_infotype type,
+                  char *info, size_t size, void *data ATTRIBUTE_UNUSED)
+{
+    switch (type) {
+      case CURLINFO_TEXT:
+        VIR_DEBUG0("CURLINFO_TEXT");
+        fwrite(info, 1, size, stderr);
+        printf("\n\n");
+        break;
+
+      case CURLINFO_HEADER_IN:
+        VIR_DEBUG0("CURLINFO_HEADER_IN");
+        break;
+
+      case CURLINFO_HEADER_OUT:
+        VIR_DEBUG0("CURLINFO_HEADER_OUT");
+        break;
+
+      case CURLINFO_DATA_IN:
+        VIR_DEBUG0("CURLINFO_DATA_IN");
+        break;
+
+      case CURLINFO_DATA_OUT:
+        VIR_DEBUG0("CURLINFO_DATA_OUT");
+        break;
+
+      default:
+        VIR_DEBUG0("unknown");
+        break;
+    }
+
+    return 0;
+}
+#endif
+
+int
+esxVI_Context_Connect(virConnectPtr conn, esxVI_Context *ctx, const char *url,
+                      const char *username, const char *password)
+{
+    int result = 0;
+    esxVI_String *propertyNameList = NULL;
+    esxVI_ObjectContent *datacenterList = NULL;
+    esxVI_DynamicProperty *dynamicProperty = NULL;
+
+    if (ctx == NULL || url == NULL || username == NULL || password == NULL ||
+        ctx->url != NULL || ctx->service != NULL || ctx->curl_handle != NULL ||
+        ctx->curl_headers != NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        goto failure;
+    }
+
+    if (esxVI_String_DeepCopyValue(conn, &ctx->url, url) < 0) {
+        goto failure;
+    }
+
+    ctx->curl_handle = curl_easy_init();
+
+    if (ctx->curl_handle == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                     "Could not initialize CURL");
+        goto failure;
+    }
+
+    ctx->curl_headers = curl_slist_append(ctx->curl_headers, "Content-Type: "
+                                          "text/xml; charset=UTF-8");
+
+    /*
+     * Add a dummy expect header to stop CURL from waiting for a response code
+     * 100 (Continue) from the server before continuing the POST operation.
+     * Waiting for this response would slowdown each communication with the
+     * server by approx. 2 sec, because the server doesn't send the expected
+     * 100 (Continue) response and the wait times out resulting in wasting
+     * approx. 2 sec per POST operation.
+     */
+    ctx->curl_headers = curl_slist_append(ctx->curl_headers,
+                                          "Expect: nothing");
+
+    if (ctx->curl_headers == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                     "Could not build CURL header list");
+        goto failure;
+    }
+
+    curl_easy_setopt(ctx->curl_handle, CURLOPT_URL, ctx->url);
+    curl_easy_setopt(ctx->curl_handle, CURLOPT_USERAGENT, "libvirt-esx");
+    curl_easy_setopt(ctx->curl_handle, CURLOPT_HEADER, 0);
+    curl_easy_setopt(ctx->curl_handle, CURLOPT_FOLLOWLOCATION, 1);
+    curl_easy_setopt(ctx->curl_handle, CURLOPT_COOKIEFILE, "");
+    curl_easy_setopt(ctx->curl_handle, CURLOPT_HTTPHEADER, ctx->curl_headers);
+    curl_easy_setopt(ctx->curl_handle, CURLOPT_WRITEFUNCTION,
+                     _esxVI_CURL_WriteBuffer);
+#if ESX_VI__CURL__ENABLE_DEBUG_OUTPUT
+    curl_easy_setopt(ctx->curl_handle, CURLOPT_DEBUGFUNCTION,
+                     _esxVI_CURL_Debug);
+#endif
+
+    if (virMutexInit(&ctx->curl_lock) < 0) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                     "Could not initialize CURL mutex");
+        goto failure;
+    }
+
+    ctx->username = strdup(username);
+    ctx->password = strdup(password);
+
+    if (ctx->username == NULL || ctx->password == NULL) {
+        virReportOOMError(conn);
+        goto failure;
+    }
+
+    if (esxVI_RetrieveServiceContent(conn, ctx, &ctx->service) < 0) {
+        goto failure;
+    }
+
+    if (STREQ(ctx->service->about->apiType, "HostAgent")) {
+        if (STRNEQ(ctx->service->about->apiVersion, "2.5.0") &&
+            STRNEQ(ctx->service->about->apiVersion, "2.5u2")) {
+            ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                         "Expecting VI API version '2.5.0' or '2.5u2' but "
+                         "found '%s'", ctx->service->about->apiVersion);
+            goto failure;
+        }
+    } else if (STREQ(ctx->service->about->apiType, "VirtualCenter")) {
+        if (STRNEQ(ctx->service->about->apiVersion, "2.5u2")) {
+            ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                         "Expecting VI API version '2.5u2' but found '%s'",
+                         ctx->service->about->apiVersion);
+            goto failure;
+        }
+    } else {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                     "Expecting VI API type 'HostAgent' or 'VirtualCenter' "
+                     "but found '%s'", ctx->service->about->apiType);
+        goto failure;
+    }
+
+    if (esxVI_Login(conn, ctx, username, password, &ctx->session) < 0) {
+        goto failure;
+    }
+
+    esxVI_BuildFullTraversalSpecList(conn, &ctx->fullTraversalSpecList);
+
+    if (esxVI_String_AppendValueListToList(conn, &propertyNameList,
+                                           "vmFolder\0"
+                                           "hostFolder\0") < 0) {
+        goto failure;
+    }
+
+    /* Get pointer to Datacenter for later use */
+    if (esxVI_GetObjectContent(conn, ctx, ctx->service->rootFolder,
+                               "Datacenter", propertyNameList,
+                               esxVI_Boolean_True, &datacenterList) < 0) {
+        goto failure;
+    }
+
+    if (datacenterList == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                     "Could not retrieve the 'datacenter' object from the VI "
+                     "host/center");
+        goto failure;
+    }
+
+    ctx->datacenter = datacenterList->obj;
+    datacenterList->obj = NULL;
+
+    /* Get pointer to vmFolder and hostFolder for later use */
+    for (dynamicProperty = datacenterList->propSet; dynamicProperty != NULL;
+         dynamicProperty = dynamicProperty->_next) {
+        if (STREQ(dynamicProperty->name, "vmFolder")) {
+            if (esxVI_ManagedObjectReference_CastFromAnyType
+                  (conn, dynamicProperty->val, &ctx->vmFolder, "Folder")) {
+                goto failure;
+            }
+        } else if (STREQ(dynamicProperty->name, "hostFolder")) {
+            if (esxVI_ManagedObjectReference_CastFromAnyType
+                  (conn, dynamicProperty->val, &ctx->hostFolder, "Folder")) {
+                goto failure;
+            }
+        } else {
+            VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
+        }
+    }
+
+    if (ctx->vmFolder == NULL || ctx->hostFolder == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                     "The 'datacenter' object is missing the "
+                     "'vmFolder'/'hostFolder' propoerty");
+        goto failure;
+    }
+
+  cleanup:
+    esxVI_String_Free(&propertyNameList);
+    esxVI_ObjectContent_Free(&datacenterList);
+
+    return result;
+
+  failure:
+    result = -1;
+
+    goto cleanup;
+}
+
+int
+esxVI_Context_Download(virConnectPtr conn, esxVI_Context *ctx, const char *url,
+                       char **content)
+{
+    virBuffer buffer = VIR_BUFFER_INITIALIZER;
+    CURLcode error_code;
+    long response_code;
+
+    if (content == NULL || *content != NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        goto failure;
+    }
+
+    virMutexLock(&ctx->curl_lock);
+
+    curl_easy_setopt(ctx->curl_handle, CURLOPT_URL, url);
+    curl_easy_setopt(ctx->curl_handle, CURLOPT_WRITEDATA, &buffer);
+    curl_easy_setopt(ctx->curl_handle, CURLOPT_HTTPGET, 1);
+
+    error_code = curl_easy_perform(ctx->curl_handle);
+
+    if (error_code != CURLE_OK) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                     "curl_easy_perform() returned an error: %s (%d)",
+                     curl_easy_strerror(error_code), error_code);
+        goto unlock;
+    }
+
+    error_code = curl_easy_getinfo(ctx->curl_handle, CURLINFO_RESPONSE_CODE,
+                                   &response_code);
+
+    if (error_code != CURLE_OK) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                     "curl_easy_getinfo() returned an error: %s (%d)",
+                     curl_easy_strerror(error_code), error_code);
+        goto unlock;
+    }
+
+    virMutexUnlock(&ctx->curl_lock);
+
+    if (virBufferError(&buffer)) {
+        virReportOOMError(conn);
+        goto failure;
+    }
+
+    *content = virBufferContentAndReset(&buffer);
+
+    if (response_code != 200) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                     "HTTP response code %d", (int)response_code);
+        goto failure;
+    }
+
+    return 0;
+
+  failure:
+    free(virBufferContentAndReset(&buffer));
+
+    return -1;
+
+  unlock:
+    virMutexUnlock(&ctx->curl_lock);
+
+    goto failure;
+}
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * RemoteRequest
+ */
+
+/* esxVI_RemoteRequest_Alloc */
+ESX_VI__TEMPLATE__ALLOC(RemoteRequest);
+
+/* esxVI_RemoteRequest_Free */
+ESX_VI__TEMPLATE__FREE(RemoteRequest,
+{
+    VIR_FREE(item->request);
+    VIR_FREE(item->xpathExpression);
+});
+
+int
+esxVI_RemoteRequest_Execute(virConnectPtr conn, esxVI_Context *ctx,
+                            esxVI_RemoteRequest *remoteRequest,
+                            esxVI_RemoteResponse **remoteResponse)
+{
+    virBuffer buffer = VIR_BUFFER_INITIALIZER;
+    esxVI_Fault *fault = NULL;
+    CURLcode error_code;
+
+    if (remoteRequest == NULL || remoteRequest->request == NULL ||
+        remoteResponse == NULL || *remoteResponse != NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        goto failure;
+    }
+
+    if (esxVI_RemoteResponse_Alloc(conn, remoteResponse) < 0) {
+        goto failure;
+    }
+
+    virMutexLock(&ctx->curl_lock);
+
+    curl_easy_setopt(ctx->curl_handle, CURLOPT_URL, ctx->url);
+    curl_easy_setopt(ctx->curl_handle, CURLOPT_WRITEDATA, &buffer);
+    curl_easy_setopt(ctx->curl_handle, CURLOPT_POSTFIELDS,
+                     remoteRequest->request);
+    curl_easy_setopt(ctx->curl_handle, CURLOPT_POSTFIELDSIZE,
+                     strlen(remoteRequest->request));
+
+    error_code = curl_easy_perform(ctx->curl_handle);
+
+    if (error_code != CURLE_OK) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                     "curl_easy_perform() returned an error: %s (%d)",
+                     curl_easy_strerror(error_code), error_code);
+        goto unlock;
+    }
+
+    error_code = curl_easy_getinfo(ctx->curl_handle, CURLINFO_RESPONSE_CODE,
+                                   &(*remoteResponse)->response_code);
+
+    if (error_code != CURLE_OK) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                     "curl_easy_getinfo() returned an error: %s (%d)",
+                     curl_easy_strerror(error_code), error_code);
+        goto unlock;
+    }
+
+    virMutexUnlock(&ctx->curl_lock);
+
+    if (virBufferError(&buffer)) {
+        virReportOOMError(conn);
+        goto failure;
+    }
+
+    (*remoteResponse)->response = virBufferContentAndReset(&buffer);
+
+    if ((*remoteResponse)->response_code == 500 ||
+        (remoteRequest->xpathExpression != NULL &&
+         (*remoteResponse)->response_code == 200)) {
+        (*remoteResponse)->document =
+          xmlReadDoc(BAD_CAST(*remoteResponse)->response, "", NULL,
+                     XML_PARSE_NONET);
+
+        if ((*remoteResponse)->document == NULL) {
+            ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                         "Could not parse XML response");
+            goto failure;
+        }
+
+        if (xmlDocGetRootElement((*remoteResponse)->document) == NULL) {
+            ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                         "XML response is an empty document");
+            goto failure;
+        }
+
+        (*remoteResponse)->xpathContext =
+            xmlXPathNewContext((*remoteResponse)->document);
+
+        if ((*remoteResponse)->xpathContext == NULL) {
+            ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                         "Could not create XPath context");
+            goto failure;
+        }
+
+        xmlXPathRegisterNs((*remoteResponse)->xpathContext, BAD_CAST "soapenv",
+                           BAD_CAST "http://schemas.xmlsoap.org/soap/envelope/";);
+        xmlXPathRegisterNs((*remoteResponse)->xpathContext, BAD_CAST "vim",
+                           BAD_CAST "urn:vim25");
+
+        if ((*remoteResponse)->response_code == 500) {
+            (*remoteResponse)->xpathObject =
+                xmlXPathEval(BAD_CAST
+                             "/soapenv:Envelope/soapenv:Body/soapenv:Fault",
+                             (*remoteResponse)->xpathContext);
+
+            if (esxVI_RemoteResponse_DeserializeXPathObject
+                  (conn, *remoteResponse,
+                   (esxVI_RemoteResponse_DeserializeFunc)
+                     esxVI_Fault_Deserialize,
+                   (void **)&fault) < 0) {
+                goto failure;
+            }
+
+            ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                         "HTTP response code %d. VI Fault: %s - %s",
+                         (int)(*remoteResponse)->response_code,
+                         fault->faultcode, fault->faultstring);
+
+            goto failure;
+        } else {
+            (*remoteResponse)->xpathObject =
+              xmlXPathEval(BAD_CAST remoteRequest->xpathExpression,
+                           (*remoteResponse)->xpathContext);
+        }
+    } else if ((*remoteResponse)->response_code != 200) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                     "HTTP response code %d",
+                     (int)(*remoteResponse)->response_code);
+
+        goto failure;
+    }
+
+    return 0;
+
+  failure:
+    free(virBufferContentAndReset(&buffer));
+    esxVI_RemoteResponse_Free(remoteResponse);
+    esxVI_Fault_Free(&fault);
+
+    return -1;
+
+  unlock:
+    virMutexUnlock(&ctx->curl_lock);
+
+    goto failure;
+}
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * RemoteResponse
+ */
+
+/* esxVI_RemoteResponse_Alloc */
+ESX_VI__TEMPLATE__ALLOC(RemoteResponse);
+
+/* esxVI_RemoteResponse_Free */
+ESX_VI__TEMPLATE__FREE(RemoteResponse,
+{
+    VIR_FREE(item->response);
+
+    xmlXPathFreeObject(item->xpathObject);
+    xmlXPathFreeContext(item->xpathContext);
+
+    if (item->document != NULL) {
+        xmlFreeDoc(item->document);
+    }
+});
+
+int
+esxVI_RemoteResponse_DeserializeXPathObject
+  (virConnectPtr conn, esxVI_RemoteResponse *remoteResponse,
+   esxVI_RemoteResponse_DeserializeFunc deserializeFunc, void **item)
+{
+    xmlNodePtr node = NULL;
+
+    if (remoteResponse->xpathObject != NULL &&
+        remoteResponse->xpathObject->type == XPATH_NODESET) {
+        if (remoteResponse->xpathObject->nodesetval->nodeNr != 1) {
+            ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                         "Expecting 1 XML node but found '%d'",
+                         remoteResponse->xpathObject->nodesetval->nodeNr);
+            return -1;
+        }
+
+        node = remoteResponse->xpathObject->nodesetval->nodeTab[0];
+
+        if (node->type != XML_ELEMENT_NODE) {
+            ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                         "Wrong XML element type %d", node->type);
+            return -1;
+        }
+
+        if (deserializeFunc(conn, node, item) < 0) {
+            return -1;
+        }
+    } else {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "XPath error");
+        return -1;
+    }
+
+    return 0;
+}
+
+int
+esxVI_RemoteResponse_DeserializeXPathObjectList
+  (virConnectPtr conn, esxVI_RemoteResponse *remoteResponse,
+   esxVI_RemoteResponse_DeserializeListFunc deserializeListFunc,
+   esxVI_List **list)
+{
+    xmlNodePtr node = NULL;
+
+    if (remoteResponse->xpathObject != NULL &&
+        remoteResponse->xpathObject->type == XPATH_NODESET) {
+        if (remoteResponse->xpathObject->nodesetval->nodeNr > 0) {
+            node = remoteResponse->xpathObject->nodesetval->nodeTab[0];
+
+            if (node->type != XML_ELEMENT_NODE) {
+                ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                             "Wrong XML element type %d", node->type);
+                return -1;
+            }
+        } else {
+            node = NULL;
+        }
+
+        if (deserializeListFunc(conn, node, list) < 0) {
+            return -1;
+        }
+    } else {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "XPath error");
+        return -1;
+    }
+
+    return 0;
+}
+
+int
+esxVI_RemoteResponse_DeserializeXPathObjectAsManagedObjectReference
+  (virConnectPtr conn, esxVI_RemoteResponse *remoteResponse,
+   esxVI_ManagedObjectReference **managedObjectReference,
+   const char *expectedType)
+{
+    xmlNodePtr node = NULL;
+
+    if (remoteResponse->xpathObject != NULL &&
+        remoteResponse->xpathObject->type == XPATH_NODESET) {
+        if (remoteResponse->xpathObject->nodesetval->nodeNr != 1) {
+            ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                         "Expecting 1 XML node but found '%d'",
+                         remoteResponse->xpathObject->nodesetval->nodeNr);
+            return -1;
+        }
+
+        node = remoteResponse->xpathObject->nodesetval->nodeTab[0];
+
+        if (node->type != XML_ELEMENT_NODE) {
+            ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                         "Wrong XML element type %d", node->type);
+            return -1;
+        }
+
+        if (esxVI_ManagedObjectReference_Deserialize(conn, node,
+                                                     managedObjectReference,
+                                                     expectedType) < 0) {
+            return -1;
+        }
+    } else {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "XPath error");
+        return -1;
+    }
+
+    return 0;
+}
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Enumeration
+ */
+
+int
+esxVI_Enumeration_CastFromAnyType(virConnectPtr conn,
+                                  const esxVI_Enumeration *enumeration,
+                                  esxVI_AnyType *anyType, int *value)
+{
+    int i;
+
+    if (anyType == NULL || value == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    *value = 0; /* undefined */
+
+    if (STRNEQ(anyType->other, enumeration->type)) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                     "Expecting type '%s' but found '%s'", enumeration->type,
+                     anyType->other);
+        return -1;
+    }
+
+    for (i = 0; enumeration->values[i].name != NULL; ++i) {
+        if (STREQ(anyType->value, enumeration->values[i].name)) {
+            *value = enumeration->values[i].value;
+            return 0;
+        }
+    }
+
+    ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                 "Unknown value '%s' for %s", anyType->value,
+                 enumeration->type);
+
+    return -1;
+}
+
+int
+esxVI_Enumeration_Serialize(virConnectPtr conn,
+                            const esxVI_Enumeration *enumeration,
+                            int value, const char *element,
+                            virBufferPtr output, esxVI_Boolean required)
+{
+    int i;
+    const char *name = NULL;
+
+    if (element == NULL || output == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    if (value == 0) { /* undefined */
+        return esxVI_CheckSerializationNecessity(conn, element, required);
+    }
+
+    for (i = 0; enumeration->values[i].name != NULL; ++i) {
+        if (value == enumeration->values[i].value) {
+            name = enumeration->values[i].name;
+            break;
+        }
+    }
+
+    if (name == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    ESV_VI__XML_TAG__OPEN(output, element, enumeration->type);
+
+    virBufferAdd(output, name, -1);
+
+    ESV_VI__XML_TAG__CLOSE(output, element);
+
+    return 0;
+}
+
+int
+esxVI_Enumeration_Deserialize(virConnectPtr conn,
+                              const esxVI_Enumeration *enumeration,
+                              xmlNodePtr node, int *value)
+{
+    int i;
+    int result = 0;
+    char *name = NULL;
+
+    if (value == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        goto failure;
+    }
+
+    *value = 0; /* undefined */
+
+    if (esxVI_String_DeserializeValue(conn, node, &name) < 0) {
+        goto failure;
+    }
+
+    for (i = 0; enumeration->values[i].name != NULL; ++i) {
+        if (STREQ(name, enumeration->values[i].name)) {
+            *value = enumeration->values[i].value;
+            goto cleanup;
+        }
+    }
+
+    ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Unknown value '%s' for %s",
+                 name, enumeration->type);
+
+  cleanup:
+    VIR_FREE(name);
+
+    return result;
+
+  failure:
+    goto cleanup;
+
+    result = -1;
+}
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * List
+ */
+
+int
+esxVI_List_Append(virConnectPtr conn, esxVI_List **list, esxVI_List *item)
+{
+    esxVI_List *next = NULL;
+
+    if (list == NULL || item == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    if (*list == NULL) {
+        *list = item;
+        return 0;
+    }
+
+    next = *list;
+
+    while (next->_next != NULL) {
+        next = next->_next;
+    }
+
+    next->_next = item;
+
+    return 0;
+}
+
+int
+esxVI_List_DeepCopy(virConnectPtr conn, esxVI_List **destList,
+                    esxVI_List *srcList,
+                    esxVI_List_DeepCopyFunc deepCopyFunc,
+                    esxVI_List_FreeFunc freeFunc)
+{
+    esxVI_List *dest = NULL;
+    esxVI_List *src = NULL;
+
+    if (destList == NULL || *destList != NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        goto failure;
+    }
+
+    for (src = srcList; src != NULL; src = src->_next) {
+        if (deepCopyFunc(conn, &dest, src) < 0 ||
+            esxVI_List_Append(conn, destList, dest) < 0) {
+            goto failure;
+        }
+
+        dest = NULL;
+    }
+
+    return 0;
+
+  failure:
+    freeFunc(&dest);
+    freeFunc(destList);
+
+    return -1;
+}
+
+int
+esxVI_List_Serialize(virConnectPtr conn, esxVI_List *list, const char *element,
+                     virBufferPtr output, esxVI_Boolean required,
+                     esxVI_List_SerializeFunc serializeFunc)
+{
+    esxVI_List *item = NULL;
+
+    if (element == NULL || output == NULL || serializeFunc == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    if (list == NULL) {
+        return esxVI_CheckSerializationNecessity(conn, element, required);
+    }
+
+    for (item = list; item != NULL; item = item->_next) {
+        if (serializeFunc(conn, item, element, output,
+                          esxVI_Boolean_True) < 0) {
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+int
+esxVI_List_Deserialize(virConnectPtr conn, xmlNodePtr node, esxVI_List **list,
+                       esxVI_List_DeserializeFunc deserializeFunc,
+                       esxVI_List_FreeFunc freeFunc)
+{
+    esxVI_List *item = NULL;
+
+    if (list == NULL || *list != NULL ||
+        deserializeFunc == NULL || freeFunc == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    if (node == NULL) {
+        return 0;
+    }
+
+    for (; node != NULL; node = node->next) {
+        if (node->type != XML_ELEMENT_NODE) {
+            ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                         "Wrong XML element type %d", node->type);
+            goto failure;
+        }
+
+        item = NULL;
+
+        if (deserializeFunc(conn, node, &item) < 0) {
+            goto failure;
+        }
+
+        if (esxVI_List_Append(conn, list, item) < 0) {
+            goto failure;
+        }
+    }
+
+    return 0;
+
+  failure:
+    freeFunc(list);
+
+    return -1;
+}
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Utility and Convenience Functions
+ */
+
+int
+esxVI_Alloc(virConnectPtr conn, void **ptrptr, size_t size)
+{
+    if (ptrptr == NULL || *ptrptr != NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    if (virAllocN(ptrptr, size, 1) < 0) {
+        virReportOOMError(conn);
+        return -1;
+    }
+
+    return 0;
+}
+
+int
+esxVI_CheckSerializationNecessity(virConnectPtr conn, const char *element,
+                                  esxVI_Boolean required)
+{
+    if (element == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    if (required == esxVI_Boolean_True) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                     "Required property missing while trying to serialize "
+                     "'%s'", element);
+        return -1;
+    } else {
+        return 0;
+    }
+}
+
+
+
+int
+esxVI_BuildFullTraversalSpecItem(virConnectPtr conn,
+                                 esxVI_SelectionSpec **fullTraversalSpecList,
+                                 const char *name, const char *type,
+                                 const char *path, const char *selectSetNames)
+{
+    esxVI_TraversalSpec *traversalSpec = NULL;
+    esxVI_SelectionSpec *selectionSpec = NULL;
+    const char *currentSelectSetName = NULL;
+
+    if (fullTraversalSpecList == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    if (esxVI_TraversalSpec_Alloc(conn, &traversalSpec) < 0 ||
+        esxVI_String_DeepCopyValue(conn, &traversalSpec->_base->name,
+                                   name) < 0 ||
+        esxVI_String_DeepCopyValue(conn, &traversalSpec->type, type) < 0 ||
+        esxVI_String_DeepCopyValue(conn, &traversalSpec->path, path) < 0) {
+        goto failure;
+    }
+
+    traversalSpec->skip = esxVI_Boolean_False;
+
+    if (selectSetNames != NULL) {
+        currentSelectSetName = selectSetNames;
+
+        while (currentSelectSetName != NULL && *currentSelectSetName != '\0') {
+            selectionSpec = NULL;
+
+            if (esxVI_SelectionSpec_Alloc(conn, &selectionSpec) < 0 ||
+                esxVI_String_DeepCopyValue(conn, &selectionSpec->name,
+                                           currentSelectSetName) < 0 ||
+                esxVI_SelectionSpec_AppendToList(conn,
+                                                 &traversalSpec->selectSet,
+                                                 selectionSpec) < 0) {
+                goto failure;
+            }
+
+            currentSelectSetName += strlen(currentSelectSetName) + 1;
+        }
+    }
+
+    if (esxVI_SelectionSpec_AppendToList(conn, fullTraversalSpecList,
+                                         traversalSpec->_base) < 0) {
+        goto failure;
+    }
+
+    return 0;
+
+  failure:
+    esxVI_TraversalSpec_Free(&traversalSpec);
+
+    return -1;
+}
+
+
+
+int
+esxVI_BuildFullTraversalSpecList(virConnectPtr conn,
+                                 esxVI_SelectionSpec **fullTraversalSpecList)
+{
+    if (fullTraversalSpecList == NULL || *fullTraversalSpecList != NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    if (esxVI_BuildFullTraversalSpecItem(conn, fullTraversalSpecList,
+                                         "visitFolders",
+                                         "Folder", "childEntity",
+                                         "visitFolders\0"
+                                         "datacenterToVmFolder\0"
+                                         "datacenterToHostFolder\0"
+                                         "computeResourceToHost\0"
+                                         "computeResourceToResourcePool\0"
+                                         "HostSystemToVm\0"
+                                         "resourcePoolToVm\0") < 0) {
+        goto failure;
+    }
+
+    /* Traversal through vmFolder branch */
+    if (esxVI_BuildFullTraversalSpecItem(conn, fullTraversalSpecList,
+                                         "datacenterToVmFolder",
+                                         "Datacenter", "vmFolder",
+                                         "visitFolders\0") < 0) {
+        goto failure;
+    }
+
+    /* Traversal through hostFolder branch  */
+    if (esxVI_BuildFullTraversalSpecItem(conn, fullTraversalSpecList,
+                                         "datacenterToHostFolder",
+                                         "Datacenter", "hostFolder",
+                                         "visitFolders\0") < 0) {
+        goto failure;
+    }
+
+    /* Traversal through host branch  */
+    if (esxVI_BuildFullTraversalSpecItem(conn, fullTraversalSpecList,
+                                         "computeResourceToHost",
+                                         "ComputeResource", "host",
+                                         NULL) < 0) {
+        goto failure;
+    }
+
+    /* Traversal through resourcePool branch */
+    if (esxVI_BuildFullTraversalSpecItem(conn, fullTraversalSpecList,
+                                         "computeResourceToResourcePool",
+                                         "ComputeResource", "resourcePool",
+                                         "resourcePoolToResourcePool\0"
+                                         "resourcePoolToVm\0") < 0) {
+        goto failure;
+    }
+
+    /* Recurse through all resource pools */
+    if (esxVI_BuildFullTraversalSpecItem(conn, fullTraversalSpecList,
+                                         "resourcePoolToResourcePool",
+                                         "ResourcePool", "resourcePool",
+                                         "resourcePoolToResourcePool\0"
+                                         "resourcePoolToVm\0") < 0) {
+        goto failure;
+    }
+
+    /* Recurse through all hosts */
+    if (esxVI_BuildFullTraversalSpecItem(conn, fullTraversalSpecList,
+                                         "HostSystemToVm",
+                                         "HostSystem", "vm",
+                                         "visitFolders\0") < 0) {
+        goto failure;
+    }
+
+    /* Recurse through all resource pools */
+    if (esxVI_BuildFullTraversalSpecItem(conn, fullTraversalSpecList,
+                                         "resourcePoolToVm",
+                                         "ResourcePool", "vm", NULL) < 0) {
+        goto failure;
+    }
+
+    return 0;
+
+  failure:
+    esxVI_SelectionSpec_Free(fullTraversalSpecList);
+
+    return -1;
+}
+
+
+
+/*
+ * Can't use the SessionIsActive() function here, because at least
+ * 'ESX Server 3.5.0 build-64607' returns an 'method not implemented' fault if
+ * you try to call it. Query the session manager for the current session of
+ * this connection instead and re-login if there is no current session for this
+ * connection.
+ */
+#define ESX_VI_USE_SESSION_IS_ACTIVE 0
+
+int
+esxVI_EnsureSession(virConnectPtr conn, esxVI_Context *ctx)
+{
+    int result = 0;
+#if ESX_VI_USE_SESSION_IS_ACTIVE
+    esxVI_Boolean active = esxVI_Boolean_Undefined;
+#else
+    esxVI_String *propertyNameList = NULL;
+    esxVI_ObjectContent *sessionManager = NULL;
+    esxVI_DynamicProperty *dynamicProperty = NULL;
+    esxVI_UserSession *currentSession = NULL;
+#endif
+
+    if (ctx->session == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid call");
+        return -1;
+    }
+
+#if ESX_VI_USE_SESSION_IS_ACTIVE
+    if (esxVI_SessionIsActive(conn, ctx, ctx->session->key,
+                              ctx->session->userName, &active) < 0) {
+        return -1;
+    }
+
+    if (active != esxVI_Boolean_True) {
+        esxVI_UserSession_Free(&ctx->session);
+
+        if (esxVI_Login(conn, ctx, ctx->username, ctx->password,
+                        &ctx->session) < 0) {
+            return -1;
+        }
+    }
+#else
+    if (esxVI_String_AppendValueToList(conn, &propertyNameList,
+                                       "currentSession") < 0 ||
+        esxVI_GetObjectContent(conn, ctx, ctx->service->sessionManager,
+                               "SessionManager", propertyNameList,
+                               esxVI_Boolean_False, &sessionManager) < 0) {
+        goto failure;
+    }
+
+    for (dynamicProperty = sessionManager->propSet; dynamicProperty != NULL;
+         dynamicProperty = dynamicProperty->_next) {
+        if (STREQ(dynamicProperty->name, "currentSession")) {
+            if (esxVI_UserSession_CastFromAnyType(conn, dynamicProperty->val,
+                                                  &currentSession) < 0) {
+                goto failure;
+            }
+
+            break;
+        } else {
+            VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
+        }
+    }
+
+    if (currentSession == NULL) {
+        esxVI_UserSession_Free(&ctx->session);
+
+        if (esxVI_Login(conn, ctx, ctx->username, ctx->password,
+                        &ctx->session) < 0) {
+            goto failure;
+        }
+    } else if (STRNEQ(ctx->session->key, currentSession->key)) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                     "Key of the current session differs from the key at "
+                     "last login");
+        goto failure;
+    }
+#endif
+
+  cleanup:
+#if ESX_VI_USE_SESSION_IS_ACTIVE
+    /* nothing */
+#else
+    esxVI_String_Free(&propertyNameList);
+    esxVI_ObjectContent_Free(&sessionManager);
+    esxVI_UserSession_Free(&currentSession);
+#endif
+
+    return result;
+
+  failure:
+    result = -1;
+
+    goto cleanup;
+
+    return 0;
+}
+
+
+
+int
+esxVI_GetObjectContent(virConnectPtr conn, esxVI_Context *ctx,
+                       esxVI_ManagedObjectReference *root,
+                       const char *type, esxVI_String *propertyNameList,
+                       esxVI_Boolean recurse,
+                       esxVI_ObjectContent **objectContentList)
+{
+    int result = 0;
+    esxVI_ObjectSpec *objectSpec = NULL;
+    esxVI_PropertySpec *propertySpec = NULL;
+    esxVI_PropertyFilterSpec *propertyFilterSpec = NULL;
+
+    if (ctx->fullTraversalSpecList == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid call");
+        return -1;
+    }
+
+    if (esxVI_ObjectSpec_Alloc(conn, &objectSpec) < 0) {
+        goto failure;
+    }
+
+    objectSpec->obj = root;
+    objectSpec->skip = esxVI_Boolean_False;
+
+    if (recurse == esxVI_Boolean_True) {
+        objectSpec->selectSet = ctx->fullTraversalSpecList;
+    }
+
+    if (esxVI_PropertySpec_Alloc(conn, &propertySpec) < 0) {
+        goto failure;
+    }
+
+    propertySpec->type = (char *)type;
+    propertySpec->pathSet = propertyNameList;
+
+    if (esxVI_PropertyFilterSpec_Alloc(conn, &propertyFilterSpec) < 0 ||
+        esxVI_PropertySpec_AppendToList(conn, &propertyFilterSpec->propSet,
+                                        propertySpec) < 0 ||
+        esxVI_ObjectSpec_AppendToList(conn, &propertyFilterSpec->objectSet,
+                                      objectSpec) < 0) {
+        goto failure;
+    }
+
+    result = esxVI_RetrieveProperties(conn, ctx, propertyFilterSpec,
+                                      objectContentList);
+
+  cleanup:
+    /*
+     * Remove values given by the caller from the data structures to prevent
+     * them from being freed by the call to esxVI_PropertyFilterSpec_Free().
+     */
+    if (objectSpec != NULL) {
+        objectSpec->obj = NULL;
+        objectSpec->selectSet = NULL;
+    }
+
+    if (propertySpec != NULL) {
+        propertySpec->type = NULL;
+        propertySpec->pathSet = NULL;
+    }
+
+    esxVI_PropertyFilterSpec_Free(&propertyFilterSpec);
+
+    return result;
+
+  failure:
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+int
+esxVI_GetVirtualMachinePowerState(virConnectPtr conn,
+                                  esxVI_ObjectContent *virtualMachine,
+                                  esxVI_VirtualMachinePowerState *powerState)
+{
+    esxVI_DynamicProperty *dynamicProperty;
+
+    for (dynamicProperty = virtualMachine->propSet; dynamicProperty != NULL;
+         dynamicProperty = dynamicProperty->_next) {
+        if (STREQ(dynamicProperty->name, "runtime.powerState")) {
+            return esxVI_VirtualMachinePowerState_CastFromAnyType
+                     (conn, dynamicProperty->val, powerState);
+        }
+    }
+
+    ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                 "Missing 'runtime.powerState' property");
+
+    return -1;
+}
+
+
+
+int
+esxVI_GetNumberOfDomainsByPowerState(virConnectPtr conn, esxVI_Context *ctx,
+                                     esxVI_VirtualMachinePowerState powerState,
+                                     esxVI_Boolean inverse)
+{
+    esxVI_String *propertyNameList = NULL;
+    esxVI_ObjectContent *virtualMachineList = NULL;
+    esxVI_ObjectContent *virtualMachine = NULL;
+    esxVI_DynamicProperty *dynamicProperty = NULL;
+    esxVI_VirtualMachinePowerState powerState_;
+    int numberOfDomains = 0;
+
+    if (esxVI_String_AppendValueToList(conn, &propertyNameList,
+                                       "runtime.powerState") < 0 ||
+        esxVI_GetObjectContent(conn, ctx, ctx->vmFolder, "VirtualMachine",
+                               propertyNameList, esxVI_Boolean_True,
+                               &virtualMachineList) < 0) {
+        goto failure;
+    }
+
+    for (virtualMachine = virtualMachineList; virtualMachine != NULL;
+         virtualMachine = virtualMachine->_next) {
+        for (dynamicProperty = virtualMachine->propSet;
+             dynamicProperty != NULL;
+             dynamicProperty = dynamicProperty->_next) {
+            if (STREQ(dynamicProperty->name, "runtime.powerState")) {
+                if (esxVI_VirtualMachinePowerState_CastFromAnyType
+                      (conn, dynamicProperty->val, &powerState_) < 0) {
+                    goto failure;
+                }
+
+                if ((inverse != esxVI_Boolean_True &&
+                     powerState_ == powerState) ||
+                    (inverse == esxVI_Boolean_True &&
+                     powerState_ != powerState)) {
+                    numberOfDomains++;
+                }
+            } else {
+                VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
+            }
+        }
+    }
+
+  cleanup:
+    esxVI_String_Free(&propertyNameList);
+    esxVI_ObjectContent_Free(&virtualMachineList);
+
+    return numberOfDomains;
+
+  failure:
+    numberOfDomains = -1;
+
+    goto cleanup;
+}
+
+
+
+int
+esxVI_GetVirtualMachineIdentity(virConnectPtr conn,
+                                esxVI_ObjectContent *virtualMachine,
+                                int *id, char **name, unsigned char *uuid)
+{
+    const char *uuid_string = NULL;
+    esxVI_DynamicProperty *dynamicProperty = NULL;
+
+    if (STRNEQ(virtualMachine->obj->type, "VirtualMachine")) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                     "ObjectContent does not reference a virtual machine");
+        return -1;
+    }
+
+    if (id != NULL) {
+        if (esxUtil_ParseVirtualMachineIDString
+              (virtualMachine->obj->value, id) < 0 || *id <= 0) {
+            ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                         "Could not parse positive integer from '%s'",
+                         virtualMachine->obj->value);
+            goto failure;
+        }
+    }
+
+    if (name != NULL) {
+        if (*name != NULL) {
+            ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+            goto failure;
+        }
+
+        for (dynamicProperty = virtualMachine->propSet;
+             dynamicProperty != NULL;
+             dynamicProperty = dynamicProperty->_next) {
+            if (STREQ(dynamicProperty->name, "name")) {
+                if (esxVI_AnyType_ExpectType(conn, dynamicProperty->val,
+                                             esxVI_Type_String) < 0) {
+                    goto failure;
+                }
+
+                *name = strdup(dynamicProperty->val->string);
+
+                if (*name == NULL) {
+                    virReportOOMError(conn);
+                    goto failure;
+                }
+
+                break;
+            }
+        }
+
+        if (*name == NULL) {
+            ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                         "Could not get name of virtual machine");
+            goto failure;
+        }
+    }
+
+    if (uuid != NULL) {
+        for (dynamicProperty = virtualMachine->propSet;
+             dynamicProperty != NULL;
+             dynamicProperty = dynamicProperty->_next) {
+            if (STREQ(dynamicProperty->name, "summary.config.uuid")) {
+                if (esxVI_AnyType_ExpectType(conn, dynamicProperty->val,
+                                             esxVI_Type_String) < 0) {
+                    goto failure;
+                }
+
+                uuid_string = dynamicProperty->val->string;
+                break;
+            }
+        }
+
+        if (uuid_string == NULL) {
+            ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                         "Could not get UUID of virtual machine");
+            goto failure;
+        }
+
+        if (virUUIDParse(uuid_string, uuid) < 0) {
+            ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                         "Could not parse UUID from string '%s'", uuid_string);
+            goto failure;
+        }
+    }
+
+    return 0;
+
+  failure:
+    if (name != NULL) {
+        VIR_FREE(*name);
+    }
+
+    return -1;
+}
+
+
+
+int
+esxVI_LookupHostSystemByIp(virConnectPtr conn, esxVI_Context *ctx,
+                           const char *ip, esxVI_String *propertyNameList,
+                           esxVI_ObjectContent **hostSystem)
+{
+    int result = 0;
+    esxVI_ManagedObjectReference *managedObjectReference = NULL;
+
+    if (hostSystem == NULL || *hostSystem != NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    if (esxVI_FindByIp(conn, ctx, ctx->datacenter, ip, esxVI_Boolean_False,
+                       &managedObjectReference) < 0) {
+        goto failure;
+    }
+
+    if (esxVI_GetObjectContent(conn, ctx, managedObjectReference,
+                               "HostSystem", propertyNameList,
+                               esxVI_Boolean_False, hostSystem) < 0) {
+        goto failure;
+    }
+
+  cleanup:
+    esxVI_ManagedObjectReference_Free(&managedObjectReference);
+
+    return result;
+
+  failure:
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+int
+esxVI_LookupVirtualMachineByUuid(virConnectPtr conn, esxVI_Context *ctx,
+                                 const unsigned char *uuid,
+                                 esxVI_String *propertyNameList,
+                                 esxVI_ObjectContent **virtualMachine)
+{
+    int result = 0;
+    esxVI_ManagedObjectReference *managedObjectReference = NULL;
+
+    if (virtualMachine == NULL || *virtualMachine != NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    if (esxVI_FindByUuid(conn, ctx, ctx->datacenter, uuid, esxVI_Boolean_True,
+                         &managedObjectReference) < 0) {
+        goto failure;
+    }
+
+    if (esxVI_GetObjectContent(conn, ctx, managedObjectReference,
+                               "VirtualMachine", propertyNameList,
+                               esxVI_Boolean_False, virtualMachine) < 0) {
+        goto failure;
+    }
+
+  cleanup:
+    esxVI_ManagedObjectReference_Free(&managedObjectReference);
+
+    return result;
+
+  failure:
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+int
+esxVI_StartVirtualMachineTask(virConnectPtr conn, esxVI_Context *ctx,
+                              const char *name, const char *request,
+                              esxVI_ManagedObjectReference **task)
+{
+    int result = 0;
+    esxVI_RemoteRequest *remoteRequest = NULL;
+    esxVI_RemoteResponse *remoteResponse = NULL;
+
+    if (esxVI_RemoteRequest_Alloc(conn, &remoteRequest) < 0) {
+        goto failure;
+    }
+
+    remoteRequest->request = (char *)request;
+
+    if (virAsprintf(&remoteRequest->xpathExpression,
+                    ESX_VI__SOAP__RESPONSE_XPATH("%s_Task"), name) < 0) {
+        virReportOOMError(conn);
+        goto failure;
+    }
+
+    if (esxVI_RemoteRequest_Execute(conn, ctx, remoteRequest,
+                                    &remoteResponse) < 0 ||
+        esxVI_RemoteResponse_DeserializeXPathObjectAsManagedObjectReference
+          (conn, remoteResponse, task, "Task") < 0) {
+        goto failure;
+    }
+
+  cleanup:
+    /*
+     * Remove values given by the caller from the data structures to prevent
+     * them from being freed by the call to esxVI_RemoteRequest_Free().
+     */
+    if (remoteRequest != NULL) {
+        remoteRequest->request = NULL;
+    }
+
+    esxVI_RemoteRequest_Free(&remoteRequest);
+    esxVI_RemoteResponse_Free(&remoteResponse);
+
+    return result;
+
+  failure:
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+int
+esxVI_StartSimpleVirtualMachineTask
+  (virConnectPtr conn, esxVI_Context *ctx, const char *name,
+   esxVI_ManagedObjectReference *virtualMachine,
+   esxVI_ManagedObjectReference **task)
+{
+    int result = 0;
+    virBuffer buffer = VIR_BUFFER_INITIALIZER;
+    char *request = NULL;
+
+    virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_HEADER);
+    virBufferAddLit(&buffer, "<");
+    virBufferAdd(&buffer, name, -1);
+    virBufferAddLit(&buffer, "_Task xmlns=\"urn:vim25\">");
+
+    if (esxVI_ManagedObjectReference_Serialize(conn, virtualMachine, "_this",
+                                               &buffer,
+                                               esxVI_Boolean_True) < 0) {
+        goto failure;
+    }
+
+    virBufferAddLit(&buffer, "</");
+    virBufferAdd(&buffer, name, -1);
+    virBufferAddLit(&buffer, "_Task>");
+    virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_FOOTER);
+
+    if (virBufferError(&buffer)) {
+        virReportOOMError(conn);
+        goto failure;
+    }
+
+    request = virBufferContentAndReset(&buffer);
+
+    if (esxVI_StartVirtualMachineTask(conn, ctx, name, request, task) < 0) {
+        goto failure;
+    }
+
+  cleanup:
+    VIR_FREE(request);
+
+    return result;
+
+  failure:
+    free(virBufferContentAndReset(&buffer));
+
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+int
+esxVI_SimpleVirtualMachineMethod(virConnectPtr conn, esxVI_Context *ctx,
+                                const char *name,
+                                esxVI_ManagedObjectReference *virtualMachine)
+{
+    int result = 0;
+    esxVI_RemoteRequest *remoteRequest = NULL;
+    esxVI_RemoteResponse *remoteResponse = NULL;
+    virBuffer buffer = VIR_BUFFER_INITIALIZER;
+
+    if (ctx->service == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_HEADER);
+    virBufferAddLit(&buffer, "<");
+    virBufferAdd(&buffer, name, -1);
+    virBufferAddLit(&buffer, " xmlns=\"urn:vim25\">");
+
+    if (esxVI_RemoteRequest_Alloc(conn, &remoteRequest) < 0 ||
+        esxVI_ManagedObjectReference_Serialize(conn, virtualMachine, "_this",
+                                               &buffer,
+                                               esxVI_Boolean_True) < 0) {
+        goto failure;
+    }
+
+    virBufferAddLit(&buffer, "</");
+    virBufferAdd(&buffer, name, -1);
+    virBufferAddLit(&buffer, ">");
+    virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_FOOTER);
+
+    if (virBufferError(&buffer)) {
+        virReportOOMError(conn);
+        goto failure;
+    }
+
+    remoteRequest->request = virBufferContentAndReset(&buffer);
+
+    if (esxVI_RemoteRequest_Execute(conn, ctx, remoteRequest,
+                                    &remoteResponse) < 0) {
+        goto failure;
+    }
+
+  cleanup:
+    esxVI_RemoteRequest_Free(&remoteRequest);
+    esxVI_RemoteResponse_Free(&remoteResponse);
+
+    return result;
+
+  failure:
+    free(virBufferContentAndReset(&buffer));
+
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+int
+esxVI_WaitForTaskCompletion(virConnectPtr conn, esxVI_Context *ctx,
+                            esxVI_ManagedObjectReference *task,
+                            esxVI_TaskInfoState *finalState)
+{
+    int result = 0;
+    esxVI_ObjectSpec *objectSpec = NULL;
+    esxVI_PropertySpec *propertySpec = NULL;
+    esxVI_PropertyFilterSpec *propertyFilterSpec = NULL;
+    esxVI_ManagedObjectReference *propertyFilter = NULL;
+    char *version = NULL;
+    esxVI_UpdateSet *updateSet = NULL;
+    esxVI_PropertyFilterUpdate *propertyFilterUpdate = NULL;
+    esxVI_ObjectUpdate *objectUpdate = NULL;
+    esxVI_PropertyChange *propertyChange = NULL;
+    esxVI_AnyType *propertyValue = NULL;
+    esxVI_TaskInfoState state = esxVI_TaskInfoState_Undefined;
+
+    version = strdup("");
+
+    if (version == NULL) {
+        virReportOOMError(conn);
+        goto failure;
+    }
+
+    if (esxVI_ObjectSpec_Alloc(conn, &objectSpec) < 0) {
+        goto failure;
+    }
+
+    objectSpec->obj = task;
+    objectSpec->skip = esxVI_Boolean_False;
+
+    if (esxVI_PropertySpec_Alloc(conn, &propertySpec) < 0) {
+        goto failure;
+    }
+
+    propertySpec->type = task->type;
+
+    if (esxVI_String_AppendValueToList(conn, &propertySpec->pathSet,
+                                       "info.state") < 0 ||
+        esxVI_PropertyFilterSpec_Alloc(conn, &propertyFilterSpec) < 0 ||
+        esxVI_PropertySpec_AppendToList(conn, &propertyFilterSpec->propSet,
+                                        propertySpec) < 0 ||
+        esxVI_ObjectSpec_AppendToList(conn, &propertyFilterSpec->objectSet,
+                                      objectSpec) < 0 ||
+        esxVI_CreateFilter(conn, ctx, propertyFilterSpec, esxVI_Boolean_True,
+                           &propertyFilter) < 0) {
+        goto failure;
+    }
+
+    while (state != esxVI_TaskInfoState_Success &&
+           state != esxVI_TaskInfoState_Error) {
+        esxVI_UpdateSet_Free(&updateSet);
+
+        if (esxVI_WaitForUpdates(conn, ctx, version, &updateSet) < 0) {
+            goto failure;
+        }
+
+        VIR_FREE(version);
+        version = strdup(updateSet->version);
+
+        if (version == NULL) {
+            virReportOOMError(conn);
+            goto failure;
+        }
+
+        if (updateSet->filterSet == NULL) {
+            continue;
+        }
+
+        for (propertyFilterUpdate = updateSet->filterSet;
+             propertyFilterUpdate != NULL;
+             propertyFilterUpdate = propertyFilterUpdate->_next) {
+            for (objectUpdate = propertyFilterUpdate->objectSet;
+                 objectUpdate != NULL; objectUpdate = objectUpdate->_next) {
+                for (propertyChange = objectUpdate->changeSet;
+                     propertyChange != NULL;
+                     propertyChange = propertyChange->_next) {
+                    if (STREQ(propertyChange->name, "info.state")) {
+                        if (propertyChange->op == esxVI_PropertyChangeOp_Add ||
+                            propertyChange->op == esxVI_PropertyChangeOp_Assign) {
+                            propertyValue = propertyChange->val;
+                        } else {
+                            propertyValue = NULL;
+                        }
+                    }
+                }
+            }
+        }
+
+        if (propertyValue == NULL) {
+            continue;
+        }
+
+        if (esxVI_TaskInfoState_CastFromAnyType(conn, propertyValue,
+                                                &state) < 0) {
+            goto failure;
+        }
+    }
+
+    if (esxVI_DestroyPropertyFilter(conn, ctx, propertyFilter) < 0) {
+        VIR_DEBUG0("DestroyPropertyFilter failed");
+    }
+
+    if (esxVI_TaskInfoState_CastFromAnyType(conn, propertyValue,
+                                            finalState) < 0) {
+        goto failure;
+    }
+
+  cleanup:
+    /*
+     * Remove values given by the caller from the data structures to prevent
+     * them from being freed by the call to esxVI_PropertyFilterSpec_Free().
+     */
+    if (objectSpec != NULL) {
+        objectSpec->obj = NULL;
+    }
+
+    if (propertySpec != NULL) {
+        propertySpec->type = NULL;
+    }
+
+    esxVI_PropertyFilterSpec_Free(&propertyFilterSpec);
+    esxVI_ManagedObjectReference_Free(&propertyFilter);
+    VIR_FREE(version);
+    esxVI_UpdateSet_Free(&updateSet);
+
+    return result;
+
+  failure:
+    result = -1;
+
+    goto cleanup;
+}
diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h
new file mode 100644
index 0000000..a9343fb
--- /dev/null
+++ b/src/esx/esx_vi.h
@@ -0,0 +1,251 @@
+
+/*
+ * esx_vi.h: client for the VMware VI API 2.5 to manage ESX hosts
+ *
+ * Copyright (C) 2009 Matthias Bolte <matthias.bolte@xxxxxxxxxxxxxx>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ */
+
+#ifndef __ESX_VI_H__
+#define __ESX_VI_H__
+
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+#include <curl/curl.h>
+
+#include "internal.h"
+#include "datatypes.h"
+#include "esx_vi_types.h"
+
+typedef struct _esxVI_Context esxVI_Context;
+typedef struct _esxVI_RemoteResponse esxVI_RemoteResponse;
+typedef struct _esxVI_RemoteRequest esxVI_RemoteRequest;
+typedef struct _esxVI_Enumeration esxVI_Enumeration;
+typedef struct _esxVI_EnumerationValue esxVI_EnumerationValue;
+typedef struct _esxVI_List esxVI_List;
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Context
+ */
+
+struct _esxVI_Context {
+    char *url;
+    CURL *curl_handle;
+    struct curl_slist *curl_headers;
+    virMutex curl_lock;
+    char *username;
+    char *password;
+    esxVI_ServiceContent *service;
+    esxVI_UserSession *session;
+    esxVI_ManagedObjectReference *datacenter;
+    esxVI_ManagedObjectReference *vmFolder;
+    esxVI_ManagedObjectReference *hostFolder;
+    esxVI_SelectionSpec *fullTraversalSpecList;
+};
+
+int esxVI_Context_Alloc(virConnectPtr conn, esxVI_Context **ctx);
+void esxVI_Context_Free(esxVI_Context **ctx);
+int esxVI_Context_Connect(virConnectPtr conn, esxVI_Context *ctx,
+                          const char *url, const char *username,
+                          const char *password);
+int esxVI_Context_Download(virConnectPtr conn, esxVI_Context *ctx,
+                           const char *url, char **content);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * RemoteRequest
+ */
+
+struct _esxVI_RemoteRequest {
+    char *request;                                    /* required */
+    char *xpathExpression;                            /* optional */
+};
+
+int esxVI_RemoteRequest_Alloc(virConnectPtr conn,
+                              esxVI_RemoteRequest **remoteRequest);
+void esxVI_RemoteRequest_Free(esxVI_RemoteRequest **remoteRequest);
+int esxVI_RemoteRequest_Execute(virConnectPtr conn, esxVI_Context *ctx,
+                                esxVI_RemoteRequest *remoteRequest,
+                                esxVI_RemoteResponse **remoteResponse);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * RemoteResponse
+ */
+
+struct _esxVI_RemoteResponse {
+    long response_code;                               /* required */
+    char *response;                                   /* required */
+    xmlDocPtr document;                               /* optional */
+    xmlXPathContextPtr xpathContext;                  /* optional */
+    xmlXPathObjectPtr xpathObject;                    /* optional */
+};
+
+typedef int (*esxVI_RemoteResponse_DeserializeFunc) (virConnectPtr conn,
+                                                     xmlNodePtr node,
+                                                     void **item);
+typedef int (*esxVI_RemoteResponse_DeserializeListFunc) (virConnectPtr conn,
+                                                         xmlNodePtr node,
+                                                         esxVI_List **list);
+
+int esxVI_RemoteResponse_Alloc(virConnectPtr conn,
+                               esxVI_RemoteResponse **remoteResponse);
+void esxVI_RemoteResponse_Free(esxVI_RemoteResponse **remoteResponse);
+int esxVI_RemoteResponse_DeserializeXPathObject
+      (virConnectPtr conn, esxVI_RemoteResponse *remoteResponse,
+       esxVI_RemoteResponse_DeserializeFunc deserializeFunc, void **item);
+int esxVI_RemoteResponse_DeserializeXPathObjectList
+      (virConnectPtr conn, esxVI_RemoteResponse *remoteResponse,
+       esxVI_RemoteResponse_DeserializeListFunc deserializeListFunc,
+       esxVI_List **list);
+int esxVI_RemoteResponse_DeserializeXPathObjectAsManagedObjectReference
+    (virConnectPtr conn, esxVI_RemoteResponse *remoteResponse,
+     esxVI_ManagedObjectReference **managedObjectReference,
+     const char *expectedType);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Enumeration
+ */
+
+struct _esxVI_EnumerationValue {
+    const char *name;
+    int value;
+};
+
+struct _esxVI_Enumeration {
+    const char *type;
+    esxVI_EnumerationValue values[10];
+};
+
+int esxVI_Enumeration_CastFromAnyType(virConnectPtr conn,
+                                      const esxVI_Enumeration *enumeration,
+                                      esxVI_AnyType *anyType, int *boolean);
+int esxVI_Enumeration_Serialize(virConnectPtr conn,
+                                const esxVI_Enumeration *enumeration,
+                                int value, const char *element,
+                                virBufferPtr output, esxVI_Boolean required);
+int esxVI_Enumeration_Deserialize(virConnectPtr conn,
+                                  const esxVI_Enumeration *enumeration,
+                                  xmlNodePtr node, int *value);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * List
+ */
+
+struct _esxVI_List {
+    esxVI_List *_next;
+};
+
+typedef int (*esxVI_List_FreeFunc) (esxVI_List **item);
+typedef int (*esxVI_List_DeepCopyFunc) (virConnectPtr conn, esxVI_List **dest,
+                                        esxVI_List *src);
+typedef int (*esxVI_List_SerializeFunc) (virConnectPtr conn, esxVI_List *item,
+                                         const char *element,
+                                         virBufferPtr output,
+                                         esxVI_Boolean required);
+typedef int (*esxVI_List_DeserializeFunc) (virConnectPtr conn, xmlNodePtr node,
+                                           esxVI_List **item);
+
+int esxVI_List_Append(virConnectPtr conn, esxVI_List **list, esxVI_List *item);
+int esxVI_List_DeepCopy(virConnectPtr conn, esxVI_List **destList,
+                        esxVI_List *srcList,
+                        esxVI_List_DeepCopyFunc deepCopyFunc,
+                        esxVI_List_FreeFunc freeFunc);
+int esxVI_List_Serialize(virConnectPtr conn, esxVI_List *list,
+                         const char *element, virBufferPtr output,
+                         esxVI_Boolean required,
+                         esxVI_List_SerializeFunc serializeFunc);
+int esxVI_List_Deserialize(virConnectPtr conn, xmlNodePtr node,
+                           esxVI_List **list,
+                           esxVI_List_DeserializeFunc deserializeFunc,
+                           esxVI_List_FreeFunc freeFunc);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Utility and Convenience Functions
+ */
+
+int
+esxVI_Alloc(virConnectPtr conn, void **ptrptr, size_t size);
+
+int
+esxVI_CheckSerializationNecessity(virConnectPtr conn, const char *element,
+                                  esxVI_Boolean required);
+
+int esxVI_BuildFullTraversalSpecItem
+      (virConnectPtr conn, esxVI_SelectionSpec **fullTraversalSpecList,
+       const char *name, const char *type, const char *path,
+       const char *selectSetNames);
+int esxVI_BuildFullTraversalSpecList
+      (virConnectPtr conn, esxVI_SelectionSpec **fullTraversalSpecList);
+
+int esxVI_EnsureSession(virConnectPtr conn, esxVI_Context *ctx);
+
+int esxVI_GetObjectContent(virConnectPtr conn, esxVI_Context *ctx,
+                           esxVI_ManagedObjectReference *root,
+                           const char *type, esxVI_String *propertyNameList,
+                           esxVI_Boolean recurse,
+                           esxVI_ObjectContent **objectContentList);
+
+int esxVI_GetVirtualMachinePowerState
+      (virConnectPtr conn, esxVI_ObjectContent *virtualMachine,
+       esxVI_VirtualMachinePowerState *powerState);
+
+int esxVI_GetNumberOfDomainsByPowerState
+      (virConnectPtr conn, esxVI_Context *ctx,
+       esxVI_VirtualMachinePowerState powerState, esxVI_Boolean inverse);
+
+int esxVI_GetVirtualMachineIdentity(virConnectPtr conn,
+                                    esxVI_ObjectContent *virtualMachine,
+                                    int *id, char **name, unsigned char *uuid);
+
+int esxVI_LookupHostSystemByIp(virConnectPtr conn, esxVI_Context *ctx,
+                               const char *ip, esxVI_String *propertyNameList,
+                               esxVI_ObjectContent **hostSystem);
+
+int esxVI_LookupVirtualMachineByUuid(virConnectPtr conn, esxVI_Context *ctx,
+                                     const unsigned char *uuid,
+                                     esxVI_String *propertyNameList,
+                                     esxVI_ObjectContent **virtualMachine);
+
+int esxVI_StartVirtualMachineTask(virConnectPtr conn, esxVI_Context *ctx,
+                                  const char *name, const char *request,
+                                  esxVI_ManagedObjectReference **task);
+
+int esxVI_StartSimpleVirtualMachineTask
+      (virConnectPtr conn, esxVI_Context *ctx, const char *name,
+       esxVI_ManagedObjectReference *virtualMachine,
+       esxVI_ManagedObjectReference **task);
+
+int esxVI_SimpleVirtualMachineMethod
+      (virConnectPtr conn, esxVI_Context *ctx, const char *name,
+       esxVI_ManagedObjectReference *virtualMachine);
+
+int esxVI_WaitForTaskCompletion(virConnectPtr conn, esxVI_Context *ctx,
+                                esxVI_ManagedObjectReference *task,
+                                esxVI_TaskInfoState *finalState);
+
+#endif /* __ESX_VI_H__ */
diff --git a/src/esx/esx_vi_methods.c b/src/esx/esx_vi_methods.c
new file mode 100644
index 0000000..9a659df
--- /dev/null
+++ b/src/esx/esx_vi_methods.c
@@ -0,0 +1,1315 @@
+
+/*
+ * esx_vi_methods.c: client for the VMware VI API 2.5 to manage ESX hosts
+ *
+ * Copyright (C) 2009 Matthias Bolte <matthias.bolte@xxxxxxxxxxxxxx>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ */
+
+#include <config.h>
+
+#include "buf.h"
+#include "memory.h"
+#include "logging.h"
+#include "uuid.h"
+#include "virterror_internal.h"
+#include "esx_vi_methods.h"
+#include "esx_util.h"
+
+#define VIR_FROM_THIS VIR_FROM_ESX
+
+#define ESX_VI_ERROR(conn, code, fmt...)                                      \
+    virReportErrorHelper(conn, VIR_FROM_ESX, code, __FILE__,  __FUNCTION__,   \
+                         __LINE__, fmt)
+
+#define ESX_VI__SOAP__REQUEST_HEADER                                          \
+    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"                            \
+    "<soapenv:Envelope "                                                      \
+      "xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"; "          \
+      "xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\"; "          \
+      "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"; "              \
+      "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\";>"                       \
+    "<soapenv:Body>"
+
+#define ESX_VI__SOAP__REQUEST_FOOTER                                          \
+    "</soapenv:Body>"                                                         \
+    "</soapenv:Envelope>"
+
+#define ESX_VI__SOAP__RESPONSE_XPATH(_type)                                   \
+    ((char *)"/soapenv:Envelope/soapenv:Body/"                                \
+             "vim:"_type"Response/vim:returnval")
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Methods
+ */
+
+static const char *_esxVI_RetrieveServiceContentRequest =
+ESX_VI__SOAP__REQUEST_HEADER
+  "<RetrieveServiceContent xmlns=\"urn:vim25\">"
+    "<_this xmlns=\"urn:vim25\" "
+           "xsi:type=\"ManagedObjectReference\" "
+           "type=\"ServiceInstance\">"
+      "ServiceInstance"
+    "</_this>"
+  "</RetrieveServiceContent>"
+ESX_VI__SOAP__REQUEST_FOOTER;
+
+int
+esxVI_RetrieveServiceContent(virConnectPtr conn, esxVI_Context *ctx,
+                             esxVI_ServiceContent **serviceContent)
+{
+    int result = 0;
+    esxVI_RemoteRequest *remoteRequest = NULL;
+    esxVI_RemoteResponse *remoteResponse = NULL;
+
+    if (serviceContent == NULL || *serviceContent != NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    if (esxVI_RemoteRequest_Alloc(conn, &remoteRequest) < 0) {
+        goto failure;
+    }
+
+    remoteRequest->request = (char *)_esxVI_RetrieveServiceContentRequest;
+    remoteRequest->xpathExpression =
+      ESX_VI__SOAP__RESPONSE_XPATH("RetrieveServiceContent");
+
+    if (esxVI_RemoteRequest_Execute(conn, ctx, remoteRequest,
+                                    &remoteResponse) < 0 ||
+        esxVI_RemoteResponse_DeserializeXPathObject
+          (conn, remoteResponse,
+           (esxVI_RemoteResponse_DeserializeFunc)
+             esxVI_ServiceContent_Deserialize,
+           (void **)serviceContent) < 0) {
+        goto failure;
+    }
+
+  cleanup:
+    /*
+     * Remove static values from the data structures to prevent them from
+     * being freed by the call to esxVI_RemoteRequest_Free().
+     */
+    if (remoteRequest != NULL) {
+        remoteRequest->request = NULL;
+        remoteRequest->xpathExpression = NULL;
+    }
+
+    esxVI_RemoteRequest_Free(&remoteRequest);
+    esxVI_RemoteResponse_Free(&remoteResponse);
+
+    return result;
+
+  failure:
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+int
+esxVI_Login(virConnectPtr conn, esxVI_Context *ctx,
+            const char *userName, const char *password,
+            esxVI_UserSession **userSession)
+{
+    int result = 0;
+    esxVI_RemoteRequest *remoteRequest = NULL;
+    esxVI_RemoteResponse *remoteResponse = NULL;
+    virBuffer buffer = VIR_BUFFER_INITIALIZER;
+
+    if (ctx->service == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid call");
+        return -1;
+    }
+
+    if (userSession == NULL || *userSession != NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_HEADER);
+    virBufferAddLit(&buffer, "<Login xmlns=\"urn:vim25\">");
+
+    if (esxVI_RemoteRequest_Alloc(conn, &remoteRequest) < 0 ||
+        esxVI_ManagedObjectReference_Serialize(conn,
+                                               ctx->service->sessionManager,
+                                               "_this", &buffer,
+                                               esxVI_Boolean_True) < 0 ||
+        esxVI_String_SerializeValue(conn, userName, "userName", &buffer,
+                                    esxVI_Boolean_True) < 0 ||
+        esxVI_String_SerializeValue(conn, password, "password", &buffer,
+                                    esxVI_Boolean_True) < 0) {
+        goto failure;
+    }
+
+    virBufferAddLit(&buffer, "</Login>");
+    virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_FOOTER);
+
+    if (virBufferError(&buffer)) {
+        virReportOOMError(conn);
+        goto failure;
+    }
+
+    remoteRequest->request = virBufferContentAndReset(&buffer);
+    remoteRequest->xpathExpression = ESX_VI__SOAP__RESPONSE_XPATH("Login");
+
+    if (esxVI_RemoteRequest_Execute(conn, ctx, remoteRequest,
+                                    &remoteResponse) < 0 ||
+        esxVI_RemoteResponse_DeserializeXPathObject
+          (conn, remoteResponse,
+           (esxVI_RemoteResponse_DeserializeFunc)
+             esxVI_UserSession_Deserialize,
+           (void **)userSession) < 0) {
+        goto failure;
+    }
+
+  cleanup:
+    /*
+     * Remove static values from the data structures to prevent them from
+     * being freed by the call to esxVI_RemoteRequest_Free().
+     */
+    if (remoteRequest != NULL) {
+        remoteRequest->xpathExpression = NULL;
+    }
+
+    esxVI_RemoteRequest_Free(&remoteRequest);
+    esxVI_RemoteResponse_Free(&remoteResponse);
+
+    return result;
+
+  failure:
+    free(virBufferContentAndReset(&buffer));
+
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+int
+esxVI_Logout(virConnectPtr conn, esxVI_Context *ctx)
+{
+    int result = 0;
+    esxVI_RemoteRequest *remoteRequest = NULL;
+    esxVI_RemoteResponse *remoteResponse = NULL;
+    virBuffer buffer = VIR_BUFFER_INITIALIZER;
+
+    if (ctx->service == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid call");
+        return -1;
+    }
+
+    virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_HEADER);
+    virBufferAddLit(&buffer, "<Logout xmlns=\"urn:vim25\">");
+
+    if (esxVI_RemoteRequest_Alloc(conn, &remoteRequest) < 0 ||
+        esxVI_ManagedObjectReference_Serialize(conn,
+                                               ctx->service->sessionManager,
+                                               "_this", &buffer,
+                                               esxVI_Boolean_True) < 0) {
+        goto failure;
+    }
+
+    virBufferAddLit(&buffer, "</Logout>");
+    virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_FOOTER);
+
+    if (virBufferError(&buffer)) {
+        virReportOOMError(conn);
+        goto failure;
+    }
+
+    remoteRequest->request = virBufferContentAndReset(&buffer);
+
+    if (esxVI_RemoteRequest_Execute(conn, ctx, remoteRequest,
+                                    &remoteResponse) < 0) {
+        goto failure;
+    }
+
+  cleanup:
+    esxVI_RemoteRequest_Free(&remoteRequest);
+    esxVI_RemoteResponse_Free(&remoteResponse);
+
+    return result;
+
+  failure:
+    free(virBufferContentAndReset(&buffer));
+
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+int
+esxVI_SessionIsActive(virConnectPtr conn, esxVI_Context *ctx,
+                      const char *sessionID, const char *userName,
+                      esxVI_Boolean *active)
+{
+    int result = 0;
+    esxVI_RemoteRequest *remoteRequest = NULL;
+    esxVI_RemoteResponse *remoteResponse = NULL;
+    virBuffer buffer = VIR_BUFFER_INITIALIZER;
+
+    if (ctx->service == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid call");
+        return -1;
+    }
+
+    if (active == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_HEADER);
+    virBufferAddLit(&buffer, "<SessionIsActive xmlns=\"urn:vim25\">");
+
+    if (esxVI_RemoteRequest_Alloc(conn, &remoteRequest) < 0 ||
+        esxVI_ManagedObjectReference_Serialize(conn,
+                                               ctx->service->sessionManager,
+                                               "_this", &buffer,
+                                               esxVI_Boolean_True) < 0 ||
+        esxVI_String_SerializeValue(conn, sessionID, "sessionID", &buffer,
+                                    esxVI_Boolean_True) < 0 ||
+        esxVI_String_SerializeValue(conn, userName, "userName", &buffer,
+                                    esxVI_Boolean_True) < 0) {
+        goto failure;
+    }
+
+    virBufferAddLit(&buffer, "</SessionIsActive>");
+    virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_FOOTER);
+
+    if (virBufferError(&buffer)) {
+        virReportOOMError(conn);
+        goto failure;
+    }
+
+    remoteRequest->request = virBufferContentAndReset(&buffer);
+    remoteRequest->xpathExpression =
+      ESX_VI__SOAP__RESPONSE_XPATH("SessionIsActive");
+
+    if (esxVI_RemoteRequest_Execute(conn, ctx, remoteRequest,
+                                    &remoteResponse) < 0 ||
+        esxVI_RemoteResponse_DeserializeXPathObject
+          (conn, remoteResponse,
+           /*
+            * FIXME: esxVI_Boolean_Deserialize expects *boolean,
+            *        esxVI_RemoteResponse_DeserializeFunc expects void **,
+            *        passing *boolean casted to void * to it
+            */
+           (esxVI_RemoteResponse_DeserializeFunc)esxVI_Boolean_Deserialize,
+           (void *)active) < 0) {
+        goto failure;
+    }
+
+  cleanup:
+    /*
+     * Remove static values from the data structures to prevent them from
+     * being freed by the call to esxVI_RemoteRequest_Free().
+     */
+    if (remoteRequest != NULL) {
+        remoteRequest->xpathExpression = NULL;
+    }
+
+    esxVI_RemoteRequest_Free(&remoteRequest);
+    esxVI_RemoteResponse_Free(&remoteResponse);
+
+    return result;
+
+  failure:
+    free(virBufferContentAndReset(&buffer));
+
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+int
+esxVI_RetrieveProperties(virConnectPtr conn, esxVI_Context *ctx,
+                         esxVI_PropertyFilterSpec *propertyFilterSpecList,
+                         esxVI_ObjectContent **objectContentList)
+{
+    int result = 0;
+    esxVI_RemoteRequest *remoteRequest = NULL;
+    esxVI_RemoteResponse *remoteResponse = NULL;
+    virBuffer buffer = VIR_BUFFER_INITIALIZER;
+
+    if (ctx->service == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid call");
+        return -1;
+    }
+
+    if (objectContentList == NULL || *objectContentList != NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_HEADER);
+    virBufferAddLit(&buffer, "<RetrieveProperties xmlns=\"urn:vim25\">");
+
+    if (esxVI_RemoteRequest_Alloc(conn, &remoteRequest) < 0 ||
+        esxVI_ManagedObjectReference_Serialize(conn,
+                                               ctx->service->propertyCollector,
+                                               "_this", &buffer,
+                                               esxVI_Boolean_True) < 0 ||
+        esxVI_PropertyFilterSpec_SerializeList(conn, propertyFilterSpecList,
+                                               "specSet", &buffer,
+                                               esxVI_Boolean_True) < 0) {
+        goto failure;
+    }
+
+    virBufferAddLit(&buffer, "</RetrieveProperties>");
+    virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_FOOTER);
+
+    if (virBufferError(&buffer)) {
+        virReportOOMError(conn);
+        goto failure;
+    }
+
+    remoteRequest->request = virBufferContentAndReset(&buffer);
+    remoteRequest->xpathExpression =
+      ESX_VI__SOAP__RESPONSE_XPATH("RetrieveProperties");
+
+    if (esxVI_RemoteRequest_Execute(conn, ctx, remoteRequest,
+                                    &remoteResponse) < 0 ||
+        esxVI_RemoteResponse_DeserializeXPathObjectList
+          (conn, remoteResponse,
+           (esxVI_RemoteResponse_DeserializeListFunc)
+             esxVI_ObjectContent_DeserializeList,
+           (esxVI_List **)objectContentList) < 0) {
+        goto failure;
+    }
+
+  cleanup:
+    /*
+     * Remove static values from the data structures to prevent them from
+     * being freed by the call to esxVI_RemoteRequest_Free().
+     */
+    if (remoteRequest != NULL) {
+        remoteRequest->xpathExpression = NULL;
+    }
+
+    esxVI_RemoteRequest_Free(&remoteRequest);
+    esxVI_RemoteResponse_Free(&remoteResponse);
+
+    return result;
+
+  failure:
+    free(virBufferContentAndReset(&buffer));
+
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+int
+esxVI_PowerOnVM_Task(virConnectPtr conn, esxVI_Context *ctx,
+                     esxVI_ManagedObjectReference *virtualMachine,
+                     esxVI_ManagedObjectReference **task)
+{
+    return esxVI_StartSimpleVirtualMachineTask(conn, ctx, "PowerOnVM",
+                                               virtualMachine, task);
+}
+
+
+
+int
+esxVI_PowerOffVM_Task(virConnectPtr conn, esxVI_Context *ctx,
+                      esxVI_ManagedObjectReference *virtualMachine,
+                      esxVI_ManagedObjectReference **task)
+{
+    return esxVI_StartSimpleVirtualMachineTask(conn, ctx, "PowerOffVM",
+                                               virtualMachine, task);
+}
+
+
+
+int
+esxVI_SuspendVM_Task(virConnectPtr conn, esxVI_Context *ctx,
+                     esxVI_ManagedObjectReference *virtualMachine,
+                     esxVI_ManagedObjectReference **task)
+{
+    return esxVI_StartSimpleVirtualMachineTask(conn, ctx, "SuspendVM",
+                                               virtualMachine, task);
+}
+
+
+
+int
+esxVI_MigrateVM_Task(virConnectPtr conn, esxVI_Context *ctx,
+                     esxVI_ManagedObjectReference *virtualMachine,
+                     esxVI_ManagedObjectReference *resourcePool,
+                     esxVI_ManagedObjectReference *hostSystem,
+                     esxVI_ManagedObjectReference **task)
+{
+    int result = 0;
+    virBuffer buffer = VIR_BUFFER_INITIALIZER;
+    char *request = NULL;
+
+    if (task == NULL || *task != NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_HEADER);
+    virBufferAddLit(&buffer, "<MigrateVM_Task xmlns=\"urn:vim25\">");
+
+    if (esxVI_ManagedObjectReference_Serialize(conn, virtualMachine, "_this",
+                                               &buffer,
+                                               esxVI_Boolean_True) < 0 ||
+        esxVI_ManagedObjectReference_Serialize(conn, resourcePool, "pool",
+                                               &buffer,
+                                               esxVI_Boolean_True) < 0 ||
+        esxVI_ManagedObjectReference_Serialize(conn, hostSystem, "host",
+                                               &buffer,
+                                               esxVI_Boolean_True) < 0 ||
+        esxVI_VirtualMachineMovePriority_Serialize
+          (conn, esxVI_VirtualMachineMovePriority_DefaultPriority,
+           "priority", &buffer, esxVI_Boolean_True) < 0) {
+        goto failure;
+    }
+
+    virBufferAddLit(&buffer, "</MigrateVM_Task>");
+    virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_FOOTER);
+
+    if (virBufferError(&buffer)) {
+        virReportOOMError(conn);
+        goto failure;
+    }
+
+    request = virBufferContentAndReset(&buffer);
+
+    if (esxVI_StartVirtualMachineTask(conn, ctx, "MigrateVM", request,
+                                      task) < 0) {
+        goto failure;
+    }
+
+  cleanup:
+    VIR_FREE(request);
+
+    return result;
+
+  failure:
+    free(virBufferContentAndReset(&buffer));
+
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+int
+esxVI_ReconfigVM_Task(virConnectPtr conn, esxVI_Context *ctx,
+                      esxVI_ManagedObjectReference *virtualMachine,
+                      esxVI_VirtualMachineConfigSpec *spec,
+                      esxVI_ManagedObjectReference **task)
+{
+    int result = 0;
+    virBuffer buffer = VIR_BUFFER_INITIALIZER;
+    char *request = NULL;
+
+    if (task == NULL || *task != NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_HEADER);
+    virBufferAddLit(&buffer, "<ReconfigVM_Task xmlns=\"urn:vim25\">");
+
+    if (esxVI_ManagedObjectReference_Serialize(conn, virtualMachine, "_this",
+                                               &buffer,
+                                               esxVI_Boolean_True) < 0 ||
+        esxVI_VirtualMachineConfigSpec_Serialize(conn, spec, "spec", &buffer,
+                                                 esxVI_Boolean_True) < 0) {
+        goto failure;
+    }
+
+    virBufferAddLit(&buffer, "</ReconfigVM_Task>");
+    virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_FOOTER);
+
+    if (virBufferError(&buffer)) {
+        virReportOOMError(conn);
+        goto failure;
+    }
+
+    request = virBufferContentAndReset(&buffer);
+
+    if (esxVI_StartVirtualMachineTask(conn, ctx, "ReconfigVM", request,
+                                      task) < 0) {
+        goto failure;
+    }
+
+  cleanup:
+    VIR_FREE(request);
+
+    return result;
+
+  failure:
+    free(virBufferContentAndReset(&buffer));
+
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+int
+esxVI_CreateFilter(virConnectPtr conn, esxVI_Context *ctx,
+                   esxVI_PropertyFilterSpec *propertyFilterSpec,
+                   esxVI_Boolean partialUpdates,
+                   esxVI_ManagedObjectReference **propertyFilter)
+{
+    int result = 0;
+    esxVI_RemoteRequest *remoteRequest = NULL;
+    esxVI_RemoteResponse *remoteResponse = NULL;
+    virBuffer buffer = VIR_BUFFER_INITIALIZER;
+
+    if (ctx->service == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid call");
+        return -1;
+    }
+
+    if (propertyFilter == NULL || *propertyFilter != NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_HEADER);
+    virBufferAddLit(&buffer, "<CreateFilter xmlns=\"urn:vim25\">");
+
+    if (esxVI_RemoteRequest_Alloc(conn, &remoteRequest) < 0 ||
+        esxVI_ManagedObjectReference_Serialize(conn,
+                                               ctx->service->propertyCollector,
+                                               "_this", &buffer,
+                                               esxVI_Boolean_True) < 0 ||
+        esxVI_PropertyFilterSpec_Serialize(conn, propertyFilterSpec, "spec",
+                                           &buffer, esxVI_Boolean_True) < 0 ||
+        esxVI_Boolean_Serialize(conn, partialUpdates, "partialUpdates",
+                                &buffer, esxVI_Boolean_True) < 0) {
+        goto failure;
+    }
+
+    virBufferAddLit(&buffer, "</CreateFilter>");
+    virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_FOOTER);
+
+    if (virBufferError(&buffer)) {
+        virReportOOMError(conn);
+        goto failure;
+    }
+
+    remoteRequest->request = virBufferContentAndReset(&buffer);
+    remoteRequest->xpathExpression =
+      ESX_VI__SOAP__RESPONSE_XPATH("CreateFilter");
+
+    if (esxVI_RemoteRequest_Execute(conn, ctx, remoteRequest,
+                                    &remoteResponse) < 0 ||
+        esxVI_RemoteResponse_DeserializeXPathObjectAsManagedObjectReference
+          (conn, remoteResponse, propertyFilter, "PropertyFilter") < 0) {
+        goto failure;
+    }
+
+  cleanup:
+    /*
+     * Remove static values from the data structures to prevent them from
+     * being freed by the call to esxVI_RemoteRequest_Free().
+     */
+    if (remoteRequest != NULL) {
+        remoteRequest->xpathExpression = NULL;
+    }
+
+    esxVI_RemoteRequest_Free(&remoteRequest);
+    esxVI_RemoteResponse_Free(&remoteResponse);
+
+    return result;
+
+  failure:
+    free(virBufferContentAndReset(&buffer));
+
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+int
+esxVI_DestroyPropertyFilter(virConnectPtr conn, esxVI_Context *ctx,
+                            esxVI_ManagedObjectReference *propertyFilter)
+{
+    int result = 0;
+    esxVI_RemoteRequest *remoteRequest = NULL;
+    esxVI_RemoteResponse *remoteResponse = NULL;
+    virBuffer buffer = VIR_BUFFER_INITIALIZER;
+
+    if (ctx->service == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid call");
+        return -1;
+    }
+
+    virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_HEADER);
+    virBufferAddLit(&buffer, "<DestroyPropertyFilter xmlns=\"urn:vim25\">");
+
+    if (esxVI_RemoteRequest_Alloc(conn, &remoteRequest) < 0 ||
+        esxVI_ManagedObjectReference_Serialize(conn, propertyFilter, "_this",
+                                               &buffer,
+                                               esxVI_Boolean_True) < 0) {
+        goto failure;
+    }
+
+    virBufferAddLit(&buffer, "</DestroyPropertyFilter>");
+    virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_FOOTER);
+
+    if (virBufferError(&buffer)) {
+        virReportOOMError(conn);
+        goto failure;
+    }
+
+    remoteRequest->request = virBufferContentAndReset(&buffer);
+
+    if (esxVI_RemoteRequest_Execute(conn, ctx, remoteRequest,
+                                    &remoteResponse) < 0) {
+        goto failure;
+    }
+
+  cleanup:
+    esxVI_RemoteRequest_Free(&remoteRequest);
+    esxVI_RemoteResponse_Free(&remoteResponse);
+
+    return result;
+
+  failure:
+    free(virBufferContentAndReset(&buffer));
+
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+int
+esxVI_WaitForUpdates(virConnectPtr conn, esxVI_Context *ctx,
+                     const char *version, esxVI_UpdateSet **updateSet)
+{
+    int result = 0;
+    esxVI_RemoteRequest *remoteRequest = NULL;
+    esxVI_RemoteResponse *remoteResponse = NULL;
+    virBuffer buffer = VIR_BUFFER_INITIALIZER;
+
+    if (ctx->service == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid call");
+        return -1;
+    }
+
+    if (updateSet == NULL || *updateSet != NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_HEADER);
+    virBufferAddLit(&buffer, "<WaitForUpdates xmlns=\"urn:vim25\">");
+
+    if (esxVI_RemoteRequest_Alloc(conn, &remoteRequest) < 0 ||
+        esxVI_ManagedObjectReference_Serialize(conn,
+                                               ctx->service->propertyCollector,
+                                               "_this", &buffer,
+                                               esxVI_Boolean_True) < 0 ||
+        esxVI_String_SerializeValue(conn, version, "version", &buffer,
+                                    esxVI_Boolean_True) < 0) {
+        goto failure;
+    }
+
+    virBufferAddLit(&buffer, "</WaitForUpdates>");
+    virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_FOOTER);
+
+    if (virBufferError(&buffer)) {
+        virReportOOMError(conn);
+        goto failure;
+    }
+
+    remoteRequest->request = virBufferContentAndReset(&buffer);
+    remoteRequest->xpathExpression =
+      ESX_VI__SOAP__RESPONSE_XPATH("WaitForUpdates");
+
+    if (esxVI_RemoteRequest_Execute(conn, ctx, remoteRequest,
+                                    &remoteResponse) < 0 ||
+        esxVI_RemoteResponse_DeserializeXPathObject
+          (conn, remoteResponse,
+           (esxVI_RemoteResponse_DeserializeFunc)esxVI_UpdateSet_Deserialize,
+           (void **)updateSet) < 0) {
+        goto failure;
+    }
+
+  cleanup:
+    /*
+     * Remove static values from the data structures to prevent them from
+     * being freed by the call to esxVI_RemoteRequest_Free().
+     */
+    if (remoteRequest != NULL) {
+        remoteRequest->xpathExpression = NULL;
+    }
+
+    esxVI_RemoteRequest_Free(&remoteRequest);
+    esxVI_RemoteResponse_Free(&remoteResponse);
+
+    return result;
+
+  failure:
+    free(virBufferContentAndReset(&buffer));
+
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+int
+esxVI_RebootGuest(virConnectPtr conn, esxVI_Context *ctx,
+                  esxVI_ManagedObjectReference *virtualMachine)
+{
+    return esxVI_SimpleVirtualMachineMethod(conn, ctx, "RebootGuest",
+                                            virtualMachine);
+}
+
+
+
+int
+esxVI_ShutdownGuest(virConnectPtr conn, esxVI_Context *ctx,
+                    esxVI_ManagedObjectReference *virtualMachine)
+{
+    return esxVI_SimpleVirtualMachineMethod(conn, ctx, "ShutdownGuest",
+                                            virtualMachine);
+}
+
+
+
+int
+esxVI_ValidateMigration(virConnectPtr conn, esxVI_Context *ctx,
+                        esxVI_ManagedObjectReference *virtualMachineList,
+                        esxVI_VirtualMachinePowerState powerState,
+                        esxVI_String *testTypeList,
+                        esxVI_ManagedObjectReference *resourcePool,
+                        esxVI_ManagedObjectReference *hostSystem,
+                        esxVI_Event **eventList)
+{
+    int result = 0;
+    esxVI_RemoteRequest *remoteRequest = NULL;
+    esxVI_RemoteResponse *remoteResponse = NULL;
+    virBuffer buffer = VIR_BUFFER_INITIALIZER;
+
+    if (ctx->service == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid call");
+        return -1;
+    }
+
+    if (eventList == NULL || *eventList != NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_HEADER);
+    virBufferAddLit(&buffer, "<ValidateMigration xmlns=\"urn:vim25\">"
+                             "<_this xmlns=\"urn:vim25\" "
+                                    "xsi:type=\"ManagedObjectReference\" "
+                                    "type=\"ServiceInstance\">"
+                               "ServiceInstance"
+                             "</_this>");
+
+    if (esxVI_RemoteRequest_Alloc(conn, &remoteRequest) < 0 ||
+        esxVI_ManagedObjectReference_SerializeList(conn, virtualMachineList,
+                                                   "vm", &buffer,
+                                                   esxVI_Boolean_True) < 0 ||
+        esxVI_VirtualMachinePowerState_Serialize(conn, powerState, "state",
+                                                 &buffer,
+                                                 esxVI_Boolean_False) < 0 ||
+        esxVI_String_SerializeList(conn, testTypeList, "testType", &buffer,
+                                   esxVI_Boolean_False) < 0 ||
+        esxVI_ManagedObjectReference_Serialize(conn, resourcePool, "pool",
+                                               &buffer,
+                                               esxVI_Boolean_True) < 0 ||
+        esxVI_ManagedObjectReference_Serialize(conn, hostSystem, "host",
+                                               &buffer,
+                                               esxVI_Boolean_True) < 0) {
+        goto failure;
+    }
+
+    virBufferAddLit(&buffer, "</ValidateMigration>");
+    virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_FOOTER);
+
+    if (virBufferError(&buffer)) {
+        virReportOOMError(conn);
+        goto failure;
+    }
+
+    remoteRequest->request = virBufferContentAndReset(&buffer);
+    remoteRequest->xpathExpression =
+      ESX_VI__SOAP__RESPONSE_XPATH("ValidateMigration");
+
+    if (esxVI_RemoteRequest_Execute(conn, ctx, remoteRequest,
+                                    &remoteResponse) < 0 ||
+        esxVI_RemoteResponse_DeserializeXPathObjectList
+          (conn, remoteResponse,
+           (esxVI_RemoteResponse_DeserializeListFunc)
+             esxVI_Event_DeserializeList,
+           (esxVI_List **)eventList) < 0) {
+        goto failure;
+    }
+
+  cleanup:
+    /*
+     * Remove static values from the data structures to prevent them from
+     * being freed by the call to esxVI_RemoteRequest_Free().
+     */
+    if (remoteRequest != NULL) {
+        remoteRequest->xpathExpression = NULL;
+    }
+
+    esxVI_RemoteRequest_Free(&remoteRequest);
+    esxVI_RemoteResponse_Free(&remoteResponse);
+
+    return result;
+
+  failure:
+    free(virBufferContentAndReset(&buffer));
+
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+int
+esxVI_FindByIp(virConnectPtr conn, esxVI_Context *ctx,
+                 esxVI_ManagedObjectReference *datacenter,
+                 const char *ip, esxVI_Boolean vmSearch,
+                 esxVI_ManagedObjectReference **managedObjectReference)
+{
+    int result = 0;
+    esxVI_RemoteRequest *remoteRequest = NULL;
+    esxVI_RemoteResponse *remoteResponse = NULL;
+    virBuffer buffer = VIR_BUFFER_INITIALIZER;
+
+    if (ctx->service == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid call");
+        return -1;
+    }
+
+    if (managedObjectReference == NULL || *managedObjectReference != NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_HEADER);
+    virBufferAddLit(&buffer, "<FindByIp xmlns=\"urn:vim25\">");
+
+    if (esxVI_RemoteRequest_Alloc(conn, &remoteRequest) < 0 ||
+        esxVI_ManagedObjectReference_Serialize(conn, ctx->service->searchIndex,
+                                               "_this", &buffer,
+                                               esxVI_Boolean_True) < 0 ||
+        esxVI_ManagedObjectReference_Serialize(conn, datacenter,
+                                               "datacenter", &buffer,
+                                               esxVI_Boolean_False) < 0 ||
+        esxVI_String_SerializeValue(conn, ip, "ip", &buffer,
+                                    esxVI_Boolean_True) < 0 ||
+        esxVI_Boolean_Serialize(conn, vmSearch, "vmSearch", &buffer,
+                                esxVI_Boolean_True) < 0) {
+        goto failure;
+    }
+
+    virBufferAddLit(&buffer, "</FindByIp>");
+    virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_FOOTER);
+
+    if (virBufferError(&buffer)) {
+        virReportOOMError(conn);
+        goto failure;
+    }
+
+    remoteRequest->request = virBufferContentAndReset(&buffer);
+    remoteRequest->xpathExpression =
+      ESX_VI__SOAP__RESPONSE_XPATH("FindByIp");
+
+    if (esxVI_RemoteRequest_Execute(conn, ctx, remoteRequest,
+                                    &remoteResponse) < 0 ||
+        esxVI_RemoteResponse_DeserializeXPathObjectAsManagedObjectReference
+          (conn, remoteResponse, managedObjectReference,
+           vmSearch == esxVI_Boolean_True ? "VirtualMachine"
+                                          : "HostSystem") < 0) {
+        goto failure;
+    }
+
+  cleanup:
+    /*
+     * Remove static values from the data structures to prevent them from
+     * being freed by the call to esxVI_RemoteRequest_Free().
+     */
+    if (remoteRequest != NULL) {
+        remoteRequest->xpathExpression = NULL;
+    }
+
+    esxVI_RemoteRequest_Free(&remoteRequest);
+    esxVI_RemoteResponse_Free(&remoteResponse);
+
+    return result;
+
+  failure:
+    free(virBufferContentAndReset(&buffer));
+
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+int
+esxVI_FindByUuid(virConnectPtr conn, esxVI_Context *ctx,
+                 esxVI_ManagedObjectReference *datacenter,
+                 const unsigned char *uuid, esxVI_Boolean vmSearch,
+                 esxVI_ManagedObjectReference **managedObjectReference)
+{
+    int result = 0;
+    esxVI_RemoteRequest *remoteRequest = NULL;
+    esxVI_RemoteResponse *remoteResponse = NULL;
+    char uuid_string[VIR_UUID_STRING_BUFLEN] = "";
+    virBuffer buffer = VIR_BUFFER_INITIALIZER;
+
+    if (ctx->service == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid call");
+        return -1;
+    }
+
+    if (managedObjectReference == NULL || *managedObjectReference != NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    virUUIDFormat(uuid, uuid_string);
+
+    virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_HEADER);
+    virBufferAddLit(&buffer, "<FindByUuid xmlns=\"urn:vim25\">");
+
+    if (esxVI_RemoteRequest_Alloc(conn, &remoteRequest) < 0 ||
+        esxVI_ManagedObjectReference_Serialize(conn, ctx->service->searchIndex,
+                                               "_this", &buffer,
+                                               esxVI_Boolean_True) < 0 ||
+        esxVI_ManagedObjectReference_Serialize(conn, datacenter,
+                                               "datacenter", &buffer,
+                                               esxVI_Boolean_False) < 0 ||
+        esxVI_String_SerializeValue(conn, uuid_string, "uuid", &buffer,
+                                    esxVI_Boolean_True) < 0 ||
+        esxVI_Boolean_Serialize(conn, vmSearch, "vmSearch", &buffer,
+                                esxVI_Boolean_True) < 0) {
+        goto failure;
+    }
+
+    virBufferAddLit(&buffer, "</FindByUuid>");
+    virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_FOOTER);
+
+    if (virBufferError(&buffer)) {
+        virReportOOMError(conn);
+        goto failure;
+    }
+
+    remoteRequest->request = virBufferContentAndReset(&buffer);
+    remoteRequest->xpathExpression =
+      ESX_VI__SOAP__RESPONSE_XPATH("FindByUuid");
+
+    if (esxVI_RemoteRequest_Execute(conn, ctx, remoteRequest,
+                                    &remoteResponse) < 0 ||
+        esxVI_RemoteResponse_DeserializeXPathObjectAsManagedObjectReference
+          (conn, remoteResponse, managedObjectReference,
+           vmSearch == esxVI_Boolean_True ? "VirtualMachine"
+                                          : "HostSystem") < 0) {
+        goto failure;
+    }
+
+  cleanup:
+    /*
+     * Remove static values from the data structures to prevent them from
+     * being freed by the call to esxVI_RemoteRequest_Free().
+     */
+    if (remoteRequest != NULL) {
+        remoteRequest->xpathExpression = NULL;
+    }
+
+    esxVI_RemoteRequest_Free(&remoteRequest);
+    esxVI_RemoteResponse_Free(&remoteResponse);
+
+    return result;
+
+  failure:
+    free(virBufferContentAndReset(&buffer));
+
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+int
+esxVI_QueryAvailablePerfMetric(virConnectPtr conn, esxVI_Context *ctx,
+                               esxVI_ManagedObjectReference *entity,
+                               esxVI_DateTime *beginTime,
+                               esxVI_DateTime *endTime, esxVI_Int *intervalId,
+                               esxVI_PerfMetricId **perfMetricIdList)
+{
+    int result = 0;
+    esxVI_RemoteRequest *remoteRequest = NULL;
+    esxVI_RemoteResponse *remoteResponse = NULL;
+    virBuffer buffer = VIR_BUFFER_INITIALIZER;
+
+    if (ctx->service == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid call");
+        return -1;
+    }
+
+    if (perfMetricIdList == NULL || *perfMetricIdList != NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_HEADER);
+    virBufferAddLit(&buffer, "<QueryAvailablePerfMetric xmlns=\"urn:vim25\">");
+
+    if (esxVI_RemoteRequest_Alloc(conn, &remoteRequest) < 0 ||
+        esxVI_ManagedObjectReference_Serialize(conn, ctx->service->perfManager,
+                                               "_this", &buffer,
+                                               esxVI_Boolean_True) < 0 ||
+        esxVI_ManagedObjectReference_Serialize(conn, entity,
+                                               "entity", &buffer,
+                                               esxVI_Boolean_True) < 0 ||
+        esxVI_DateTime_Serialize(conn, beginTime, "beginTime", &buffer,
+                                 esxVI_Boolean_False) < 0 ||
+        esxVI_DateTime_Serialize(conn, endTime, "endTime", &buffer,
+                                 esxVI_Boolean_False) < 0 ||
+        esxVI_Int_Serialize(conn, intervalId, "intervalId", &buffer,
+                            esxVI_Boolean_False) < 0) {
+        goto failure;
+    }
+
+    virBufferAddLit(&buffer, "</QueryAvailablePerfMetric>");
+    virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_FOOTER);
+
+    if (virBufferError(&buffer)) {
+        virReportOOMError(conn);
+        goto failure;
+    }
+
+    remoteRequest->request = virBufferContentAndReset(&buffer);
+    remoteRequest->xpathExpression =
+      ESX_VI__SOAP__RESPONSE_XPATH("QueryAvailablePerfMetric");
+
+    if (esxVI_RemoteRequest_Execute(conn, ctx, remoteRequest,
+                                    &remoteResponse) < 0 ||
+        esxVI_RemoteResponse_DeserializeXPathObjectList
+          (conn, remoteResponse,
+           (esxVI_RemoteResponse_DeserializeListFunc)
+             esxVI_PerfMetricId_DeserializeList,
+           (esxVI_List **)perfMetricIdList) < 0) {
+        goto failure;
+    }
+
+  cleanup:
+    /*
+     * Remove static values from the data structures to prevent them from
+     * being freed by the call to esxVI_RemoteRequest_Free().
+     */
+    if (remoteRequest != NULL) {
+        remoteRequest->xpathExpression = NULL;
+    }
+
+    esxVI_RemoteRequest_Free(&remoteRequest);
+    esxVI_RemoteResponse_Free(&remoteResponse);
+
+    return result;
+
+  failure:
+    free(virBufferContentAndReset(&buffer));
+
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+int
+esxVI_QueryPerfCounter(virConnectPtr conn, esxVI_Context *ctx,
+                       esxVI_Int *counterIdList,
+                       esxVI_PerfCounterInfo **perfCounterInfoList)
+{
+    int result = 0;
+    esxVI_RemoteRequest *remoteRequest = NULL;
+    esxVI_RemoteResponse *remoteResponse = NULL;
+    virBuffer buffer = VIR_BUFFER_INITIALIZER;
+
+    if (ctx->service == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid call");
+        return -1;
+    }
+
+    if (perfCounterInfoList == NULL || *perfCounterInfoList != NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_HEADER);
+    virBufferAddLit(&buffer, "<QueryPerfCounter xmlns=\"urn:vim25\">");
+
+    if (esxVI_RemoteRequest_Alloc(conn, &remoteRequest) < 0 ||
+        esxVI_ManagedObjectReference_Serialize(conn, ctx->service->perfManager,
+                                               "_this", &buffer,
+                                               esxVI_Boolean_True) < 0 ||
+        esxVI_Int_SerializeList(conn, counterIdList, "counterId", &buffer,
+                                esxVI_Boolean_True) < 0) {
+        goto failure;
+    }
+
+    virBufferAddLit(&buffer, "</QueryPerfCounter>");
+    virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_FOOTER);
+
+    if (virBufferError(&buffer)) {
+        virReportOOMError(conn);
+        goto failure;
+    }
+
+    remoteRequest->request = virBufferContentAndReset(&buffer);
+    remoteRequest->xpathExpression =
+      ESX_VI__SOAP__RESPONSE_XPATH("QueryPerfCounter");
+
+    if (esxVI_RemoteRequest_Execute(conn, ctx, remoteRequest,
+                                    &remoteResponse) < 0 ||
+        esxVI_RemoteResponse_DeserializeXPathObjectList
+          (conn, remoteResponse,
+           (esxVI_RemoteResponse_DeserializeListFunc)
+             esxVI_PerfCounterInfo_DeserializeList,
+           (esxVI_List **)perfCounterInfoList) < 0) {
+        goto failure;
+    }
+
+  cleanup:
+    /*
+     * Remove static values from the data structures to prevent them from
+     * being freed by the call to esxVI_RemoteRequest_Free().
+     */
+    if (remoteRequest != NULL) {
+        remoteRequest->xpathExpression = NULL;
+    }
+
+    esxVI_RemoteRequest_Free(&remoteRequest);
+    esxVI_RemoteResponse_Free(&remoteResponse);
+
+    return result;
+
+  failure:
+    free(virBufferContentAndReset(&buffer));
+
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+int
+esxVI_QueryPerf(virConnectPtr conn, esxVI_Context *ctx,
+                esxVI_PerfQuerySpec *querySpecList,
+                esxVI_PerfEntityMetric **perfEntityMetricList)
+{
+    int result = 0;
+    esxVI_RemoteRequest *remoteRequest = NULL;
+    esxVI_RemoteResponse *remoteResponse = NULL;
+    virBuffer buffer = VIR_BUFFER_INITIALIZER;
+
+    if (ctx->service == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid call");
+        return -1;
+    }
+
+    if (perfEntityMetricList == NULL || *perfEntityMetricList != NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_HEADER);
+    virBufferAddLit(&buffer, "<QueryPerf xmlns=\"urn:vim25\">");
+
+    if (esxVI_RemoteRequest_Alloc(conn, &remoteRequest) < 0 ||
+        esxVI_ManagedObjectReference_Serialize(conn, ctx->service->perfManager,
+                                               "_this", &buffer,
+                                               esxVI_Boolean_True) < 0 ||
+        esxVI_PerfQuerySpec_SerializeList(conn, querySpecList, "querySpec",
+                                          &buffer,
+                                          esxVI_Boolean_True) < 0) {
+        goto failure;
+    }
+
+    virBufferAddLit(&buffer, "</QueryPerf>");
+    virBufferAddLit(&buffer, ESX_VI__SOAP__REQUEST_FOOTER);
+
+    if (virBufferError(&buffer)) {
+        virReportOOMError(conn);
+        goto failure;
+    }
+
+    remoteRequest->request = virBufferContentAndReset(&buffer);
+    remoteRequest->xpathExpression = ESX_VI__SOAP__RESPONSE_XPATH("QueryPerf");
+
+    if (esxVI_RemoteRequest_Execute(conn, ctx, remoteRequest,
+                                    &remoteResponse) < 0 ||
+        esxVI_RemoteResponse_DeserializeXPathObjectList
+          (conn, remoteResponse,
+           (esxVI_RemoteResponse_DeserializeListFunc)
+             esxVI_PerfEntityMetric_DeserializeList,
+           (esxVI_List **)perfEntityMetricList) < 0) {
+        goto failure;
+    }
+
+  cleanup:
+    /*
+     * Remove static values from the data structures to prevent them from
+     * being freed by the call to esxVI_RemoteRequest_Free().
+     */
+    if (remoteRequest != NULL) {
+        remoteRequest->xpathExpression = NULL;
+    }
+
+    esxVI_RemoteRequest_Free(&remoteRequest);
+    esxVI_RemoteResponse_Free(&remoteResponse);
+
+    return result;
+
+  failure:
+    free(virBufferContentAndReset(&buffer));
+
+    result = -1;
+
+    goto cleanup;
+}
diff --git a/src/esx/esx_vi_methods.h b/src/esx/esx_vi_methods.h
new file mode 100644
index 0000000..630bff2
--- /dev/null
+++ b/src/esx/esx_vi_methods.h
@@ -0,0 +1,125 @@
+
+/*
+ * esx_vi_methods.h: client for the VMware VI API 2.5 to manage ESX hosts
+ *
+ * Copyright (C) 2009 Matthias Bolte <matthias.bolte@xxxxxxxxxxxxxx>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ */
+
+#ifndef __ESX_VI_METHODS_H__
+#define __ESX_VI_METHODS_H__
+
+#include "esx_vi.h"
+#include "esx_vi_types.h"
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Methods
+ */
+
+int esxVI_RetrieveServiceContent(virConnectPtr conn, esxVI_Context *ctx,
+                                 esxVI_ServiceContent **serviceContent);
+
+int esxVI_Login(virConnectPtr conn, esxVI_Context *ctx,
+                const char *userName, const char *password,
+                esxVI_UserSession **userSession);
+
+int esxVI_Logout(virConnectPtr conn, esxVI_Context *ctx);
+
+int esxVI_SessionIsActive(virConnectPtr conn, esxVI_Context *ctx,
+                          const char *sessionID, const char *userName,
+                          esxVI_Boolean *active);
+
+int esxVI_RetrieveProperties(virConnectPtr conn, esxVI_Context *ctx,
+                             esxVI_PropertyFilterSpec *propertyFilterSpecList,
+                             esxVI_ObjectContent **objectContentList);
+
+int esxVI_PowerOnVM_Task(virConnectPtr conn, esxVI_Context *ctx,
+                         esxVI_ManagedObjectReference *virtualMachine,
+                         esxVI_ManagedObjectReference **task);
+
+int esxVI_PowerOffVM_Task(virConnectPtr conn, esxVI_Context *ctx,
+                          esxVI_ManagedObjectReference *virtualMachine,
+                          esxVI_ManagedObjectReference **task);
+
+int esxVI_SuspendVM_Task(virConnectPtr conn, esxVI_Context *ctx,
+                         esxVI_ManagedObjectReference *virtualMachine,
+                         esxVI_ManagedObjectReference **task);
+
+int esxVI_MigrateVM_Task(virConnectPtr conn, esxVI_Context *ctx,
+                         esxVI_ManagedObjectReference *virtualMachine,
+                         esxVI_ManagedObjectReference *resourcePool,
+                         esxVI_ManagedObjectReference *hostSystem,
+                         esxVI_ManagedObjectReference **task);
+
+int esxVI_ReconfigVM_Task(virConnectPtr conn, esxVI_Context *ctx,
+                          esxVI_ManagedObjectReference *virtualMachine,
+                          esxVI_VirtualMachineConfigSpec *spec,
+                          esxVI_ManagedObjectReference **task);
+
+int esxVI_CreateFilter(virConnectPtr conn, esxVI_Context *ctx,
+                       esxVI_PropertyFilterSpec *propertyFilterSpec,
+                       esxVI_Boolean partialUpdates,
+                       esxVI_ManagedObjectReference **propertyFilter);
+
+int esxVI_DestroyPropertyFilter(virConnectPtr conn, esxVI_Context *ctx,
+                                esxVI_ManagedObjectReference *propertyFilter);
+
+int esxVI_WaitForUpdates(virConnectPtr conn, esxVI_Context *ctx,
+                         const char *version, esxVI_UpdateSet **updateSet);
+
+int esxVI_RebootGuest(virConnectPtr conn, esxVI_Context *ctx,
+                      esxVI_ManagedObjectReference *virtualMachine);
+
+int esxVI_ShutdownGuest(virConnectPtr conn, esxVI_Context *ctx,
+                        esxVI_ManagedObjectReference *virtualMachine);
+
+int esxVI_ValidateMigration(virConnectPtr conn, esxVI_Context *ctx,
+                            esxVI_ManagedObjectReference *virtualMachineList,
+                            esxVI_VirtualMachinePowerState powerState,
+                            esxVI_String *testTypeList, // FIXME: see ValidateMigrationTestType
+                            esxVI_ManagedObjectReference *resourcePool,
+                            esxVI_ManagedObjectReference *hostSystem,
+                            esxVI_Event **eventList);
+
+int esxVI_FindByIp(virConnectPtr conn, esxVI_Context *ctx,
+                   esxVI_ManagedObjectReference *datacenter,
+                   const char *ip, esxVI_Boolean vmSearch,
+                   esxVI_ManagedObjectReference **managedObjectReference);
+
+int esxVI_FindByUuid(virConnectPtr conn, esxVI_Context *ctx,
+                     esxVI_ManagedObjectReference *datacenter,
+                     const unsigned char *uuid, esxVI_Boolean vmSearch,
+                     esxVI_ManagedObjectReference **managedObjectReference);
+
+int esxVI_QueryAvailablePerfMetric(virConnectPtr conn, esxVI_Context *ctx,
+                                   esxVI_ManagedObjectReference *entity,
+                                   esxVI_DateTime *beginTime,
+                                   esxVI_DateTime *endTime,
+                                   esxVI_Int *intervalId,
+                                   esxVI_PerfMetricId **perfMetricIdList);
+
+int esxVI_QueryPerfCounter(virConnectPtr conn, esxVI_Context *ctx,
+                           esxVI_Int *counterIdList,
+                           esxVI_PerfCounterInfo **perfCounterInfoList);
+
+int esxVI_QueryPerf(virConnectPtr conn, esxVI_Context *ctx,
+                    esxVI_PerfQuerySpec *querySpecList,
+                    esxVI_PerfEntityMetric **perfEntityMetricList);
+
+#endif /* __ESX_VI_METHODS_H__ */
diff --git a/src/esx/esx_vi_types.c b/src/esx/esx_vi_types.c
new file mode 100644
index 0000000..684b8c7
--- /dev/null
+++ b/src/esx/esx_vi_types.c
@@ -0,0 +1,2581 @@
+
+/*
+ * esx_vi_types.c: client for the VMware VI API 2.5 to manage ESX hosts
+ *
+ * Copyright (C) 2009 Matthias Bolte <matthias.bolte@xxxxxxxxxxxxxx>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ */
+
+#include <config.h>
+
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+
+#include <libxml/parser.h>
+#include <libxml/xpathInternals.h>
+
+#include "buf.h"
+#include "datatypes.h"
+#include "memory.h"
+#include "logging.h"
+#include "util.h"
+#include "virterror_internal.h"
+#include "esx_vi.h"
+#include "esx_vi_types.h"
+
+#define VIR_FROM_THIS VIR_FROM_ESX
+
+#define ESX_VI_ERROR(conn, code, fmt...)                                      \
+    virReportErrorHelper(conn, VIR_FROM_ESX, code, __FILE__, __FUNCTION__,    \
+                         __LINE__, fmt)
+
+
+
+#define ESV_VI__XML_TAG__OPEN(_buffer, _element, _type)                       \
+    do {                                                                      \
+        virBufferAddLit(_buffer, "<");                                        \
+        virBufferAdd(_buffer, _element, -1);                                  \
+        virBufferAddLit(_buffer, " xmlns=\"urn:vim25\" xsi:type=\"");         \
+        virBufferAdd(_buffer, _type, -1);                                     \
+        virBufferAddLit(_buffer, "\">");                                      \
+    } while (0)
+
+
+
+#define ESV_VI__XML_TAG__CLOSE(_buffer, _element)                             \
+    do {                                                                      \
+        virBufferAddLit(_buffer, "</");                                       \
+        virBufferAdd(_buffer, _element, -1);                                  \
+        virBufferAddLit(_buffer, ">");                                        \
+    } while (0)
+
+
+
+#define ESX_VI__TEMPLATE__ALLOC(_type)                                        \
+    int                                                                       \
+    esxVI_##_type##_Alloc(virConnectPtr conn, esxVI_##_type **ptrptr)         \
+    {                                                                         \
+        return esxVI_Alloc(conn, (void **)ptrptr, sizeof (esxVI_##_type));    \
+    }
+
+
+
+#define ESX_VI__TEMPLATE__FREE(_type, _body)                                  \
+    void                                                                      \
+    esxVI_##_type##_Free(esxVI_##_type **ptrptr)                              \
+    {                                                                         \
+        esxVI_##_type *item = NULL;                                           \
+                                                                              \
+        if (ptrptr == NULL || *ptrptr == NULL) {                              \
+            return;                                                           \
+        }                                                                     \
+                                                                              \
+        item = *ptrptr;                                                       \
+                                                                              \
+        _body                                                                 \
+                                                                              \
+        VIR_FREE(*ptrptr);                                                    \
+    }
+
+
+
+#define ESX_VI__TEMPLATE__LIST__APPEND(_type)                                 \
+    int                                                                       \
+    esxVI_##_type##_AppendToList(virConnectPtr conn, esxVI_##_type **list,    \
+                                 esxVI_##_type *item)                         \
+    {                                                                         \
+        return esxVI_List_Append(conn, (esxVI_List **)list,                   \
+                                 (esxVI_List *)item);                         \
+    }
+
+
+
+#define ESX_VI__TEMPLATE__LIST__DEEP_COPY(_type)                              \
+    int                                                                       \
+    esxVI_##_type##_DeepCopyList(virConnectPtr conn,                          \
+                                 esxVI_##_type **destList,                    \
+                                 esxVI_##_type *srcList)                      \
+    {                                                                         \
+        return esxVI_List_DeepCopy                                            \
+                 (conn, (esxVI_List **)destList, (esxVI_List *)srcList,       \
+                  (esxVI_List_DeepCopyFunc)esxVI_##_type##_DeepCopy,          \
+                  (esxVI_List_FreeFunc)esxVI_##_type##_Free);                 \
+    }
+
+
+
+#define ESX_VI__TEMPLATE__LIST__SERIALIZE(_type)                              \
+    int                                                                       \
+    esxVI_##_type##_SerializeList(virConnectPtr conn, esxVI_##_type *list,    \
+                                  const char* element, virBufferPtr output,   \
+                                  esxVI_Boolean required)                     \
+    {                                                                         \
+        return esxVI_List_Serialize(conn, (esxVI_List *)list,                 \
+                                    element, output, required,                \
+                                    (esxVI_List_SerializeFunc)                \
+                                      esxVI_##_type##_Serialize);             \
+    }
+
+
+
+#define ESX_VI__TEMPLATE__LIST__DESERIALIZE(_type)                            \
+    int                                                                       \
+    esxVI_##_type##_DeserializeList(virConnectPtr conn, xmlNodePtr node,      \
+                                    esxVI_##_type **list)                     \
+    {                                                                         \
+        return esxVI_List_Deserialize                                         \
+                 (conn, node, (esxVI_List **)list,                            \
+                  (esxVI_List_DeserializeFunc)esxVI_##_type##_Deserialize,    \
+                  (esxVI_List_FreeFunc)esxVI_##_type##_Free);                 \
+    }
+
+
+
+#define ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE(_type)                           \
+    int                                                                       \
+    esxVI_##_type##_CastFromAnyType(virConnectPtr conn,                       \
+                                    esxVI_AnyType *anyType,                   \
+                                    esxVI_##_type **ptrptr)                   \
+    {                                                                         \
+        if (anyType == NULL || ptrptr == NULL || *ptrptr != NULL) {           \
+            ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");   \
+            return -1;                                                        \
+        }                                                                     \
+                                                                              \
+        if (STRNEQ(anyType->other, #_type)) {                                 \
+            ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,                        \
+                         "Expecting type '%s' but found '%s'",                \
+                         #_type, anyType->other);                             \
+            return -1;                                                        \
+        }                                                                     \
+                                                                              \
+        return esxVI_##_type##_Deserialize(conn, anyType->_node, ptrptr);     \
+    }
+
+
+
+#define ESX_VI__TEMPLATE__SERIALIZE_EXTRA(_type, _type_string, _serialize)    \
+    int                                                                       \
+    esxVI_##_type##_Serialize(virConnectPtr conn,                             \
+                              esxVI_##_type *item,                            \
+                              const char *element, virBufferPtr output,       \
+                              esxVI_Boolean required)                         \
+    {                                                                         \
+        if (element == NULL || output == NULL ) {                             \
+            ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");   \
+            return -1;                                                        \
+        }                                                                     \
+                                                                              \
+        if (item == NULL) {                                                   \
+            return esxVI_CheckSerializationNecessity(conn, element,           \
+                                                     required);               \
+        }                                                                     \
+                                                                              \
+        ESV_VI__XML_TAG__OPEN(output, element, _type_string);                 \
+                                                                              \
+        _serialize                                                            \
+                                                                              \
+        ESV_VI__XML_TAG__CLOSE(output, element);                              \
+                                                                              \
+        return 0;                                                             \
+    }
+
+
+
+#define ESX_VI__TEMPLATE__SERIALIZE(_type, _serialize)                        \
+    ESX_VI__TEMPLATE__SERIALIZE_EXTRA(_type, #_type, _serialize)
+
+
+
+#define ESX_VI__TEMPLATE__DESERIALIZE(_type, _deserialize, _require)          \
+    int                                                                       \
+    esxVI_##_type##_Deserialize(virConnectPtr conn, xmlNodePtr node,          \
+                                esxVI_##_type **ptrptr)                       \
+    {                                                                         \
+        xmlNodePtr childNode = NULL;                                          \
+                                                                              \
+        if (ptrptr == NULL || *ptrptr != NULL) {                              \
+            ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");   \
+            return -1;                                                        \
+        }                                                                     \
+                                                                              \
+        if (esxVI_##_type##_Alloc(conn, ptrptr) < 0) {                        \
+            return -1;                                                        \
+        }                                                                     \
+                                                                              \
+        for (childNode = node->xmlChildrenNode; childNode != NULL;            \
+             childNode = childNode->next) {                                   \
+            if (childNode->type != XML_ELEMENT_NODE) {                        \
+                ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,                    \
+                             "Wrong XML element type %d", childNode->type);   \
+                goto failure;                                                 \
+            }                                                                 \
+                                                                              \
+            _deserialize                                                      \
+                                                                              \
+            VIR_WARN("Unexpected '%s' property", childNode->name);            \
+        }                                                                     \
+                                                                              \
+        _require                                                              \
+                                                                              \
+        return 0;                                                             \
+                                                                              \
+      failure:                                                                \
+        esxVI_##_type##_Free(ptrptr);                                         \
+                                                                              \
+        return -1;                                                            \
+    }
+
+
+
+#define ESX_VI__TEMPLATE__DESERIALIZE_NUMBER(_type, _xsdType, _min, _max)     \
+    int                                                                       \
+    esxVI_##_type##_Deserialize(virConnectPtr conn, xmlNodePtr node,          \
+                                esxVI_##_type **number)                       \
+    {                                                                         \
+        int result = 0;                                                       \
+        char *string;                                                         \
+        long long value;                                                      \
+                                                                              \
+        if (number == NULL || *number != NULL) {                              \
+            ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");   \
+            return -1;                                                        \
+        }                                                                     \
+                                                                              \
+        if (esxVI_##_type##_Alloc(conn, number) < 0) {                        \
+            return -1;                                                        \
+        }                                                                     \
+                                                                              \
+        string = (char *)xmlNodeListGetString(node->doc,                      \
+                                              node->xmlChildrenNode, 1);      \
+                                                                              \
+        if (string == NULL) {                                                 \
+            ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,                        \
+                         "XML node doesn't contain text, expecting an "       \
+                         _xsdType" value");                                   \
+            goto failure;                                                     \
+        }                                                                     \
+                                                                              \
+        if (virStrToLong_ll(string, NULL, 10, &value) < 0) {                  \
+            ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,                        \
+                         "Unknown value '%s' for "_xsdType, string);          \
+            goto failure;                                                     \
+        }                                                                     \
+                                                                              \
+        if (value < (_min) || value > (_max)) {                               \
+            ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,                        \
+                         "Value '%s' is not representable as "_xsdType,       \
+                         (const char *) string);                              \
+            goto failure;                                                     \
+        }                                                                     \
+                                                                              \
+        (*number)->value = value;                                             \
+                                                                              \
+      cleanup:                                                                \
+        VIR_FREE(string);                                                     \
+                                                                              \
+        return result;                                                        \
+                                                                              \
+      failure:                                                                \
+        esxVI_##_type##_Free(number);                                         \
+                                                                              \
+        result = -1;                                                          \
+                                                                              \
+        goto cleanup;                                                         \
+    }
+
+
+
+#define ESX_VI__TEMPLATE__PROPERTY__SERIALIZE(_type, _name, _required)        \
+    if (esxVI_##_type##_Serialize(conn, item->_name, #_name, output,          \
+                                  esxVI_Boolean_##_required) < 0) {           \
+        return -1;                                                            \
+    }
+
+
+
+#define ESX_VI__TEMPLATE__PROPERTY__SERIALIZE_VALUE(_type, _name, _required)  \
+    if (esxVI_##_type##_SerializeValue(conn, item->_name, #_name, output,     \
+                                       esxVI_Boolean_##_required) < 0) {      \
+        return -1;                                                            \
+    }
+
+
+
+#define ESX_VI__TEMPLATE__PROPERTY__SERIALIZE_LIST(_type, _name, _required)   \
+    if (esxVI_##_type##_SerializeList(conn, item->_name, #_name, output,      \
+                                      esxVI_Boolean_##_required) < 0) {       \
+        return -1;                                                            \
+    }
+
+
+
+#define ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(_type, _name)                 \
+    if (xmlStrEqual(childNode->name, BAD_CAST #_name)) {                      \
+        if (esxVI_##_type##_Deserialize(conn, childNode,                      \
+                                        &(*ptrptr)->_name) < 0) {             \
+            goto failure;                                                     \
+        }                                                                     \
+                                                                              \
+        continue;                                                             \
+    }
+
+
+
+#define ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(_type, _name)           \
+    if (xmlStrEqual(childNode->name, BAD_CAST #_name)) {                      \
+        if (esxVI_##_type##_DeserializeValue(conn, childNode,                 \
+                                             &(*ptrptr)->_name) < 0) {        \
+            goto failure;                                                     \
+        }                                                                     \
+                                                                              \
+        continue;                                                             \
+    }
+
+
+
+#define ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_EXPECTED(_type, _expected,    \
+                                                        _name)                \
+    if (xmlStrEqual(childNode->name, BAD_CAST #_name)) {                      \
+        if (esxVI_##_type##_Deserialize(conn, childNode, &(*ptrptr)->_name,   \
+                                        _expected) < 0) {                     \
+            goto failure;                                                     \
+        }                                                                     \
+                                                                              \
+        continue;                                                             \
+    }
+
+
+
+#define ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_NOOP(_name)                   \
+    if (xmlStrEqual(childNode->name, BAD_CAST #_name)) {                      \
+        continue;                                                             \
+    }
+
+
+
+#define ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_LIST(_type, _name)            \
+    if (xmlStrEqual(childNode->name, BAD_CAST #_name)) {                      \
+        esxVI_##_type *_name##Item = NULL;                                    \
+                                                                              \
+        if (esxVI_##_type##_Deserialize(conn, childNode, &_name##Item) < 0) { \
+            goto failure;                                                     \
+        }                                                                     \
+                                                                              \
+        if (esxVI_##_type##_AppendToList(conn, &(*ptrptr)->_name,             \
+                                         _name##Item) < 0) {                  \
+            esxVI_##_type##_Free(&_name##Item);                               \
+            goto failure;                                                     \
+        }                                                                     \
+                                                                              \
+        continue;                                                             \
+    }
+
+
+
+/*
+ * A required property must be != 0 (NULL for pointers, "undefined" == 0 for
+ * enumeration values).
+ */
+#define ESX_VI__TEMPLATE__PROPERTY__REQUIRED(_name)                           \
+    if ((*ptrptr)->_name == 0) {                                              \
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,                            \
+                     "Missing required '%s' property", #_name);               \
+        goto failure;                                                         \
+    }
+
+
+
+#define ESX_VI__TEMPLATE__ENUMERATION__CAST_FROM_ANY_TYPE(_type)              \
+    int                                                                       \
+    esxVI_##_type##_CastFromAnyType(virConnectPtr conn,                       \
+                                    esxVI_AnyType *anyType,                   \
+                                    esxVI_##_type *value)                     \
+    {                                                                         \
+        return esxVI_Enumeration_CastFromAnyType                              \
+                 (conn, &_esxVI_##_type##_Enumeration, anyType,               \
+                  (int *)value);                                              \
+    }
+
+
+
+#define ESX_VI__TEMPLATE__ENUMERATION__SERIALIZE(_type)                       \
+    int                                                                       \
+    esxVI_##_type##_Serialize(virConnectPtr conn, esxVI_##_type value,        \
+                              const char *element, virBufferPtr output,       \
+                              esxVI_Boolean required)                         \
+    {                                                                         \
+        return esxVI_Enumeration_Serialize(conn,                              \
+                                           &_esxVI_##_type##_Enumeration,     \
+                                           value, element, output,            \
+                                           required);                         \
+    }
+
+
+
+#define ESX_VI__TEMPLATE__ENUMERATION__DESERIALIZE(_type)                     \
+    int                                                                       \
+    esxVI_##_type##_Deserialize(virConnectPtr conn, xmlNodePtr node,          \
+                                esxVI_##_type *value)                         \
+    {                                                                         \
+        return esxVI_Enumeration_Deserialize(conn,                            \
+                                             &_esxVI_##_type##_Enumeration,   \
+                                             node, (int *)value);             \
+    }
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * XSI: Type
+ */
+
+const char *
+esxVI_Type_Name(esxVI_Type type)
+{
+    switch (type) {
+      case esxVI_Type_Undefined:
+        return "undefined";
+
+      case esxVI_Type_Boolean:
+        return "xsd:boolean";
+
+      case esxVI_Type_String:
+        return "xsd:string";
+
+      case esxVI_Type_Short:
+        return "xsd:short";
+
+      case esxVI_Type_Int:
+        return "xsd:int";
+
+      case esxVI_Type_Long:
+        return "xsd:long";
+
+      case esxVI_Type_Other:
+        return "other";
+
+      default:
+        return "unknown";
+    }
+}
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * XSD: Boolean
+ */
+
+static const esxVI_Enumeration _esxVI_Boolean_Enumeration = {
+    "xsd:boolean", {
+        { "true", esxVI_Boolean_True },
+        { "false", esxVI_Boolean_False },
+        { NULL, -1 },
+    },
+};
+
+/* esxVI_Boolean_Serialize */
+ESX_VI__TEMPLATE__ENUMERATION__SERIALIZE(Boolean);
+
+/* esxVI_Boolean_Deserialize */
+ESX_VI__TEMPLATE__ENUMERATION__DESERIALIZE(Boolean);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * XSD: AnyType
+ */
+
+/* esxVI_AnyType_Alloc */
+ESX_VI__TEMPLATE__ALLOC(AnyType);
+
+/* esxVI_AnyType_Free */
+ESX_VI__TEMPLATE__FREE(AnyType,
+{
+    xmlFreeNode(item->_node);
+    VIR_FREE(item->other);
+    VIR_FREE(item->value);
+});
+
+int
+esxVI_AnyType_ExpectType(virConnectPtr conn, esxVI_AnyType *anyType,
+                         esxVI_Type type)
+{
+    if (anyType->type != type) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                     "Expecting type '%s' but found '%s'",
+                     esxVI_Type_Name(type),
+                     anyType->type != esxVI_Type_Other
+                       ? esxVI_Type_Name(anyType->type)
+                       : anyType->other);
+        return -1;
+    }
+
+    return 0;
+}
+
+int
+esxVI_AnyType_DeepCopy(virConnectPtr conn, esxVI_AnyType **dest,
+                       esxVI_AnyType *src)
+{
+    if (dest == NULL || *dest != NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    if (src == NULL) {
+        return 0;
+    }
+
+    if (esxVI_AnyType_Alloc(conn, dest) < 0) {
+        goto failure;
+    }
+
+    (*dest)->_node = xmlCopyNode(src->_node, 1);
+
+    if ((*dest)->_node == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                     "Could not copy an XML node");
+        goto failure;
+    }
+
+    (*dest)->type = src->type;
+
+    if (esxVI_String_DeepCopyValue(conn, &(*dest)->other, src->other) < 0 ||
+        esxVI_String_DeepCopyValue(conn, &(*dest)->value, src->value) < 0) {
+        goto failure;
+    }
+
+    switch (src->type) {
+      case esxVI_Type_Boolean:
+        (*dest)->boolean = src->boolean;
+        break;
+
+      case esxVI_Type_String:
+        (*dest)->string = (*dest)->value;
+        break;
+
+      case esxVI_Type_Short:
+        (*dest)->int16 = src->int16;
+        break;
+
+      case esxVI_Type_Int:
+        (*dest)->int32 = src->int32;
+        break;
+
+      case esxVI_Type_Long:
+        (*dest)->int64 = src->int64;
+        break;
+
+      default:
+        break;
+    }
+
+    return 0;
+
+  failure:
+    esxVI_AnyType_Free(dest);
+
+    return -1;
+}
+
+int
+esxVI_AnyType_Deserialize(virConnectPtr conn, xmlNodePtr node,
+                          esxVI_AnyType **anyType)
+{
+    long long number;
+
+    if (anyType == NULL || *anyType != NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    if (esxVI_AnyType_Alloc(conn, anyType) < 0) {
+        return -1;
+    }
+
+    (*anyType)->_node = xmlCopyNode(node, 1);
+
+    if ((*anyType)->_node == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                     "Could not copy an XML node");
+        goto failure;
+    }
+
+    (*anyType)->other =
+      (char *)xmlGetNsProp
+                (node, BAD_CAST "type",
+                 BAD_CAST "http://www.w3.org/2001/XMLSchema-instance";);
+
+    if ((*anyType)->other == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Missing 'type' property");
+        goto failure;
+    }
+
+    (*anyType)->value =
+      (char *)xmlNodeListGetString(node->doc, node->xmlChildrenNode, 1);
+
+    if ((*anyType)->value == NULL) {
+        (*anyType)->value = strdup("");
+
+        if ((*anyType)->value == NULL) {
+            virReportOOMError(conn);
+            goto failure;
+        }
+    }
+
+    #define _DESERIALIZE_NUMBER(_type, _xsdType, _name, _min, _max)           \
+        do {                                                                  \
+            if (virStrToLong_ll((*anyType)->value, NULL, 10, &number) < 0) {  \
+                ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,                    \
+                             "Unknown value '%s' for "_xsdType,               \
+                             (*anyType)->value);                              \
+                goto failure;                                                 \
+            }                                                                 \
+                                                                              \
+            if (number < (_min) || number > (_max)) {                         \
+                ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,                    \
+                             "Value '%s' is out of "_xsdType" range",         \
+                             (*anyType)->value);                              \
+                goto failure;                                                 \
+            }                                                                 \
+                                                                              \
+            (*anyType)->type = esxVI_Type_##_type;                            \
+            (*anyType)->_name = number;                                       \
+        } while (0)
+
+    if (STREQ((*anyType)->other, "xsd:boolean")) {
+        (*anyType)->type = esxVI_Type_Boolean;
+
+        if (STREQ((*anyType)->value, "true")) {
+            (*anyType)->boolean = esxVI_Boolean_True;
+        } else if (STREQ((*anyType)->value, "false")) {
+            (*anyType)->boolean = esxVI_Boolean_False;
+        } else {
+            ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                         "Unknown value '%s' for xsd:boolean",
+                         (*anyType)->value);
+            goto failure;
+        }
+    } else if (STREQ((*anyType)->other, "xsd:string")) {
+        (*anyType)->type = esxVI_Type_String;
+        (*anyType)->string = (*anyType)->value;
+    } else if (STREQ((*anyType)->other, "xsd:short")) {
+        _DESERIALIZE_NUMBER(Short, "xsd:short", int16, INT16_MIN, INT16_MAX);
+    } else if (STREQ((*anyType)->other, "xsd:int")) {
+        _DESERIALIZE_NUMBER(Int, "xsd:int", int32, INT32_MIN, INT32_MAX);
+    } else if (STREQ((*anyType)->other, "xsd:long")) {
+        _DESERIALIZE_NUMBER(Long, "xsd:long", int64, INT64_MIN, INT64_MAX);
+    }
+
+    #undef _DESERIALIZE_NUMBER
+
+    return 0;
+
+  failure:
+    esxVI_AnyType_Free(anyType);
+
+    return -1;
+}
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * XSD: String
+ */
+
+/* esxVI_String_Alloc */
+ESX_VI__TEMPLATE__ALLOC(String);
+
+/* esxVI_String_Free */
+ESX_VI__TEMPLATE__FREE(String,
+{
+    esxVI_String_Free(&item->_next);
+
+    VIR_FREE(item->value);
+});
+
+/* esxVI_String_AppendToList */
+ESX_VI__TEMPLATE__LIST__APPEND(String);
+
+int
+esxVI_String_AppendValueToList(virConnectPtr conn,
+                               esxVI_String **stringList, const char *value)
+{
+    esxVI_String *string = NULL;
+
+    if (esxVI_String_Alloc(conn, &string) < 0) {
+        goto failure;
+    }
+
+    string->value = strdup(value);
+
+    if (string->value == NULL) {
+        virReportOOMError(conn);
+        goto failure;
+    }
+
+    if (esxVI_String_AppendToList(conn, stringList, string) < 0) {
+        goto failure;
+    }
+
+    return 0;
+
+  failure:
+    esxVI_String_Free(&string);
+
+    return -1;
+}
+
+int
+esxVI_String_AppendValueListToList(virConnectPtr conn,
+                                   esxVI_String **stringList,
+                                   const char *valueList)
+{
+    esxVI_String *stringListToAppend = NULL;
+    const char *value = valueList;
+
+    while (value != NULL && *value != '\0') {
+        if (esxVI_String_AppendValueToList(conn, &stringListToAppend,
+                                           value) < 0) {
+            goto failure;
+        }
+
+        value += strlen(value) + 1;
+    }
+
+    if (esxVI_String_AppendToList(conn, stringList, stringListToAppend) < 0) {
+        goto failure;
+    }
+
+    return 0;
+
+  failure:
+    esxVI_String_Free(&stringListToAppend);
+
+    return -1;
+}
+
+int
+esxVI_String_DeepCopy(virConnectPtr conn, esxVI_String **dest,
+                      esxVI_String *src)
+{
+    if (dest == NULL || *dest != NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    if (src == NULL) {
+        return 0;
+    }
+
+    if (esxVI_String_Alloc(conn, dest) < 0 ||
+        esxVI_String_DeepCopyValue(conn, &(*dest)->value, src->value)) {
+        goto failure;
+    }
+
+    return 0;
+
+  failure:
+    esxVI_String_Free(dest);
+
+    return -1;
+}
+
+/* esxVI_String_DeepCopyList */
+ESX_VI__TEMPLATE__LIST__DEEP_COPY(String);
+
+int
+esxVI_String_DeepCopyValue(virConnectPtr conn, char **dest, const char *src)
+{
+    if (dest == NULL || *dest != NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    if (src == NULL) {
+        return 0;
+    }
+
+    *dest = strdup(src);
+
+    if (*dest == NULL) {
+        virReportOOMError(conn);
+        return -1;
+    }
+
+    return 0;
+}
+
+int
+esxVI_String_Serialize(virConnectPtr conn, esxVI_String *string,
+                       const char *element, virBufferPtr output,
+                       esxVI_Boolean required)
+{
+    return esxVI_String_SerializeValue(conn,
+                                       string != NULL ? string->value : NULL,
+                                       element, output, required);
+}
+
+/* esxVI_String_SerializeList */
+ESX_VI__TEMPLATE__LIST__SERIALIZE(String);
+
+int
+esxVI_String_SerializeValue(virConnectPtr conn, const char *value,
+                            const char *element, virBufferPtr output,
+                            esxVI_Boolean required)
+{
+    if (element == NULL || output == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    if (value == NULL) {
+        return esxVI_CheckSerializationNecessity(conn, element, required);
+    }
+
+    ESV_VI__XML_TAG__OPEN(output, element, "xsd:string");
+
+    virBufferAdd(output, value, -1);
+
+    ESV_VI__XML_TAG__CLOSE(output, element);
+
+    return 0;
+}
+
+int
+esxVI_String_Deserialize(virConnectPtr conn, xmlNodePtr node,
+                         esxVI_String **string)
+{
+    if (string == NULL || *string != NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    if (esxVI_String_Alloc(conn, string) < 0) {
+        return -1;
+    }
+
+    (*string)->value =
+      (char *)xmlNodeListGetString(node->doc, node->xmlChildrenNode, 1);
+
+    if ((*string)->value == NULL) {
+        (*string)->value = strdup("");
+
+        if ((*string)->value == NULL) {
+            virReportOOMError(conn);
+            goto failure;
+        }
+    }
+
+    return 0;
+
+  failure:
+    esxVI_String_Free(string);
+
+    return -1;
+}
+
+/* esxVI_String_DeserializeList */
+ESX_VI__TEMPLATE__LIST__DESERIALIZE(String);
+
+int
+esxVI_String_DeserializeValue(virConnectPtr conn, xmlNodePtr node,
+                              char **value)
+{
+    if (value == NULL || *value != NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    *value = (char *)xmlNodeListGetString(node->doc, node->xmlChildrenNode, 1);
+
+    if (*value == NULL) {
+        *value = strdup("");
+
+        if (*value == NULL) {
+            virReportOOMError(conn);
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * XSD: Int
+ */
+
+/* esxVI_Int_Alloc */
+ESX_VI__TEMPLATE__ALLOC(Int);
+
+/* esxVI_Int_Free */
+ESX_VI__TEMPLATE__FREE(Int,
+{
+    esxVI_Int_Free(&item->_next);
+});
+
+/* esxVI_Int_AppendToList */
+ESX_VI__TEMPLATE__LIST__APPEND(Int);
+
+int
+esxVI_Int_DeepCopy(virConnectPtr conn, esxVI_Int **dest, esxVI_Int *src)
+{
+    if (dest == NULL || *dest != NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    if (src == NULL) {
+        return 0;
+    }
+
+    if (esxVI_Int_Alloc(conn, dest) < 0) {
+        goto failure;
+    }
+
+    (*dest)->value = src->value;
+
+    return 0;
+
+  failure:
+    esxVI_Int_Free(dest);
+
+    return -1;
+}
+
+/* esxVI_Int_Serialize */
+ESX_VI__TEMPLATE__SERIALIZE_EXTRA(Int, "xsd:int",
+{
+    virBufferVSprintf(output, "%"PRIi32, item->value);
+});
+
+/* esxVI_Int_SerializeList */
+ESX_VI__TEMPLATE__LIST__SERIALIZE(Int);
+
+/* esxVI_Int_Deserialize */
+ESX_VI__TEMPLATE__DESERIALIZE_NUMBER(Int, "xsd:int", INT32_MIN, INT32_MAX);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * XSD: Long
+ */
+
+/* esxVI_Long_Alloc */
+ESX_VI__TEMPLATE__ALLOC(Long);
+
+/* esxVI_Long_Free */
+ESX_VI__TEMPLATE__FREE(Long,
+{
+    esxVI_Long_Free(&item->_next);
+});
+
+/* esxVI_Long_AppendToList */
+ESX_VI__TEMPLATE__LIST__APPEND(Long);
+
+/* esxVI_Long_Serialize */
+ESX_VI__TEMPLATE__SERIALIZE_EXTRA(Long, "xsd:long",
+{
+    virBufferVSprintf(output, "%"PRIi64, item->value);
+});
+
+/* esxVI_Long_SerializeList */
+ESX_VI__TEMPLATE__LIST__SERIALIZE(Long);
+
+
+/* esxVI_Long_Deserialize */
+ESX_VI__TEMPLATE__DESERIALIZE_NUMBER(Long, "xsd:long", INT64_MIN, INT64_MAX);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * XSD: DateTime
+ */
+
+/* esxVI_DateTime_Alloc */
+ESX_VI__TEMPLATE__ALLOC(DateTime);
+
+/* esxVI_DateTime_Free */
+ESX_VI__TEMPLATE__FREE(DateTime,
+{
+    VIR_FREE(item->value);
+});
+
+/* esxVI_DateTime_Serialize */
+ESX_VI__TEMPLATE__SERIALIZE_EXTRA(DateTime, "xsd:dateTime",
+{
+    virBufferAdd(output, item->value, -1);
+});
+
+int
+esxVI_DateTime_Deserialize(virConnectPtr conn, xmlNodePtr node,
+                           esxVI_DateTime **dateTime)
+{
+    if (dateTime == NULL || *dateTime != NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    if (esxVI_DateTime_Alloc(conn, dateTime) < 0) {
+        return -1;
+    }
+
+    (*dateTime)->value =
+      (char *)xmlNodeListGetString(node->doc, node->xmlChildrenNode, 1);
+
+    if ((*dateTime)->value == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                     "XML node doesn't contain text, expecting an "
+                     "xsd:dateTime value");
+        goto failure;
+    }
+
+    return 0;
+
+  failure:
+    esxVI_DateTime_Free(dateTime);
+
+    return -1;
+}
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Enum: ObjectUpdateKind
+ */
+
+static const esxVI_Enumeration _esxVI_ObjectUpdateKind_Enumeration = {
+    "ObjectUpdateKind", {
+        { "enter", esxVI_ObjectUpdateKind_Enter },
+        { "leave", esxVI_ObjectUpdateKind_Leave },
+        { "modify", esxVI_ObjectUpdateKind_Modify },
+        { NULL, -1 },
+    },
+};
+
+/* esxVI_ObjectUpdateKind_Deserialize */
+ESX_VI__TEMPLATE__ENUMERATION__DESERIALIZE(ObjectUpdateKind);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Enum: PerfSummaryType
+ */
+
+static const esxVI_Enumeration _esxVI_PerfSummaryType_Enumeration = {
+    "PerfSummaryType", {
+        { "average", esxVI_PerfSummaryType_Average },
+        { "latest", esxVI_PerfSummaryType_Latest },
+        { "maximum", esxVI_PerfSummaryType_Maximum },
+        { "minimum", esxVI_PerfSummaryType_Minimum },
+        { "none", esxVI_PerfSummaryType_None },
+        { "summation", esxVI_PerfSummaryType_Summation },
+        { NULL, -1 },
+    },
+};
+
+/* esxVI_PerfSummaryType_Deserialize */
+ESX_VI__TEMPLATE__ENUMERATION__DESERIALIZE(PerfSummaryType);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Enum: PerfStatsType
+ */
+
+static const esxVI_Enumeration _esxVI_PerfStatsType_Enumeration = {
+    "PerfStatsType", {
+        { "absolute", esxVI_PerfStatsType_Absolute },
+        { "delta", esxVI_PerfStatsType_Delta },
+        { "rate", esxVI_PerfStatsType_Rate },
+        { NULL, -1 },
+    },
+};
+
+/* esxVI_PerfStatsType_Deserialize */
+ESX_VI__TEMPLATE__ENUMERATION__DESERIALIZE(PerfStatsType);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Enum: PropertyChangeOp
+ */
+
+static const esxVI_Enumeration _esxVI_PropertyChangeOp_Enumeration = {
+    "PropertyChangeOp", {
+        { "add", esxVI_PropertyChangeOp_Add },
+        { "remove", esxVI_PropertyChangeOp_Remove },
+        { "assign", esxVI_PropertyChangeOp_Assign },
+        { "indirectRemove", esxVI_PropertyChangeOp_IndirectRemove },
+        { NULL, -1 },
+    },
+};
+
+/* esxVI_PropertyChangeOp_Deserialize */
+ESX_VI__TEMPLATE__ENUMERATION__DESERIALIZE(PropertyChangeOp);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Enum: SharesLevel
+ */
+
+static const esxVI_Enumeration _esxVI_SharesLevel_Enumeration = {
+    "SharesLevel", {
+        { "custom", esxVI_SharesLevel_Custom },
+        { "high", esxVI_SharesLevel_High },
+        { "low", esxVI_SharesLevel_Low },
+        { "normal", esxVI_SharesLevel_Normal },
+        { NULL, -1 },
+    },
+};
+
+/* esxVI_SharesLevel_Serialize */
+ESX_VI__TEMPLATE__ENUMERATION__SERIALIZE(SharesLevel);
+
+/* esxVI_SharesLevel_Deserialize */
+ESX_VI__TEMPLATE__ENUMERATION__DESERIALIZE(SharesLevel);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Enum: TaskInfoState
+ */
+
+static const esxVI_Enumeration _esxVI_TaskInfoState_Enumeration = {
+    "TaskInfoState", {
+        { "error", esxVI_TaskInfoState_Error },
+        { "queued", esxVI_TaskInfoState_Queued },
+        { "running", esxVI_TaskInfoState_Running },
+        { "success", esxVI_TaskInfoState_Success },
+        { NULL, -1 },
+    },
+};
+
+/* esxVI_TaskInfoState_CastFromAnyType */
+ESX_VI__TEMPLATE__ENUMERATION__CAST_FROM_ANY_TYPE(TaskInfoState);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Enum: VirtualMachineMovePriority
+ */
+
+static const esxVI_Enumeration _esxVI_VirtualMachineMovePriority_Enumeration = {
+    "VirtualMachineMovePriority", {
+        { "lowPriority", esxVI_VirtualMachineMovePriority_LowPriority },
+        { "highPriority", esxVI_VirtualMachineMovePriority_HighPriority },
+        { "defaultPriority", esxVI_VirtualMachineMovePriority_DefaultPriority },
+        { NULL, -1 },
+    },
+};
+
+/* esxVI_VirtualMachineMovePriority_Serialize */
+ESX_VI__TEMPLATE__ENUMERATION__SERIALIZE(VirtualMachineMovePriority);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Enum: VirtualMachinePowerState
+ */
+
+static const esxVI_Enumeration _esxVI_VirtualMachinePowerState_Enumeration = {
+    "VirtualMachinePowerState", {
+        { "poweredOff", esxVI_VirtualMachinePowerState_PoweredOff },
+        { "poweredOn", esxVI_VirtualMachinePowerState_PoweredOn },
+        { "suspended", esxVI_VirtualMachinePowerState_Suspended },
+        { NULL, -1 },
+    },
+};
+
+/* esxVI_VirtualMachinePowerState_CastFromAnyType */
+ESX_VI__TEMPLATE__ENUMERATION__CAST_FROM_ANY_TYPE(VirtualMachinePowerState);
+
+/* esxVI_VirtualMachinePowerState_Serialize */
+ESX_VI__TEMPLATE__ENUMERATION__SERIALIZE(VirtualMachinePowerState);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: Fault
+ */
+
+/* esxVI_Fault_Alloc */
+ESX_VI__TEMPLATE__ALLOC(Fault);
+
+/* esxVI_Fault_Free */
+ESX_VI__TEMPLATE__FREE(Fault,
+{
+    VIR_FREE(item->faultcode);
+    VIR_FREE(item->faultstring);
+});
+
+/* esxVI_Fault_Deserialize */
+ESX_VI__TEMPLATE__DESERIALIZE(Fault,
+{
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, faultcode);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, faultstring);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_NOOP(detail); /* FIXME */
+},
+{
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(faultcode);
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(faultstring);
+});
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: ManagedObjectReference
+ */
+
+/* esxVI_ManagedObjectReference_Alloc */
+ESX_VI__TEMPLATE__ALLOC(ManagedObjectReference);
+
+/* esxVI_ManagedObjectReference_Free */
+ESX_VI__TEMPLATE__FREE(ManagedObjectReference,
+{
+    esxVI_ManagedObjectReference_Free(&item->_next);
+
+    VIR_FREE(item->type);
+    VIR_FREE(item->value);
+});
+
+int
+esxVI_ManagedObjectReference_DeepCopy(virConnectPtr conn,
+                                      esxVI_ManagedObjectReference **dest,
+                                      esxVI_ManagedObjectReference *src)
+{
+    if (dest == NULL || *dest != NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    if (src == NULL) {
+        return 0;
+    }
+
+    if (esxVI_ManagedObjectReference_Alloc(conn, dest) < 0 ||
+        esxVI_String_DeepCopyValue(conn, &(*dest)->type, src->type) < 0 ||
+        esxVI_String_DeepCopyValue(conn, &(*dest)->value, src->value) < 0) {
+        goto failure;
+    }
+
+    return 0;
+
+  failure:
+    esxVI_ManagedObjectReference_Free(dest);
+
+    return -1;
+}
+
+int
+esxVI_ManagedObjectReference_CastFromAnyType
+  (virConnectPtr conn, esxVI_AnyType *anyType,
+   esxVI_ManagedObjectReference **managedObjectReference,
+   const char *expectedType)
+{
+    if (anyType == NULL || managedObjectReference == NULL ||
+        *managedObjectReference != NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    if (STRNEQ(anyType->other, "ManagedObjectReference")) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                     "Expecting type 'ManagedObjectReference' but found '%s'",
+                     anyType->other);
+        return -1;
+    }
+
+    return esxVI_ManagedObjectReference_Deserialize(conn, anyType->_node,
+                                                    managedObjectReference,
+                                                    expectedType);
+}
+
+int
+esxVI_ManagedObjectReference_Serialize
+  (virConnectPtr conn, esxVI_ManagedObjectReference *managedObjectReference,
+   const char *element, virBufferPtr output, esxVI_Boolean required)
+{
+    if (element == NULL || output == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    if (managedObjectReference == NULL) {
+        return esxVI_CheckSerializationNecessity(conn, element, required);
+    }
+
+    virBufferAddLit(output, "<");
+    virBufferAdd(output, element, -1);
+    virBufferVSprintf(output,
+                      " xmlns=\"urn:vim25\" "
+                      "xsi:type=\"ManagedObjectReference\" type=\"%s\">",
+                      managedObjectReference->type);
+
+    virBufferAdd(output, managedObjectReference->value, -1);
+
+    ESV_VI__XML_TAG__CLOSE(output, element);
+
+    return 0;
+}
+
+/* esxVI_ManagedObjectReference_SerializeList */
+ESX_VI__TEMPLATE__LIST__SERIALIZE(ManagedObjectReference);
+
+int
+esxVI_ManagedObjectReference_Deserialize
+  (virConnectPtr conn, xmlNodePtr node,
+   esxVI_ManagedObjectReference **managedObjectReference,
+   const char *expectedType)
+{
+    if (managedObjectReference == NULL || *managedObjectReference != NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    if (esxVI_ManagedObjectReference_Alloc(conn, managedObjectReference) < 0) {
+        return -1;
+    }
+
+    (*managedObjectReference)->type =
+      (char *)xmlGetNoNsProp(node, BAD_CAST "type");
+
+    if ((*managedObjectReference)->type == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Missing 'type' property");
+        goto failure;
+    }
+
+    if (expectedType != NULL &&
+        !STREQ(expectedType, (*managedObjectReference)->type)) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                     "Expected type '%s' but found '%s'", expectedType,
+                     (*managedObjectReference)->type);
+        goto failure;
+    }
+
+    if (esxVI_String_DeserializeValue(conn, node,
+                                      &(*managedObjectReference)->value) < 0) {
+        goto failure;
+    }
+
+    return 0;
+
+  failure:
+    esxVI_ManagedObjectReference_Free(managedObjectReference);
+
+    return -1;
+}
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: DynamicProperty
+ */
+
+/* esxVI_DynamicProperty_Alloc */
+ESX_VI__TEMPLATE__ALLOC(DynamicProperty);
+
+/* esxVI_DynamicProperty_Free */
+ESX_VI__TEMPLATE__FREE(DynamicProperty,
+{
+    esxVI_DynamicProperty_Free(&item->_next);
+
+    VIR_FREE(item->name);
+    esxVI_AnyType_Free(&item->val);
+});
+
+int
+esxVI_DynamicProperty_DeepCopy(virConnectPtr conn,
+                               esxVI_DynamicProperty **dest,
+                               esxVI_DynamicProperty *src)
+{
+    if (dest == NULL || *dest != NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    if (src == NULL) {
+        return 0;
+    }
+
+    if (esxVI_DynamicProperty_Alloc(conn, dest) < 0 ||
+        esxVI_String_DeepCopyValue(conn, &(*dest)->name, src->name) < 0 ||
+        esxVI_AnyType_DeepCopy(conn, &(*dest)->val, src->val) < 0) {
+        goto failure;
+    }
+
+    return 0;
+
+  failure:
+    esxVI_DynamicProperty_Free(dest);
+
+    return -1;
+}
+
+/* esxVI_DynamicProperty_DeepCopyList */
+ESX_VI__TEMPLATE__LIST__DEEP_COPY(DynamicProperty);
+
+/* esxVI_DynamicProperty_AppendToList */
+ESX_VI__TEMPLATE__LIST__APPEND(DynamicProperty);
+
+/* esxVI_DynamicProperty_Deserialize */
+ESX_VI__TEMPLATE__DESERIALIZE(DynamicProperty,
+{
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, name);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(AnyType, val);
+},
+{
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(name);
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(val);
+});
+
+/* esxVI_DynamicProperty_DeserializeList */
+ESX_VI__TEMPLATE__LIST__DESERIALIZE(DynamicProperty);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: SelectionSpec
+ */
+
+/* esxVI_SelectionSpec_Alloc */
+ESX_VI__TEMPLATE__ALLOC(SelectionSpec);
+
+void
+esxVI_SelectionSpec_Free(esxVI_SelectionSpec **selectionSpec)
+{
+    esxVI_SelectionSpec *local = NULL;
+
+    if (selectionSpec == NULL || *selectionSpec == NULL) {
+        return;
+    }
+
+    esxVI_SelectionSpec_Free(&(*selectionSpec)->_next);
+
+    if ((*selectionSpec)->_super != NULL) {
+        /*
+         * Explicitly set this pointer to NULL here, otherwise this is will
+         * result in a dangling pointer. The actual memory of this object is
+         * freed by a call from the esxVI_TraversalSpec_Free function to the
+         * esxVI_SelectionSpec_Free function with the base pointer.
+         *
+         * Use a local copy of the pointer and set the reference to NULL,
+         * otherwise Valgrind complains about invalid writes.
+         */
+        local = *selectionSpec;
+        *selectionSpec = NULL;
+
+        esxVI_TraversalSpec_Free(&local->_super);
+    } else {
+        VIR_FREE((*selectionSpec)->name);
+
+        VIR_FREE(*selectionSpec);
+    }
+}
+
+/* esxVI_SelectionSpec_AppendToList */
+ESX_VI__TEMPLATE__LIST__APPEND(SelectionSpec);
+
+int
+esxVI_SelectionSpec_Serialize(virConnectPtr conn,
+                              esxVI_SelectionSpec *selectionSpec,
+                              const char *element, virBufferPtr output,
+                              esxVI_Boolean required)
+{
+    if (element == NULL || output == NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    if (selectionSpec == NULL) {
+        return esxVI_CheckSerializationNecessity(conn, element, required);
+    }
+
+    if (selectionSpec->_super != NULL) {
+        return esxVI_TraversalSpec_Serialize(conn, selectionSpec->_super,
+                                             element, output, required);
+    }
+
+    ESV_VI__XML_TAG__OPEN(output, element, "SelectionSpec");
+
+    if (esxVI_String_SerializeValue(conn, selectionSpec->name, "name", output,
+                                    esxVI_Boolean_False) < 0) {
+        return -1;
+    }
+
+    ESV_VI__XML_TAG__CLOSE(output, element);
+
+    return 0;
+}
+
+/* esxVI_SelectionSpec_SerializeList */
+ESX_VI__TEMPLATE__LIST__SERIALIZE(SelectionSpec);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: TraversalSpec extends SelectionSpec
+ */
+
+int
+esxVI_TraversalSpec_Alloc(virConnectPtr conn,
+                          esxVI_TraversalSpec **traversalSpec)
+{
+    if (esxVI_Alloc(conn, (void **)traversalSpec,
+                    sizeof (esxVI_TraversalSpec)) < 0) {
+        return -1;
+    }
+
+    if (esxVI_SelectionSpec_Alloc(conn, &(*traversalSpec)->_base) < 0) {
+        esxVI_TraversalSpec_Free(traversalSpec);
+        return -1;
+    }
+
+    (*traversalSpec)->_base->_super = *traversalSpec;
+
+    return 0;
+}
+
+void
+esxVI_TraversalSpec_Free(esxVI_TraversalSpec **traversalSpec)
+{
+    esxVI_TraversalSpec *local = NULL;
+
+    if (traversalSpec == NULL || *traversalSpec == NULL) {
+        return;
+    }
+
+    /*
+     * Need to store the traversalSpec pointer in a local variable here,
+     * because it is possible that the traversalSpec pointer and the _super
+     * pointer represent the same location in memory, e.g. if
+     * esxVI_SelectionSpec_Free calls esxVI_TraversalSpec_Free with the _super
+     * pointer as argument. Setting the _super pointer to NULL sets the
+     * traversalSpec pointer also to NULL, because we're working on a reference
+     * to this pointer here.
+     *
+     * Also use a local copy of the pointer and set the reference to NULL,
+     * otherwise Valgrind complains about invalid writes.
+     */
+    local = *traversalSpec;
+    *traversalSpec = NULL;
+
+    /*
+     * Setting the _super pointer to NULL here is important, otherwise
+     * esxVI_SelectionSpec_Free would call esxVI_TraversalSpec_Free again,
+     * resulting in both functions calling each other trying to free the
+     * _base/_super object until a stackoverflow occurs.
+     */
+    local->_base->_super = NULL;
+
+    esxVI_SelectionSpec_Free(&local->_base);
+    VIR_FREE(local->type);
+    VIR_FREE(local->path);
+    esxVI_SelectionSpec_Free(&local->selectSet);
+
+    VIR_FREE(local);
+}
+
+/* esxVI_TraversalSpec_Serialize */
+ESX_VI__TEMPLATE__SERIALIZE(TraversalSpec,
+{
+    if (esxVI_String_SerializeValue(conn, item->_base->name, "name", output,
+                                    esxVI_Boolean_False) < 0) {
+        return -1;
+    }
+
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE_VALUE(String, type, True);
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE_VALUE(String, path, True);
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE(Boolean, skip, False);
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE_LIST(SelectionSpec, selectSet, False);
+});
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: ObjectSpec
+ */
+
+/* esxVI_ObjectSpec_Alloc */
+ESX_VI__TEMPLATE__ALLOC(ObjectSpec);
+
+/* esxVI_ObjectSpec_Free */
+ESX_VI__TEMPLATE__FREE(ObjectSpec,
+{
+    esxVI_ObjectSpec_Free(&item->_next);
+
+    esxVI_ManagedObjectReference_Free(&item->obj);
+    esxVI_SelectionSpec_Free(&item->selectSet);
+});
+
+/* esxVI_ObjectSpec_AppendToList */
+ESX_VI__TEMPLATE__LIST__APPEND(ObjectSpec);
+
+/* esxVI_ObjectSpec_Serialize */
+ESX_VI__TEMPLATE__SERIALIZE(ObjectSpec,
+{
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE(ManagedObjectReference, obj, True);
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE(Boolean, skip, False);
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE_LIST(SelectionSpec, selectSet, False);
+});
+
+/* esxVI_ObjectSpec_SerializeList */
+ESX_VI__TEMPLATE__LIST__SERIALIZE(ObjectSpec);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: PropertyChange
+ */
+
+/* esxVI_PropertyChange_Alloc */
+ESX_VI__TEMPLATE__ALLOC(PropertyChange);
+
+/* esxVI_PropertyChange_Free */
+ESX_VI__TEMPLATE__FREE(PropertyChange,
+{
+    esxVI_PropertyChange_Free(&item->_next);
+
+    VIR_FREE(item->name);
+    esxVI_AnyType_Free(&item->val);
+});
+
+/* esxVI_PropertyChange_AppendToList */
+ESX_VI__TEMPLATE__LIST__APPEND(PropertyChange);
+
+/* esxVI_PropertyChange_Deserialize */
+ESX_VI__TEMPLATE__DESERIALIZE(PropertyChange,
+{
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, name);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(PropertyChangeOp, op);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(AnyType, val);
+},
+{
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(name);
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(op);
+});
+
+/* esxVI_PropertyChange_DeserializeList */
+ESX_VI__TEMPLATE__LIST__DESERIALIZE(PropertyChange);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: PropertySpec
+ */
+
+/* esxVI_PropertySpec_Alloc */
+ESX_VI__TEMPLATE__ALLOC(PropertySpec);
+
+/* esxVI_PropertySpec_Free */
+ESX_VI__TEMPLATE__FREE(PropertySpec,
+{
+    esxVI_PropertySpec_Free(&item->_next);
+
+    VIR_FREE(item->type);
+    esxVI_String_Free(&item->pathSet);
+});
+
+/* esxVI_PropertySpec_AppendToList */
+ESX_VI__TEMPLATE__LIST__APPEND(PropertySpec);
+
+/* esxVI_PropertySpec_Serialize */
+ESX_VI__TEMPLATE__SERIALIZE(PropertySpec,
+{
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE_VALUE(String, type, True);
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE(Boolean, all, False);
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE_LIST(String, pathSet, False);
+});
+
+/* esxVI_PropertySpec_SerializeList */
+ESX_VI__TEMPLATE__LIST__SERIALIZE(PropertySpec);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: PropertyFilterSpec
+ */
+
+/* esxVI_PropertyFilterSpec_Alloc */
+ESX_VI__TEMPLATE__ALLOC(PropertyFilterSpec);
+
+/* esxVI_PropertyFilterSpec_Free */
+ESX_VI__TEMPLATE__FREE(PropertyFilterSpec,
+{
+    esxVI_PropertyFilterSpec_Free(&item->_next);
+
+    esxVI_PropertySpec_Free(&item->propSet);
+    esxVI_ObjectSpec_Free(&item->objectSet);
+});
+
+/* esxVI_PropertyFilterSpec_AppendToList */
+ESX_VI__TEMPLATE__LIST__APPEND(PropertyFilterSpec);
+
+/* esxVI_PropertyFilterSpec_Serialize */
+ESX_VI__TEMPLATE__SERIALIZE(PropertyFilterSpec,
+{
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE_LIST(PropertySpec, propSet, True);
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE_LIST(ObjectSpec, objectSet, True);
+});
+
+/* esxVI_PropertyFilterSpec_SerializeList */
+ESX_VI__TEMPLATE__LIST__SERIALIZE(PropertyFilterSpec);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: ObjectContent
+ */
+
+/* esxVI_ObjectContent_Alloc */
+ESX_VI__TEMPLATE__ALLOC(ObjectContent);
+
+/* esxVI_ObjectContent_Free */
+ESX_VI__TEMPLATE__FREE(ObjectContent,
+{
+    esxVI_ObjectContent_Free(&item->_next);
+
+    esxVI_ManagedObjectReference_Free(&item->obj);
+    esxVI_DynamicProperty_Free(&item->propSet);
+    /*esxVI_MissingProperty_Free(&item->missingSet);*//* FIXME */
+});
+
+/* esxVI_ObjectContent_AppendToList */
+ESX_VI__TEMPLATE__LIST__APPEND(ObjectContent);
+
+int
+esxVI_ObjectContent_DeepCopy(virConnectPtr conn,
+                             esxVI_ObjectContent **dest,
+                             esxVI_ObjectContent *src)
+{
+    if (dest == NULL || *dest != NULL) {
+        ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    if (src == NULL) {
+        return 0;
+    }
+
+    if (esxVI_ObjectContent_Alloc(conn, dest) < 0 ||
+        esxVI_ManagedObjectReference_DeepCopy(conn, &(*dest)->obj,
+                                              src->obj) < 0 ||
+        esxVI_DynamicProperty_DeepCopyList(conn, &(*dest)->propSet,
+                                           src->propSet) < 0) {
+        goto failure;
+    }
+
+#if 0 /* FIXME */
+    if (esxVI_MissingProperty_DeepCopyList(&(*dest)->missingSet,
+                                           src->missingSet) < 0) {
+        goto failure;
+    }
+#endif
+
+    return 0;
+
+  failure:
+    esxVI_ObjectContent_Free(dest);
+
+    return -1;
+}
+
+/* esxVI_ObjectContent_Deserialize */
+ESX_VI__TEMPLATE__DESERIALIZE(ObjectContent,
+{
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_EXPECTED(ManagedObjectReference,
+                                                     NULL, obj);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_LIST(DynamicProperty, propSet);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_NOOP(missingSet); /* FIXME */
+},
+{
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(obj);
+});
+
+/* esxVI_ObjectContent_DeserializeList */
+ESX_VI__TEMPLATE__LIST__DESERIALIZE(ObjectContent);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: ObjectUpdate
+ */
+
+/* esxVI_ObjectUpdate_Alloc */
+ESX_VI__TEMPLATE__ALLOC(ObjectUpdate);
+
+/* esxVI_ObjectUpdate_Free */
+ESX_VI__TEMPLATE__FREE(ObjectUpdate,
+{
+    esxVI_ObjectUpdate_Free(&item->_next);
+
+    esxVI_ManagedObjectReference_Free(&item->obj);
+    esxVI_PropertyChange_Free(&item->changeSet);
+    /*esxVI_MissingProperty_Free(&item->missingSet);*//* FIXME */
+});
+
+/* esxVI_ObjectUpdate_AppendToList */
+ESX_VI__TEMPLATE__LIST__APPEND(ObjectUpdate);
+
+/* esxVI_ObjectUpdate_Deserialize */
+ESX_VI__TEMPLATE__DESERIALIZE(ObjectUpdate,
+{
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(ObjectUpdateKind, kind);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_EXPECTED(ManagedObjectReference,
+                                                     NULL, obj);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_LIST(PropertyChange, changeSet);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_NOOP(missingSet); /* FIXME */
+},
+{
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(kind);
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(obj);
+});
+
+/* esxVI_ObjectUpdate_DeserializeList */
+ESX_VI__TEMPLATE__LIST__DESERIALIZE(ObjectUpdate);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: PropertyFilterUpdate
+ */
+
+/* esxVI_PropertyFilterUpdate_Alloc */
+ESX_VI__TEMPLATE__ALLOC(PropertyFilterUpdate);
+
+/* esxVI_PropertyFilterUpdate_Free */
+ESX_VI__TEMPLATE__FREE(PropertyFilterUpdate,
+{
+    esxVI_PropertyFilterUpdate_Free(&item->_next);
+
+    esxVI_ManagedObjectReference_Free(&item->filter);
+    esxVI_ObjectUpdate_Free(&item->objectSet);
+    /*esxVI_MissingProperty_Free(&item->missingSet);*//* FIXME */
+});
+
+/* esxVI_PropertyFilterUpdate_AppendToList */
+ESX_VI__TEMPLATE__LIST__APPEND(PropertyFilterUpdate);
+
+/* esxVI_PropertyFilterUpdate_Deserialize */
+ESX_VI__TEMPLATE__DESERIALIZE(PropertyFilterUpdate,
+{
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_EXPECTED(ManagedObjectReference,
+                                                     NULL, filter);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_LIST(ObjectUpdate, objectSet);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_NOOP(missingSet); /* FIXME */
+},
+{
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(filter);
+});
+
+/* esxVI_PropertyFilterUpdate_DeserializeList */
+ESX_VI__TEMPLATE__LIST__DESERIALIZE(PropertyFilterUpdate);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: AboutInfo
+ */
+
+/* esxVI_AboutInfo_Alloc */
+ESX_VI__TEMPLATE__ALLOC(AboutInfo);
+
+/* esxVI_AboutInfo_Free */
+ESX_VI__TEMPLATE__FREE(AboutInfo,
+{
+    VIR_FREE(item->name);
+    VIR_FREE(item->fullName);
+    VIR_FREE(item->vendor);
+    VIR_FREE(item->version);
+    VIR_FREE(item->build);
+    VIR_FREE(item->localeVersion);
+    VIR_FREE(item->localeBuild);
+    VIR_FREE(item->osType);
+    VIR_FREE(item->productLineId);
+    VIR_FREE(item->apiType);
+    VIR_FREE(item->apiVersion);
+});
+
+/* esxVI_AboutInfo_Deserialize */
+ESX_VI__TEMPLATE__DESERIALIZE(AboutInfo,
+{
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, name);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, fullName);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, vendor);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, version);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, build);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, localeVersion);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, localeBuild);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, osType);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, productLineId);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, apiType);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, apiVersion);
+},
+{
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(name);
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(fullName);
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(vendor);
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(version);
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(build);
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(localeVersion);
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(localeBuild);
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(osType);
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(productLineId);
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(apiType);
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(apiVersion);
+});
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: ServiceContent
+ */
+
+/* esxVI_ServiceContent_Alloc */
+ESX_VI__TEMPLATE__ALLOC(ServiceContent);
+
+/* esxVI_ServiceContent_Free */
+ESX_VI__TEMPLATE__FREE(ServiceContent,
+{
+    esxVI_ManagedObjectReference_Free(&item->rootFolder);
+    esxVI_ManagedObjectReference_Free(&item->propertyCollector);
+    esxVI_ManagedObjectReference_Free(&item->viewManager);
+    esxVI_AboutInfo_Free(&item->about);
+    esxVI_ManagedObjectReference_Free(&item->setting);
+    esxVI_ManagedObjectReference_Free(&item->userDirectory);
+    esxVI_ManagedObjectReference_Free(&item->sessionManager);
+    esxVI_ManagedObjectReference_Free(&item->authorizationManager);
+    esxVI_ManagedObjectReference_Free(&item->perfManager);
+    esxVI_ManagedObjectReference_Free(&item->scheduledTaskManager);
+    esxVI_ManagedObjectReference_Free(&item->alarmManager);
+    esxVI_ManagedObjectReference_Free(&item->eventManager);
+    esxVI_ManagedObjectReference_Free(&item->taskManager);
+    esxVI_ManagedObjectReference_Free(&item->extensionManager);
+    esxVI_ManagedObjectReference_Free(&item->customizationSpecManager);
+    esxVI_ManagedObjectReference_Free(&item->customFieldsManager);
+    esxVI_ManagedObjectReference_Free(&item->accountManager);
+    esxVI_ManagedObjectReference_Free(&item->diagnosticManager);
+    esxVI_ManagedObjectReference_Free(&item->licenseManager);
+    esxVI_ManagedObjectReference_Free(&item->searchIndex);
+    esxVI_ManagedObjectReference_Free(&item->fileManager);
+    esxVI_ManagedObjectReference_Free(&item->virtualDiskManager);
+    esxVI_ManagedObjectReference_Free(&item->virtualizationManager);
+});
+
+/* esxVI_ServiceContent_Deserialize */
+ESX_VI__TEMPLATE__DESERIALIZE(ServiceContent,
+{
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_EXPECTED(ManagedObjectReference,
+                                                     "Folder", rootFolder);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_EXPECTED(ManagedObjectReference,
+                                                    "PropertyCollector",
+                                                     propertyCollector);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_EXPECTED(ManagedObjectReference,
+                                                     "ViewManager",
+                                                     viewManager);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(AboutInfo, about);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_EXPECTED(ManagedObjectReference,
+                                                     "OptionManager", setting);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_EXPECTED(ManagedObjectReference,
+                                                     "UserDirectory",
+                                                     userDirectory);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_EXPECTED(ManagedObjectReference,
+                                                     "SessionManager",
+                                                     sessionManager);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_EXPECTED(ManagedObjectReference,
+                                                     "AuthorizationManager",
+                                                     authorizationManager);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_EXPECTED(ManagedObjectReference,
+                                                     "PerformanceManager",
+                                                     perfManager);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_EXPECTED(ManagedObjectReference,
+                                                     "ScheduledTaskManager",
+                                                     scheduledTaskManager);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_EXPECTED(ManagedObjectReference,
+                                                     "AlarmManager",
+                                                     alarmManager);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_EXPECTED(ManagedObjectReference,
+                                                     "EventManager",
+                                                     eventManager);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_EXPECTED(ManagedObjectReference,
+                                                     "TaskManager",
+                                                     taskManager);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_EXPECTED(ManagedObjectReference,
+                                                     "ExtensionManager",
+                                                     extensionManager);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_EXPECTED(ManagedObjectReference,
+                                                     "CustomizationSpecManager",
+                                                     customizationSpecManager);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_EXPECTED(ManagedObjectReference,
+                                                     "CustomFieldsManager",
+                                                     customFieldsManager);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_EXPECTED(ManagedObjectReference,
+                                                     "HostLocalAccountManager",
+                                                     accountManager);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_EXPECTED(ManagedObjectReference,
+                                                     "DiagnosticManager",
+                                                     diagnosticManager);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_EXPECTED(ManagedObjectReference,
+                                                     "LicenseManager",
+                                                     licenseManager);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_EXPECTED(ManagedObjectReference,
+                                                     "SearchIndex",
+                                                     searchIndex);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_EXPECTED(ManagedObjectReference,
+                                                     "FileManager",
+                                                     fileManager);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_EXPECTED(ManagedObjectReference,
+                                                     "VirtualDiskManager",
+                                                     virtualDiskManager);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_EXPECTED(ManagedObjectReference,
+                                                     "VirtualizationManager",
+                                                     virtualizationManager);
+},
+{
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(rootFolder);
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(propertyCollector);
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(about);
+});
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: UpdateSet
+ */
+
+/* esxVI_UpdateSet_Alloc */
+ESX_VI__TEMPLATE__ALLOC(UpdateSet);
+
+/* esxVI_UpdateSet_Free */
+ESX_VI__TEMPLATE__FREE(UpdateSet,
+{
+    VIR_FREE(item->version);
+    esxVI_PropertyFilterUpdate_Free(&item->filterSet);
+});
+
+/* esxVI_UpdateSet_Deserialize */
+ESX_VI__TEMPLATE__DESERIALIZE(UpdateSet,
+{
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, version);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_LIST(PropertyFilterUpdate,
+                                                 filterSet);
+},
+{
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(version);
+});
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: SharesInfo
+ */
+
+/* esxVI_SharesInfo_Alloc */
+ESX_VI__TEMPLATE__ALLOC(SharesInfo);
+
+/* esxVI_SharesInfo_Free */
+ESX_VI__TEMPLATE__FREE(SharesInfo,
+{
+    esxVI_Int_Free(&item->shares);
+});
+
+/* esxVI_SharesInfo_CastFromAnyType */
+ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE(SharesInfo);
+
+/* esxVI_SharesInfo_Deserialize */
+ESX_VI__TEMPLATE__DESERIALIZE(SharesInfo,
+{
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(Int, shares);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(SharesLevel, level);
+},
+{
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(shares);
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(level);
+});
+
+/* esxVI_SharesInfo_Serialize */
+ESX_VI__TEMPLATE__SERIALIZE(SharesInfo,
+{
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE(Int, shares, True);
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE(SharesLevel, level, True);
+});
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: ResourceAllocationInfo
+ */
+
+/* esxVI_ResourceAllocationInfo_Alloc */
+ESX_VI__TEMPLATE__ALLOC(ResourceAllocationInfo);
+
+/* esxVI_ResourceAllocationInfo_Free */
+ESX_VI__TEMPLATE__FREE(ResourceAllocationInfo,
+{
+    esxVI_Long_Free(&item->reservation);
+    esxVI_Long_Free(&item->limit);
+    esxVI_SharesInfo_Free(&item->shares);
+    esxVI_Long_Free(&item->overheadLimit);
+});
+
+/* esxVI_ResourceAllocationInfo_Serialize */
+ESX_VI__TEMPLATE__SERIALIZE(ResourceAllocationInfo,
+{
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE(Long, reservation, False);
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE(Boolean, expandableReservation,
+                                          False);
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE(Long, limit, False);
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE(SharesInfo, shares, False);
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE(Long, overheadLimit, False);
+});
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: VirtualMachineConfigSpec
+ */
+
+/* esxVI_VirtualMachineConfigSpec_Alloc */
+ESX_VI__TEMPLATE__ALLOC(VirtualMachineConfigSpec);
+
+/* esxVI_VirtualMachineConfigSpec_Free */
+ESX_VI__TEMPLATE__FREE(VirtualMachineConfigSpec,
+{
+    VIR_FREE(item->changeVersion);
+    VIR_FREE(item->name);
+    VIR_FREE(item->version);
+    VIR_FREE(item->uuid);
+    esxVI_Long_Free(&item->npivNodeWorldWideName);
+    esxVI_Long_Free(&item->npivPortWorldWideName);
+    VIR_FREE(item->npivWorldWideNameType);
+    VIR_FREE(item->npivWorldWideNameOp);
+    VIR_FREE(item->locationId);
+    VIR_FREE(item->guestId);
+    VIR_FREE(item->alternateGuestName);
+    VIR_FREE(item->annotation);
+    /* FIXME: implement missing */
+    esxVI_Int_Free(&item->numCPUs);
+    esxVI_Long_Free(&item->memoryMB);
+    /* FIXME: implement missing */
+    esxVI_ResourceAllocationInfo_Free(&item->cpuAllocation);
+    esxVI_ResourceAllocationInfo_Free(&item->memoryAllocation);
+    /* FIXME: implement missing */
+    VIR_FREE(item->swapPlacement);
+    /* FIXME: implement missing */
+});
+
+/* esxVI_VirtualMachineConfigSpec_Serialize */
+ESX_VI__TEMPLATE__SERIALIZE(VirtualMachineConfigSpec,
+{
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE_VALUE(String, changeVersion, False);
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE_VALUE(String, name, False);
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE_VALUE(String, version, False);
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE_VALUE(String, uuid, False);
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE_LIST(Long, npivNodeWorldWideName,
+                                               False);
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE_LIST(Long, npivPortWorldWideName,
+                                               False);
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE_VALUE(String, npivWorldWideNameType,
+                                                False);
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE_VALUE(String, npivWorldWideNameOp,
+                                                False);
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE_VALUE(String, locationId, False);
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE_VALUE(String, guestId, False);
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE_VALUE(String, alternateGuestName,
+                                                False);
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE_VALUE(String, annotation, False);
+    /* FIXME: implement missing */
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE(Int, numCPUs, False);
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE(Long, memoryMB, False);
+    /* FIXME: implement missing */
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE(ResourceAllocationInfo,
+                                          cpuAllocation, False);
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE(ResourceAllocationInfo,
+                                          memoryAllocation, False);
+    /* FIXME: implement missing */
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE_VALUE(String, swapPlacement, False);
+    /* FIXME: implement missing */
+});
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: Event
+ */
+
+/* esxVI_Event_Alloc */
+ESX_VI__TEMPLATE__ALLOC(Event);
+
+/* esxVI_Event_Free */
+ESX_VI__TEMPLATE__FREE(Event,
+{
+    esxVI_Event_Free(&item->_next);
+
+    /* FIXME: implement the rest */
+    esxVI_Int_Free(&item->key);
+    esxVI_Int_Free(&item->chainId);
+    esxVI_DateTime_Free(&item->createdTime);
+    VIR_FREE(item->userName);
+    VIR_FREE(item->fullFormattedMessage);
+});
+
+/* esxVI_Event_Deserialize */
+ESX_VI__TEMPLATE__DESERIALIZE(Event,
+{
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(Int, key);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(Int, chainId);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(DateTime, createdTime);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, userName);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_NOOP(datacenter); /* FIXME */
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_NOOP(computeResource); /* FIXME */
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_NOOP(host); /* FIXME */
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_NOOP(vm); /* FIXME */
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, fullFormattedMessage);
+},
+{
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(key);
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(chainId);
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(createdTime);
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(userName);
+});
+
+/* esxVI_Event_DeserializeList */
+ESX_VI__TEMPLATE__LIST__DESERIALIZE(Event);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: UserSession
+ */
+
+/* esxVI_UserSession_Alloc */
+ESX_VI__TEMPLATE__ALLOC(UserSession);
+
+/* esxVI_UserSession_Free */
+ESX_VI__TEMPLATE__FREE(UserSession,
+{
+    VIR_FREE(item->key);
+    VIR_FREE(item->userName);
+    VIR_FREE(item->fullName);
+    esxVI_DateTime_Free(&item->loginTime);
+    esxVI_DateTime_Free(&item->lastActiveTime);
+    VIR_FREE(item->locale);
+    VIR_FREE(item->messageLocale);
+});
+
+/* esxVI_UserSession_CastFromAnyType */
+ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE(UserSession);
+
+/* esxVI_UserSession_Deserialize */
+ESX_VI__TEMPLATE__DESERIALIZE(UserSession,
+{
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, key);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, userName);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, fullName);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(DateTime, loginTime);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(DateTime, lastActiveTime);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, locale);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, messageLocale);
+},
+{
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(key);
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(userName);
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(fullName);
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(loginTime);
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(lastActiveTime);
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(locale);
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(messageLocale);
+});
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: ElementDescription extends Description
+ *
+ *          In contrast to SelectionSpec and TraversalSpec just merge
+ *          Description into ElementDescription for simplicity, because
+ *          only ElementDescription is used.
+ */
+
+/* esxVI_ElementDescription_Alloc */
+ESX_VI__TEMPLATE__ALLOC(ElementDescription);
+
+/* esxVI_ElementDescription_Free */
+ESX_VI__TEMPLATE__FREE(ElementDescription,
+{
+    esxVI_ElementDescription_Free(&item->_next);
+
+    VIR_FREE(item->label);
+    VIR_FREE(item->summary);
+    VIR_FREE(item->key);
+});
+
+/* esxVI_ElementDescription_Deserialize */
+ESX_VI__TEMPLATE__DESERIALIZE(ElementDescription,
+{
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, label);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, summary);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, key);
+},
+{
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(label);
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(summary);
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(key);
+});
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: PerfMetricId
+ */
+
+/* esxVI_PerfMetricId_Alloc */
+ESX_VI__TEMPLATE__ALLOC(PerfMetricId);
+
+/* esxVI_PerfMetricId_Free */
+ESX_VI__TEMPLATE__FREE(PerfMetricId,
+{
+    esxVI_PerfMetricId_Free(&item->_next);
+
+    esxVI_Int_Free(&item->counterId);
+    VIR_FREE(item->instance);
+});
+
+/* esxVI_PerfMetricId_Serialize */
+ESX_VI__TEMPLATE__SERIALIZE(PerfMetricId,
+{
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE(Int, counterId, True);
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE_VALUE(String, instance, True);
+});
+
+/* esxVI_PerfMetricId_SerializeList */
+ESX_VI__TEMPLATE__LIST__SERIALIZE(PerfMetricId);
+
+/* esxVI_PerfMetricId_Deserialize */
+ESX_VI__TEMPLATE__DESERIALIZE(PerfMetricId,
+{
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(Int, counterId);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, instance);
+},
+{
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(counterId);
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(instance);
+});
+
+/* esxVI_PerfMetricId_DeserializeList */
+ESX_VI__TEMPLATE__LIST__DESERIALIZE(PerfMetricId);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: PerfCounterInfo
+ */
+
+/* esxVI_PerfCounterInfo_Alloc */
+ESX_VI__TEMPLATE__ALLOC(PerfCounterInfo);
+
+/* esxVI_PerfCounterInfo_Free */
+ESX_VI__TEMPLATE__FREE(PerfCounterInfo,
+{
+    esxVI_PerfCounterInfo_Free(&item->_next);
+
+    esxVI_Int_Free(&item->key);
+    esxVI_ElementDescription_Free(&item->nameInfo);
+    esxVI_ElementDescription_Free(&item->groupInfo);
+    esxVI_ElementDescription_Free(&item->unitInfo);
+    esxVI_Int_Free(&item->level);
+    esxVI_Int_Free(&item->associatedCounterId);
+});
+
+/* esxVI_PerfCounterInfo_Deserialize */
+ESX_VI__TEMPLATE__DESERIALIZE(PerfCounterInfo,
+{
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(Int, key);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(ElementDescription, nameInfo);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(ElementDescription, groupInfo);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(ElementDescription, unitInfo);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(PerfSummaryType, rollupType);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(PerfStatsType, statsType);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(Int, level);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_LIST(Int, associatedCounterId);
+},
+{
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(key);
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(nameInfo);
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(groupInfo);
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(unitInfo);
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(rollupType);
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(statsType);
+});
+
+/* esxVI_PerfCounterInfo_DeserializeList */
+ESX_VI__TEMPLATE__LIST__DESERIALIZE(PerfCounterInfo);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: PerfQuerySpec
+ */
+
+/* esxVI_PerfQuerySpec_Alloc */
+ESX_VI__TEMPLATE__ALLOC(PerfQuerySpec);
+
+/* esxVI_PerfQuerySpec_Free */
+ESX_VI__TEMPLATE__FREE(PerfQuerySpec,
+{
+    esxVI_PerfQuerySpec_Free(&item->_next);
+
+    esxVI_ManagedObjectReference_Free(&item->entity);
+    esxVI_DateTime_Free(&item->startTime);
+    esxVI_DateTime_Free(&item->endTime);
+    esxVI_Int_Free(&item->maxSample);
+    esxVI_PerfMetricId_Free(&item->metricId);
+    esxVI_Int_Free(&item->intervalId);
+    VIR_FREE(item->format);
+});
+
+/* esxVI_PerfQuerySpec_Serialize */
+ESX_VI__TEMPLATE__SERIALIZE(PerfQuerySpec,
+{
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE(ManagedObjectReference, entity, True);
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE(DateTime, startTime, False);
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE(DateTime, endTime, False);
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE(Int, maxSample, False);
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE_LIST(PerfMetricId, metricId, False);
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE(Int, intervalId, False);
+    ESX_VI__TEMPLATE__PROPERTY__SERIALIZE_VALUE(String, format, False);
+});
+
+/* esxVI_PerfQuerySpec_SerializeList */
+ESX_VI__TEMPLATE__LIST__SERIALIZE(PerfQuerySpec);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: PerfSampleInfo
+ */
+
+/* esxVI_PerfSampleInfo_Alloc */
+ESX_VI__TEMPLATE__ALLOC(PerfSampleInfo);
+
+/* esxVI_PerfSampleInfo_Free */
+ESX_VI__TEMPLATE__FREE(PerfSampleInfo,
+{
+    esxVI_PerfSampleInfo_Free(&item->_next);
+
+    esxVI_DateTime_Free(&item->timestamp);
+    esxVI_Int_Free(&item->interval);
+});
+
+/* esxVI_PerfSampleInfo_AppendToList */
+ESX_VI__TEMPLATE__LIST__APPEND(PerfSampleInfo);
+
+/* esxVI_PerfSampleInfo_Deserialize */
+ESX_VI__TEMPLATE__DESERIALIZE(PerfSampleInfo,
+{
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(DateTime, timestamp);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(Int, interval);
+},
+{
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(timestamp);
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(interval);
+});
+
+/* esxVI_PerfSampleInfo_DeserializeList */
+ESX_VI__TEMPLATE__LIST__DESERIALIZE(PerfSampleInfo);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: PerfMetricIntSeries extends PerfMetricSeries
+ *
+ *          In contrast to SelectionSpec and TraversalSpec just merge
+ *          PerfMetricSeries into PerfMetricIntSeries for simplicity, because
+ *          only PerfMetricIntSeries is used and the other type inheriting
+ *          PerfMetricSeries (PerfMetricSeriesCSV) is not used.
+ */
+
+/* esxVI_PerfMetricIntSeries_Alloc */
+ESX_VI__TEMPLATE__ALLOC(PerfMetricIntSeries);
+
+/* esxVI_PerfMetricIntSeries_Free */
+ESX_VI__TEMPLATE__FREE(PerfMetricIntSeries,
+{
+    esxVI_PerfMetricIntSeries_Free(&item->_next);
+
+    esxVI_PerfMetricId_Free(&item->id);
+    esxVI_Long_Free(&item->value);
+});
+
+/* esxVI_PerfMetricIntSeries_AppendToList */
+ESX_VI__TEMPLATE__LIST__APPEND(PerfMetricIntSeries);
+
+/* esxVI_PerfMetricIntSeries_Deserialize */
+ESX_VI__TEMPLATE__DESERIALIZE(PerfMetricIntSeries,
+{
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(PerfMetricId, id);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_LIST(Long, value);
+},
+{
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(id);
+});
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: PerfEntityMetric extends PerfEntityMetricBase
+ *
+ *          In contrast to SelectionSpec and TraversalSpec just merge
+ *          PerfEntityMetricBase into PerfEntityMetric for simplicity, because
+ *          only PerfEntityMetric is used and the other type inheriting
+ *          PerfEntityMetric (PerfEntityMetricCSV) is not used.
+ *
+ *          Also use PerfMetricIntSeries instead of the correct base type
+ *          PerfMetricSeries for the value property, because only
+ *          PerfMetricIntSeries is used.
+ */
+
+/* esxVI_PerfEntityMetric_Alloc */
+ESX_VI__TEMPLATE__ALLOC(PerfEntityMetric);
+
+/* esxVI_PerfEntityMetric_Free */
+ESX_VI__TEMPLATE__FREE(PerfEntityMetric,
+{
+    esxVI_PerfEntityMetric_Free(&item->_next);
+
+    esxVI_ManagedObjectReference_Free(&item->entity);
+    esxVI_PerfSampleInfo_Free(&item->sampleInfo);
+    esxVI_PerfMetricIntSeries_Free(&item->value);
+});
+
+/* esxVI_PerfEntityMetric_Deserialize */
+ESX_VI__TEMPLATE__DESERIALIZE(PerfEntityMetric,
+{
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_EXPECTED(ManagedObjectReference,
+                                                     NULL, entity);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_LIST(PerfSampleInfo, sampleInfo);
+    ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_LIST(PerfMetricIntSeries, value);
+},
+{
+    ESX_VI__TEMPLATE__PROPERTY__REQUIRED(entity);
+});
+
+/* esxVI_PerfEntityMetric_DeserializeList */
+ESX_VI__TEMPLATE__LIST__DESERIALIZE(PerfEntityMetric);
diff --git a/src/esx/esx_vi_types.h b/src/esx/esx_vi_types.h
new file mode 100644
index 0000000..84d657d
--- /dev/null
+++ b/src/esx/esx_vi_types.h
@@ -0,0 +1,1195 @@
+
+/*
+ * esx_vi_types.h: client for the VMware VI API 2.5 to manage ESX hosts
+ *
+ * Copyright (C) 2009 Matthias Bolte <matthias.bolte@xxxxxxxxxxxxxx>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ */
+
+#ifndef __ESX_VI_TYPES_H__
+#define __ESX_VI_TYPES_H__
+
+#include "buf.h"
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * XSI
+ */
+
+typedef enum _esxVI_Type esxVI_Type;
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * XSD
+ */
+
+typedef enum _esxVI_Boolean esxVI_Boolean;
+typedef struct _esxVI_AnyType esxVI_AnyType;
+typedef struct _esxVI_String esxVI_String;
+typedef struct _esxVI_Int esxVI_Int;
+typedef struct _esxVI_Long esxVI_Long;
+typedef struct _esxVI_DateTime esxVI_DateTime;
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Enums
+ */
+
+typedef enum _esxVI_ObjectUpdateKind esxVI_ObjectUpdateKind;
+typedef enum _esxVI_PerfSummaryType esxVI_PerfSummaryType;
+typedef enum _esxVI_PerfStatsType esxVI_PerfStatsType;
+typedef enum _esxVI_PropertyChangeOp esxVI_PropertyChangeOp;
+typedef enum _esxVI_SharesLevel esxVI_SharesLevel;
+typedef enum _esxVI_TaskInfoState esxVI_TaskInfoState;
+typedef enum _esxVI_VirtualMachineMovePriority esxVI_VirtualMachineMovePriority;
+typedef enum _esxVI_VirtualMachinePowerState esxVI_VirtualMachinePowerState;
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Types
+ */
+
+typedef struct _esxVI_Fault esxVI_Fault;
+typedef struct _esxVI_ManagedObjectReference esxVI_ManagedObjectReference;
+typedef struct _esxVI_DynamicProperty esxVI_DynamicProperty;
+typedef struct _esxVI_SelectionSpec esxVI_SelectionSpec;
+typedef struct _esxVI_TraversalSpec esxVI_TraversalSpec;
+typedef struct _esxVI_ObjectSpec esxVI_ObjectSpec;
+typedef struct _esxVI_PropertyChange esxVI_PropertyChange;
+typedef struct _esxVI_PropertySpec esxVI_PropertySpec;
+typedef struct _esxVI_PropertyFilterSpec esxVI_PropertyFilterSpec;
+typedef struct _esxVI_ObjectContent esxVI_ObjectContent;
+typedef struct _esxVI_ObjectUpdate esxVI_ObjectUpdate;
+typedef struct _esxVI_PropertyFilterUpdate esxVI_PropertyFilterUpdate;
+typedef struct _esxVI_AboutInfo esxVI_AboutInfo;
+typedef struct _esxVI_ServiceContent esxVI_ServiceContent;
+typedef struct _esxVI_UpdateSet esxVI_UpdateSet;
+typedef struct _esxVI_SharesInfo esxVI_SharesInfo;
+typedef struct _esxVI_ResourceAllocationInfo esxVI_ResourceAllocationInfo;
+typedef struct _esxVI_VirtualMachineConfigSpec esxVI_VirtualMachineConfigSpec;
+typedef struct _esxVI_Event esxVI_Event;
+typedef struct _esxVI_UserSession esxVI_UserSession;
+typedef struct _esxVI_ElementDescription esxVI_ElementDescription;
+typedef struct _esxVI_PerfMetricId esxVI_PerfMetricId;
+typedef struct _esxVI_PerfCounterInfo esxVI_PerfCounterInfo;
+typedef struct _esxVI_PerfQuerySpec esxVI_PerfQuerySpec;
+typedef struct _esxVI_PerfSampleInfo esxVI_PerfSampleInfo;
+typedef struct _esxVI_PerfMetricIntSeries esxVI_PerfMetricIntSeries;
+typedef struct _esxVI_PerfEntityMetric esxVI_PerfEntityMetric;
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * XSI: Type
+ */
+
+enum _esxVI_Type {
+    esxVI_Type_Undefined = 0,
+    esxVI_Type_Boolean,
+    esxVI_Type_String,
+    esxVI_Type_Short,
+    esxVI_Type_Int,
+    esxVI_Type_Long,
+    esxVI_Type_Other,
+};
+
+const char *esxVI_Type_Name(esxVI_Type type);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * XSD: Boolean
+ */
+
+enum _esxVI_Boolean {
+    esxVI_Boolean_Undefined = 0,
+    esxVI_Boolean_True,
+    esxVI_Boolean_False,
+};
+
+int esxVI_Boolean_Serialize(virConnectPtr conn, esxVI_Boolean boolean,
+                            const char *element, virBufferPtr output,
+                            esxVI_Boolean required);
+int esxVI_Boolean_Deserialize(virConnectPtr conn, xmlNodePtr node,
+                              esxVI_Boolean *boolean);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * XSD: AnyType
+ */
+
+struct _esxVI_AnyType {
+    xmlNodePtr _node;                                      /* required */
+
+    esxVI_Type type;                                       /* required */
+    char *other;                                           /* required */
+    char *value;                                           /* required */
+    union {
+        esxVI_Boolean boolean;                             /* optional */
+        char *string;                                      /* optional */
+        int16_t int16;                                     /* optional */
+        int32_t int32;                                     /* optional */
+        int64_t int64;                                     /* optional */
+    };
+};
+
+int esxVI_AnyType_Alloc(virConnectPtr conn, esxVI_AnyType **anyType);
+void esxVI_AnyType_Free(esxVI_AnyType **anyType);
+int esxVI_AnyType_ExpectType(virConnectPtr conn, esxVI_AnyType *anyType,
+                             esxVI_Type type);
+int esxVI_AnyType_DeepCopy(virConnectPtr conn, esxVI_AnyType **dest,
+                           esxVI_AnyType *src);
+int esxVI_AnyType_Deserialize(virConnectPtr conn, xmlNodePtr node,
+                              esxVI_AnyType **anyType);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * XSD: String
+ */
+
+struct _esxVI_String {
+    esxVI_String *_next;                                   /* optional */
+
+    char *value;                                           /* required */
+};
+
+int esxVI_String_Alloc(virConnectPtr conn, esxVI_String **string);
+void esxVI_String_Free(esxVI_String **stringList);
+int esxVI_String_AppendToList(virConnectPtr conn, esxVI_String **stringList,
+                              esxVI_String *string);
+int esxVI_String_AppendValueToList(virConnectPtr conn,
+                                   esxVI_String **stringList,
+                                   const char *value);
+int esxVI_String_AppendValueListToList(virConnectPtr conn,
+                                       esxVI_String **stringList,
+                                       const char *valueList);
+int esxVI_String_DeepCopy(virConnectPtr conn, esxVI_String **dest,
+                          esxVI_String *src);
+int esxVI_String_DeepCopyList(virConnectPtr conn, esxVI_String **destList,
+                              esxVI_String *srcList);
+int esxVI_String_DeepCopyValue(virConnectPtr conn, char **dest,
+                               const char *src);
+int esxVI_String_Serialize(virConnectPtr conn, esxVI_String *string,
+                           const char *element, virBufferPtr output,
+                           esxVI_Boolean required);
+int esxVI_String_SerializeList(virConnectPtr conn, esxVI_String *stringList,
+                               const char *element, virBufferPtr output,
+                               esxVI_Boolean required);
+int esxVI_String_SerializeValue(virConnectPtr conn, const char *value,
+                                const char *element, virBufferPtr output,
+                                esxVI_Boolean required);
+int esxVI_String_Deserialize(virConnectPtr conn, xmlNodePtr node,
+                             esxVI_String **string);
+int esxVI_String_DeserializeList(virConnectPtr conn, xmlNodePtr node,
+                                 esxVI_String **stringList);
+int esxVI_String_DeserializeValue(virConnectPtr conn, xmlNodePtr node,
+                                  char **value);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * XSD: Int
+ */
+
+struct _esxVI_Int {
+    esxVI_Int *_next;                                      /* optional */
+
+    int32_t value;                                         /* required */
+};
+
+int esxVI_Int_Alloc(virConnectPtr conn, esxVI_Int **number);
+void esxVI_Int_Free(esxVI_Int **numberList);
+int esxVI_Int_AppendToList(virConnectPtr conn, esxVI_Int **numberList,
+                           esxVI_Int *number);
+int esxVI_Int_DeepCopy(virConnectPtr conn, esxVI_Int **dest, esxVI_Int *src);
+int esxVI_Int_Serialize(virConnectPtr conn, esxVI_Int *number,
+                        const char *element, virBufferPtr output,
+                        esxVI_Boolean required);
+int esxVI_Int_SerializeList(virConnectPtr conn, esxVI_Int *numberList,
+                            const char *element, virBufferPtr output,
+                            esxVI_Boolean required);
+int esxVI_Int_Deserialize(virConnectPtr conn, xmlNodePtr node,
+                          esxVI_Int **number);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * XSD: Long
+ */
+
+struct _esxVI_Long {
+    esxVI_Long *_next;                                     /* optional */
+
+    int64_t value;                                         /* required */
+};
+
+int esxVI_Long_Alloc(virConnectPtr conn, esxVI_Long **number);
+void esxVI_Long_Free(esxVI_Long **numberList);
+int esxVI_Long_AppendToList(virConnectPtr conn, esxVI_Long **numberList,
+                            esxVI_Long *number);
+int esxVI_Long_Serialize(virConnectPtr conn, esxVI_Long *number,
+                         const char *element, virBufferPtr output,
+                         esxVI_Boolean required);
+int esxVI_Long_SerializeList(virConnectPtr conn, esxVI_Long *numberList,
+                             const char *element, virBufferPtr output,
+                             esxVI_Boolean required);
+int esxVI_Long_Deserialize(virConnectPtr conn, xmlNodePtr node,
+                           esxVI_Long **number);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * XSD: DateTime
+ */
+
+struct _esxVI_DateTime {
+    char *value;                                           /* required */
+};
+
+int esxVI_DateTime_Alloc(virConnectPtr conn, esxVI_DateTime **dateTime);
+void esxVI_DateTime_Free(esxVI_DateTime **dateTime);
+int esxVI_DateTime_Serialize(virConnectPtr conn, esxVI_DateTime *dateTime,
+                             const char *element, virBufferPtr output,
+                             esxVI_Boolean required);
+int esxVI_DateTime_Deserialize(virConnectPtr conn, xmlNodePtr node,
+                               esxVI_DateTime **dateTime);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Enum: ObjectUpdateKind
+ */
+
+enum _esxVI_ObjectUpdateKind {
+    esxVI_ObjectUpdateKind_Undefined = 0,
+    esxVI_ObjectUpdateKind_Enter,
+    esxVI_ObjectUpdateKind_Leave,
+    esxVI_ObjectUpdateKind_Modify,
+};
+
+int esxVI_ObjectUpdateKind_Deserialize
+      (virConnectPtr conn, xmlNodePtr node,
+       esxVI_ObjectUpdateKind *objectUpdateKind);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Enum: PerfSummaryType
+ */
+
+enum _esxVI_PerfSummaryType {
+    esxVI_PerfSummaryType_Undefined = 0,
+    esxVI_PerfSummaryType_Average,
+    esxVI_PerfSummaryType_Latest,
+    esxVI_PerfSummaryType_Maximum,
+    esxVI_PerfSummaryType_Minimum,
+    esxVI_PerfSummaryType_None,
+    esxVI_PerfSummaryType_Summation,
+};
+
+int esxVI_PerfSummaryType_Deserialize(virConnectPtr conn, xmlNodePtr node,
+                                      esxVI_PerfSummaryType *perfSummaryType);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Enum: PerfStatsType
+ */
+
+enum _esxVI_PerfStatsType {
+    esxVI_PerfStatsType_Undefined = 0,
+    esxVI_PerfStatsType_Absolute,
+    esxVI_PerfStatsType_Delta,
+    esxVI_PerfStatsType_Rate,
+};
+
+int esxVI_PerfStatsType_Deserialize(virConnectPtr conn, xmlNodePtr node,
+                                    esxVI_PerfStatsType *perfStatsType);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Enum: PropertyChangeOp
+ */
+
+enum _esxVI_PropertyChangeOp {
+    esxVI_PropertyChangeOp_Undefined = 0,
+    esxVI_PropertyChangeOp_Add,
+    esxVI_PropertyChangeOp_Remove,
+    esxVI_PropertyChangeOp_Assign,
+    esxVI_PropertyChangeOp_IndirectRemove,
+};
+
+int esxVI_PropertyChangeOp_Deserialize
+      (virConnectPtr conn, xmlNodePtr node,
+       esxVI_PropertyChangeOp *propertyChangeOp);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Enum: SharesLevel
+ */
+
+enum _esxVI_SharesLevel {
+    esxVI_SharesLevel_Undefined = 0,
+    esxVI_SharesLevel_Custom,
+    esxVI_SharesLevel_High,
+    esxVI_SharesLevel_Low,
+    esxVI_SharesLevel_Normal,
+};
+
+int esxVI_SharesLevel_Serialize(virConnectPtr conn,
+                                esxVI_SharesLevel sharesLevel,
+                                const char *element, virBufferPtr output,
+                                esxVI_Boolean required);
+int esxVI_SharesLevel_Deserialize(virConnectPtr conn, xmlNodePtr node,
+                                  esxVI_SharesLevel *sharesLevel);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Enum: TaskInfoState
+ */
+
+enum _esxVI_TaskInfoState {
+    esxVI_TaskInfoState_Undefined = 0,
+    esxVI_TaskInfoState_Error,
+    esxVI_TaskInfoState_Queued,
+    esxVI_TaskInfoState_Running,
+    esxVI_TaskInfoState_Success,
+};
+
+int esxVI_TaskInfoState_CastFromAnyType(virConnectPtr conn,
+                                        esxVI_AnyType *anyType,
+                                        esxVI_TaskInfoState *taskInfoState);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Enum: VirtualMachineMovePriority
+ */
+
+enum _esxVI_VirtualMachineMovePriority {
+    esxVI_VirtualMachineMovePriority_Undefined = 0,
+    esxVI_VirtualMachineMovePriority_LowPriority,
+    esxVI_VirtualMachineMovePriority_HighPriority,
+    esxVI_VirtualMachineMovePriority_DefaultPriority,
+};
+
+int esxVI_VirtualMachineMovePriority_Serialize
+      (virConnectPtr conn,
+       esxVI_VirtualMachineMovePriority virtualMachineMovePriority,
+       const char *element, virBufferPtr output, esxVI_Boolean required);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Enum: VirtualMachinePowerState
+ */
+
+enum _esxVI_VirtualMachinePowerState {
+    esxVI_VirtualMachinePowerState_Undefined = 0,
+    esxVI_VirtualMachinePowerState_PoweredOff,
+    esxVI_VirtualMachinePowerState_PoweredOn,
+    esxVI_VirtualMachinePowerState_Suspended,
+};
+
+int esxVI_VirtualMachinePowerState_CastFromAnyType
+      (virConnectPtr conn, esxVI_AnyType *anyType,
+       esxVI_VirtualMachinePowerState *virtualMachinePowerState);
+int esxVI_VirtualMachinePowerState_Serialize
+      (virConnectPtr conn,
+       esxVI_VirtualMachinePowerState virtualMachinePowerState,
+       const char *element, virBufferPtr output, esxVI_Boolean required);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: Fault
+ */
+
+struct _esxVI_Fault {
+    char *faultcode;                                       /* required */
+    char *faultstring;                                     /* required */
+};
+
+int esxVI_Fault_Alloc(virConnectPtr conn, esxVI_Fault **fault);
+void esxVI_Fault_Free(esxVI_Fault **fault);
+int esxVI_Fault_Deserialize(virConnectPtr conn, xmlNodePtr node,
+                            esxVI_Fault **fault);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: ManagedObjectReference
+ */
+
+struct _esxVI_ManagedObjectReference {
+    esxVI_ManagedObjectReference *_next;                   /* optional */
+
+    char *type;                                            /* required */
+    char *value;                                           /* required */
+};
+
+int esxVI_ManagedObjectReference_Alloc
+      (virConnectPtr conn,
+       esxVI_ManagedObjectReference **managedObjectReference);
+void esxVI_ManagedObjectReference_Free
+       (esxVI_ManagedObjectReference **managedObjectReferenceList);
+int esxVI_ManagedObjectReference_DeepCopy(virConnectPtr conn,
+                                          esxVI_ManagedObjectReference **dest,
+                                          esxVI_ManagedObjectReference *src);
+int esxVI_ManagedObjectReference_CastFromAnyType(virConnectPtr conn,
+                                                 esxVI_AnyType *anyType,
+                                                 esxVI_ManagedObjectReference
+                                                 **managedObjectReference,
+                                                 const char *expectedType);
+int esxVI_ManagedObjectReference_Serialize
+      (virConnectPtr conn,
+       esxVI_ManagedObjectReference *managedObjectReference,
+       const char *element, virBufferPtr output, esxVI_Boolean required);
+int esxVI_ManagedObjectReference_SerializeList
+      (virConnectPtr conn,
+       esxVI_ManagedObjectReference *managedObjectReference,
+       const char *element, virBufferPtr output, esxVI_Boolean required);
+int esxVI_ManagedObjectReference_Deserialize
+      (virConnectPtr conn, xmlNodePtr node,
+       esxVI_ManagedObjectReference **managedObjectReference,
+       const char *expectedType);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: DynamicProperty
+ */
+
+struct _esxVI_DynamicProperty {
+    esxVI_DynamicProperty *_next;                          /* optional */
+
+    char *name;                                            /* required */
+    esxVI_AnyType *val;                                    /* required */
+};
+
+int esxVI_DynamicProperty_Alloc(virConnectPtr conn,
+                                esxVI_DynamicProperty **dynamicProperty);
+void esxVI_DynamicProperty_Free
+       (esxVI_DynamicProperty **dynamicPropertyList);
+int esxVI_DynamicProperty_DeepCopy(virConnectPtr conn,
+                                   esxVI_DynamicProperty **dest,
+                                   esxVI_DynamicProperty *src);
+int esxVI_DynamicProperty_DeepCopyList(virConnectPtr conn,
+                                       esxVI_DynamicProperty **destList,
+                                       esxVI_DynamicProperty *srcList);
+int esxVI_DynamicProperty_AppendToList
+      (virConnectPtr conn, esxVI_DynamicProperty **dynamicPropertyList,
+       esxVI_DynamicProperty *dynamicProperty);
+int esxVI_DynamicProperty_Deserialize(virConnectPtr conn, xmlNodePtr node,
+                                      esxVI_DynamicProperty **dynamicProperty);
+int esxVI_DynamicProperty_DeserializeList
+      (virConnectPtr conn, xmlNodePtr node,
+       esxVI_DynamicProperty **dynamicProperty);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: SelectionSpec
+ */
+
+struct _esxVI_SelectionSpec {
+    esxVI_SelectionSpec *_next;                            /* optional */
+    esxVI_TraversalSpec *_super;                           /* optional */
+
+    char *name;                                            /* optional */
+};
+
+int esxVI_SelectionSpec_Alloc(virConnectPtr conn,
+                              esxVI_SelectionSpec **selectionSpec);
+void esxVI_SelectionSpec_Free(esxVI_SelectionSpec **selectionSpecList);
+int esxVI_SelectionSpec_AppendToList(virConnectPtr conn,
+                                     esxVI_SelectionSpec **selectionSpecList,
+                                     esxVI_SelectionSpec *selectionSpec);
+int esxVI_SelectionSpec_Serialize(virConnectPtr conn,
+                                  esxVI_SelectionSpec *selectionSpec,
+                                  const char *element, virBufferPtr output,
+                                  esxVI_Boolean required);
+int esxVI_SelectionSpec_SerializeList(virConnectPtr conn,
+                                      esxVI_SelectionSpec *selectionSpecList,
+                                      const char *element, virBufferPtr output,
+                                      esxVI_Boolean required);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: TraversalSpec extends SelectionSpec
+ */
+
+struct _esxVI_TraversalSpec {
+    esxVI_SelectionSpec *_base;                            /* required */
+
+    char *type;                                            /* required */
+    char *path;                                            /* required */
+    esxVI_Boolean skip;                                    /* optional */
+    esxVI_SelectionSpec *selectSet;                        /* optional, list */
+};
+
+int esxVI_TraversalSpec_Alloc(virConnectPtr conn,
+                              esxVI_TraversalSpec **traversalSpec);
+void esxVI_TraversalSpec_Free(esxVI_TraversalSpec **traversalSpec);
+int esxVI_TraversalSpec_Serialize(virConnectPtr conn,
+                                  esxVI_TraversalSpec *traversalSpec,
+                                  const char *element, virBufferPtr output,
+                                  esxVI_Boolean required);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: ObjectSpec
+ */
+
+struct _esxVI_ObjectSpec {
+    esxVI_ObjectSpec *_next;                               /* optional */
+
+    esxVI_ManagedObjectReference *obj;                     /* required */
+    esxVI_Boolean skip;                                    /* optional */
+    esxVI_SelectionSpec *selectSet;                        /* optional, list */
+};
+
+int esxVI_ObjectSpec_Alloc(virConnectPtr conn, esxVI_ObjectSpec **objectSpec);
+void esxVI_ObjectSpec_Free(esxVI_ObjectSpec **objectSpecList);
+int esxVI_ObjectSpec_AppendToList(virConnectPtr conn,
+                                  esxVI_ObjectSpec **objectSpecList,
+                                  esxVI_ObjectSpec *objectSpec);
+int esxVI_ObjectSpec_Serialize(virConnectPtr conn,
+                               esxVI_ObjectSpec *objectSpec,
+                               const char *element, virBufferPtr output,
+                               esxVI_Boolean required);
+int esxVI_ObjectSpec_SerializeList(virConnectPtr conn,
+                                   esxVI_ObjectSpec *objectSpecList,
+                                   const char *element, virBufferPtr output,
+                                   esxVI_Boolean required);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: PropertyChange
+ */
+
+struct _esxVI_PropertyChange {
+    esxVI_PropertyChange *_next;                           /* optional */
+
+    char *name;                                            /* required */
+    esxVI_PropertyChangeOp op;                             /* required */
+    esxVI_AnyType *val;                                    /* optional */
+};
+
+int esxVI_PropertyChange_Alloc(virConnectPtr conn,
+                               esxVI_PropertyChange **propertyChange);
+void esxVI_PropertyChange_Free(esxVI_PropertyChange **propertyChangeList);
+int esxVI_PropertyChange_AppendToList
+      (virConnectPtr conn, esxVI_PropertyChange **propertyChangeList,
+       esxVI_PropertyChange *propertyChange);
+int esxVI_PropertyChange_Deserialize(virConnectPtr conn, xmlNodePtr node,
+                                     esxVI_PropertyChange **propertyChange);
+int esxVI_PropertyChange_DeserializeList
+      (virConnectPtr conn, xmlNodePtr node,
+       esxVI_PropertyChange **propertyChange);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: PropertySpec
+ */
+
+struct _esxVI_PropertySpec {
+    esxVI_PropertySpec *_next;                             /* optional */
+
+    char *type;                                            /* required */
+    esxVI_Boolean all;                                     /* optional */
+    esxVI_String *pathSet;                                 /* optional, list */
+};
+
+int esxVI_PropertySpec_Alloc(virConnectPtr conn,
+                             esxVI_PropertySpec **propertySpec);
+void esxVI_PropertySpec_Free(esxVI_PropertySpec **propertySpecList);
+int esxVI_PropertySpec_AppendToList(virConnectPtr conn,
+                                    esxVI_PropertySpec **propertySpecList,
+                                    esxVI_PropertySpec *propertySpec);
+int esxVI_PropertySpec_Serialize(virConnectPtr conn,
+                                 esxVI_PropertySpec *propertySpec,
+                                 const char *element, virBufferPtr output,
+                                 esxVI_Boolean required);
+int esxVI_PropertySpec_SerializeList(virConnectPtr conn,
+                                     esxVI_PropertySpec *propertySpecList,
+                                     const char *element, virBufferPtr output,
+                                     esxVI_Boolean required);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: PropertyFilterSpec
+ */
+
+struct _esxVI_PropertyFilterSpec {
+    esxVI_PropertyFilterSpec *_next;                       /* optional */
+
+    esxVI_PropertySpec *propSet;                           /* required, list */
+    esxVI_ObjectSpec *objectSet;                           /* required, list */
+};
+
+int esxVI_PropertyFilterSpec_Alloc
+      (virConnectPtr conn, esxVI_PropertyFilterSpec **propertyFilterSpec);
+void esxVI_PropertyFilterSpec_Free
+       (esxVI_PropertyFilterSpec **propertyFilterSpecList);
+int esxVI_PropertyFilterSpec_AppendToList
+      (virConnectPtr conn, esxVI_PropertyFilterSpec **propertyFilterSpecList,
+       esxVI_PropertyFilterSpec *propertyFilterSpec);
+int esxVI_PropertyFilterSpec_Serialize
+      (virConnectPtr conn, esxVI_PropertyFilterSpec *propertyFilterSpec,
+       const char *element, virBufferPtr output, esxVI_Boolean required);
+int esxVI_PropertyFilterSpec_SerializeList
+      (virConnectPtr conn, esxVI_PropertyFilterSpec *propertyFilterSpecList,
+       const char *element, virBufferPtr output, esxVI_Boolean required);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: ObjectContent
+ */
+
+struct _esxVI_ObjectContent {
+    esxVI_ObjectContent *_next;                            /* optional */
+
+    esxVI_ManagedObjectReference *obj;                     /* required */
+    esxVI_DynamicProperty *propSet;                        /* optional, list */
+    /*esxVI_MissingProperty *missingSet; *//* optional, list *//* FIXME */
+};
+
+int esxVI_ObjectContent_Alloc(virConnectPtr conn,
+                              esxVI_ObjectContent **objectContent);
+void esxVI_ObjectContent_Free(esxVI_ObjectContent **objectContentList);
+int esxVI_ObjectContent_AppendToList(virConnectPtr conn,
+                                     esxVI_ObjectContent **objectContentList,
+                                     esxVI_ObjectContent *objectContent);
+int esxVI_ObjectContent_DeepCopy(virConnectPtr conn,
+                                 esxVI_ObjectContent **dest,
+                                 esxVI_ObjectContent *src);
+int esxVI_ObjectContent_Deserialize(virConnectPtr conn, xmlNodePtr node,
+                                    esxVI_ObjectContent **objectContent);
+int esxVI_ObjectContent_DeserializeList
+      (virConnectPtr conn, xmlNodePtr node,
+       esxVI_ObjectContent **objectContentList);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: ObjectUpdate
+ */
+
+struct _esxVI_ObjectUpdate {
+    esxVI_ObjectUpdate *_next;                             /* optional */
+
+    esxVI_ObjectUpdateKind kind;                           /* required */
+    esxVI_ManagedObjectReference *obj;                     /* required */
+    esxVI_PropertyChange *changeSet;                       /* optional, list */
+    /*esxVI_MissingProperty *missingSet; *//* optional, list *//* FIXME */
+};
+
+int esxVI_ObjectUpdate_Alloc(virConnectPtr conn,
+                             esxVI_ObjectUpdate **objectUpdate);
+void esxVI_ObjectUpdate_Free(esxVI_ObjectUpdate **objectUpdateList);
+int esxVI_ObjectUpdate_AppendToList(virConnectPtr conn,
+                                    esxVI_ObjectUpdate **objectUpdateList,
+                                    esxVI_ObjectUpdate *objectUpdate);
+int esxVI_ObjectUpdate_Deserialize(virConnectPtr conn, xmlNodePtr node,
+                                   esxVI_ObjectUpdate **objectUpdate);
+int esxVI_ObjectUpdate_DeserializeList(virConnectPtr conn, xmlNodePtr node,
+                                       esxVI_ObjectUpdate **objectUpdateList);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: PropertyFilterUpdate
+ */
+
+struct _esxVI_PropertyFilterUpdate {
+    esxVI_PropertyFilterUpdate *_next;                     /* optional */
+
+    esxVI_ManagedObjectReference *filter;                  /* required */
+    esxVI_ObjectUpdate *objectSet;                         /* optional, list */
+    /*esxVI_MissingProperty *missingSet; *//* optional, list *//* FIXME */
+};
+
+int esxVI_PropertyFilterUpdate_Alloc
+      (virConnectPtr conn,
+       esxVI_PropertyFilterUpdate **propertyFilterUpdate);
+void esxVI_PropertyFilterUpdate_Free
+       (esxVI_PropertyFilterUpdate **propertyFilterUpdateList);
+int esxVI_PropertyFilterUpdate_AppendToList
+      (virConnectPtr conn,
+       esxVI_PropertyFilterUpdate **propertyFilterUpdateList,
+       esxVI_PropertyFilterUpdate *propertyFilterUpdate);
+int esxVI_PropertyFilterUpdate_Deserialize
+      (virConnectPtr conn, xmlNodePtr node,
+       esxVI_PropertyFilterUpdate **propertyFilterUpdate);
+int esxVI_PropertyFilterUpdate_DeserializeList
+      (virConnectPtr conn, xmlNodePtr node,
+       esxVI_PropertyFilterUpdate **propertyFilterUpdateList);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: AboutInfo
+ */
+
+struct _esxVI_AboutInfo {
+    char *name;                                            /* required */
+    char *fullName;                                        /* required */
+    char *vendor;                                          /* required */
+    char *version;                                         /* required */
+    char *build;                                           /* required */
+    char *localeVersion;                                   /* optional */
+    char *localeBuild;                                     /* optional */
+    char *osType;                                          /* required */
+    char *productLineId;                                   /* required */
+    char *apiType;                                         /* required */
+    char *apiVersion;                                      /* required */
+};
+
+int esxVI_AboutInfo_Alloc(virConnectPtr conn, esxVI_AboutInfo **aboutInfo);
+void esxVI_AboutInfo_Free(esxVI_AboutInfo **aboutInfo);
+int esxVI_AboutInfo_Deserialize(virConnectPtr conn, xmlNodePtr node,
+                                esxVI_AboutInfo **aboutInfo);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: ServiceContent
+ */
+
+struct _esxVI_ServiceContent {
+    esxVI_ManagedObjectReference *rootFolder;              /* required */
+    esxVI_ManagedObjectReference *propertyCollector;       /* required */
+    esxVI_ManagedObjectReference *viewManager;             /* optional */
+    esxVI_AboutInfo *about;                                /* required */
+    esxVI_ManagedObjectReference *setting;                 /* optional */
+    esxVI_ManagedObjectReference *userDirectory;           /* optional */
+    esxVI_ManagedObjectReference *sessionManager;          /* optional */
+    esxVI_ManagedObjectReference *authorizationManager;    /* optional */
+    esxVI_ManagedObjectReference *perfManager;             /* optional */
+    esxVI_ManagedObjectReference *scheduledTaskManager;    /* optional */
+    esxVI_ManagedObjectReference *alarmManager;            /* optional */
+    esxVI_ManagedObjectReference *eventManager;            /* optional */
+    esxVI_ManagedObjectReference *taskManager;             /* optional */
+    esxVI_ManagedObjectReference *extensionManager;        /* optional */
+    esxVI_ManagedObjectReference *customizationSpecManager; /* optional */
+    esxVI_ManagedObjectReference *customFieldsManager;     /* optional */
+    esxVI_ManagedObjectReference *accountManager;          /* optional */
+    esxVI_ManagedObjectReference *diagnosticManager;       /* optional */
+    esxVI_ManagedObjectReference *licenseManager;          /* optional */
+    esxVI_ManagedObjectReference *searchIndex;             /* optional */
+    esxVI_ManagedObjectReference *fileManager;             /* optional */
+    esxVI_ManagedObjectReference *virtualDiskManager;      /* optional */
+    esxVI_ManagedObjectReference *virtualizationManager;   /* optional */
+};
+
+int esxVI_ServiceContent_Alloc(virConnectPtr conn,
+                               esxVI_ServiceContent **serviceContent);
+void esxVI_ServiceContent_Free(esxVI_ServiceContent **serviceContent);
+int esxVI_ServiceContent_Deserialize(virConnectPtr conn, xmlNodePtr node,
+                                     esxVI_ServiceContent **serviceContent);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: UpdateSet
+ */
+
+struct _esxVI_UpdateSet {
+    char *version;                                         /* required */
+    esxVI_PropertyFilterUpdate *filterSet;                 /* optional, list */
+};
+
+int esxVI_UpdateSet_Alloc(virConnectPtr conn, esxVI_UpdateSet **updateSet);
+void esxVI_UpdateSet_Free(esxVI_UpdateSet **updateSet);
+int esxVI_UpdateSet_Deserialize(virConnectPtr conn, xmlNodePtr node,
+                                esxVI_UpdateSet **updateSet);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: SharesInfo
+ */
+
+struct _esxVI_SharesInfo {
+    esxVI_Int *shares;                                     /* required */
+    esxVI_SharesLevel level;                               /* required */
+};
+
+int esxVI_SharesInfo_Alloc(virConnectPtr conn, esxVI_SharesInfo **sharesInfo);
+void esxVI_SharesInfo_Free(esxVI_SharesInfo **sharesInfo);
+int esxVI_SharesInfo_CastFromAnyType(virConnectPtr conn,
+                                     esxVI_AnyType *anyType,
+                                     esxVI_SharesInfo **sharesInfo);
+int esxVI_SharesInfo_Deserialize(virConnectPtr conn, xmlNodePtr node,
+                                 esxVI_SharesInfo **sharesInfo);
+int esxVI_SharesInfo_Serialize(virConnectPtr conn,
+                               esxVI_SharesInfo *sharesInfo,
+                               const char *element, virBufferPtr output,
+                               esxVI_Boolean required);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: ResourceAllocationInfo
+ */
+
+struct _esxVI_ResourceAllocationInfo {
+    esxVI_Long *reservation;                               /* optional */
+    esxVI_Boolean expandableReservation;                   /* optional */
+    esxVI_Long *limit;                                     /* optional */
+    esxVI_SharesInfo *shares;                              /* optional */
+    esxVI_Long *overheadLimit;                             /* optional */
+};
+
+int esxVI_ResourceAllocationInfo_Alloc
+      (virConnectPtr conn,
+       esxVI_ResourceAllocationInfo **resourceAllocationInfo);
+void esxVI_ResourceAllocationInfo_Free
+       (esxVI_ResourceAllocationInfo **resourceAllocationInfo);
+int esxVI_ResourceAllocationInfo_Serialize
+      (virConnectPtr conn, esxVI_ResourceAllocationInfo *resourceAllocationInfo,
+       const char *element, virBufferPtr output, esxVI_Boolean required);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: VirtualMachineConfigSpec
+ */
+
+/* FIXME: implement the rest */
+struct _esxVI_VirtualMachineConfigSpec {
+    char *changeVersion;                                   /* optional */
+    char *name;                                            /* optional */
+    char *version;                                         /* optional */
+    char *uuid;                                            /* optional */
+    esxVI_Long *npivNodeWorldWideName;                     /* optional, list */
+    esxVI_Long *npivPortWorldWideName;                     /* optional, list */
+    char *npivWorldWideNameType;                           /* optional */
+    char *npivWorldWideNameOp;                             /* optional */
+    char *locationId;                                      /* optional */
+    char *guestId;                                         /* optional */
+    char *alternateGuestName;                              /* optional */
+    char *annotation;                                      /* optional */
+    //esxVI_VirtualMachineFileInfo *files; /* optional */
+    //esxVI_ToolsConfigInfo *tools; /* optional */
+    //esxVI_VirtualMachineFlagInfo *flags; /* optional */
+    //esxVI_VirtualMachineConsolePreferences *consolePreferences; /* optional */
+    //esxVI_VirtualMachineDefaultPowerOpInfo *powerOpInfo; /* optional */
+    esxVI_Int *numCPUs;                                    /* optional */
+    esxVI_Long *memoryMB;                                  /* optional */
+    //esxVI_VirtualDeviceConfigSpec *deviceChange; /* optional, list */
+    esxVI_ResourceAllocationInfo *cpuAllocation;           /* optional */
+    esxVI_ResourceAllocationInfo *memoryAllocation;        /* optional */
+    //esxVI_VirtualMachineAffinityInfo *cpuAffinity; /* optional */
+    //esxVI_VirtualMachineAffinityInfo *memoryAffinity; /* optional */
+    //esxVI_VirtualMachineNetworkShaperInfo *networkShaper; /* optional */
+    //esxVI_VirtualMachineCpuIdInfoSpec *cpuFeatureMask; /* optional, list */
+    //esxVI_OptionValue *extraConfig; /* optional, list */
+    char *swapPlacement;                                   /* optional */
+    //esxVI_VirtualMachineBootOptions *bootOptions; /* optional */
+};
+
+int esxVI_VirtualMachineConfigSpec_Alloc
+      (virConnectPtr conn,
+       esxVI_VirtualMachineConfigSpec **virtualMachineConfigSpec);
+void esxVI_VirtualMachineConfigSpec_Free
+       (esxVI_VirtualMachineConfigSpec **virtualMachineConfigSpec);
+int esxVI_VirtualMachineConfigSpec_Serialize
+      (virConnectPtr conn,
+       esxVI_VirtualMachineConfigSpec *virtualMachineConfigSpec,
+       const char *element, virBufferPtr output, esxVI_Boolean required);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: Event
+ */
+
+/* FIXME: implement the rest */
+struct _esxVI_Event {
+    esxVI_Event *_next;                                    /* optional */
+
+    esxVI_Int *key;                                        /* required */
+    esxVI_Int *chainId;                                    /* required */
+    esxVI_DateTime *createdTime;                           /* required */
+    char *userName;                                        /* required */
+    //??? datacenter;                                      /* optional */
+    //??? computeResource;                                 /* optional */
+    //??? host;                                            /* optional */
+    //??? vm;                                              /* optional */
+    char *fullFormattedMessage;                            /* optional */
+};
+
+int esxVI_Event_Alloc(virConnectPtr conn, esxVI_Event **event);
+void esxVI_Event_Free(esxVI_Event **eventList);
+int esxVI_Event_Deserialize(virConnectPtr conn, xmlNodePtr node,
+                            esxVI_Event **event);
+int esxVI_Event_DeserializeList(virConnectPtr conn, xmlNodePtr node,
+                                esxVI_Event **eventList);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: UserSession
+ */
+
+struct _esxVI_UserSession {
+    char *key;                                             /* required */
+    char *userName;                                        /* required */
+    char *fullName;                                        /* required */
+    esxVI_DateTime *loginTime;                             /* required */
+    esxVI_DateTime *lastActiveTime;                        /* required */
+    char *locale;                                          /* required */
+    char *messageLocale;                                   /* required */
+};
+
+int esxVI_UserSession_Alloc(virConnectPtr conn,
+                            esxVI_UserSession **userSession);
+void esxVI_UserSession_Free(esxVI_UserSession **userSession);
+int esxVI_UserSession_CastFromAnyType(virConnectPtr conn,
+                                      esxVI_AnyType *anyType,
+                                      esxVI_UserSession **userSession);
+int esxVI_UserSession_Deserialize(virConnectPtr conn, xmlNodePtr node,
+                                  esxVI_UserSession **userSession);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: ElementDescription extends Description
+ *
+ *          In contrast to SelectionSpec and TraversalSpec just merge
+ *          Description into ElementDescription for simplicity, because
+ *          only ElementDescription is used.
+ */
+
+struct _esxVI_ElementDescription {
+    esxVI_ElementDescription *_next;                       /* optional */
+
+    /* Description */
+    char *label;                                           /* required */
+    char *summary;                                         /* required */
+
+    /* ElementDescription */
+    char *key;                                             /* required */
+};
+
+int esxVI_ElementDescription_Alloc
+      (virConnectPtr conn, esxVI_ElementDescription **elementDescription);
+void esxVI_ElementDescription_Free
+       (esxVI_ElementDescription **elementDescription);
+int esxVI_ElementDescription_Deserialize
+      (virConnectPtr conn, xmlNodePtr node,
+       esxVI_ElementDescription **elementDescription);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: PerfMetricId
+ */
+
+struct _esxVI_PerfMetricId {
+    esxVI_PerfMetricId *_next;                             /* optional */
+
+    esxVI_Int *counterId;                                  /* required */
+    char *instance;                                        /* required */
+};
+
+int esxVI_PerfMetricId_Alloc(virConnectPtr conn,
+                             esxVI_PerfMetricId **perfMetricId);
+void esxVI_PerfMetricId_Free(esxVI_PerfMetricId **perfMetricId);
+int esxVI_PerfMetricId_Serialize(virConnectPtr conn,
+                                 esxVI_PerfMetricId *perfMetricId,
+                                 const char *element, virBufferPtr output,
+                                 esxVI_Boolean required);
+int esxVI_PerfMetricId_SerializeList(virConnectPtr conn,
+                                     esxVI_PerfMetricId *perfMetricIdList,
+                                     const char *element, virBufferPtr output,
+                                     esxVI_Boolean required);
+int esxVI_PerfMetricId_Deserialize(virConnectPtr conn, xmlNodePtr node,
+                                   esxVI_PerfMetricId **perfMetricId);
+int esxVI_PerfMetricId_DeserializeList(virConnectPtr conn, xmlNodePtr node,
+                                       esxVI_PerfMetricId **perfMetricIdList);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: PerfCounterInfo
+ */
+
+struct _esxVI_PerfCounterInfo {
+    esxVI_PerfCounterInfo *_next;                          /* optional */
+
+    esxVI_Int *key;                                        /* required */
+    esxVI_ElementDescription *nameInfo;                    /* required */
+    esxVI_ElementDescription *groupInfo;                   /* required */
+    esxVI_ElementDescription *unitInfo;                    /* required */
+    esxVI_PerfSummaryType rollupType;                      /* required */
+    esxVI_PerfStatsType statsType;                         /* required */
+    esxVI_Int *level;                                      /* optional */
+    esxVI_Int *associatedCounterId;                        /* optional, list */
+};
+
+int esxVI_PerfCounterInfo_Alloc(virConnectPtr conn,
+                                esxVI_PerfCounterInfo **perfCounterInfo);
+void esxVI_PerfCounterInfo_Free(esxVI_PerfCounterInfo **perfCounterInfo);
+int esxVI_PerfCounterInfo_Deserialize(virConnectPtr conn, xmlNodePtr node,
+                                      esxVI_PerfCounterInfo **perfCounterInfo);
+int esxVI_PerfCounterInfo_DeserializeList
+      (virConnectPtr conn, xmlNodePtr node,
+       esxVI_PerfCounterInfo **perfCounterInfoList);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: PerfQuerySpec
+ */
+
+struct _esxVI_PerfQuerySpec {
+    esxVI_PerfQuerySpec *_next;                            /* optional */
+
+    esxVI_ManagedObjectReference* entity;                  /* required */
+    esxVI_DateTime* startTime;                             /* optional */
+    esxVI_DateTime* endTime;                               /* optional */
+    esxVI_Int *maxSample;                                  /* optional */
+    esxVI_PerfMetricId *metricId;                          /* optional, list */
+    esxVI_Int *intervalId;                                 /* optional */
+    char* format;                                          /* optional */ // FIXME: see PerfFormat
+};
+
+int esxVI_PerfQuerySpec_Alloc(virConnectPtr conn,
+                              esxVI_PerfQuerySpec **perfQuerySpec);
+void esxVI_PerfQuerySpec_Free(esxVI_PerfQuerySpec **perfQuerySpec);
+int esxVI_PerfQuerySpec_Serialize(virConnectPtr conn,
+                                  esxVI_PerfQuerySpec *perfQuerySpec,
+                                  const char *element, virBufferPtr output,
+                                  esxVI_Boolean required);
+int esxVI_PerfQuerySpec_SerializeList(virConnectPtr conn,
+                                      esxVI_PerfQuerySpec *perfQuerySpecList,
+                                      const char *element, virBufferPtr output,
+                                      esxVI_Boolean required);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: PerfSampleInfo
+ */
+
+struct _esxVI_PerfSampleInfo {
+    esxVI_PerfSampleInfo *_next;                           /* optional */
+
+    esxVI_DateTime* timestamp;                             /* required */
+    esxVI_Int* interval;                                   /* required */
+};
+
+int esxVI_PerfSampleInfo_Alloc(virConnectPtr conn,
+                               esxVI_PerfSampleInfo **perfSampleInfo);
+void esxVI_PerfSampleInfo_Free(esxVI_PerfSampleInfo **perfSampleInfo);
+int esxVI_PerfSampleInfo_AppendToList(virConnectPtr conn,
+                                      esxVI_PerfSampleInfo **perfSampleInfoList,
+                                      esxVI_PerfSampleInfo *perfSampleInfo);
+int esxVI_PerfSampleInfo_Deserialize(virConnectPtr conn, xmlNodePtr node,
+                                     esxVI_PerfSampleInfo **perfSampleInfo);
+int esxVI_PerfSampleInfo_DeserializeList
+      (virConnectPtr conn, xmlNodePtr node,
+       esxVI_PerfSampleInfo **perfSampleInfoList);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: PerfMetricIntSeries extends PerfMetricSeries
+ *
+ *          In contrast to SelectionSpec and TraversalSpec just merge
+ *          PerfMetricSeries into PerfMetricIntSeries for simplicity, because
+ *          only PerfMetricIntSeries is used and the other type inheriting
+ *          PerfMetricSeries (PerfMetricSeriesCSV) is not used.
+ */
+
+struct _esxVI_PerfMetricIntSeries {
+    esxVI_PerfMetricIntSeries *_next;                      /* optional */
+
+    /* PerfMetricSeries */
+    esxVI_PerfMetricId *id;                                /* required */
+
+    /* PerfMetricIntSeries */
+    esxVI_Long *value;                                     /* optional, list */
+};
+
+int esxVI_PerfMetricIntSeries_Alloc
+      (virConnectPtr conn, esxVI_PerfMetricIntSeries **perfMetricIntSeries);
+void esxVI_PerfMetricIntSeries_Free
+       (esxVI_PerfMetricIntSeries **perfMetricIntSeries);
+int esxVI_PerfMetricIntSeries_AppendToList
+      (virConnectPtr conn, esxVI_PerfMetricIntSeries **perfMetricIntSeriesList,
+       esxVI_PerfMetricIntSeries *perfMetricIntSeries);
+int esxVI_PerfMetricIntSeries_Deserialize
+      (virConnectPtr conn, xmlNodePtr node,
+       esxVI_PerfMetricIntSeries **perfMetricIntSeries);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * VI Type: PerfEntityMetric extends PerfEntityMetricBase
+ *
+ *          In contrast to SelectionSpec and TraversalSpec just merge
+ *          PerfEntityMetricBase into PerfEntityMetric for simplicity, because
+ *          only PerfEntityMetric is used and the other type inheriting
+ *          PerfEntityMetric (PerfEntityMetricCSV) is not used.
+ *
+ *          Also use PerfMetricIntSeries instead of the correct base type
+ *          PerfMetricSeries for the value property, because only
+ *          PerfMetricIntSeries is used.
+ */
+
+struct _esxVI_PerfEntityMetric {
+    esxVI_PerfEntityMetric *_next;                         /* optional */
+
+    /* PerfEntityMetricBase */
+    esxVI_ManagedObjectReference *entity;                  /* required */
+
+    /* PerfEntityMetric */
+    esxVI_PerfSampleInfo *sampleInfo;                      /* optional, list */
+    esxVI_PerfMetricIntSeries *value;                      /* optional, list */
+};
+
+int esxVI_PerfEntityMetric_Alloc(virConnectPtr conn,
+                                 esxVI_PerfEntityMetric **perfEntityMetric);
+void esxVI_PerfEntityMetric_Free
+       (esxVI_PerfEntityMetric **perfEntityMetric);
+int esxVI_PerfEntityMetric_Deserialize
+      (virConnectPtr conn, xmlNodePtr node,
+       esxVI_PerfEntityMetric **perfEntityMetric);
+int esxVI_PerfEntityMetric_DeserializeList
+      (virConnectPtr conn, xmlNodePtr node,
+       esxVI_PerfEntityMetric **perfEntityMetricList);
+
+#endif /* __ESX_VI_TYPES_H__ */
diff --git a/src/esx/esx_vmx.c b/src/esx/esx_vmx.c
new file mode 100644
index 0000000..635a483
--- /dev/null
+++ b/src/esx/esx_vmx.c
@@ -0,0 +1,1666 @@
+
+/*
+ * esx_vmx.c: VMX related methods for the VMware ESX driver
+ *
+ * Copyright (C) 2009 Matthias Bolte <matthias.bolte@xxxxxxxxxxxxxx>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ */
+
+#include <config.h>
+
+#include "internal.h"
+#include "virterror_internal.h"
+#include "memory.h"
+#include "logging.h"
+#include "esx_util.h"
+#include "esx_vmx.h"
+
+/*
+
+mapping:
+
+domain-xml                        <=>   vmx
+
+
+                                        config.version = "8"                    # essential
+                                        virtualHW.version = "4"                 # essential
+
+
+???                               <=>   guestOS = "<value>"                     # essential, FIXME: not representable
+def->id = <value>                 <=>   ???                                     # not representable
+def->uuid = <value>               <=>   uuid.bios = "<value>"
+def->name = <value>               <=>   displayName = "<value>"
+def->maxmem = <value kilobyte>    <=>   memsize = "<value megabyte>"            # must be a multiple of 4, defaults to 32
+def->memory = <value kilobyte>    <=>   sched.mem.max = "<value megabyte>"      # defaults to "unlimited" -> def->memory = def->maxmem
+def->vcpus = <value>              <=>   numvcpus = "<value>"                    # must be 1 or a multiple of 2, defaults to 1
+def->cpumask = <uint list>        <=>   sched.cpu.affinity = "<uint list>"
+
+
+
+################################################################################
+## os ##########################################################################
+
+def->os
+
+->type = "hvm"
+->arch
+->machine
+->nBootDevs
+->bootDevs
+->init
+->kernel
+->initrd
+->cmdline
+->root
+->loader
+->bootloader
+->bootloaderArgs
+
+
+
+################################################################################
+## disks #######################################################################
+
+                                        scsi[0..3]:[0..6,8..15] -> <controller>:<id>
+                                        ide[0..1]:[0..1]        -> <controller>:<id>
+                                        floppy[0..1]            -> <controller>
+
+def->disks[0]...
+
+## disks: scsi hard drive from .vmdk image #####################################
+
+                                        scsi0.present = "true"                  # defaults to "false"
+                                        scsi0:0.present = "true"                # defaults to "false"
+                                        scsi0:0.startConnected = "true"         # defaults to "true"
+
+???                               <=>   scsi0:0.mode = "persistent"             # defaults to "persistent"
+                                        scsi0:0.mode = "undoable"
+                                        scsi0:0.mode = "independent-persistent"
+                                        scsi0:0.mode = "independent-nonpersistent"
+
+...
+->type = _DISK_TYPE_FILE          <=>   scsi0:0.deviceType = "scsi-hardDisk"    # defaults to ?
+->device = _DISK_DEVICE_DISK      <=>   scsi0:0.deviceType = "scsi-hardDisk"    # defaults to ?
+->bus = _DISK_BUS_SCSI
+->src = <value>.vmdk              <=>   scsi0:0.fileName = "<value>.vmdk"
+->dst = sd[<controller> * 16 + <id> mapped to [a-z]+]
+->driverName = <driver>           <=>   scsi0.virtualDev = "<driver>"           # default depends on guestOS value
+->driverType
+->cachemode                       <=>   scsi0:0.writeThrough = "<value>"        # defaults to false, true -> _DISK_CACHE_WRITETHRU, false _DISK_CACHE_DEFAULT
+->readonly
+->shared
+->slotnum
+
+
+## disks: ide hard drive from .vmdk image ######################################
+
+                                        ide0.present = "true"                   # defaults to "false"
+                                        ide0:0.present = "true"                 # defaults to "false"
+                                        ide0:0.startConnected = "true"          # defaults to "true"
+
+???                               <=>   ide0:0.mode = "persistent"              # defaults to "persistent"
+                                        ide0:0.mode = "undoable"
+                                        ide0:0.mode = "independent-persistent"
+                                        ide0:0.mode = "independent-nonpersistent"
+
+...
+->type = _DISK_TYPE_FILE          <=>   ide0:0.deviceType = "ata-hardDisk"      # defaults to ?
+->device = _DISK_DEVICE_DISK      <=>   ide0:0.deviceType = "ata-hardDisk"      # defaults to ?
+->bus = _DISK_BUS_IDE
+->src = <value>.vmdk              <=>   ide0:0.fileName = "<value>.vmdk"
+->dst = hd[<controller> * 2 + <id> mapped to [a-z]+]
+->driverName
+->driverType
+->cachemode                       <=>   ide0:0.writeThrough = "<value>"         # defaults to false, true -> _DISK_CACHE_WRITETHRU, false _DISK_CACHE_DEFAULT
+->readonly
+->shared
+->slotnum
+
+
+## disks: scsi cdrom from .iso image ###########################################
+
+                                        scsi0.present = "true"                  # defaults to "false"
+                                        scsi0:0.present = "true"                # defaults to "false"
+                                        scsi0:0.startConnected = "true"         # defaults to "true"
+
+...
+->type = _DISK_TYPE_FILE          <=>   scsi0:0.deviceType = "cdrom-image"      # defaults to ?
+->device = _DISK_DEVICE_CDROM     <=>   scsi0:0.deviceType = "cdrom-image"      # defaults to ?
+->bus = _DISK_BUS_SCSI
+->src = <value>.iso               <=>   scsi0:0.fileName = "<value>.iso"
+->dst = sd[<controller> * 16 + <id> mapped to [a-z]+]
+->driverName = <driver>           <=>   scsi0.virtualDev = "<driver>"           # default depends on guestOS value
+->driverType
+->cachemode
+->readonly
+->shared
+->slotnum
+
+
+## disks: ide cdrom from .iso image ############################################
+
+                                        ide0.present = "true"                   # defaults to "false"
+                                        ide0:0.present = "true"                 # defaults to "false"
+                                        ide0:0.startConnected = "true"          # defaults to "true"
+
+...
+->type = _DISK_TYPE_FILE          <=>   ide0:0.deviceType = "cdrom-image"       # defaults to ?
+->device = _DISK_DEVICE_CDROM     <=>   ide0:0.deviceType = "cdrom-image"       # defaults to ?
+->bus = _DISK_BUS_IDE
+->src = <value>.iso               <=>   ide0:0.fileName = "<value>.iso"
+->dst = hd[<controller> * 2 + <id> mapped to [a-z]+]
+->driverName
+->driverType
+->cachemode
+->readonly
+->shared
+->slotnum
+
+
+## disks: scsi cdrom from host device ##########################################
+
+                                        scsi0.present = "true"                  # defaults to "false"
+                                        scsi0:0.present = "true"                # defaults to "false"
+                                        scsi0:0.startConnected = "true"         # defaults to "true"
+
+...
+->type = _DISK_TYPE_BLOCK         <=>   scsi0:0.deviceType = "atapi-cdrom"      # defaults to ?
+->device = _DISK_DEVICE_CDROM     <=>   scsi0:0.deviceType = "atapi-cdrom"      # defaults to ?
+->bus = _DISK_BUS_SCSI
+->src = <value>                   <=>   scsi0:0.fileName = "<value>"            # e.g. "/dev/scd0" ?
+->dst = sd[<controller> * 16 + <id> mapped to [a-z]+]
+->driverName = <driver>           <=>   scsi0.virtualDev = "<driver>"           # default depends on guestOS value
+->driverType
+->cachemode
+->readonly
+->shared
+->slotnum
+
+
+## disks: ide cdrom from host device ###########################################
+
+                                        ide0.present = "true"                   # defaults to "false"
+                                        ide0:0.present = "true"                 # defaults to "false"
+                                        ide0:0.startConnected = "true"          # defaults to "true"
+                                        ide0:0.clientDevice = "false"           # defaults to "false"
+
+...
+->type = _DISK_TYPE_BLOCK         <=>   ide0:0.deviceType = "atapi-cdrom"       # defaults to ?
+->device = _DISK_DEVICE_CDROM     <=>   ide0:0.deviceType = "atapi-cdrom"       # defaults to ?
+->bus = _DISK_BUS_IDE
+->src = <value>                   <=>   ide0:0.fileName = "<value>"             # e.g. "/dev/scd0"
+->dst = hd[<controller> * 2 + <id> mapped to [a-z]+]
+->driverName
+->driverType
+->cachemode
+->readonly
+->shared
+->slotnum
+
+
+## disks: floppy from .flp image ###############################################
+
+                                        floppy0.present = "true"                # defaults to "false"
+                                        floppy0.startConnected = "true"         # defaults to "true"
+                                        floppy0.clientDevice = "false"          # defaults to "false"
+
+...
+->type = _DISK_TYPE_FILE          <=>   floppy0.fileType = "file"               # defaults to ?
+->device = _DISK_DEVICE_FLOPPY
+->bus = _DISK_BUS_FDC
+->src = <value>.flp               <=>   floppy0.fileName = "<value>.flp"
+->dst = fd[<controller> mapped to [a-z]+]
+->driverName
+->driverType
+->cachemode
+->readonly
+->shared
+->slotnum
+
+
+## disks: floppy from host device ##############################################
+
+                                        floppy0.present = "true"                # defaults to "false"
+                                        floppy0.startConnected = "true"         # defaults to "true"
+                                        floppy0.clientDevice = "false"          # defaults to "false"
+
+...
+->type = _DISK_TYPE_BLOCK         <=>   floppy0.fileType = "device"             # defaults to ?
+->device = _DISK_DEVICE_FLOPPY
+->bus = _DISK_BUS_FDC
+->src = <value>                   <=>   floppy0.fileName = "<value>"            # e.g. "/dev/fd0"
+->dst = fd[<controller> mapped to [a-z]+]
+->driverName
+->driverType
+->cachemode
+->readonly
+->shared
+->slotnum
+
+
+
+################################################################################
+## nets ########################################################################
+
+                                        ethernet[0..3] -> <controller>
+
+                                        ethernet0.present = "true"              # defaults to "false"
+                                        ethernet0.startConnected = "true"       # defaults to "true"
+
+                                        ethernet0.networkName = "VM Network"    # FIXME
+
+def->nets[0]...
+->model = <model>                 <=>   ethernet0.virtualDev = "<model>"        # default depends on guestOS value
+
+
+                                        ethernet0.addressType = "generated"     # default to "generated"
+                                        ethernet0.generatedAddressOffset = "0"  # ?
+->mac = <value>                   <=>   ethernet0.generatedAddress = "<value>"
+
+
+                                        ethernet0.addressType = "static"        # default to "generated"
+->mac = <value>                   <=>   ethernet0.address = "<value>"
+
+                                                                                # 00:0c:29 prefix for autogenerated mac's
+                                                                                # 00:50:56 prefix for manual configured mac's
+                                                                                # 00:05:69 old prefix from esx 1.5
+
+
+## nets: bridged ###############################################################
+
+...
+->type = _NET_TYPE_BRIDGE         <=>   ethernet0.connectionType = "bridged"    # defaults to "bridged"
+
+
+## nets: hostonly ##############################################################
+
+...                                                                             # FIXME: maybe not supported by ESX?
+->type = _NET_TYPE_NETWORK        <=>   ethernet0.connectionType = "hostonly"   # defaults to "bridged"
+
+
+## nets: nat ###################################################################
+
+...                                                                             # FIXME: maybe not supported by ESX?
+->type = _NET_TYPE_USER           <=>   ethernet0.connectionType = "nat"        # defaults to "bridged"
+
+
+## nets: custom ################################################################
+
+...
+->type = _NET_TYPE_BRIDGE         <=>   ethernet0.connectionType = "custom"     # defaults to "bridged"
+->data.bridge.brname = <value>    <=>   ethernet0.vnet = "<value>"
+
+
+
+################################################################################
+## serials #####################################################################
+
+                                        serial[0..3] -> <port>
+
+                                        serial0.present = "true"                # defaults to "false"
+                                        serial0.startConnected = "true"         # defaults to "true"
+
+def->serials[0]...
+->dstPort = <port>
+
+
+## serials: device #############################################################
+
+->type = _CHR_TYPE_DEV            <=>   serial0.fileType = "device"
+->data.file.path = <value>        <=>   serial0.fileName = "<value>"            # e.g. "/dev/ttyS0"
+???                               <=>   serial0.tryNoRxLoss = "false"           # defaults to "false", FIXME: not representable
+
+
+## serials: file ###############################################################
+
+->type = _CHR_TYPE_FILE           <=>   serial0.fileType = "file"
+->data.file.path = <value>        <=>   serial0.fileName = "<value>"            # e.g. "serial0.file"
+???                               <=>   serial0.tryNoRxLoss = "false"           # defaults to "false", FIXME: not representable
+
+
+## serials: pipe, far end -> app ###############################################
+
+->type = _CHR_TYPE_PIPE           <=>   serial0.fileType = "pipe"
+->data.file.path = <value>        <=>   serial0.fileName = "<value>"            # e.g. "serial0.pipe"
+???                               <=>   serial0.pipe.endPoint = "client"        # defaults to "server", FIXME: not representable
+???                               <=>   serial0.tryNoRxLoss = "true"            # defaults to "false", FIXME: not representable
+
+->type = _CHR_TYPE_PIPE           <=>   serial0.fileType = "pipe"
+->data.file.path = <value>        <=>   serial0.fileName = "<value>"            # e.g. "serial0.pipe"
+???                               <=>   serial0.pipe.endPoint = "server"        # defaults to "server", FIXME: not representable
+???                               <=>   serial0.tryNoRxLoss = "true"            # defaults to "false", FIXME: not representable
+
+
+## serials: pipe, far end -> vm ################################################
+
+->type = _CHR_TYPE_PIPE           <=>   serial0.fileType = "pipe"
+->data.file.path = <value>        <=>   serial0.fileName = "<value>"            # e.g. "serial0.pipe"
+???                               <=>   serial0.pipe.endPoint = "client"        # defaults to "server", FIXME: not representable
+???                               <=>   serial0.tryNoRxLoss = "false"           # defaults to "false", FIXME: not representable
+
+->type = _CHR_TYPE_PIPE           <=>   serial0.fileType = "pipe"
+->data.file.path = <value>        <=>   serial0.fileName = "<value>"            # e.g. "serial0.pipe"
+???                               <=>   serial0.pipe.endPoint = "server"        # defaults to "server", FIXME: not representable
+???                               <=>   serial0.tryNoRxLoss = "false"           # defaults to "false", FIXME: not representable
+
+
+
+################################################################################
+## parallels ###################################################################
+
+                                        parallel[0..2] -> <port>
+
+                                        parallel0.present = "true"              # defaults to "false"
+                                        parallel0.startConnected = "true"       # defaults to "true"
+
+def->parallels[0]...
+->dstPort = <port>
+
+
+## parallels: device #############################################################
+
+->type = _CHR_TYPE_DEV            <=>   parallel0.fileType = "device"
+->data.file.path = <value>        <=>   parallel0.fileName = "<value>"          # e.g. "/dev/parport0"
+???                               <=>   parallel0.bidirectional = "<value>"     # defaults to ?, FIXME: not representable
+
+
+## parallels: file #############################################################
+
+->type = _CHR_TYPE_FILE           <=>   parallel0.fileType = "file"
+->data.file.path = <value>        <=>   parallel0.fileName = "<value>"          # e.g. "parallel0.file"
+???                               <=>   parallel0.bidirectional = "<value>"     # must be "false" for fileType = "file", FIXME: not representable
+
+*/
+
+#define VIR_FROM_THIS VIR_FROM_ESX
+
+#define ESX_ERROR(conn, code, fmt...)                                         \
+    virReportErrorHelper (conn, VIR_FROM_ESX, code, __FILE__, __FUNCTION__,   \
+                          __LINE__, fmt)
+
+
+
+#define ESX_BUILD_VMX_NAME(_suffix)                                           \
+    do {                                                                      \
+        strncpy(_suffix##_name, prefix, sizeof (_suffix##_name) - 1);         \
+        _suffix##_name[sizeof (_suffix##_name) - 1] = '\0';                   \
+        strncat(_suffix##_name, "."#_suffix,                                  \
+                sizeof (_suffix##_name) - 1 - strlen(_suffix##_name));        \
+    } while (0)
+
+
+
+virDomainDefPtr
+esxVMX_ParseConfig(virConnectPtr conn, const char *vmx)
+{
+    virConfPtr conf = NULL;
+    virDomainDefPtr def = NULL;
+    long long config_version = 0;
+    long long virtualHW_version = 0;
+    long long memsize = 0;
+    long long memory = 0;
+    long long numvcpus = 0;
+    char *sched_cpu_affinity = NULL;
+    int controller;
+    int port;
+    int present;
+    char *scsi_virtualDev = NULL;
+    int id;
+
+    conf = virConfReadMem(vmx, strlen(vmx), VIR_CONF_FLAG_VMX_FORMAT);
+
+    if (conf == NULL) {
+        return NULL;
+    }
+
+    if (VIR_ALLOC(def) < 0) {
+        virReportOOMError(conn);
+        goto failure;
+    }
+
+    def->virtType = VIR_DOMAIN_VIRT_VMWARE; /* FIXME: maybe add VIR_DOMAIN_VIRT_ESX ? */
+    def->id = -1;
+
+    if (esxUtil_GetConfigLong(conn, conf, "config.version",
+                              &config_version, 0, 0) < 0) {
+        goto failure;
+    }
+
+    if (config_version != 8) {
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                  "Expecting VMX entry 'config.version' to be \"8\" but "
+                  "found \"%lld\"", config_version);
+        goto failure;
+    }
+
+    if (esxUtil_GetConfigLong(conn, conf, "virtualHW.version",
+                              &virtualHW_version, 0, 0) < 0) {
+        goto failure;
+    }
+
+    if (virtualHW_version != 4) {
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                  "Expecting VMX entry 'virtualHW.version' to be \"4\" but "
+                  "found \"%lld\"", virtualHW_version);
+        goto failure;
+    }
+
+    /* def:uuid */
+    /* FIXME: Need to handle 'uuid.action = "create"' */
+    if (esxUtil_GetConfigUUID(conn, conf, "uuid.bios", def->uuid, 1) < 0) {
+        goto failure;
+    }
+
+    /* def:name */
+    if (esxUtil_GetConfigString(conn, conf, "displayName",
+                                &def->name, 1) < 0) {
+        goto failure;
+    }
+
+    /* def:maxmem */
+    if (esxUtil_GetConfigLong(conn, conf, "memsize", &memsize, 32, 1) < 0) {
+        goto failure;
+    }
+
+    if (memsize <= 0 || memsize % 4 != 0) {
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                  "Expecting VMX entry 'memsize' to be an unsigned "
+                  "integer (multiple of 4) but found %lld", memsize);
+        goto failure;
+    }
+
+    def->maxmem = memsize * 1024; /* Scale from megabytes to kilobytes */
+
+    /* def:memory */
+    if (esxUtil_GetConfigLong(conn, conf, "sched.mem.max", &memory,
+                              memsize, 1) < 0) {
+        goto failure;
+    }
+
+    if (memory < 0) {
+        memory = memsize;
+    }
+
+    def->memory = memory * 1024; /* Scale from megabytes to kilobytes */
+
+    if (def->memory > def->maxmem) {
+        def->memory = def->maxmem;
+    }
+
+    /* def:vcpus */
+    if (esxUtil_GetConfigLong(conn, conf, "numvcpus", &numvcpus, 1, 1) < 0) {
+        goto failure;
+    }
+
+    if (numvcpus <= 0 || (numvcpus % 2 != 0 && numvcpus != 1)) {
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                  "Expecting VMX entry 'numvcpus' to be an unsigned "
+                  "integer (1 or a multiple of 2) but found %lld", numvcpus);
+        goto failure;
+    }
+
+    def->vcpus = numvcpus;
+
+    /* def:cpumask */
+    // VirtualMachine:config.cpuAffinity.affinitySet
+    if (esxUtil_GetConfigString(conn, conf, "sched.cpu.affinity",
+                                &sched_cpu_affinity, 1) < 0) {
+        goto failure;
+    }
+
+    if (sched_cpu_affinity != NULL && STRNEQ(sched_cpu_affinity, "all")) {
+        const char *current = sched_cpu_affinity;
+        int number, count = 0;
+
+        def->cpumasklen = 0;
+
+        if (VIR_ALLOC_N(def->cpumask, VIR_DOMAIN_CPUMASK_LEN) < 0) {
+            virReportOOMError(conn);
+            goto failure;
+        }
+
+        while (*current != '\0') {
+            virSkipSpaces(&current);
+
+            number = virParseNumber(&current);
+
+            if (number < 0) {
+                ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                          "Expecting VMX entry 'sched.cpu.affinity' to be "
+                          "a comma separated list of unsigned integers but "
+                          "found '%s'", sched_cpu_affinity);
+                goto failure;
+            }
+
+            if (number >= VIR_DOMAIN_CPUMASK_LEN) {
+                ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                          "VMX entry 'sched.cpu.affinity' contains a %d, this "
+                          "value is too large", number);
+                goto failure;
+            }
+
+            if (number + 1 > def->cpumasklen) {
+                def->cpumasklen = number + 1;
+            }
+
+            def->cpumask[number] = 1;
+            ++count;
+
+            virSkipSpaces(&current);
+
+            if (*current == ',') {
+                ++current;
+            } else if (*current == '\0') {
+                break;
+            } else {
+                ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                          "Expecting VMX entry 'sched.cpu.affinity' to be "
+                          "a comma separated list of unsigned integers but "
+                          "found '%s'", sched_cpu_affinity);
+                goto failure;
+            }
+
+            virSkipSpaces(&current);
+        }
+
+        if (count < numvcpus) {
+            ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                      "Expecting VMX entry 'sched.cpu.affinity' to contain "
+                      "at least as many values as 'numvcpus' (%lld) but "
+                      "found only %d value(s)", numvcpus, count);
+            goto failure;
+        }
+    }
+
+    /* def:lifecycle */
+    def->onReboot = VIR_DOMAIN_LIFECYCLE_RESTART;
+    def->onPoweroff = VIR_DOMAIN_LIFECYCLE_DESTROY;
+    def->onCrash = VIR_DOMAIN_LIFECYCLE_DESTROY;
+
+    /* def:os */
+    def->os.type = strdup("hvm");
+
+    if (def->os.type == NULL) {
+        virReportOOMError(conn);
+        goto failure;
+    }
+
+/*
+    def->emulator
+    def->features*/
+
+/*
+    def->localtime*/
+
+    /* def:graphics */
+    /* FIXME */
+
+    /* def:disks: 4 * 16 scsi + 2 * 2 ide + 2 floppy = 70 */
+    if (VIR_ALLOC_N(def->disks, 72) < 0) {
+        virReportOOMError(conn);
+        goto failure;
+    }
+
+    def->ndisks = 0;
+
+    /* def:disks (scsi) */
+    for (controller = 0; controller < 4; ++controller) {
+        VIR_FREE(scsi_virtualDev);
+
+        if (esxVMX_ParseSCSIController(conn, conf, controller,
+                                       &present, &scsi_virtualDev) < 0) {
+            goto failure;
+        }
+
+        if (! present) {
+            continue;
+        }
+
+        for (id = 0; id < 16; ++id) {
+            if (id == 7) {
+                /*
+                 * SCSI ID 7 is assigned to the SCSI controller and cannot be
+                 * used for disk devices.
+                 */
+                continue;
+            }
+
+            if (esxVMX_ParseDisk(conn, conf, VIR_DOMAIN_DISK_DEVICE_DISK,
+                                 VIR_DOMAIN_DISK_BUS_SCSI, controller, id,
+                                 scsi_virtualDev,
+                                 &def->disks[def->ndisks]) < 0) {
+                goto failure;
+            }
+
+            if (def->disks[def->ndisks] != NULL) {
+                ++def->ndisks;
+                continue;
+            }
+
+            if (esxVMX_ParseDisk(conn, conf, VIR_DOMAIN_DISK_DEVICE_CDROM,
+                                 VIR_DOMAIN_DISK_BUS_SCSI, controller, id,
+                                 scsi_virtualDev,
+                                 &def->disks[def->ndisks]) < 0) {
+                goto failure;
+            }
+
+            if (def->disks[def->ndisks] != NULL) {
+                ++def->ndisks;
+            }
+        }
+    }
+
+    /* def:disks (ide) */
+    for (controller = 0; controller < 2; ++controller) {
+        for (id = 0; id < 2; ++id) {
+            if (esxVMX_ParseDisk(conn, conf, VIR_DOMAIN_DISK_DEVICE_DISK,
+                                 VIR_DOMAIN_DISK_BUS_IDE, controller, id,
+                                 NULL, &def->disks[def->ndisks]) < 0) {
+                goto failure;
+            }
+
+            if (def->disks[def->ndisks] != NULL) {
+                ++def->ndisks;
+                continue;
+            }
+
+            if (esxVMX_ParseDisk(conn, conf, VIR_DOMAIN_DISK_DEVICE_CDROM,
+                                 VIR_DOMAIN_DISK_BUS_IDE, controller, id,
+                                 NULL, &def->disks[def->ndisks]) < 0) {
+                goto failure;
+            }
+
+            if (def->disks[def->ndisks] != NULL) {
+                ++def->ndisks;
+            }
+        }
+    }
+
+    /* def:disks (floppy) */
+    for (controller = 0; controller < 2; ++controller) {
+        if (esxVMX_ParseDisk(conn, conf, VIR_DOMAIN_DISK_DEVICE_FLOPPY,
+                             VIR_DOMAIN_DISK_BUS_FDC, controller, -1, NULL,
+                             &def->disks[def->ndisks]) < 0) {
+            goto failure;
+        }
+
+        if (def->disks[def->ndisks] != NULL) {
+            ++def->ndisks;
+        }
+    }
+
+    /* def:fss */
+    /* FIXME */
+
+    /* def:nets */
+    if (VIR_ALLOC_N(def->nets, 4) < 0) {
+        virReportOOMError(conn);
+        goto failure;
+    }
+
+    def->nnets = 0;
+
+    for (controller = 0; controller < 4; ++controller) {
+        if (esxVMX_ParseEthernet(conn, conf, controller,
+                                 &def->nets[def->nnets]) < 0) {
+            goto failure;
+        }
+
+        if (def->nets[def->nnets] != NULL) {
+            ++def->nnets;
+        }
+    }
+
+    /* def:inputs */
+    /* FIXME */
+
+    /* def:sounds */
+    /* FIXME */
+
+    /* def:hostdevs */
+    /* FIXME */
+
+    /* def:serials */
+    if (VIR_ALLOC_N(def->serials, 4) < 0) {
+        virReportOOMError(conn);
+        goto failure;
+    }
+
+    def->nserials = 0;
+
+    for (port = 0; port < 4; ++port) {
+        if (esxVMX_ParseSerial(conn, conf, port,
+                               &def->serials[def->nserials]) < 0) {
+            goto failure;
+        }
+
+        if (def->serials[def->nserials] != NULL) {
+            ++def->nserials;
+        }
+    }
+
+    /* def:parallels */
+    if (VIR_ALLOC_N(def->parallels, 3) < 0) {
+        virReportOOMError(conn);
+        goto failure;
+    }
+
+    def->nparallels = 0;
+
+    for (port = 0; port < 3; ++port) {
+        if (esxVMX_ParseParallel(conn, conf, port,
+                                 &def->parallels[def->nparallels]) < 0) {
+            goto failure;
+        }
+
+        if (def->parallels[def->nparallels] != NULL) {
+            ++def->nparallels;
+        }
+    }
+
+cleanup:
+    virConfFree(conf);
+    VIR_FREE(sched_cpu_affinity);
+    VIR_FREE(scsi_virtualDev);
+
+    return def;
+
+failure:
+    virDomainDefFree(def);
+    def = NULL;
+
+    goto cleanup;
+}
+
+
+
+int
+esxVMX_ParseSCSIController(virConnectPtr conn, virConfPtr conf, int controller,
+                           int *present, char **virtualDev)
+{
+    char present_name[32];
+    char virtualDev_name[32];
+
+    if (virtualDev == NULL || *virtualDev != NULL) {
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        goto failure;
+    }
+
+    if (controller < 0 || controller > 3) {
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                  "SCSI controller index %d out of [0..3] range",
+                  controller);
+        goto failure;
+    }
+
+    strncpy(present_name, "scsiX.present", sizeof (virtualDev_name));
+    strncpy(virtualDev_name, "scsiX.virtualDev", sizeof (virtualDev_name));
+
+    present_name[4] = '0' + controller;
+    virtualDev_name[4] = '0' + controller;
+
+    if (esxUtil_GetConfigBoolean(conn, conf, present_name, present, 0, 1) < 0) {
+        goto failure;
+    }
+
+    if (! *present) {
+        return 0;
+    }
+
+    if (esxUtil_GetConfigString(conn, conf, virtualDev_name,
+                                virtualDev, 0) < 0) {
+        goto failure;
+    }
+
+    if (*virtualDev != NULL &&
+        STRCASENEQ(*virtualDev, "buslogic") &&
+        STRCASENEQ(*virtualDev, "lsilogic")) {
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                  "Expecting VMX entry '%s' to be 'buslogic' or 'lsilogic' "
+                  "but found '%s'", virtualDev_name, *virtualDev);
+        goto failure;
+    }
+
+    return 0;
+
+failure:
+    VIR_FREE(*virtualDev);
+
+    return -1;
+}
+
+
+
+char *
+esxVMX_IndexToDiskName(virConnectPtr conn, int idx, const char *prefix)
+{
+    char buffer[32] = "";
+    char *name = NULL;
+    size_t length = strlen(prefix);
+
+    if (length > sizeof (buffer) - 2 - 1) {
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                  "Disk name prefix '%s' is too long", prefix);
+        return NULL;
+    }
+
+    strncpy(buffer, prefix, sizeof (buffer) - 1);
+    buffer[sizeof (buffer) - 1] = '\0';
+
+    if (idx < 26) {
+        buffer[length] = 'a' + idx;
+    } else if (idx < 702) {
+        buffer[length] = 'a' + idx / 26 - 1;
+        buffer[length + 1] = 'a' + idx % 26;
+    } else {
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                  "Disk index %d is too large", idx);
+        return NULL;
+    }
+
+    name = strdup(buffer);
+
+    if (name == NULL) {
+        virReportOOMError(conn);
+        return NULL;
+    }
+
+    return name;
+}
+
+
+
+/*
+struct _virDomainDiskDef {
+    int type;               // partly done
+    int device;             // done
+    int bus;                // done
+    char *src;              // done
+    char *dst;              // done
+    char *driverName;       // done
+    char *driverType;
+    int cachemode;          // done
+    unsigned int readonly : 1;
+    unsigned int shared : 1;
+    int slotnum;
+};*/
+
+int
+esxVMX_ParseDisk(virConnectPtr conn, virConfPtr conf, int device, int bus,
+                 int controller, int id, const char *virtualDev,
+                 virDomainDiskDefPtr *def)
+{
+    /*
+     *     device = {VIR_DOMAIN_DISK_DEVICE_DISK, VIR_DOMAIN_DISK_DEVICE_CDROM}
+     *        bus = VIR_DOMAIN_DISK_BUS_SCSI
+     * controller = [0..3]
+     *         id = [0..6,8..15]
+     * virtualDev = {'buslogic', 'lsilogic'}
+     *
+     *     device = {VIR_DOMAIN_DISK_DEVICE_DISK, VIR_DOMAIN_DISK_DEVICE_CDROM}
+     *        bus = VIR_DOMAIN_DISK_BUS_IDE
+     * controller = [0..1]
+     *         id = [0..1]
+     * virtualDev = NULL
+     *
+     *     device = VIR_DOMAIN_DISK_DEVICE_FLOPPY
+     *        bus = VIR_DOMAIN_DISK_BUS_FDC
+     * controller = [0..1]
+     *         id = -1
+     * virtualDev = NULL
+     */
+
+    int result = 0;
+    char *prefix = NULL;
+
+    char present_name[32] = "";
+    int present = 0;
+
+    char startConnected_name[32] = "";
+    int startConnected = 0;
+
+    char deviceType_name[32] = "";
+    char *deviceType = NULL;
+
+    char clientDevice_name[32] = "";
+    int clientDevice = 0;
+
+    char fileType_name[32] = "";
+    char *fileType = NULL;
+
+    char fileName_name[32] = "";
+    char *fileName = NULL;
+
+    char writeThrough_name[32] = "";
+    int writeThrough = 0;
+
+    if (def == NULL || *def != NULL) {
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    if (VIR_ALLOC(*def) < 0) {
+        virReportOOMError(conn);
+        goto failure;
+    }
+
+    (*def)->device = device;
+    (*def)->bus = bus;
+
+    /* def:dst, def:driverName */
+    if (device == VIR_DOMAIN_DISK_DEVICE_DISK ||
+        device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
+        if (bus == VIR_DOMAIN_DISK_BUS_SCSI) {
+            if (controller < 0 || controller > 3) {
+                ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                          "SCSI controller index %d out of [0..3] range",
+                          controller);
+                goto failure;
+            }
+
+            if (id < 0 || id > 15 || id == 7) {
+                ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                          "SCSI ID %d out of [0..6,8..15] range", id);
+                goto failure;
+            }
+
+            if (virAsprintf(&prefix, "scsi%d:%d", controller, id) < 0) {
+                virReportOOMError(conn);
+                goto failure;
+            }
+
+            (*def)->dst = esxVMX_IndexToDiskName(conn, controller * 16 + id,
+                                                 "sd");
+
+            if ((*def)->dst == NULL) {
+                goto failure;
+            }
+
+            if (virtualDev != NULL) {
+                (*def)->driverName = strdup(virtualDev);
+
+                if ((*def)->driverName == NULL) {
+                    virReportOOMError(conn);
+                    goto failure;
+                }
+            }
+        } else if (bus == VIR_DOMAIN_DISK_BUS_IDE) {
+            if (controller < 0 || controller > 1) {
+                ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                          "IDE controller index %d out of [0..1] range",
+                          controller);
+                goto failure;
+            }
+
+            if (id < 0 || id > 1) {
+                ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                          "IDE ID %d out of [0..1] range", id);
+                goto failure;
+            }
+
+            if (virAsprintf(&prefix, "ide%d:%d", controller, id) < 0) {
+                virReportOOMError(conn);
+                goto failure;
+            }
+
+            (*def)->dst = esxVMX_IndexToDiskName(conn, controller * 2 + id,
+                                                 "hd");
+
+            if ((*def)->dst == NULL) {
+                goto failure;
+            }
+        } else {
+            ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                      "Unsupported bus type '%s' for '%s' device type",
+                      virDomainDiskBusTypeToString (bus),
+                      virDomainDiskDeviceTypeToString (device));
+            goto failure;
+        }
+    } else if (device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
+        if (bus == VIR_DOMAIN_DISK_BUS_FDC) {
+            if (controller < 0 || controller > 1) {
+                ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                          "Floppy controller index %d out of [0..1] range",
+                          controller);
+                goto failure;
+            }
+
+            if (virAsprintf(&prefix, "floppy%d", controller) < 0) {
+                virReportOOMError(conn);
+                goto failure;
+            }
+
+            (*def)->dst = esxVMX_IndexToDiskName(conn, controller, "fd");
+
+            if ((*def)->dst == NULL) {
+                goto failure;
+            }
+        } else {
+            ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                      "Unsupported bus type '%s' for '%s' device type",
+                      virDomainDiskBusTypeToString (bus),
+                      virDomainDiskDeviceTypeToString (device));
+            goto failure;
+        }
+    } else {
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                  "Unsupported device type '%s'",
+                  virDomainDiskDeviceTypeToString (device));
+        goto failure;
+    }
+
+    ESX_BUILD_VMX_NAME(present);
+    ESX_BUILD_VMX_NAME(startConnected);
+    ESX_BUILD_VMX_NAME(deviceType);
+    ESX_BUILD_VMX_NAME(clientDevice);
+    ESX_BUILD_VMX_NAME(fileType);
+    ESX_BUILD_VMX_NAME(fileName);
+    ESX_BUILD_VMX_NAME(writeThrough);
+
+    /* vmx:present */
+    if (esxUtil_GetConfigBoolean(conn, conf, present_name,
+                                 &present, 0, 1) < 0) {
+        goto failure;
+    }
+
+    /* vmx:startConnected */
+    if (esxUtil_GetConfigBoolean(conn, conf, startConnected_name,
+                                 &startConnected, 1, 1) < 0) {
+        goto failure;
+    }
+
+    /* FIXME: Need to distiguish between active and inactive domains here */
+    if (! present/* && ! startConnected*/) {
+        goto ignore;
+    }
+
+    /* vmx:deviceType -> def:type */
+    if (esxUtil_GetConfigString(conn, conf, deviceType_name,
+                                &deviceType, 1) < 0) {
+        goto failure;
+    }
+
+    /* vmx:clientDevice */
+    if (esxUtil_GetConfigBoolean(conn, conf, clientDevice_name,
+                                 &clientDevice, 0, 1) < 0) {
+        goto failure;
+    }
+
+    if (clientDevice) {
+        /*
+         * Just ignore devices in client mode, because I have no clue how to
+         * handle them (e.g. assign an image) without the VI client GUI.
+         */
+        goto ignore;
+    }
+
+    /* vmx:fileType -> def:type */
+    if (esxUtil_GetConfigString(conn, conf, fileType_name, &fileType, 1) < 0) {
+        goto failure;
+    }
+
+    /* vmx:fileName -> def:src, def:type */
+    if (esxUtil_GetConfigString(conn, conf, fileName_name,
+                                &fileName, 0) < 0) {
+        goto failure;
+    }
+
+    /* vmx:writeThrough -> def:cachemode */
+    if (esxUtil_GetConfigBoolean(conn, conf, writeThrough_name,
+                                 &writeThrough, 0, 1) < 0) {
+        goto failure;
+    }
+
+    /* Setup virDomainDiskDef */
+    /* FIXME: Need the datastore name for fileName */
+    if (device == VIR_DOMAIN_DISK_DEVICE_DISK) {
+        if (esxUtil_EqualSuffix(fileName, ".vmdk")) {
+            if (deviceType != NULL) {
+                if (bus == VIR_DOMAIN_DISK_BUS_SCSI &&
+                    STRCASENEQ(deviceType, "scsi-hardDisk")) {
+                    ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                              "Expecting VMX entry '%s' to be 'scsi-hardDisk' "
+                              "but found '%s'", deviceType_name, deviceType);
+                    goto failure;
+                } else if (bus == VIR_DOMAIN_DISK_BUS_IDE &&
+                           STRCASENEQ(deviceType, "ata-hardDisk")) {
+                    ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                              "Expecting VMX entry '%s' to be 'ata-hardDisk' "
+                              "but found '%s'", deviceType_name, deviceType);
+                    goto failure;
+                }
+            }
+
+            (*def)->type = VIR_DOMAIN_DISK_TYPE_FILE;
+            (*def)->src = fileName;
+            (*def)->cachemode = writeThrough ? VIR_DOMAIN_DISK_CACHE_WRITETHRU
+                                             : VIR_DOMAIN_DISK_CACHE_DEFAULT;
+
+            fileName = NULL;
+        } else if (esxUtil_EqualSuffix(fileName, ".iso") ||
+                   STREQ(deviceType, "atapi-cdrom")) {
+            /*
+             * This function was called in order to parse a harddisk device,
+             * but .iso files and 'atapi-cdrom' devices are for CDROM devices
+             * only. Just ignore it, another call to this function to parse a
+             * CDROM device may handle it.
+             */
+            goto ignore;
+        } else {
+            ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                      "Invalid or not yet handled value '%s' for VMX entry "
+                      "'%s'", fileName, fileName_name);
+            goto failure;
+        }
+    } else if (device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
+        if (esxUtil_EqualSuffix(fileName, ".iso")) {
+            if (deviceType != NULL) {
+                if (STRCASENEQ(deviceType, "cdrom-image")) {
+                    ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                              "Expecting VMX entry '%s' to be 'cdrom-image' "
+                              "but found '%s'", deviceType_name, deviceType);
+                    goto failure;
+                }
+            }
+
+            (*def)->type = VIR_DOMAIN_DISK_TYPE_FILE;
+            (*def)->src = fileName;
+
+            fileName = NULL;
+        } else if (esxUtil_EqualSuffix(fileName, ".vmdk")) {
+            /*
+             * This function was called in order to parse a CDROM device, but
+             * .vmdk files are for harddisk devices only. Just ignore it,
+             * another call to this function to parse a harddisk device may
+             * handle it.
+             */
+            goto ignore;
+        } else if (STREQ(deviceType, "atapi-cdrom")) {
+            (*def)->type = VIR_DOMAIN_DISK_TYPE_BLOCK;
+            (*def)->src = fileName;
+
+            fileName = NULL;
+        } else {
+            ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                      "Invalid or not yet handled value '%s' for VMX entry "
+                      "'%s'", fileName, fileName_name);
+            goto failure;
+        }
+    } else if (device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
+        if (esxUtil_EqualSuffix(fileName, ".flp")) {
+            if (fileType != NULL) {
+                if (STRCASENEQ(fileType, "file")) {
+                    ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                              "Expecting VMX entry '%s' to be 'file' but "
+                              "found '%s'", fileType_name, fileType);
+                    goto failure;
+                }
+            }
+
+            (*def)->type = VIR_DOMAIN_DISK_TYPE_FILE;
+            (*def)->src = fileName;
+
+            fileName = NULL;
+        } else if (fileType != NULL && STREQ(fileType, "device")) {
+            (*def)->type = VIR_DOMAIN_DISK_TYPE_BLOCK;
+            (*def)->src = fileName;
+
+            fileName = NULL;
+        } else {
+            ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                      "Invalid or not yet handled value '%s' for VMX entry "
+                      "'%s'", fileName, fileName_name);
+            goto failure;
+        }
+    } else {
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                  "Unsupported device type '%s'",
+                  virDomainDiskDeviceTypeToString (device));
+        goto failure;
+    }
+
+cleanup:
+    VIR_FREE(prefix);
+    VIR_FREE(deviceType);
+    VIR_FREE(fileType);
+    VIR_FREE(fileName);
+
+    return result;
+
+failure:
+    result = -1;
+
+ignore:
+    virDomainDiskDefFree(*def);
+    *def = NULL;
+
+    goto cleanup;
+}
+
+
+
+int
+esxVMX_ParseEthernet(virConnectPtr conn, virConfPtr conf, int controller,
+                     virDomainNetDefPtr *def)
+{
+    int result = 0;
+    char prefix[48] = "";
+
+    char present_name[48] = "";
+    int present = 0;
+
+    char startConnected_name[48] = "";
+    int startConnected = 0;
+
+    char connectionType_name[48] = "";
+    char *connectionType = NULL;
+
+    char addressType_name[48] = "";
+    char *addressType = NULL;
+
+    char generatedAddress_name[48] = "";
+    char *generatedAddress = NULL;
+
+    char address_name[48] = "";
+    char *address = NULL;
+
+    char virtualDev_name[48] = "";
+    char *virtualDev = NULL;
+
+    char vnet_name[48] = "";
+    char *vnet = NULL;
+
+    if (def == NULL || *def != NULL) {
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    if (controller < 0 || controller > 3) {
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                  "Ethernet controller index %d out of [0..3] range",
+                  controller);
+        goto failure;
+    }
+
+    if (VIR_ALLOC(*def) < 0) {
+        virReportOOMError(conn);
+        goto failure;
+    }
+
+    strncpy(prefix, "ethernetX", sizeof (prefix));
+    prefix[8] = '0' + controller;
+
+    ESX_BUILD_VMX_NAME(present);
+    ESX_BUILD_VMX_NAME(startConnected);
+    ESX_BUILD_VMX_NAME(connectionType);
+    ESX_BUILD_VMX_NAME(addressType);
+    ESX_BUILD_VMX_NAME(generatedAddress);
+    ESX_BUILD_VMX_NAME(address);
+    ESX_BUILD_VMX_NAME(virtualDev);
+
+    /* vmx:present */
+    if (esxUtil_GetConfigBoolean(conn, conf, present_name,
+                                 &present, 0, 1) < 0) {
+        goto failure;
+    }
+
+    /* vmx:startConnected */
+    if (esxUtil_GetConfigBoolean(conn, conf, startConnected_name,
+                                 &startConnected, 1, 1) < 0) {
+        goto failure;
+    }
+
+    /* FIXME: Need to distiguish between active and inactive domains here */
+    if (! present/* && ! startConnected*/) {
+        goto ignore;
+    }
+
+    /* vmx:connectionType -> def:type */
+    if (esxUtil_GetConfigString(conn, conf, connectionType_name,
+                                &connectionType, 1) < 0) {
+        goto failure;
+    }
+
+    /* vmx:addressType, vmx:generatedAddress, vmx:address -> def:mac */
+    if (esxUtil_GetConfigString(conn, conf, addressType_name,
+                                &addressType, 1) < 0 ||
+        esxUtil_GetConfigString(conn, conf, generatedAddress_name,
+                                &generatedAddress, 1) < 0 ||
+        esxUtil_GetConfigString(conn, conf, address_name, &address, 1) < 0) {
+        goto failure;
+    }
+
+    if (addressType == NULL || STRCASEEQ(addressType, "generated")) {
+        if (generatedAddress != NULL) {
+            if (virParseMacAddr(generatedAddress, (*def)->mac) < 0) {
+                ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                          "Expecting VMX entry '%s' to be MAC address but "
+                          "found '%s'", generatedAddress_name,
+                          generatedAddress);
+                goto failure;
+            }
+        }
+    } else if (STRCASEEQ(addressType, "static")) {
+        if (address != NULL) {
+            if (virParseMacAddr(address, (*def)->mac) < 0) {
+                ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                          "Expecting VMX entry '%s' to be MAC address but "
+                          "found '%s'", address_name, address);
+                goto failure;
+            }
+        }
+    } else {
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                  "Expecting VMX entry '%s' to be 'generated' or 'static' but "
+                  "found '%s'", addressType_name, addressType);
+        goto failure;
+    }
+
+    /* vmx:virtualDev -> def:model */
+    if (esxUtil_GetConfigString(conn, conf, virtualDev_name,
+                                &virtualDev, 1) < 0) {
+        goto failure;
+    }
+
+    if (virtualDev != NULL &&
+        STRCASENEQ(virtualDev, "vlance") &&
+        STRCASENEQ(virtualDev, "vmxnet") &&
+        STRCASENEQ(virtualDev, "e1000")) {
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                  "Expecting VMX entry '%s' to be 'vlance' or 'vmxnet' or "
+                  "'e1000' but found '%s'", virtualDev_name, virtualDev);
+        goto failure;
+    }
+
+    /* vmx:vnet -> def:data.bridge.brname */
+    if (connectionType != NULL && STRCASEEQ(connectionType, "custom") &&
+        esxUtil_GetConfigString(conn, conf, vnet_name, &vnet, 0) < 0) {
+        goto failure;
+    }
+
+    /* Setup virDomainNetDef */
+    if (connectionType == NULL || STRCASEEQ(connectionType, "bridged")) {
+        (*def)->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
+        (*def)->model = virtualDev;
+
+        virtualDev = NULL;
+    } else if (STRCASEEQ(connectionType, "hostonly")) {
+        /* FIXME */
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                  "No yet handled value '%s' for VMX entry '%s'",
+                  connectionType, connectionType_name);
+        goto failure;
+    } else if (STRCASEEQ(connectionType, "nat")) {
+        /* FIXME */
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                  "No yet handled value '%s' for VMX entry '%s'",
+                  connectionType, connectionType_name);
+        goto failure;
+    } else if (STRCASEEQ(connectionType, "custom")) {
+        (*def)->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
+        (*def)->model = virtualDev;
+        (*def)->data.bridge.brname = vnet;
+
+        virtualDev = NULL;
+        vnet = NULL;
+    } else {
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                  "Invalid value '%s' for VMX entry '%s'", connectionType,
+                  connectionType_name);
+        goto failure;
+    }
+
+cleanup:
+    VIR_FREE(connectionType);
+    VIR_FREE(addressType);
+    VIR_FREE(generatedAddress);
+    VIR_FREE(address);
+    VIR_FREE(virtualDev);
+    VIR_FREE(vnet);
+
+    return result;
+
+failure:
+    result = -1;
+
+ignore:
+    virDomainNetDefFree(*def);
+    *def = NULL;
+
+    goto cleanup;
+}
+
+
+
+int
+esxVMX_ParseSerial(virConnectPtr conn, virConfPtr conf, int port,
+                   virDomainChrDefPtr *def)
+{
+    int result = 0;
+    char prefix[48] = "";
+
+    char present_name[48] = "";
+    int present = 0;
+
+    char startConnected_name[48] = "";
+    int startConnected = 0;
+
+    char fileType_name[48] = "";
+    char *fileType = NULL;
+
+    char fileName_name[48] = "";
+    char *fileName = NULL;
+
+    if (def == NULL || *def != NULL) {
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    if (port < 0 || port > 3) {
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                  "Serial port index %d out of [0..3] range", port);
+        goto failure;
+    }
+
+    if (VIR_ALLOC(*def) < 0) {
+        virReportOOMError(conn);
+        goto failure;
+    }
+
+    strncpy(prefix, "serialX", sizeof (prefix));
+    prefix[6] = '0' + port;
+
+    ESX_BUILD_VMX_NAME(present);
+    ESX_BUILD_VMX_NAME(startConnected);
+    ESX_BUILD_VMX_NAME(fileType);
+    ESX_BUILD_VMX_NAME(fileName);
+
+    /* vmx:present */
+    if (esxUtil_GetConfigBoolean(conn, conf, present_name,
+                                 &present, 0, 1) < 0) {
+        goto failure;
+    }
+
+    /* vmx:startConnected */
+    if (esxUtil_GetConfigBoolean(conn, conf, startConnected_name,
+                                 &startConnected, 1, 1) < 0) {
+        goto failure;
+    }
+
+    /* FIXME: Need to distiguish between active and inactive domains here */
+    if (! present/* && ! startConnected*/) {
+        goto ignore;
+    }
+
+    /* vmx:fileType -> def:type */
+    if (esxUtil_GetConfigString(conn, conf, fileType_name, &fileType, 0) < 0) {
+        goto failure;
+    }
+
+    /* vmx:fileName -> def:data.file.path */
+    if (esxUtil_GetConfigString(conn, conf, fileName_name, &fileName, 0) < 0) {
+        goto failure;
+    }
+
+    /* Setup virDomainChrDef */
+    if (STRCASEEQ(fileType, "device")) {
+        (*def)->dstPort = port;
+        (*def)->type = VIR_DOMAIN_CHR_TYPE_DEV;
+        (*def)->data.file.path = fileName;
+
+        fileName = NULL;
+    } else if (STRCASEEQ(fileType, "file")) {
+        (*def)->dstPort = port;
+        (*def)->type = VIR_DOMAIN_CHR_TYPE_FILE;
+        (*def)->data.file.path = fileName;
+
+        fileName = NULL;
+    } else if (STRCASEEQ(fileType, "pipe")) {
+        /* FIXME */
+        VIR_WARN("Serial port %d has currently unsupported type '%s', "
+                 "ignoring it", port, fileType);
+        goto ignore;
+    } else {
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                  "Expecting VMX entry '%s' to be 'device', 'file' or 'pipe' "
+                  "but found '%s'", fileType_name, fileType);
+        goto failure;
+    }
+
+cleanup:
+    VIR_FREE(fileType);
+    VIR_FREE(fileName);
+
+    return result;
+
+failure:
+    result = -1;
+
+ignore:
+    virDomainChrDefFree(*def);
+    *def = NULL;
+
+    goto cleanup;
+}
+
+
+
+int
+esxVMX_ParseParallel(virConnectPtr conn, virConfPtr conf, int port,
+                     virDomainChrDefPtr *def)
+{
+    int result = 0;
+    char prefix[48] = "";
+
+    char present_name[48] = "";
+    int present = 0;
+
+    char startConnected_name[48] = "";
+    int startConnected = 0;
+
+    char fileType_name[48] = "";
+    char *fileType = NULL;
+
+    char fileName_name[48] = "";
+    char *fileName = NULL;
+
+    if (def == NULL || *def != NULL) {
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
+        return -1;
+    }
+
+    if (port < 0 || port > 2) {
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                  "Parallel port index %d out of [0..2] range", port);
+        goto failure;
+    }
+
+    if (VIR_ALLOC(*def) < 0) {
+        virReportOOMError(conn);
+        goto failure;
+    }
+
+    strncpy(prefix, "parallelX", sizeof (prefix));
+    prefix[8] = '0' + port;
+
+    ESX_BUILD_VMX_NAME(present);
+    ESX_BUILD_VMX_NAME(startConnected);
+    ESX_BUILD_VMX_NAME(fileType);
+    ESX_BUILD_VMX_NAME(fileName);
+
+    /* vmx:present */
+    if (esxUtil_GetConfigBoolean(conn, conf, present_name,
+                                 &present, 0, 1) < 0) {
+        goto failure;
+    }
+
+    /* vmx:startConnected */
+    if (esxUtil_GetConfigBoolean(conn, conf, startConnected_name,
+                                 &startConnected, 1, 1) < 0) {
+        goto failure;
+    }
+
+    /* FIXME: Need to distiguish between active and inactive domains here */
+    if (! present/* && ! startConnected*/) {
+        goto ignore;
+    }
+
+    /* vmx:fileType -> def:type */
+    if (esxUtil_GetConfigString(conn, conf, fileType_name, &fileType, 0) < 0) {
+        goto failure;
+    }
+
+    /* vmx:fileName -> def:data.file.path */
+    if (esxUtil_GetConfigString(conn, conf, fileName_name, &fileName, 0) < 0) {
+        goto failure;
+    }
+
+    /* Setup virDomainChrDef */
+    if (STRCASEEQ(fileType, "device")) {
+        (*def)->dstPort = port;
+        (*def)->type = VIR_DOMAIN_CHR_TYPE_DEV;
+        (*def)->data.file.path = fileName;
+
+        fileName = NULL;
+    } else if (STRCASEEQ(fileType, "file")) {
+        (*def)->dstPort = port;
+        (*def)->type = VIR_DOMAIN_CHR_TYPE_FILE;
+        (*def)->data.file.path = fileName;
+
+        fileName = NULL;
+    } else {
+        ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                  "Expecting VMX entry '%s' to be 'device' or 'file' but "
+                  "found '%s'", fileType_name, fileType);
+        goto failure;
+    }
+
+cleanup:
+    VIR_FREE(fileType);
+    VIR_FREE(fileName);
+
+    return result;
+
+failure:
+    result = -1;
+
+ignore:
+    virDomainChrDefFree(*def);
+    *def = NULL;
+
+    goto cleanup;
+}
diff --git a/src/esx/esx_vmx.h b/src/esx/esx_vmx.h
new file mode 100644
index 0000000..f32a50a
--- /dev/null
+++ b/src/esx/esx_vmx.h
@@ -0,0 +1,55 @@
+
+/*
+ * esx_vmx.c: VMX related methods for the VMware ESX driver
+ *
+ * Copyright (C) 2009 Matthias Bolte <matthias.bolte@xxxxxxxxxxxxxx>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ */
+
+#ifndef __ESX_VMX_H__
+#define __ESX_VMX_H__
+
+#include "internal.h"
+#include "domain_conf.h"
+
+virDomainDefPtr
+esxVMX_ParseConfig(virConnectPtr conn, const char *vmx);
+
+int
+esxVMX_ParseSCSIController(virConnectPtr conn, virConfPtr conf,
+                          int controller, int *present, char **virtualDev);
+
+char *
+esxVMX_IndexToDiskName(virConnectPtr conn, int idx, const char *prefix);
+
+int
+esxVMX_ParseDisk(virConnectPtr conn, virConfPtr conf, int device, int bus,
+                 int controller, int id, const char *virtualDev,
+                 virDomainDiskDefPtr *def);
+int
+esxVMX_ParseEthernet(virConnectPtr conn, virConfPtr conf, int controller,
+                     virDomainNetDefPtr *def);
+
+int
+esxVMX_ParseSerial(virConnectPtr conn, virConfPtr conf, int port,
+                   virDomainChrDefPtr *def);
+
+int
+esxVMX_ParseParallel(virConnectPtr conn, virConfPtr conf, int port,
+                     virDomainChrDefPtr *def);
+
+#endif /* __ESX_VMX_H__ */
--
Libvir-list mailing list
Libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list

[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]