[ --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],
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
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
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])
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([])
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;
./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
+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
$(ONE_DRIVER_SOURCES) \
$(OPENVZ_DRIVER_SOURCES) \
$(VBOX_DRIVER_SOURCES) \
+ $(ESX_DRIVER_SOURCES) \
$(NETWORK_DRIVER_SOURCES) \
$(INTERFACE_DRIVER_SOURCES) \
$(STORAGE_DRIVER_SOURCES) \
VIR_DRV_UML = 7,
VIR_DRV_VBOX = 8,
VIR_DRV_ONE = 9,
+ VIR_DRV_ESX = 10,
} virDrvNo;
--- /dev/null
+
+/*
+ * esx_driver.c: core driver methods for managing VMware ESX hosts
+ *
+ * Copyright (C) 2009 Matthias Bolte <matthias.bolte@googlemail.com>
+ * Copyright (C) 2009 Maximilian Wilhelm <max@rfc2324.org>
+ *
+ * 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;
+}
--- /dev/null
+
+/*
+ * esx_driver.h: core driver methods for managing VMware ESX hosts
+ *
+ * Copyright (C) 2009 Matthias Bolte <matthias.bolte@googlemail.com>
+ * Copyright (C) 2009 Maximilian Wilhelm <max@rfc2324.org>
+ *
+ * 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__ */
--- /dev/null
+
+/*
+ * esx_util.c: utility methods for the VMware ESX driver
+ *
+ * Copyright (C) 2009 Matthias Bolte <matthias.bolte@googlemail.com>
+ * Copyright (C) 2009 Maximilian Wilhelm <max@rfc2324.org>
+ *
+ * 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);
+ }
+}
--- /dev/null
+
+/*
+ * esx_util.h: utility methods for the VMware ESX driver
+ *
+ * Copyright (C) 2009 Matthias Bolte <matthias.bolte@googlemail.com>
+ *
+ * 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__ */
--- /dev/null
+
+/*
+ * esx_vi.c: client for the VMware VI API 2.5 to manage ESX hosts
+ *
+ * Copyright (C) 2009 Matthias Bolte <matthias.bolte@googlemail.com>
+ *
+ * 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,
+ ¤tSession) < 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(¤tSession);
+#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;
+}
--- /dev/null
+
+/*
+ * esx_vi.h: client for the VMware VI API 2.5 to manage ESX hosts
+ *
+ * Copyright (C) 2009 Matthias Bolte <matthias.bolte@googlemail.com>
+ *
+ * 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__ */
--- /dev/null
+
+/*
+ * esx_vi_methods.c: client for the VMware VI API 2.5 to manage ESX hosts
+ *
+ * Copyright (C) 2009 Matthias Bolte <matthias.bolte@googlemail.com>
+ *
+ * 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;
+}
--- /dev/null
+
+/*
+ * esx_vi_methods.h: client for the VMware VI API 2.5 to manage ESX hosts
+ *
+ * Copyright (C) 2009 Matthias Bolte <matthias.bolte@googlemail.com>
+ *
+ * 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__ */
--- /dev/null
+
+/*
+ * esx_vi_types.c: client for the VMware VI API 2.5 to manage ESX hosts
+ *
+ * Copyright (C) 2009 Matthias Bolte <matthias.bolte@googlemail.com>
+ *
+ * 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);
--- /dev/null
+
+/*
+ * esx_vi_types.h: client for the VMware VI API 2.5 to manage ESX hosts
+ *
+ * Copyright (C) 2009 Matthias Bolte <matthias.bolte@googlemail.com>
+ *
+ * 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__ */
--- /dev/null
+
+/*
+ * esx_vmx.c: VMX related methods for the VMware ESX driver
+ *
+ * Copyright (C) 2009 Matthias Bolte <matthias.bolte@googlemail.com>
+ *
+ * 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(¤t);
+
+ number = virParseNumber(¤t);
+
+ 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(¤t);
+
+ 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(¤t);
+ }
+
+ 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;
+}
--- /dev/null
+
+/*
+ * esx_vmx.c: VMX related methods for the VMware ESX driver
+ *
+ * Copyright (C) 2009 Matthias Bolte <matthias.bolte@googlemail.com>
+ *
+ * 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__ */
#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
virDriverLoadModule("xen");
virDriverLoadModule("openvz");
virDriverLoadModule("vbox");
+ virDriverLoadModule("esx");
virDriverLoadModule("remote");
#else
#ifdef WITH_TEST
#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
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();
case VIR_FROM_ONE:
dom = "ONE ";
break;
+ case VIR_FROM_ESX:
+ dom = "ESX ";
+ break;
}
return(dom);
}