]> xenbits.xensource.com Git - libvirt.git/commitdiff
xenapi: Initial commit of the new driver
authorSharadha Prabhakar <sharadha.prabhakar@citrix.com>
Sun, 14 Mar 2010 11:11:51 +0000 (12:11 +0100)
committerMatthias Bolte <matthias.bolte@googlemail.com>
Sun, 14 Mar 2010 18:30:00 +0000 (19:30 +0100)
configure.ac
include/libvirt/virterror.h
src/Makefile.am
src/driver.h
src/libvirt.c
src/util/virterror.c
src/xenapi/xenapi_driver.c [new file with mode: 0644]
src/xenapi/xenapi_driver.h [new file with mode: 0644]
src/xenapi/xenapi_driver_private.h [new file with mode: 0644]
src/xenapi/xenapi_utils.c [new file with mode: 0644]
src/xenapi/xenapi_utils.h [new file with mode: 0644]

index ab69e5228b30938bc5302faae44c9cc0892b6191..654b9a84a6f4355afa681fa7da92d13d2b48e1de 100644 (file)
@@ -219,6 +219,8 @@ AC_ARG_WITH([libssh2],
   AC_HELP_STRING([--with-libssh2=@<:@PFX@:>@], [libssh2 location @<:@default=/usr/local/lib@:>@]),[],[with_libssh2=yes])
 AC_ARG_WITH([phyp],
   AC_HELP_STRING([--with-phyp], [add PHYP support @<:@default=check@:>@]),[],[with_phyp=check])
+AC_ARG_WITH([xenapi],
+  AC_HELP_STRING([--with-xenapi], [add XenAPI support @<:@default=check@:>@]),[],[with_xenapi=check])
 AC_ARG_WITH([vbox],
   AC_HELP_STRING([--with-vbox], [add VirtualBox support @<:@default=yes@:>@]),[],[with_vbox=yes])
 AC_ARG_WITH([lxc],
@@ -341,6 +343,46 @@ if test "$with_libvirtd" = "yes" ; then
 fi
 AM_CONDITIONAL([WITH_LIBVIRTD], [test "$with_libvirtd" = "yes"])
 
+
+old_LIBS="$LIBS"
+old_CFLAGS="$CFLAGS"
+LIBXENSERVER_LIBS=""
+LIBXENSERVER_CFLAGS=""
+dnl search for the XenServer library
+if test "$with_xenapi" != "no" ; then
+    if test "$with_xenapi" != "yes" -a "$with_xenapi" != "check" ; then
+        LIBXENSERVER_CFLAGS="-I$with_xenapi/include"
+        LIBXENSERVER_LIBS="-L$with_xenapi"
+    fi
+    fail=0
+    CFLAGS="$CFLAGS $LIBXENSERVER_CFLAGS"
+    LIBS="$LIBS $LIBXENSERVER_LIBS"
+    AC_CHECK_LIB([xenserver], [xen_vm_start], [
+        with_xenapi=yes
+        LIBXENSERVER_LIBS="$LIBXENSERVER_LIBS -lxenserver"
+    ],[
+        if test "$with_xenapi" = "yes"; then
+            fail=1
+        fi
+            with_xenapi=no
+    ])
+fi
+
+LIBS="$old_LIBS"
+CFLAGS="$old_CFLAGS"
+
+if test $fail = 1; then
+    AC_MSG_ERROR([You must install the XenServer Library to compile XenAPI driver with -lxenserver])
+fi
+
+if test "$with_xenapi" = "yes"; then
+    AC_DEFINE_UNQUOTED([WITH_XENAPI], 1, [whether XenAPI driver is enabled])
+fi
+
+AC_SUBST([LIBXENSERVER_CFLAGS])
+AC_SUBST([LIBXENSERVER_LIBS])
+
+
 old_LIBS="$LIBS"
 old_CFLAGS="$CFLAGS"
 XEN_LIBS=""
@@ -1446,31 +1488,50 @@ AC_SUBST([LIBPARTED_CFLAGS])
 AC_SUBST([LIBPARTED_LIBS])
 
 dnl
-dnl check for libcurl (ESX)
+dnl check for libcurl (ESX/XenAPI)
 dnl
 
 LIBCURL_CFLAGS=""
 LIBCURL_LIBS=""
-LIBCURL_FOUND="no"
 
-if test "$with_esx" = "yes" -o "$with_esx" = "check"; then
+if test "$with_esx" = "yes" -o "$with_esx" = "check" -o "$with_xenapi" = "yes" -o "$with_xenapi" = "check"; then
     PKG_CHECK_MODULES(LIBCURL, libcurl >= $LIBCURL_REQUIRED, [
-        LIBCURL_FOUND=yes
-        with_esx="yes"
+        if test "$with_esx" = "check"; then
+            with_esx=yes
+        fi
+
+        if test "$with_xenapi" = "check"; then
+            with_xenapi=yes
+        fi
     ], [
         if test "$with_esx" = "check"; then
             with_esx=no
-            AC_MSG_NOTICE([libcurl is required for ESX driver, disabling it])
-        else
+            AC_MSG_NOTICE([libcurl is required for the ESX driver, disabling it])
+        elif test "$with_esx" = "yes"; then
             AC_MSG_ERROR([libcurl >= $LIBCURL_REQUIRED is required for the ESX driver])
         fi
+
+        if test "$with_xenapi" = "check"; then
+            with_xenapi=no
+            AC_MSG_NOTICE([libcurl is required for the XenAPI driver, disabling it])
+        elif test "$with_xenapi" = "yes"; then
+            AC_MSG_ERROR([libcurl >= $LIBCURL_REQUIRED is required for the XenAPI driver])
+        fi
     ])
 fi
+
+
 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_xenapi" = "yes" ; then
+    AC_DEFINE_UNQUOTED([WITH_XENAPI], 1, [whether XenAPI driver is enabled])
+fi
+AM_CONDITIONAL([WITH_XENAPI], [test "$with_xenapi" = "yes"])
+
+
 AC_SUBST([LIBCURL_CFLAGS])
 AC_SUBST([LIBCURL_LIBS])
 
@@ -1909,6 +1970,7 @@ AC_MSG_NOTICE([    QEMU: $with_qemu])
 AC_MSG_NOTICE([     UML: $with_uml])
 AC_MSG_NOTICE([  OpenVZ: $with_openvz])
 AC_MSG_NOTICE([    VBox: $with_vbox])
+AC_MSG_NOTICE([  XenAPI: $with_xenapi])
 AC_MSG_NOTICE([     LXC: $with_lxc])
 AC_MSG_NOTICE([    PHYP: $with_phyp])
 AC_MSG_NOTICE([     ONE: $with_one])
@@ -2007,6 +2069,11 @@ AC_MSG_NOTICE([     xen: $XEN_CFLAGS $XEN_LIBS])
 else
 AC_MSG_NOTICE([     xen: no])
 fi
+if test "$with_xenapi" = "yes" ; then
+AC_MSG_NOTICE([  xenapi: $LIBXENSERVER_CFLAGS $LIBXENSERVER_LIBS])
+else
+AC_MSG_NOTICE([  xenapi: no])
+fi
 if test "$with_hal" = "yes" ; then
 AC_MSG_NOTICE([     hal: $HAL_CFLAGS $HAL_LIBS])
 else
index c766416d31121e17b45ec3f7bbe80b337feebe9b..d298447382ab7e5ff3929ce57345db75ad7b5dbf 100644 (file)
@@ -69,6 +69,7 @@ typedef enum {
     VIR_FROM_PHYP,      /* Error from IBM power hypervisor */
     VIR_FROM_SECRET,    /* Error from secret storage */
     VIR_FROM_CPU,       /* Error from CPU driver */
+    VIR_FROM_XENAPI     /* Error from XenAPI */
 } virErrorDomain;
 
 
index 4c12586b4a251310d0ce7484dc47d0851ae46bbd..c43797a7d1e741733e126bb511e688ffef4dacc0 100644 (file)
@@ -205,6 +205,11 @@ QEMU_DRIVER_SOURCES =                                              \
                qemu/qemu_security_dac.h                        \
                qemu/qemu_security_dac.c
 
+XENAPI_DRIVER_SOURCES =                                                                \
+               xenapi/xenapi_driver.c xenapi/xenapi_driver.h   \
+               xenapi_driver_private.h                                                 \
+               xenapi/xenapi_utils.c xenapi/xenapi_utils.h
+
 UML_DRIVER_SOURCES =                                           \
                uml/uml_conf.c uml/uml_conf.h                   \
                uml/uml_driver.c uml/uml_driver.h
@@ -467,6 +472,22 @@ libvirt_driver_vbox_la_LIBADD = $(DLOPEN_LIBS)
 libvirt_driver_vbox_la_SOURCES = $(VBOX_DRIVER_SOURCES)
 endif
 
+if WITH_XENAPI
+if WITH_DRIVER_MODULES
+mod_LTLIBRARIES += libvirt_driver_xenapi.la
+else
+noinst_LTLIBRARIES += libvirt_driver_xenapi.la
+libvirt_la_LIBADD += libvirt_driver_xenapi.la
+endif
+libvirt_driver_xenapi_la_CFLAGS = $(LIBXENSERVER_CFLAGS) $(LIBCURL_CFLAGS) \
+               -I@top_srcdir@/src/conf
+libvirt_driver_xenapi_la_LDFLAGS = $(LIBXENSERVER_LIBS) $(LIBCURL_LIBS)
+if WITH_DRIVER_MODULES
+libvirt_driver_xenapi_la_LDFLAGS += -module -avoid-version
+endif
+libvirt_driver_xenapi_la_SOURCES = $(XENAPI_DRIVER_SOURCES)
+endif
+
 if WITH_QEMU
 if WITH_DRIVER_MODULES
 mod_LTLIBRARIES += libvirt_driver_qemu.la
@@ -723,6 +744,7 @@ EXTRA_DIST +=                                                       \
                $(OPENVZ_DRIVER_SOURCES)                        \
                $(PHYP_DRIVER_SOURCES)                          \
                $(VBOX_DRIVER_SOURCES)                          \
+               $(XENAPI_DRIVER_SOURCES)                        \
                $(ESX_DRIVER_SOURCES)                           \
                $(NETWORK_DRIVER_SOURCES)                       \
                $(INTERFACE_DRIVER_SOURCES)                     \
index 8b12a9c733da0812986e1228be1d06d89db76336..a64bba026e63fe390b68a9444f587897a3d9b30f 100644 (file)
@@ -27,6 +27,7 @@ typedef enum {
     VIR_DRV_ONE = 9,
     VIR_DRV_ESX = 10,
     VIR_DRV_PHYP = 11,
+    VIR_DRV_XENAPI = 12
 } virDrvNo;
 
 
index 935ec3af87a5d786fa782a447ec57d86fa0c1668..1d9b8781b82522c0887f0dd39147db070cc1c962 100644 (file)
@@ -64,6 +64,9 @@
 # ifdef WITH_ESX
 #  include "esx/esx_driver.h"
 # endif
+# ifdef WITH_XENAPI
+#  include "xenapi/xenapi_driver.h"
+# endif
 #endif
 
 #define VIR_FROM_THIS VIR_FROM_NONE
@@ -357,6 +360,7 @@ virInitialize(void)
     virDriverLoadModule("openvz");
     virDriverLoadModule("vbox");
     virDriverLoadModule("esx");
+    virDriverLoadModule("xenapi");
     virDriverLoadModule("remote");
 #else
 # ifdef WITH_TEST
@@ -377,6 +381,9 @@ virInitialize(void)
 # ifdef WITH_ESX
     if (esxRegister() == -1) return -1;
 # endif
+# ifdef WITH_XENAPI
+    if (xenapiRegister() == -1) return -1;
+# endif
 # ifdef WITH_REMOTE
     if (remoteRegister () == -1) return -1;
 # endif
@@ -1031,6 +1038,10 @@ virGetVersion(unsigned long *libVer, const char *type,
         if (STRCASEEQ(type, "ESX"))
             *typeVer = LIBVIR_VERSION_NUMBER;
 # endif
+# if WITH_XENAPI
+        if (STRCASEEQ(type, "XenAPI"))
+            *typeVer = LIBVIR_VERSION_NUMBER;
+# endif
 # if WITH_REMOTE
         if (STRCASEEQ(type, "Remote"))
             *typeVer = remoteVersion();
index cbd0ca8e878eb1b323fddea95b0fc789273028dc..0e8bdb31945e16974c29ed6a944e2ac83e187b17 100644 (file)
@@ -85,6 +85,9 @@ static const char *virErrorDomainName(virErrorDomain domain) {
         case VIR_FROM_XEN:
             dom = "Xen ";
             break;
+        case VIR_FROM_XENAPI:
+            dom = "XenAPI ";
+            break;
         case VIR_FROM_XML:
             dom = "XML ";
             break;
diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c
new file mode 100644 (file)
index 0000000..8d5c8bb
--- /dev/null
@@ -0,0 +1,1766 @@
+/*
+ * xenapi_driver.c: Xen API driver.
+ * Copyright (C) 2009, 2010 Citrix Ltd.
+ *
+ * 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
+ *
+ * Author: Sharadha Prabhakar <sharadha.prabhakar@citrix.com>
+ */
+
+#include <config.h>
+
+#include <limits.h>
+#include <stdint.h>
+#include <string.h>
+#include <libxml/uri.h>
+#include <curl/curl.h>
+#include <xen/api/xen_all.h>
+#include "internal.h"
+#include "domain_conf.h"
+#include "virterror_internal.h"
+#include "datatypes.h"
+#include "util.h"
+#include "uuid.h"
+#include "memory.h"
+#include "buf.h"
+#include "xenapi_driver.h"
+#include "xenapi_driver_private.h"
+#include "xenapi_utils.h"
+
+
+/*
+ * getCapsObject
+ *
+ * Build the capabilities of the hypervisor
+ * Return virCapsPtr on success or NULL on failure
+ */
+static virCapsPtr
+getCapsObject (void)
+{
+    virCapsPtr caps = virCapabilitiesNew("x86_64", 0, 0);
+    if (!caps) {
+        virReportOOMError();
+        return NULL;
+    }
+    virCapsGuestPtr guest1 = virCapabilitiesAddGuest(caps, "hvm", "x86_64", 0, "", "", 0, NULL);
+    if (!guest1)
+        goto error_cleanup;
+    virCapsGuestDomainPtr domain1 = virCapabilitiesAddGuestDomain(guest1, "xen", "", "", 0, NULL);
+    if (!domain1)
+        goto error_cleanup;
+    virCapsGuestPtr guest2 = virCapabilitiesAddGuest(caps, "xen", "x86_64", 0, "", "", 0, NULL);
+    if (!guest2)
+        goto error_cleanup;
+    virCapsGuestDomainPtr domain2 = virCapabilitiesAddGuestDomain(guest2, "xen", "", "", 0, NULL);
+    if (!domain2)
+        goto error_cleanup;
+
+    return caps;
+
+  error_cleanup:
+    virCapabilitiesFree(caps);
+    return NULL;
+}
+
+/*
+ * XenapiOpen
+ *
+ * Authenticates and creates a session with the server
+ * Return VIR_DRV_OPEN_SUCCESS on success, else VIR_DRV_OPEN_ERROR
+ */
+static virDrvOpenStatus
+xenapiOpen (virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED)
+{
+    char *passwd = NULL;
+    xen_session *session;
+    struct _xenapiPrivate *privP;
+
+    if (STRCASENEQ(conn->uri->scheme, "XenAPI")) {
+        return VIR_DRV_OPEN_DECLINED;
+    }
+    if (conn->uri->server == NULL) {
+        xenapiSessionErrorHandler(conn, VIR_ERR_AUTH_FAILED, "Server name not in URI");
+        return VIR_DRV_OPEN_ERROR;
+    }
+    if (auth) {
+        passwd = xenapiUtil_RequestPassword(auth, conn->uri->user, conn->uri->server);
+    } else {
+        xenapiSessionErrorHandler(conn, VIR_ERR_AUTH_FAILED, "Authentication Credentials not found");
+        return VIR_DRV_OPEN_ERROR;
+    }
+    if (!passwd || !conn->uri->user) {
+        xenapiSessionErrorHandler(conn, VIR_ERR_AUTH_FAILED, "Username/Password not valid");
+        if (passwd) VIR_FREE(passwd);
+        return VIR_DRV_OPEN_ERROR;
+    }
+    if (VIR_ALLOC(privP) < 0) {
+        virReportOOMError();
+        return VIR_DRV_OPEN_ERROR;
+    }
+    if (virAsprintf(&privP->url, "https://%s", conn->uri->server) < 0) {
+        virReportOOMError();
+        VIR_FREE(passwd);
+        return VIR_DRV_OPEN_ERROR;
+    }
+    xenapiUtil_ParseQuery(conn, conn->uri, &privP->noVerify);
+    xmlInitParser();
+    xmlKeepBlanksDefault(0);
+    xen_init();
+    curl_global_init(CURL_GLOBAL_ALL);
+
+    session = xen_session_login_with_password(call_func, privP, conn->uri->user, passwd, xen_api_latest_version);
+
+    if (session && session->ok) {
+        privP->session = session;
+        if (!(privP->caps = getCapsObject())) {
+            xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, "Capabilities not found");
+            VIR_FREE(passwd);
+            return VIR_DRV_OPEN_ERROR;
+        }
+        conn->privateData = privP;
+        VIR_FREE(passwd);
+        return VIR_DRV_OPEN_SUCCESS;
+    } else {
+        xenapiSessionErrorHandler(conn, VIR_ERR_AUTH_FAILED, "");
+        if (session) xenSessionFree(session);
+        VIR_FREE(privP);
+        VIR_FREE(passwd);
+        return VIR_DRV_OPEN_ERROR;
+    }
+}
+
+/*
+ * xenapiClose:
+ *
+ * Returns 0 on successful session logout
+ *
+ */
+static int
+xenapiClose (virConnectPtr conn)
+{
+    xen_session_logout(((struct _xenapiPrivate *)(conn->privateData))->session);
+    virCapabilitiesFree(((struct _xenapiPrivate *)(conn->privateData))->caps);
+    VIR_FREE(((struct _xenapiPrivate *)(conn->privateData))->url);
+    VIR_FREE(conn->privateData);
+    return 0;
+}
+
+/*
+ *
+ * xenapiSupportsFeature
+ *
+ * Returns 0
+ */
+static int
+xenapiSupportsFeature (virConnectPtr conn ATTRIBUTE_UNUSED, int feature)
+{
+    switch (feature) {
+    case VIR_DRV_FEATURE_MIGRATION_V2:
+    case VIR_DRV_FEATURE_MIGRATION_P2P:
+    default:
+        return 0;
+    }
+}
+
+/*
+ * xenapiType:
+ *
+ *
+ * Returns name of the driver
+ */
+static const char *
+xenapiType (virConnectPtr conn ATTRIBUTE_UNUSED)
+{
+    return "XenAPI";
+}
+
+
+/*
+ * xenapiGetVersion:
+ *
+ * Gets the version of XenAPI
+ *
+ */
+static int
+xenapiGetVersion (virConnectPtr conn, unsigned long *hvVer)
+{
+    xen_host host;
+    xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session;
+    xen_string_string_map *result = NULL;
+    int i;
+    char *version = NULL;
+    unsigned long major = 0, minor = 0, release = 0;
+    if (!(xen_session_get_this_host(session, &host, session))) {
+        xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL);
+        return -1;
+    }
+    if (!(xen_host_get_software_version(session, &result, host))) {
+        xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL);
+        xen_host_free(host);
+        return -1;
+    }
+    xen_host_free(host);
+    if (result && result->size > 0) {
+        for (i = 0; i < result->size; i++) {
+            if (STREQ(result->contents[i].key, "xen")) {
+                if (!(version = strdup(result->contents[i].val))) {
+                    xen_string_string_map_free(result);
+                    virReportOOMError();
+                    return -1;
+                }
+                break;
+            }
+        }
+        if (version) {
+            if (sscanf(version, "%ld.%ld.%ld", &major, &minor, &release) != 3) {
+                xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, "Couldn't get version info");
+                xen_string_string_map_free(result);
+                VIR_FREE(version);
+                return -1;
+            }
+            *hvVer = major * 1000000 + minor * 1000 + release;
+            VIR_FREE(version);
+            xen_string_string_map_free(result);
+            return 0;
+        }
+    }
+    return -1;
+}
+
+
+/*
+ * xenapiGetHostname:
+ *
+ *
+ * Returns the hostname on success, or NULL on failure
+ */
+static char *
+xenapiGetHostname (virConnectPtr conn)
+{
+    char *result = NULL;
+    xen_host host;
+    xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session;
+    if (!(xen_session_get_this_host(session, &host, session))) {
+        xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL);
+        return NULL;
+    }
+    if (!(xen_host_get_hostname(session, &result, host)))
+        xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL);
+    xen_host_free(host);
+    return result;
+}
+
+
+/*
+ * xenapiGetMaxVcpus:
+ *
+ *
+ * Returns a hardcoded value for Maximum VCPUS
+ */
+static int
+xenapiGetMaxVcpus (virConnectPtr conn ATTRIBUTE_UNUSED, const char *type ATTRIBUTE_UNUSED)
+{
+    /* this is hardcoded for simplicity and set to a resonable value compared
+       to the actual value */
+    return 16;
+}
+
+
+/*
+ * xenapiNodeGetInfo:
+ *
+ *
+ * Returns Node details on success or else -1
+ */
+static int
+xenapiNodeGetInfo (virConnectPtr conn, virNodeInfoPtr info)
+{
+    int64_t memory, mhz;
+    xen_host_cpu_set *host_cpu_set;
+    xen_host_cpu host_cpu;
+    xen_host_metrics_set *xen_met_set;
+    char *modelname;
+    xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session;
+    info->nodes = 1;
+    info->threads = 1;
+    info->sockets = 1;
+
+    if (xen_host_metrics_get_all(session, &xen_met_set)) {
+        xen_host_metrics_get_memory_total(session, &memory, xen_met_set->contents[0]);
+        info->memory = (unsigned long)(memory / 1024);
+        xen_host_metrics_set_free(xen_met_set);
+    } else {
+        xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, "Unable to get host metric Information");
+        return -1;
+    }
+    if (xen_host_cpu_get_all(session, &host_cpu_set)) {
+        host_cpu = host_cpu_set->contents[0];
+        xen_host_cpu_get_modelname(session, &modelname, host_cpu);
+        if (!virStrncpy(info->model, modelname, LIBVIRT_MODELNAME_LEN - 1, LIBVIRT_MODELNAME_LEN)) {
+            virReportOOMError();
+            xen_host_cpu_set_free(host_cpu_set);
+            VIR_FREE(modelname);
+            return -1;
+        }
+        xen_host_cpu_get_speed(session, &mhz, host_cpu);
+        info->mhz = (unsigned long)mhz;
+        info->cpus = host_cpu_set->size;
+        info->cores = host_cpu_set->size;
+
+        xen_host_cpu_set_free(host_cpu_set);
+        VIR_FREE(modelname);
+        return 0;
+    }
+    xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, "Unable to get Host CPU set");
+    return -1;
+}
+
+/*
+ * xenapiGetCapabilities:
+ *
+ *
+ * Returns capabilities as an XML string
+ */
+static char *
+xenapiGetCapabilities (virConnectPtr conn)
+{
+    virCapsPtr caps = ((struct _xenapiPrivate *)(conn->privateData))->caps;
+    if (caps) {
+        char *xml = virCapabilitiesFormatXML(caps);
+        if (!xml) goto cleanup;
+        return xml;
+    }
+  cleanup:
+    xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, "Capabilities not available");
+    return NULL;
+}
+
+
+/*
+ * xenapiListDomains
+ *
+ * Collects the list of active domains, and store their ID in @maxids
+ * Returns the number of domain found or -1 in case of error
+ */
+static int
+xenapiListDomains (virConnectPtr conn, int *ids, int maxids)
+{
+    /* vm.list */
+    xen_host host;
+    xen_vm_set *result = NULL;
+    int64_t t0;
+    int i;
+    xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session;
+    if (xen_session_get_this_host(session, &host, session)) {
+        xen_host_get_resident_vms(session, &result, host);
+        xen_host_free(host);
+    } else
+        xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL);
+    if (result != NULL) {
+        for (i = 0; (i < (result->size)) && (i < maxids); i++) {
+            xen_vm_get_domid(session, &t0, result->contents[i]);
+            if (t0 > (int64_t)INT_MAX || t0 < (int64_t)INT_MIN) {
+                xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, "DomainID can't fit in 32 bits");
+                xen_vm_set_free(result);
+                return -1;
+            }
+            ids[i] = (int)t0;
+        }
+        xen_vm_set_free(result);
+        return i;
+    }
+    return -1;
+}
+
+/*
+ * xenapiNumOfDomains
+ *
+ *
+ * Returns the number of domains found or -1 in case of error
+ */
+static int
+xenapiNumOfDomains (virConnectPtr conn)
+{
+    /* #(vm.list) */
+    xen_vm_set *result = NULL;
+    xen_host host = NULL;
+    int numDomains = -1;
+    xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session;
+
+    xen_session_get_this_host(session, &host, session);
+    if (host != NULL) {
+        xen_host_get_resident_vms(session, &result, host);
+        if (result != NULL) {
+            numDomains = result->size;
+            xen_vm_set_free(result);
+        }
+        xen_host_free(host);
+    }
+    if (!session->ok)
+        xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL);
+    return numDomains;
+}
+
+/*
+ * xenapiDomainCreateXML
+ *
+ * Launches a new domain based on the XML description
+ * Returns the domain pointer or NULL in case of error
+ */
+static virDomainPtr
+xenapiDomainCreateXML (virConnectPtr conn,
+                       const char *xmlDesc,
+                       unsigned int flags ATTRIBUTE_UNUSED)
+{
+    xen_vm_record *record = NULL;
+    xen_vm vm = NULL;
+    virDomainPtr domP = NULL;
+    xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session;
+    virCapsPtr caps = ((struct _xenapiPrivate *)(conn->privateData))->caps;
+    if (!caps)
+        return NULL;
+
+    virDomainDefPtr defPtr = virDomainDefParseString(caps, xmlDesc, flags);
+    createVMRecordFromXml(conn, defPtr, &record, &vm);
+    virDomainDefFree(defPtr);
+    if (record) {
+        unsigned char raw_uuid[VIR_UUID_BUFLEN];
+        virUUIDParse(record->uuid, raw_uuid);
+        if (vm) {
+            if (xen_vm_start(session, vm, false, false)) {
+                domP = virGetDomain(conn, record->name_label, raw_uuid);
+                if (!domP) {
+                    xen_vm_record_free(record);
+                    xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, "Domain Pointer is invalid");
+                    return domP;
+                }
+                domP->id = record->domid;
+                xen_vm_free(vm);
+            }
+            else
+                xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL);
+        }
+        xen_vm_record_free(record);
+    }
+    else
+        xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL);
+    return domP;
+}
+
+/*
+ * xenapiDomainLookupByID
+ *
+ *
+ * Returns a valid domain pointer of the domain with ID same as the one passed
+ * or NULL in case of error
+ */
+static virDomainPtr
+xenapiDomainLookupByID (virConnectPtr conn, int id)
+{
+    int i;
+    int64_t domID;
+    char *uuid;
+    xen_host host;
+    xen_vm_set *result;
+    xen_vm_record *record;
+    unsigned char raw_uuid[VIR_UUID_BUFLEN];
+    virDomainPtr domP=NULL;
+    xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session;
+
+    xen_session_get_this_host(session, &host, session);
+    if (host != NULL && session->ok) {
+        xen_host_get_resident_vms(session, &result, host);
+        if (result != NULL ) {
+            for (i = 0; i < result->size; i++) {
+                xen_vm_get_domid(session, &domID, result->contents[i]);
+                if (domID == id) {
+                    xen_vm_get_record(session, &record, result->contents[i]);
+                    xen_vm_get_uuid(session, &uuid, result->contents[i]);
+                    virUUIDParse(uuid, raw_uuid);
+                    domP = virGetDomain(conn, record->name_label, raw_uuid);
+                    if (domP) {
+                        int64_t domid = -1;
+                        xen_vm_get_domid(session, &domid, result->contents[i]);
+                        domP->id = domid;
+                    } else {
+                        xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, "Domain Pointer not valid");
+                        domP = NULL;
+                    }
+                    xen_uuid_free(uuid);
+                    xen_vm_record_free(record);
+                    break;
+                }
+            }
+            xen_vm_set_free(result);
+        } else {
+            xenapiSessionErrorHandler(conn, VIR_ERR_NO_DOMAIN, NULL);
+        }
+        xen_host_free(host);
+    } else {
+        xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL);
+    }
+    return domP;
+}
+
+/*
+ * xenapiDomainLookupByUUID
+ *
+ * Returns the domain pointer of domain with matching UUID
+ * or -1 in case of error
+ */
+static virDomainPtr
+xenapiDomainLookupByUUID (virConnectPtr conn,
+                          const unsigned char *uuid)
+{
+    /* vm.get_by_uuid */
+    xen_vm vm;
+    xen_vm_record *record;
+    char uuidStr[VIR_UUID_STRING_BUFLEN];
+    virDomainPtr domP = NULL;
+    xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session;
+    virUUIDFormat(uuid,uuidStr);
+    if (xen_vm_get_by_uuid(session, &vm, uuidStr)) {
+        xen_vm_get_record(session, &record, vm);
+        if (record != NULL) {
+            domP = virGetDomain(conn, record->name_label, uuid);
+            if (!domP) {
+                xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, "Domain Pointer not valid");
+                domP = NULL;
+            } else {
+                domP->id = record->domid;
+            }
+            xen_vm_record_free(record);
+        }
+        else
+            xenapiSessionErrorHandler(conn, VIR_ERR_NO_DOMAIN, NULL);
+        xen_vm_free(vm);
+    } else
+        xenapiSessionErrorHandler(conn, VIR_ERR_NO_DOMAIN, NULL);
+    return domP;
+}
+
+/*
+ * xenapiDomainLookupByName
+ *
+ * Returns the domain pointer of domain with matching name
+ * or -1 in case of error
+ */
+static virDomainPtr
+xenapiDomainLookupByName (virConnectPtr conn,
+                          const char *name)
+{
+    /* vm.get_by_name_label */
+    xen_vm_set *vms = NULL;
+    xen_vm vm;
+    char *uuid = NULL;
+    unsigned char raw_uuid[VIR_UUID_BUFLEN];
+    virDomainPtr domP = NULL;
+    xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session;
+    if (xen_vm_get_by_name_label(session, &vms, (char *)name) && vms->size > 0) {
+        if (vms->size != 1) {
+            xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, "Domain name is not unique");
+            xen_vm_set_free(vms);
+            return NULL;
+        }
+        vm = vms->contents[0];
+        xen_vm_get_uuid(session, &uuid, vm);
+        if (uuid!=NULL) {
+            virUUIDParse(uuid, raw_uuid);
+            domP = virGetDomain(conn, name, raw_uuid);
+            if (domP != NULL) {
+                int64_t domid = -1;
+                xen_vm_get_domid(session, &domid, vm);
+                domP->id = domid;
+                xen_uuid_free(uuid);
+                xen_vm_set_free(vms);
+                return domP;
+            } else {
+                xen_uuid_free(uuid);
+                xen_vm_set_free(vms);
+            if (!session->ok)
+                xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, "Couldn't get the Domain Pointer");
+                return NULL;
+            }
+        }
+    }
+    if (vms) xen_vm_set_free(vms);
+    xenapiSessionErrorHandler(conn, VIR_ERR_NO_DOMAIN, "");
+    return NULL;
+}
+
+/*
+ * xenapiDomainSuspend
+ *
+ * a VM is paused
+ * Returns 0 on success or -1 in case of error
+ */
+static int
+xenapiDomainSuspend (virDomainPtr dom)
+{
+    /* vm.pause() */
+    xen_vm vm;
+    xen_vm_set *vms=NULL;
+    xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+    if (xen_vm_get_by_name_label(session, &vms, dom->name) &&  vms->size > 0) {
+        if (vms->size != 1) {
+            xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, "Domain name is not unique");
+            xen_vm_set_free(vms);
+            return -1;
+        } else {
+            vm = vms->contents[0];
+            if (!xen_vm_pause(session, vm)) {
+                xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL);
+                xen_vm_set_free(vms);
+                return -1;
+            }
+            xen_vm_set_free(vms);
+            return 0;
+        }
+    }
+    if (vms) xen_vm_set_free(vms);
+    xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, "");
+    return -1;
+}
+
+/*
+ * xenapiDomainResume
+ *
+ * Resumes a VM
+ * Returns 0 on success or -1 in case of error
+ */
+static int
+xenapiDomainResume (virDomainPtr dom)
+{
+    /* vm.unpause() */
+    xen_vm vm;
+    xen_vm_set *vms;
+    xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+    if (xen_vm_get_by_name_label(session, &vms, dom->name) && vms->size > 0) {
+        if (vms->size != 1) {
+            xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, "Domain name is not unique");
+            xen_vm_set_free(vms);
+            return -1;
+        } else {
+            vm = vms->contents[0];
+            if (!xen_vm_unpause(session, vm)) {
+                xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL);
+                xen_vm_set_free(vms);
+                return -1;
+            }
+            xen_vm_set_free(vms);
+            return 0;
+        }
+    }
+    if (vms) xen_vm_set_free(vms);
+    xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, "");
+    return -1;
+}
+
+/*
+ * xenapiDomainShutdown
+ *
+ * shutsdown a VM
+ * Returns 0 on success or -1 in case of error
+ */
+static int
+xenapiDomainShutdown (virDomainPtr dom)
+{
+    /* vm.clean_shutdown */
+    xen_vm vm;
+    xen_vm_set *vms;
+    xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+    if (xen_vm_get_by_name_label(session, &vms, dom->name) && vms->size > 0) {
+        if (vms->size != 1) {
+            xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, "Domain name is not unique");
+            xen_vm_set_free(vms);
+            return -1;
+        } else {
+            vm = vms->contents[0];
+            if (!xen_vm_clean_shutdown(session, vm)) {
+                xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL);
+                xen_vm_set_free(vms);
+                return -1;
+            }
+            xen_vm_set_free(vms);
+            return 0;
+        }
+    }
+    if (vms) xen_vm_set_free(vms);
+    xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, "");
+    return -1;
+}
+
+/*
+ * xenapiDomainReboot
+ *
+ * Reboots a VM
+ * Returns 0 on success or -1 in case of error
+ */
+static int
+xenapiDomainReboot (virDomainPtr dom, unsigned int flags ATTRIBUTE_UNUSED)
+{
+    /* vm.clean_reboot */
+    xen_vm vm;
+    struct xen_vm_set *vms;
+    xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+    if (xen_vm_get_by_name_label(session, &vms, dom->name) && vms->size > 0) {
+        if (vms->size != 1) {
+            xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, "Domain name is not unique");
+            xen_vm_set_free(vms);
+            return -1;
+        }
+        vm = vms->contents[0];
+        if (!xen_vm_clean_reboot(session, vm)) {
+            xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL);
+            xen_vm_set_free(vms);
+            return -1;
+        }
+        xen_vm_set_free(vms);
+        return 0;
+    }
+    if (vms) xen_vm_set_free(vms);
+    xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, "");
+    return -1;
+}
+
+/*
+ * xenapiDomaindestroy
+ *
+ * A VM is hard shutdown
+ * Returns 0 on success or -1 in case of error
+ */
+static int
+xenapiDomainDestroy (virDomainPtr dom)
+{
+    /* vm.hard_shutdown */
+    xen_vm vm;
+    struct xen_vm_set *vms;
+    xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+    if (xen_vm_get_by_name_label(session, &vms, dom->name) && vms->size > 0) {
+        if (vms->size != 1) {
+            xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, "Domain name is not unique");
+            xen_vm_set_free(vms);
+            return -1;
+        }
+        vm = vms->contents[0];
+        if (!xen_vm_hard_shutdown(session, vm)) {
+            xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL);
+            xen_vm_set_free(vms);
+            return -1;
+        }
+        xen_vm_set_free(vms);
+        return 0;
+    }
+    if (vms) xen_vm_set_free(vms);
+    xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, "");
+    return -1;
+}
+
+/*
+ * xenapiDomainGetOSType
+ *
+ *
+ * Returns OS version on success or NULL in case of error
+ */
+static char *
+xenapiDomainGetOSType (virDomainPtr dom)
+{
+    xen_vm vm=NULL;
+    xen_vm_set *vms;
+    char *ostype = NULL;
+    char *boot_policy=NULL;
+    xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+
+    if (xen_vm_get_by_name_label(session, &vms, dom->name) && vms->size > 0) {
+        if (vms->size != 1) {
+            xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, "Domain name is not unique");
+            xen_vm_set_free(vms);
+            return NULL;
+        }
+        vm = vms->contents[0];
+        if (!xen_vm_get_hvm_boot_policy(session, &boot_policy, vm)) {
+            xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL);
+            goto cleanup;
+        }
+        if (!(ostype = (STREQ(boot_policy,"BIOS order") ? strdup("hvm") : strdup("xen"))))
+            virReportOOMError();
+        VIR_FREE(boot_policy);
+    } else
+        xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, "");
+
+  cleanup:
+    if (vms) xen_vm_set_free(vms);
+    return ostype;
+}
+/*
+ * xenapiDomainGetMaxMemory
+ *
+ * Returns maximum static memory for VM on success
+ * or 0 in case of error
+ */
+static unsigned long
+xenapiDomainGetMaxMemory (virDomainPtr dom)
+{
+    int64_t mem_static_max = 0;
+    xen_vm vm;
+    xen_vm_set *vms;
+    xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+    if (xen_vm_get_by_name_label(session, &vms, dom->name) && vms->size > 0) {
+        if (vms->size != 1) {
+            xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, "Domain name is not unique");
+            xen_vm_set_free(vms);
+            return 0;
+        }
+        vm = vms->contents[0];
+        xen_vm_get_memory_static_max(session, &mem_static_max, vm);
+        xen_vm_set_free(vms);
+        return (unsigned long)(mem_static_max / 1024);
+    } else {
+        if (vms) xen_vm_set_free(vms);
+        xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL);
+        return 0;
+    }
+}
+
+/*
+ * xenapiDomainSetMaxMemory
+ *
+ * Sets maximum static memory for VM on success
+ * Returns 0 on success or -1 in case of error
+ */
+static int
+xenapiDomainSetMaxMemory (virDomainPtr dom, unsigned long memory)
+{
+    /* vm.set_memory_static_max */
+    xen_vm vm;
+    struct xen_vm_set *vms;
+    xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+    if (xen_vm_get_by_name_label(session, &vms, dom->name) && vms->size > 0) {
+        if (vms->size != 1) {
+            xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, "Domain name is not unique");
+            xen_vm_set_free(vms);
+            return -1;
+        }
+        vm = vms->contents[0];
+        if (!(xen_vm_set_memory_static_max(session, vm, memory * 1024))) {
+            xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL);
+            xen_vm_set_free(vms);
+            return -1;
+        }
+        xen_vm_set_free(vms);
+    } else {
+        if (vms) xen_vm_set_free(vms);
+        xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL);
+        return -1;
+    }
+    return 0;
+}
+
+/*
+ * xenapiDomainGetInfo:
+ *
+ * Fills a structure with domain information
+ * Returns 0 on success or -1 in case of error
+ */
+static int
+xenapiDomainGetInfo (virDomainPtr dom, virDomainInfoPtr info)
+{
+    int64_t maxmem = 0, memory = 0, vcpu = 0;
+    xen_vm vm;
+    xen_vm_record *record;
+    xen_vm_set *vms;
+    xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+    info->cpuTime = 0; /* CPU time is not advertised */
+    if (xen_vm_get_by_name_label(session, &vms, dom->name) && vms->size > 0) {
+        if (vms->size != 1) {
+            xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, "Domain name is not unique");
+            xen_vm_set_free(vms);
+            return -1;
+        }
+        vm = vms->contents[0];
+        xen_vm_get_memory_static_max(session, &maxmem, vm);
+        info->maxMem = (maxmem / 1024);
+        enum xen_vm_power_state state = XEN_VM_POWER_STATE_UNKNOWN;
+        xen_vm_get_power_state(session, &state, vm);
+        info->state = mapPowerState(state);
+        xen_vm_get_record(session, &record, vm);
+        if (record != NULL) {
+            xen_vm_metrics_get_memory_actual(session, &memory, record->metrics->u.handle);
+            info->memory = (memory / 1024);
+            xen_vm_record_free(record);
+        }
+        xen_vm_get_vcpus_max(session, &vcpu, vm);
+        info->nrVirtCpu = vcpu;
+        xen_vm_set_free(vms);
+        return 0;
+    }
+    if (vms) xen_vm_set_free(vms);
+    xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL);
+    return -1;
+}
+
+
+/*
+ * xenapiDomainSetVcpus
+ *
+ * Sets the VCPUs on the domain
+ * Return 0 on success or -1 in case of error
+ */
+static int
+xenapiDomainSetVcpus (virDomainPtr dom, unsigned int nvcpus)
+{
+
+    /* vm.set_vcpus_max */
+    xen_vm vm;
+    xen_vm_set *vms;
+    xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+    if (xen_vm_get_by_name_label(session, &vms, dom->name) && vms->size > 0) {
+        if (vms->size != 1) {
+            xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, "Domain name is not unique");
+            xen_vm_set_free(vms);
+            return -1;
+        }
+        vm = vms->contents[0];
+        if (xen_vm_set_vcpus_number_live(session, vm, (int64_t)nvcpus)) {
+            xen_vm_set_free(vms);
+            return 0;
+        }
+    }
+    if (vms) xen_vm_set_free(vms);
+    xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL);
+    return -1;
+}
+
+/*
+ * xenapiDomainPinVcpu
+ *
+ * Dynamically change the real CPUs which can be allocated to a virtual CPU
+ * Returns 0 on success or -1 in case of error
+ */
+static int
+xenapiDomainPinVcpu (virDomainPtr dom, unsigned int vcpu ATTRIBUTE_UNUSED,
+                     unsigned char *cpumap, int maplen)
+{
+    char *value = NULL;
+    xen_vm vm;
+    xen_vm_set *vms;
+    xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+    if (xen_vm_get_by_name_label(session, &vms, dom->name) && vms->size > 0) {
+        if (vms->size != 1) {
+            xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, "Domain name is not unique");
+            xen_vm_set_free(vms);
+            return -1;
+        }
+        vm = vms->contents[0];
+        if ((value = mapDomainPinVcpu(cpumap, maplen))) {
+            xen_vm_remove_from_vcpus_params(session, vm, (char *)"mask");
+            if (xen_vm_add_to_vcpus_params(session, vm, (char *)"mask", value)) {
+                xen_vm_set_free(vms);
+                VIR_FREE(value);
+                return 0;
+            }
+            VIR_FREE(value);
+        } else {
+            xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL);
+            xen_vm_set_free(vms);
+            return -1;
+        }
+    }
+    if (vms) xen_vm_set_free(vms);
+    xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL);
+    return -1;
+}
+
+/*
+ * xenapiDomainGetVcpus
+ *
+ * Gets Vcpu information
+ * Return number of structures filled on success or -1 in case of error
+ */
+static int
+xenapiDomainGetVcpus (virDomainPtr dom,
+                      virVcpuInfoPtr info, int maxinfo,
+                      unsigned char *cpumaps, int maplen)
+{
+
+    xen_vm_set *vms = NULL;
+    xen_vm vm = NULL;
+    xen_string_string_map *vcpu_params = NULL;
+    int nvcpus = 0, cpus = 0, i;
+    virDomainInfo domInfo;
+    virNodeInfo nodeInfo;
+    virVcpuInfoPtr ifptr;
+    xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+    char *mask = NULL;
+    if (cpumaps != NULL && maplen < 1)
+        return -1;
+    if (xenapiDomainGetInfo(dom, &domInfo) == 0) {
+        nvcpus = domInfo.nrVirtCpu;
+    } else {
+        xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, "Couldn't fetch Domain Information");
+        return -1;
+    }
+    if (xenapiNodeGetInfo(dom->conn, &nodeInfo) == 0)
+        cpus = nodeInfo.cpus;
+    else {
+        xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, "Couldn't fetch Node Information");
+        return -1;
+    }
+    if (nvcpus > maxinfo)
+        nvcpus = maxinfo;
+    if (cpumaps != NULL)
+        memset(cpumaps, 0, maxinfo * maplen);
+    if (!xen_vm_get_by_name_label(session, &vms, dom->name))
+        return -1;
+    if (vms->size != 1) {
+        xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, "Domain name is not unique");
+        xen_vm_set_free(vms);
+        return -1;
+    }
+    vm = vms->contents[0];
+    if (!xen_vm_get_vcpus_params(session, &vcpu_params, vm)) {
+        xen_vm_set_free(vms);
+        xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL);
+        return -1;
+    }
+    for (i = 0; i < vcpu_params->size; i++) {
+        if (STREQ(vcpu_params->contents[i].key, "mask")) {
+            if (!(mask = strdup(vcpu_params->contents[i].val))){
+                 xen_vm_set_free(vms);
+                 xen_string_string_map_free(vcpu_params);
+                 virReportOOMError();
+                 return -1;
+            }
+            break;
+         }
+    }
+    xen_string_string_map_free(vcpu_params);
+    for (i = 0, ifptr = info; i < nvcpus; i++, ifptr++) {
+        ifptr->number = i;
+        ifptr->state = VIR_VCPU_RUNNING;
+        ifptr->cpuTime = 0;
+        ifptr->cpu = 0;
+        if (mask != NULL)
+            getCpuBitMapfromString(mask, VIR_GET_CPUMAP(cpumaps, maplen, i), maplen);
+    }
+    VIR_FREE(mask);
+    xen_vm_set_free(vms);
+    return i;
+}
+
+/*
+ * xenapiDomainGetMaxVcpus
+ *
+ *
+ * Returns maximum number of Vcpus on success or -1 in case of error
+ */
+static int
+xenapiDomainGetMaxVcpus (virDomainPtr dom)
+{
+    xen_vm vm;
+    xen_vm_set *vms;
+    int64_t maxvcpu = 0;
+    enum xen_vm_power_state state;
+    xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+    if (xen_vm_get_by_name_label(session, &vms, dom->name) && vms->size > 0) {
+        if (vms->size != 1) {
+            xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, "Domain name is not unique");
+            xen_vm_set_free(vms);
+            return -1;
+        }
+        vm = vms->contents[0];
+        xen_vm_get_power_state(session, &state, vm);
+        if (state == XEN_VM_POWER_STATE_RUNNING) {
+            xen_vm_get_vcpus_max(session, &maxvcpu, vm);
+        } else {
+            maxvcpu = xenapiGetMaxVcpus(dom->conn, NULL);
+        }
+        xen_vm_set_free(vms);
+        return (int)maxvcpu;
+    }
+    if (vms) xen_vm_set_free(vms);
+    xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL);
+    return -1;
+}
+
+/*
+ * xenapiDomainDumpXML
+ *
+ *
+ * Returns XML string of the domain configuration on success or -1 in case of error
+ */
+static char *
+xenapiDomainDumpXML (virDomainPtr dom, int flags ATTRIBUTE_UNUSED)
+{
+    xen_vm vm=NULL;
+    xen_vm_set *vms;
+    xen_string_string_map *result=NULL;
+    xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+    virDomainDefPtr defPtr = NULL;
+
+    if (!xen_vm_get_by_name_label(session, &vms, dom->name)) return NULL;
+    if (vms->size != 1) {
+        xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, "Domain name is not unique");
+        xen_vm_set_free(vms);
+        return NULL;
+    }
+    if (VIR_ALLOC(defPtr) < 0) {
+        virReportOOMError();
+        xen_vm_set_free(vms);
+        return NULL;
+    }
+    vm = vms->contents[0];
+    defPtr->virtType = VIR_DOMAIN_VIRT_XEN;
+    defPtr->id = dom->id;
+    memcpy(defPtr->uuid, dom->uuid, VIR_UUID_BUFLEN);
+    if (!(defPtr->name = strdup(dom->name)))
+        goto error_cleanup;
+    char *boot_policy = NULL;
+    xen_vm_get_hvm_boot_policy(session, &boot_policy, vm);
+    if (STREQ(boot_policy,"BIOS order")) {
+        if (!(defPtr->os.type = strdup("hvm"))) {
+            VIR_FREE(boot_policy);
+            goto error_cleanup;
+        }
+        xen_vm_get_hvm_boot_params(session, &result, vm);
+        if (result != NULL) {
+            int i;
+            for (i = 0; i < result->size; i++) {
+                if (STREQ(result->contents[i].key, "order")) {
+                    int cnt = 0;
+                    while(result->contents[i].val[cnt] != '\0') {
+                        defPtr->os.bootDevs[cnt] = map2LibvirtBootOrder(result->contents[i].val[cnt]);
+                        cnt++;
+                    }
+                    defPtr->os.nBootDevs = cnt;
+                    break;
+                }
+            }
+            xen_string_string_map_free(result);
+        }
+        VIR_FREE(boot_policy);
+    } else {
+        char *value = NULL;
+        if (!(defPtr->os.type = strdup("xen"))) {
+            VIR_FREE(boot_policy);
+            goto error_cleanup;
+        }
+        if (!(defPtr->os.loader = strdup("pygrub"))) {
+            VIR_FREE(boot_policy);
+            goto error_cleanup;
+        }
+        xen_vm_get_pv_kernel(session, &value, vm);
+        if (STRNEQ(value, "")) {
+            if (!(defPtr->os.kernel = strdup(value))) {
+                VIR_FREE(boot_policy);
+                VIR_FREE(value);
+                goto error_cleanup;
+            }
+            VIR_FREE(value);
+        }
+        xen_vm_get_pv_ramdisk(session, &value, vm);
+        if (STRNEQ(value, "")) {
+            if (!(defPtr->os.initrd = strdup(value))) {
+                VIR_FREE(boot_policy);
+                VIR_FREE(value);
+                goto error_cleanup;
+            }
+            VIR_FREE(value);
+        }
+        xen_vm_get_pv_args(session, &value, vm);
+        if (STRNEQ(value, "")) {
+            if(!(defPtr->os.cmdline = strdup(value))) {
+                VIR_FREE(boot_policy);
+                VIR_FREE(value);
+                goto error_cleanup;
+            }
+            VIR_FREE(value);
+        }
+        VIR_FREE(boot_policy);
+        if (!(defPtr->os.bootloader = strdup("pygrub")))
+            goto error_cleanup;
+    }
+    char *val = NULL;
+    xen_vm_get_pv_bootloader_args(session, &val, vm);
+    if (STRNEQ(val, "")) {
+        if (!(defPtr->os.bootloaderArgs = strdup(val))) {
+            VIR_FREE(val);
+            goto error_cleanup;
+        }
+        VIR_FREE(val);
+    }
+    unsigned long memory=0;
+    memory = xenapiDomainGetMaxMemory(dom);
+    defPtr->maxmem = memory;
+    int64_t dynamic_mem=0;
+    if (xen_vm_get_memory_dynamic_max(session, &dynamic_mem, vm)) {
+        defPtr->memory = (unsigned long) (dynamic_mem / 1024);
+    } else {
+        defPtr->memory = memory;
+    }
+    defPtr->vcpus = xenapiDomainGetMaxVcpus(dom);
+    enum xen_on_normal_exit action;
+    if (xen_vm_get_actions_after_shutdown(session, &action, vm)) {
+        defPtr->onPoweroff = xenapiNormalExitEnum2virDomainLifecycle(action);
+    }
+    if (xen_vm_get_actions_after_reboot(session, &action, vm)) {
+        defPtr->onReboot = xenapiNormalExitEnum2virDomainLifecycle(action);
+    }
+    enum xen_on_crash_behaviour crash;
+    if (xen_vm_get_actions_after_crash(session, &crash, vm)) {
+        defPtr->onCrash = xenapiCrashExitEnum2virDomainLifecycle(action);
+    }
+    xen_vm_get_platform(session, &result, vm);
+    if (result != NULL) {
+        int i;
+        for(i = 0; i < result->size; i++) {
+            if (STREQ(result->contents[i].val, "true")) {
+                if (STREQ(result->contents[i].key, "acpi"))
+                    defPtr->features = defPtr->features | (1<<VIR_DOMAIN_FEATURE_ACPI);
+                else if (STREQ(result->contents[i].key, "apic"))
+                    defPtr->features = defPtr->features | (1<<VIR_DOMAIN_FEATURE_APIC);
+                else if (STREQ(result->contents[i].key, "pae"))
+                    defPtr->features = defPtr->features | (1<<VIR_DOMAIN_FEATURE_PAE);
+            }
+        }
+        xen_string_string_map_free(result);
+    }
+    struct xen_vif_set *vif_set = NULL;
+    xen_vm_get_vifs(session, &vif_set, vm);
+    if (vif_set) {
+        int i;
+        xen_vif vif;
+        xen_vif_record *vif_rec = NULL;
+        xen_network network;
+        char *bridge = NULL;
+        defPtr->nnets = vif_set->size;
+        if (VIR_ALLOC_N(defPtr->nets, vif_set->size) < 0) {
+            xen_vif_set_free(vif_set);
+            goto error_cleanup;
+        }
+        for (i = 0; i < vif_set->size; i++) {
+            if (VIR_ALLOC(defPtr->nets[i]) < 0) {
+                xen_vif_set_free(vif_set);
+                goto error_cleanup;
+            }
+            defPtr->nets[i]->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
+            vif = vif_set->contents[i];
+            xen_vif_get_network(session, &network, vif);
+            if (network != NULL) {
+                xen_network_get_bridge(session, &bridge, network);
+                if (bridge != NULL)
+                    defPtr->nets[i]->data.bridge.brname = bridge;
+                xen_network_free(network);
+            }
+            xen_vif_get_record(session, &vif_rec, vif);
+            if (vif_rec != NULL) {
+                if (virParseMacAddr((const char *)vif_rec->mac,defPtr->nets[i]->mac) < 0)
+                    xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,
+                                              "Unable to parse given mac address");
+                xen_vif_record_free(vif_rec);
+            }
+        }
+        xen_vif_set_free(vif_set);
+    }
+    if (vms) xen_vm_set_free(vms);
+    char *xml = virDomainDefFormat(defPtr, 0);
+    virDomainDefFree(defPtr);
+    return xml;
+
+  error_cleanup:
+    virReportOOMError();
+    xen_vm_set_free(vms);
+    virDomainDefFree(defPtr);
+    return NULL;
+
+}
+
+/*
+ * xenapiListDefinedDomains
+ *
+ * list the defined but inactive domains, stores the pointers to the names in @names
+ * Returns number of names provided in the array or -1 in case of error
+ */
+static int
+xenapiListDefinedDomains (virConnectPtr conn, char **const names,
+                          int maxnames)
+{
+    int i,j=0,doms;
+    xen_vm_set *result;
+    xen_vm_record *record;
+    xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session;
+    xen_vm_get_all(session, &result);
+    if (result != NULL) {
+        for (i = 0; i < result->size && j < maxnames; i++) {
+            xen_vm_get_record(session, &record, result->contents[i]);
+            if (record != NULL) {
+                if (record->is_a_template == 0) {
+                    char *usenames = NULL;
+                    if (!(usenames = strdup(record->name_label))) {
+                        virReportOOMError();
+                        xen_vm_record_free(record);
+                        xen_vm_set_free(result);
+                        while (--j >= 0) VIR_FREE(names[j]);
+                        return -1;
+                    }
+                    names[j++] = usenames;
+                }
+                xen_vm_record_free(record);
+            } else {
+                xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, "Couldn't get VM record");
+                xen_vm_set_free(result);
+                while (--j >= 0) VIR_FREE(names[j]);
+                   return -1;
+            }
+        }
+        doms = j;
+        xen_vm_set_free(result);
+        return doms;
+    }
+    xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL);
+    return -1;
+}
+
+/*
+ * xenapiNumOfDefinedDomains
+ *
+ * Provides the number of defined but inactive domains
+ * Returns number of domains found on success or -1 in case of error
+ */
+static int
+xenapiNumOfDefinedDomains (virConnectPtr conn)
+{
+    xen_vm_set *result;
+    xen_vm_record *record;
+    int DomNum = 0, i;
+    xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session;
+    xen_vm_get_all(session, &result);
+    if (result != NULL) {
+        for (i = 0; i < result->size; i++) {
+            xen_vm_get_record(session, &record, result->contents[i]);
+            if (record == NULL && !session->ok) {
+                xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL);
+                xen_vm_set_free(result);
+                return -1;
+            }
+            if (record->is_a_template == 0)
+                DomNum++;
+            xen_vm_record_free(record);
+        }
+        xen_vm_set_free(result);
+        return DomNum;
+    }
+    xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL);
+    return -1;
+}
+
+/*
+ * xenapiDomainCreate
+ *
+ * starts a VM
+ * Return 0 on success or -1 in case of error
+ */
+static int
+xenapiDomainCreate (virDomainPtr dom)
+{
+    xen_vm_set *vms;
+    xen_vm vm;
+    xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+    if (xen_vm_get_by_name_label(session, &vms, dom->name) && vms->size > 0) {
+        if (vms->size != 1) {
+            xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, "Domain name is not unique");
+            xen_vm_set_free(vms);
+            return -1;
+        }
+        vm = vms->contents[0];
+        if (!xen_vm_start(session, vm, false, false)) {
+            xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL);
+            xen_vm_set_free(vms);
+            return -1;
+        }
+        xen_vm_set_free(vms);
+    } else {
+        if (vms) xen_vm_set_free(vms);
+        xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL);
+        return -1;
+    }
+    return 0;
+}
+
+/*
+ * xenapiDomainDefineXML
+ *
+ * Defines a domain from the given XML but does not start it
+ * Returns 0 on success or -1 in case of error
+ */
+static virDomainPtr
+xenapiDomainDefineXML (virConnectPtr conn, const char *xml)
+{
+    xen_vm_record *record=NULL;
+    xen_vm vm=NULL;
+    virDomainPtr domP=NULL;
+    xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session;
+    virCapsPtr caps = ((struct _xenapiPrivate *)(conn->privateData))->caps;
+    if (!caps)
+        return NULL;
+    virDomainDefPtr defPtr = virDomainDefParseString(caps, xml, 0);
+    if (!defPtr)
+        return NULL;
+    if (createVMRecordFromXml(conn, defPtr, &record, &vm) != 0) {
+        if (!session->ok)
+            xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL);
+        else
+            xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, "Couldn't get VM information from XML");
+        virDomainDefFree(defPtr);
+        return NULL;
+    }
+    if (record != NULL) {
+        unsigned char raw_uuid[VIR_UUID_BUFLEN];
+        virUUIDParse(record->uuid, raw_uuid);
+        domP = virGetDomain(conn, record->name_label, raw_uuid);
+        if (!domP && !session->ok)
+            xenapiSessionErrorHandler(conn, VIR_ERR_NO_DOMAIN, NULL);
+        xen_vm_record_free(record);
+    }
+    else if (vm != NULL)
+        xen_vm_free(vm);
+    virDomainDefFree(defPtr);
+    return domP;
+}
+
+/*
+ * xenapiDomainUndefine
+ *
+ * destroys a domain
+ * Return 0 on success or -1 in case of error
+ */
+static int
+xenapiDomainUndefine (virDomainPtr dom)
+{
+    struct xen_vm_set *vms;
+    xen_vm vm;
+    xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+    if (xen_vm_get_by_name_label(session, &vms, dom->name) && vms->size > 0) {
+        if (vms->size != 1) {
+            xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, "Domain name is not unique");
+            xen_vm_set_free(vms);
+            return -1;
+        }
+        vm = vms->contents[0];
+        if (!xen_vm_destroy(session, vm)) {
+            xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL);
+            xen_vm_set_free(vms);
+            return -1;
+        }
+        xen_vm_set_free(vms);
+        return 0;
+    }
+    if (vms) xen_vm_set_free(vms);
+    xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, "");
+    return -1;
+}
+
+/*
+ * xenapiDomainGetAutostart
+ *
+ * Provides a boolean value indicating whether the domain configured
+ * to be automatically started when the host machine boots
+ * Return 0 on success or -1 in case of error
+ */
+static int
+xenapiDomainGetAutostart (virDomainPtr dom, int *autostart)
+{
+    int i,flag=0;
+    xen_vm_set *vms;
+    xen_vm vm;
+    xen_string_string_map *result;
+    xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+    if (xen_vm_get_by_name_label(session, &vms, dom->name) && vms->size > 0) {
+        if (vms->size != 1) {
+            xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, "Domain name is not unique");
+            xen_vm_set_free(vms);
+            return -1;
+        }
+        vm = vms->contents[0];
+        if (!xen_vm_get_other_config(session, &result, vm)) {
+            xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL);
+            xen_vm_set_free(vms);
+            return -1;
+        }
+        for (i = 0; i < result->size; i++) {
+            if (STREQ(result->contents[i].key, "auto_poweron")) {
+                flag = 1;
+                if (STREQ(result->contents[i].val, "true"))
+                    *autostart = 1;
+                else
+                    *autostart = 0;
+                break;
+            }
+        }
+        xen_vm_set_free(vms);
+        xen_string_string_map_free(result);
+        if (flag == 0) return -1;
+        return 0;
+    }
+    if (vms) xen_vm_set_free(vms);
+    xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, "");
+    return -1;
+}
+
+/*
+ * xenapiDomainSetAutostart
+ *
+ * Configure the domain to be automatically started when the host machine boots
+ * Return 0 on success or -1 in case of error
+ */
+static int
+xenapiDomainSetAutostart (virDomainPtr dom, int autostart)
+{
+    xen_vm_set *vms;
+    xen_vm vm;
+    char *value;
+    xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
+    if (xen_vm_get_by_name_label(session, &vms, dom->name) && vms->size > 0) {
+        if (vms->size != 1) {
+            xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, "Domain name is not unique");
+            xen_vm_set_free(vms);
+            return -1;
+        }
+        vm = vms->contents[0];
+        xen_vm_remove_from_other_config(session, vm, (char *)"auto_poweron");
+        if (autostart==1)
+            value = (char *)"true";
+        else
+            value = (char *)"false";
+        if (!xen_vm_add_to_other_config(session, vm, (char *)"auto_poweron", value)) {
+            xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, NULL);
+            xen_vm_set_free(vms);
+            return -1;
+        }
+        xen_vm_set_free(vms);
+        return 0;
+    }
+    if (vms) xen_vm_set_free(vms);
+    xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, "");
+    return -1;
+}
+
+static char *
+xenapiDomainGetSchedulerType (virDomainPtr dom ATTRIBUTE_UNUSED, int *nparams)
+{
+    char *result = NULL;
+    *nparams = 0;
+    if (!(result = strdup("credit")))
+        virReportOOMError();
+    return result;
+}
+
+/*
+ * xenapiNodeGetFreeMemory
+ *
+ * provides the free memory available on the Node
+ * Returns memory size on success or 0 in case of error
+ */
+static unsigned long long
+xenapiNodeGetFreeMemory (virConnectPtr conn)
+{
+    xen_host_metrics_set *xen_met_set;
+    unsigned long long freeMem = 0;
+    xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session;
+    xen_host_metrics_get_all(session, &xen_met_set);
+    if (xen_met_set != NULL) {
+        if (!xen_host_metrics_get_memory_free(session, (int64_t *)&freeMem, xen_met_set->contents[0])) {
+            xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, "Couldn't get host metrics - memory information");
+            freeMem = 0;
+        }
+        xen_host_metrics_set_free(xen_met_set);
+    } else {
+        xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, "Couldn't get host metrics");
+    }
+    return freeMem;
+}
+
+/*
+ * xenapiNodeGetCellsFreeMemory
+ *
+ *
+ * Returns the number of entries filled in freeMems, or -1 in case of error.
+ */
+static int
+xenapiNodeGetCellsFreeMemory (virConnectPtr conn, unsigned long long *freeMems,
+                              int startCell, int maxCells)
+{
+    if (maxCells > 1 && startCell > 0) {
+        xenapiSessionErrorHandler(conn, VIR_ERR_NO_SUPPORT, "");
+        return -1;
+    } else {
+        freeMems[0] = xenapiNodeGetFreeMemory(conn);
+        return 1;
+    }
+}
+
+/* The interface which we export upwards to libvirt.c. */
+static virDriver xenapiDriver = {
+    VIR_DRV_XENAPI,
+    "XenAPI",
+    xenapiOpen, /* open */
+    xenapiClose, /* close */
+    xenapiSupportsFeature, /* supports_feature */
+    xenapiType, /* type */
+    xenapiGetVersion, /* version */
+    NULL, /*getlibvirtVersion */
+    xenapiGetHostname, /* getHostname */
+    xenapiGetMaxVcpus, /* getMaxVcpus */
+    xenapiNodeGetInfo, /* nodeGetInfo */
+    xenapiGetCapabilities, /* getCapabilities */
+    xenapiListDomains, /* listDomains */
+    xenapiNumOfDomains, /* numOfDomains */
+    xenapiDomainCreateXML, /* domainCreateXML */
+    xenapiDomainLookupByID, /* domainLookupByID */
+    xenapiDomainLookupByUUID, /* domainLookupByUUID */
+    xenapiDomainLookupByName, /* domainLookupByName */
+    xenapiDomainSuspend, /* domainSuspend */
+    xenapiDomainResume, /* domainResume */
+    xenapiDomainShutdown, /* domainShutdown */
+    xenapiDomainReboot, /* domainReboot */
+    xenapiDomainDestroy, /* domainDestroy */
+    xenapiDomainGetOSType, /* domainGetOSType */
+    xenapiDomainGetMaxMemory, /* domainGetMaxMemory */
+    xenapiDomainSetMaxMemory, /* domainSetMaxMemory */
+    NULL, /* domainSetMemory */
+    xenapiDomainGetInfo, /* domainGetInfo */
+    NULL, /* domainSave */
+    NULL, /* domainRestore */
+    NULL, /* domainCoreDump */
+    xenapiDomainSetVcpus, /* domainSetVcpus */
+    xenapiDomainPinVcpu, /* domainPinVcpu */
+    xenapiDomainGetVcpus, /* domainGetVcpus */
+    xenapiDomainGetMaxVcpus, /* domainGetMaxVcpus */
+    NULL, /* domainGetSecurityLabel */
+    NULL, /* nodeGetSecurityModel */
+    xenapiDomainDumpXML, /* domainDumpXML */
+    NULL, /* domainXmlFromNative */
+    NULL, /* domainXmlToNative */
+    xenapiListDefinedDomains, /* listDefinedDomains */
+    xenapiNumOfDefinedDomains, /* numOfDefinedDomains */
+    xenapiDomainCreate, /* domainCreate */
+    xenapiDomainDefineXML, /* domainDefineXML */
+    xenapiDomainUndefine, /* domainUndefine */
+    NULL, /* domainAttachDevice */
+    NULL, /* domainAttachDeviceFlags */
+    NULL, /* domainDetachDevice */
+    NULL, /* domainDetachDeviceFlags */
+    xenapiDomainGetAutostart, /* domainGetAutostart */
+    xenapiDomainSetAutostart, /* domainSetAutostart */
+    xenapiDomainGetSchedulerType, /* domainGetSchedulerType */
+    NULL, /* domainGetSchedulerParameters */
+    NULL, /* domainSetSchedulerParameters */
+    NULL, /* domainMigratePrepare */
+    NULL, /* domainMigratePerform */
+    NULL, /* domainMigrateFinish */
+    NULL, /* domainBlockStats */
+    NULL, /* domainInterfaceStats */
+    NULL, /* domainMemoryStats */
+    NULL, /* domainBlockPeek */
+    NULL, /* domainMemoryPeek */
+    xenapiNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */
+    xenapiNodeGetFreeMemory, /* getFreeMemory */
+    NULL, /* domainEventRegister */
+    NULL, /* domainEventDeregister */
+    NULL, /* domainMigratePrepare2 */
+    NULL, /* domainMigrateFinish2 */
+    NULL, /* nodeDeviceDettach */
+    NULL, /* nodeDeviceReAttach */
+    NULL, /* nodeDeviceReset */
+    NULL, /* domainMigratePrepareTunnel */
+    NULL, /* isEncrypted */
+    NULL, /* isSecure */
+    NULL, /* domainIsActive */
+    NULL, /* domainIsPersistent */
+    NULL, /* cpuCompare */
+    NULL, /* cpuBaseline */
+    NULL, /* domainGetJobInfo */
+    NULL, /* domainAbortJob */
+};
+
+/**
+ * xenapiRegister:
+ *
+ *
+ * Returns the driver priority or -1 in case of error.
+ */
+int
+xenapiRegister (void)
+{
+    return virRegisterDriver (&xenapiDriver);
+}
+
+/*
+ * write_func
+ * used by curl to read data from the server
+ */
+size_t
+write_func(void *ptr, size_t size, size_t nmemb, void *comms_)
+{
+    xen_comms *comms = comms_;
+    size_t n = size * nmemb;
+    #ifdef PRINT_XML
+        printf("\n\n---Result from server -----------------------\n");
+        printf("%s\n",((char*) ptr));
+        fflush(stdout);
+    #endif
+    return (size_t) (comms->func(ptr, n, comms->handle) ? n : 0);
+}
+
+/*
+ * call_func
+ * sets curl options, used with xen_session_login_with_password
+ */
+int
+call_func(const void *data, size_t len, void *user_handle,
+          void *result_handle, xen_result_func result_func)
+{
+    //(void)user_handle;
+    struct _xenapiPrivate *priv = (struct _xenapiPrivate *)user_handle;
+    #ifdef PRINT_XML
+
+        printf("\n\n---Data to server: -----------------------\n");
+        printf("%s\n",((char*) data));
+        fflush(stdout);
+    #endif
+    CURL *curl = curl_easy_init();
+    if (!curl) {
+      return -1;
+    }
+    xen_comms comms = {
+     .func = result_func,
+     .handle = result_handle
+    };
+    curl_easy_setopt(curl, CURLOPT_URL, priv->url);
+    curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
+    #ifdef CURLOPT_MUTE
+        curl_easy_setopt(curl, CURLOPT_MUTE, 1);
+    #endif
+    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &write_func);
+    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &comms);
+    curl_easy_setopt(curl, CURLOPT_POST, 1);
+    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
+    curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, len);
+    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, priv->noVerify?0:1);
+    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, priv->noVerify?0:2);
+    CURLcode result = curl_easy_perform(curl);
+    curl_easy_cleanup(curl);
+    return result;
+}
diff --git a/src/xenapi/xenapi_driver.h b/src/xenapi/xenapi_driver.h
new file mode 100644 (file)
index 0000000..a47c132
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * xenapi_driver.h.c: Xen API driver header file to be included in libvirt.c.
+ * Copyright (C) 2009, 2010 Citrix Ltd.
+ *
+ * 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
+ *
+ * Author: Sharadha Prabhakar <sharadha.prabhakar@citrix.com>
+ */
+
+
+#ifndef __VIR_XENAPI_PRIV_H__
+# define __VIR_XENAPI_PRIV_H__
+
+extern int xenapiRegister(void);
+
+#endif /* __VIR_XENAPI_PRIV_H__ */
diff --git a/src/xenapi/xenapi_driver_private.h b/src/xenapi/xenapi_driver_private.h
new file mode 100644 (file)
index 0000000..2e96771
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * xenapi_driver_private.h: Xen API driver's private header file.
+ * Copyright (C) 2009, 2010 Citrix Ltd.
+ *
+ * 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
+ *
+ * Author: Sharadha Prabhakar <sharadha.prabhakar@citrix.com>
+ */
+
+
+#ifndef __VIR_XENAPI_H__
+# define __VIR_XENAPI_H__
+
+# include <libxml/tree.h>
+# include <xen/api/xen_common.h>
+# include "virterror_internal.h"
+
+//# define PRINT_XML
+# define VIR_FROM_THIS VIR_FROM_XENAPI
+# define LIBVIRT_MODELNAME_LEN  (32)
+# define xenapiSessionErrorHandler(conn, errNum, buf) \
+    xenapiSessionErrorHandle(conn, errNum, buf, \
+                             __FILE__, __FUNCTION__, __LINE__)
+
+void
+xenapiSessionErrorHandle(virConnectPtr conn, virErrorNumber errNum,
+                         const char *buf, const char *filename,
+                         const char *func, size_t lineno);
+
+typedef struct
+{
+    xen_result_func func;
+    void *handle;
+} xen_comms;
+
+
+int
+call_func(const void *data, size_t len, void *user_handle,
+          void *result_handle, xen_result_func result_func);
+size_t
+write_func(void *ptr, size_t size, size_t nmemb, void *comms);
+
+/* xenAPI driver's private data structure */
+struct _xenapiPrivate {
+    xen_session *session;
+    char *url;
+    int noVerify;
+    virCapsPtr caps;
+};
+
+#endif /* __VIR_XENAPI_H__ */
diff --git a/src/xenapi/xenapi_utils.c b/src/xenapi/xenapi_utils.c
new file mode 100644 (file)
index 0000000..4b9a6d8
--- /dev/null
@@ -0,0 +1,571 @@
+/*
+ * xenapi_utils.c: Xen API driver -- utils parts.
+ * Copyright (C) 2009, 2010 Citrix Ltd.
+ *
+ * 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
+ *
+ * Author: Sharadha Prabhakar <sharadha.prabhakar@citrix.com>
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <libxml/uri.h>
+#include <xen/api/xen_all.h>
+#include "internal.h"
+#include "domain_conf.h"
+#include "virterror_internal.h"
+#include "datatypes.h"
+#include "util.h"
+#include "uuid.h"
+#include "memory.h"
+#include "buf.h"
+#include "logging.h"
+#include "qparams.h"
+#include "xenapi_driver_private.h"
+#include "xenapi_utils.h"
+
+void
+xenSessionFree(xen_session *session)
+{
+    int i;
+    if (session->error_description != NULL) {
+        for (i = 0; i < session->error_description_count; i++)
+            VIR_FREE(session->error_description[i]);
+        VIR_FREE(session->error_description);
+    }
+    VIR_FREE(session->session_id);
+    VIR_FREE(session);
+}
+
+char *
+xenapiUtil_RequestPassword(virConnectAuthPtr auth, const char *username,
+                        const char *hostname)
+{
+    unsigned int ncred;
+    virConnectCredential cred;
+    char *prompt;
+
+    memset(&cred, 0, sizeof (virConnectCredential));
+
+    if (virAsprintf(&prompt, "Enter %s password for %s", username,
+                    hostname) < 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 = hostname;
+        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
+xenapiUtil_ParseQuery(virConnectPtr conn, xmlURIPtr uri, int *noVerify)
+{
+    int result = 0;
+    int i;
+    struct qparam_set *queryParamSet = NULL;
+    struct qparam *queryParam = NULL;
+
+#ifdef HAVE_XMLURI_QUERY_RAW
+    queryParamSet = qparam_query_parse(uri->query_raw);
+#else
+    queryParamSet = qparam_query_parse(uri->query);
+#endif
+
+    if (queryParamSet == NULL) {
+        goto failure;
+    }
+
+    for (i = 0; i < queryParamSet->n; i++) {
+        queryParam = &queryParamSet->p[i];
+        if (STRCASEEQ(queryParam->name, "no_verify")) {
+            if (noVerify == NULL) {
+                continue;
+            }
+            if (virStrToLong_i(queryParam->value, NULL, 10, noVerify) < 0 ||
+                (*noVerify != 0 && *noVerify != 1)) {
+                xenapiSessionErrorHandler(conn, VIR_ERR_INVALID_ARG,
+                           "Query parameter 'no_verify' has unexpected value (should be 0 or 1)");
+                goto failure;
+            }
+        }
+    }
+
+  cleanup:
+    if (queryParamSet != NULL) {
+        free_qparam_set(queryParamSet);
+    }
+
+    return result;
+
+  failure:
+    result = -1;
+
+    goto cleanup;
+}
+
+
+
+enum xen_on_normal_exit
+actionShutdownLibvirt2XenapiEnum(enum virDomainLifecycleAction action)
+{
+    enum xen_on_normal_exit num = XEN_ON_NORMAL_EXIT_RESTART;
+    if (action == VIR_DOMAIN_LIFECYCLE_DESTROY)
+        num = XEN_ON_NORMAL_EXIT_DESTROY;
+    else if (action == VIR_DOMAIN_LIFECYCLE_RESTART)
+        num = XEN_ON_NORMAL_EXIT_RESTART;
+    return num;
+}
+
+
+enum xen_on_crash_behaviour
+actionCrashLibvirt2XenapiEnum(enum virDomainLifecycleAction action)
+{
+    enum xen_on_crash_behaviour num = XEN_ON_CRASH_BEHAVIOUR_RESTART;
+    if (action == VIR_DOMAIN_LIFECYCLE_DESTROY)
+        num = XEN_ON_CRASH_BEHAVIOUR_DESTROY;
+    else if (action == VIR_DOMAIN_LIFECYCLE_RESTART)
+        num = XEN_ON_CRASH_BEHAVIOUR_RESTART;
+    else if (action == VIR_DOMAIN_LIFECYCLE_PRESERVE)
+        num = XEN_ON_CRASH_BEHAVIOUR_PRESERVE;
+    else if (action == VIR_DOMAIN_LIFECYCLE_RESTART_RENAME)
+        num = XEN_ON_CRASH_BEHAVIOUR_RENAME_RESTART;
+    return num;
+}
+
+/* generate XenAPI boot order format from libvirt format */
+char *
+createXenAPIBootOrderString(int nboot, int *bootDevs)
+{
+    virBuffer ret = VIR_BUFFER_INITIALIZER;
+    char *val = NULL;
+    int i;
+    for (i = 0; i < nboot; i++) {
+        if (bootDevs[i] == VIR_DOMAIN_BOOT_FLOPPY)
+            val = (char *)"a";
+        else if (bootDevs[i] == VIR_DOMAIN_BOOT_DISK)
+            val = (char *)"c";
+        else if (bootDevs[i] == VIR_DOMAIN_BOOT_CDROM)
+            val = (char *)"d";
+        else if (bootDevs[i] == VIR_DOMAIN_BOOT_NET)
+            val = (char *)"n";
+        if (val)
+            virBufferEscapeString(&ret,"%s",val);
+    }
+    return virBufferContentAndReset(&ret);
+}
+
+/* convert boot order string to libvirt boot order enum */
+enum virDomainBootOrder
+map2LibvirtBootOrder(char c) {
+    switch (c) {
+    case 'a':
+        return VIR_DOMAIN_BOOT_FLOPPY;
+    case 'c':
+        return VIR_DOMAIN_BOOT_DISK;
+    case 'd':
+        return VIR_DOMAIN_BOOT_CDROM;
+    case 'n':
+        return VIR_DOMAIN_BOOT_NET;
+    default:
+        return -1;
+    }
+}
+
+enum virDomainLifecycleAction
+xenapiNormalExitEnum2virDomainLifecycle(enum xen_on_normal_exit action)
+{
+    enum virDomainLifecycleAction num = VIR_DOMAIN_LIFECYCLE_RESTART;
+    if (action == XEN_ON_NORMAL_EXIT_DESTROY)
+        num = VIR_DOMAIN_LIFECYCLE_DESTROY;
+    else if (action == XEN_ON_NORMAL_EXIT_RESTART)
+        num = VIR_DOMAIN_LIFECYCLE_RESTART;
+    return num;
+}
+
+
+enum virDomainLifecycleAction
+xenapiCrashExitEnum2virDomainLifecycle(enum xen_on_crash_behaviour action)
+{
+    enum virDomainLifecycleAction num = VIR_DOMAIN_LIFECYCLE_RESTART;
+    if (action == XEN_ON_CRASH_BEHAVIOUR_DESTROY)
+        num = VIR_DOMAIN_LIFECYCLE_DESTROY;
+    else if (action == XEN_ON_CRASH_BEHAVIOUR_RESTART)
+        num = VIR_DOMAIN_LIFECYCLE_RESTART;
+    else if (action == XEN_ON_CRASH_BEHAVIOUR_PRESERVE)
+        num = VIR_DOMAIN_LIFECYCLE_PRESERVE;
+    else if (action == XEN_ON_CRASH_BEHAVIOUR_RENAME_RESTART)
+        num = VIR_DOMAIN_LIFECYCLE_RESTART_RENAME;
+    return num;
+}
+
+
+
+/* returns 'file' or 'block' for the storage type */
+int
+getStorageVolumeType(char *type)
+{
+    if (STREQ(type,"lvmoiscsi") ||
+        STREQ(type,"lvmohba") ||
+        STREQ(type,"lvm") ||
+        STREQ(type,"file") ||
+        STREQ(type,"iso") ||
+        STREQ(type,"ext") ||
+        STREQ(type,"nfs"))
+        return (int)VIR_STORAGE_VOL_FILE;
+    else if (STREQ(type,"iscsi") ||
+             STREQ(type,"equal") ||
+             STREQ(type,"hba") ||
+             STREQ(type,"cslg") ||
+             STREQ(type,"udev") ||
+             STREQ(type,"netapp"))
+        return (int)VIR_STORAGE_VOL_BLOCK;
+    return -1;
+}
+
+/* returns error description if any received from the server */
+char *
+returnErrorFromSession(xen_session *session)
+{
+    int i;
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    for (i = 0; i < session->error_description_count - 1; i++) {
+        if (!i)
+            virBufferEscapeString(&buf, "%s", session->error_description[i]);
+        else
+            virBufferEscapeString(&buf, " : %s", session->error_description[i]);
+    }
+    return virBufferContentAndReset(&buf);
+}
+
+/* converts bitmap to string of the form '1,2...' */
+char *
+mapDomainPinVcpu(unsigned char *cpumap, int maplen)
+{
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    size_t len;
+    char *ret = NULL;
+    int i, j;
+    for (i = 0; i < maplen; i++) {
+        for (j = 0; j < 8; j++) {
+            if (cpumap[i] & (1 << j)) {
+                virBufferVSprintf(&buf, "%d,", (8*i)+j);
+            }
+        }
+    }
+    if (virBufferError(&buf)) {
+        virReportOOMError();
+        virBufferFreeAndReset(&buf);
+        return NULL;
+    }
+    ret = virBufferContentAndReset(&buf);
+    len = strlen(ret);
+    if (len > 0 && ret[len - 1] == ',')
+        ret[len - 1] = 0;
+    return ret;
+}
+
+/* obtains the CPU bitmap from the string passed */
+void
+getCpuBitMapfromString(char *mask, unsigned char *cpumap, int maplen)
+{
+    int pos;
+    int max_bits = maplen * 8;
+    char *num = NULL, *bp = NULL;
+    bzero(cpumap, maplen);
+    num = strtok_r(mask, ",", &bp);
+    while (num != NULL) {
+        if (sscanf(num, "%d", &pos) != 1)
+            return;
+        if (pos < 0 || pos > max_bits - 1)
+            VIR_WARN ("number in str %d exceeds cpumap's max bits %d", pos, max_bits);
+        else
+            (cpumap)[pos / 8] |= (1 << (pos % 8));
+        num = strtok_r(NULL, ",", &bp);
+    }
+}
+
+
+/* mapping XenServer power state to Libvirt power state */
+virDomainState
+mapPowerState(enum xen_vm_power_state state)
+{
+    virDomainState virState;
+    switch (state) {
+    case XEN_VM_POWER_STATE_HALTED:
+    case XEN_VM_POWER_STATE_SUSPENDED:
+        virState = VIR_DOMAIN_SHUTOFF;
+        break;
+    case XEN_VM_POWER_STATE_PAUSED:
+        virState = VIR_DOMAIN_PAUSED;
+        break;
+    case XEN_VM_POWER_STATE_RUNNING:
+        virState = VIR_DOMAIN_RUNNING;
+        break;
+    case XEN_VM_POWER_STATE_UNKNOWN:
+    case XEN_VM_POWER_STATE_UNDEFINED:
+        virState = VIR_DOMAIN_NOSTATE;
+        break;
+    default:
+        virState = VIR_DOMAIN_NOSTATE;
+        break;
+    }
+    return virState;
+}
+
+/* allocate a flexible array and fill values(key,val) */
+int
+allocStringMap (xen_string_string_map **strings, char *key, char *val)
+{
+    int sz = ((*strings) == NULL) ? 0 : (*strings)->size;
+    sz++;
+    if (VIR_REALLOC_N(*strings, sizeof(xen_string_string_map) +
+                                sizeof(xen_string_string_map_contents) * sz) < 0) {
+        virReportOOMError();
+        return -1;
+    }
+    (*strings)->size = sz;
+    if (!((*strings)->contents[sz-1].key = strdup(key))) goto error;
+    if (!((*strings)->contents[sz-1].val = strdup(val))) goto error;
+    return 0;
+  error:
+    xen_string_string_map_free(*strings);
+    virReportOOMError();
+    return -1;
+}
+
+/* Error handling function returns error messages from the server if any */
+void
+xenapiSessionErrorHandle(virConnectPtr conn, virErrorNumber errNum,
+                         const char *buf, const char *filename, const char *func,
+                         size_t lineno)
+{
+    xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session;
+
+    if (buf == NULL) {
+        char *ret = returnErrorFromSession(session);
+        virReportErrorHelper(conn, VIR_FROM_XENAPI, errNum, filename, func, lineno, _("%s"), ret);
+        xen_session_clear_error(session);
+        VIR_FREE(ret);
+    } else {
+        virReportErrorHelper(conn, VIR_FROM_XENAPI, errNum, filename, func, lineno, _("%s"), buf);
+    }
+}
+
+/* creates network intereface for VM */
+int
+createVifNetwork (virConnectPtr conn, xen_vm vm, char *device,
+                  char *bridge, char *mac)
+{
+    xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session;
+    xen_vm xvm = NULL;
+    char *uuid = NULL;
+    xen_vm_get_uuid(session, &uuid, vm);
+    if (uuid) {
+        if (!xen_vm_get_by_uuid(session, &xvm, uuid))
+            return -1;
+        VIR_FREE(uuid);
+    }
+    xen_vm_record_opt *vm_opt = xen_vm_record_opt_alloc();
+    vm_opt->is_record = 0;
+    vm_opt->u.handle = xvm;
+    xen_network_set *net_set = NULL;
+    xen_network_record *net_rec = NULL;
+    int cnt;
+    if (xen_network_get_all(session, &net_set)) {
+        for(cnt = 0; cnt < net_set->size; cnt++) {
+            if (xen_network_get_record(session, &net_rec, net_set->contents[cnt])) {
+                if (STREQ(net_rec->bridge, bridge)) {
+                    break;
+                } else {
+                    xen_network_record_free(net_rec);
+                }
+            }
+        }
+    }
+    if (cnt < net_set->size && net_rec) {
+        xen_network network = NULL;
+        xen_network_get_by_uuid(session, &network, net_rec->uuid);
+        xen_network_record_opt *network_opt = xen_network_record_opt_alloc();
+        network_opt->is_record = 0;
+        network_opt->u.handle = network;
+        xen_vif_record *vif_record = xen_vif_record_alloc();
+        vif_record->mac = mac;
+        vif_record->vm = vm_opt;
+        vif_record->network = network_opt;
+        xen_vif vif = NULL;
+
+        vif_record->other_config = xen_string_string_map_alloc(0);
+        vif_record->runtime_properties = xen_string_string_map_alloc(0);
+        vif_record->qos_algorithm_params = xen_string_string_map_alloc(0);
+        vif_record->device = strdup(device);
+        xen_vif_create(session, &vif, vif_record);
+        if (!vif) {
+            xen_vif_free(vif);
+            xen_vif_record_free(vif_record);
+            xen_network_record_free(net_rec);
+            xen_network_set_free(net_set);
+            return 0;
+        }
+        xen_vif_record_free(vif_record);
+        xen_network_record_free(net_rec);
+    }
+    if (net_set != NULL) xen_network_set_free(net_set);
+    return -1;
+}
+
+/* Create a VM record from the XML description */
+int
+createVMRecordFromXml (virConnectPtr conn, virDomainDefPtr def,
+                       xen_vm_record **record, xen_vm *vm)
+{
+    char uuidStr[VIR_UUID_STRING_BUFLEN];
+    *record = xen_vm_record_alloc();
+    if (!((*record)->name_label = strdup(def->name)))
+        goto error_cleanup;
+    if (def->uuid) {
+        virUUIDFormat(def->uuid, uuidStr);
+        if (!((*record)->uuid = strdup(uuidStr)))
+            goto error_cleanup;
+    }
+    if (STREQ(def->os.type, "hvm")) {
+        char *boot_order = NULL;
+        if (!((*record)->hvm_boot_policy = strdup("BIOS order")))
+            goto error_cleanup;
+        if (def->os.nBootDevs != 0)
+            boot_order = createXenAPIBootOrderString(def->os.nBootDevs, &def->os.bootDevs[0]);
+        if (boot_order != NULL) {
+            xen_string_string_map *hvm_boot_params = NULL;
+            allocStringMap(&hvm_boot_params, (char *)"order", boot_order);
+            (*record)->hvm_boot_params = hvm_boot_params;
+            VIR_FREE(boot_order);
+        }
+    } else if (STREQ(def->os.type, "xen")) {
+        if (!((*record)->pv_bootloader = strdup("pygrub")))
+            goto error_cleanup;
+        if (def->os.kernel) {
+            if (!((*record)->pv_kernel = strdup(def->os.kernel)))
+                goto error_cleanup;
+        }
+        if (def->os.initrd) {
+            if (!((*record)->pv_ramdisk = strdup(def->os.initrd)))
+                goto error_cleanup;
+        }
+        if (def->os.cmdline) {
+            if (!((*record)->pv_args = strdup(def->os.cmdline)))
+                goto error_cleanup;
+        }
+        (*record)->hvm_boot_params = xen_string_string_map_alloc(0);
+    }
+    if (def->os.bootloaderArgs)
+        if (!((*record)->pv_bootloader_args = strdup(def->os.bootloaderArgs)))
+            goto error_cleanup;
+
+    if (def->memory)
+        (*record)->memory_static_max = (int64_t) (def->memory * 1024);
+    if (def->maxmem)
+        (*record)->memory_dynamic_max = (int64_t) (def->maxmem * 1024);
+    else
+        (*record)->memory_dynamic_max = (*record)->memory_static_max;
+
+    if (def->vcpus) {
+        (*record)->vcpus_max = (int64_t) def->vcpus;
+        (*record)->vcpus_at_startup = (int64_t) def->vcpus;
+    }
+    if (def->onPoweroff)
+        (*record)->actions_after_shutdown = actionShutdownLibvirt2XenapiEnum(def->onPoweroff);
+    if (def->onReboot)
+        (*record)->actions_after_reboot = actionShutdownLibvirt2XenapiEnum(def->onReboot);
+    if (def->onCrash)
+        (*record)->actions_after_crash = actionCrashLibvirt2XenapiEnum(def->onCrash);
+
+    xen_string_string_map *strings = NULL;
+    if (def->features) {
+        if (def->features & (1 << VIR_DOMAIN_FEATURE_ACPI))
+            allocStringMap(&strings, (char *)"acpi", (char *)"true");
+        if (def->features & (1 << VIR_DOMAIN_FEATURE_APIC))
+            allocStringMap(&strings, (char *)"apic", (char *)"true");
+        if (def->features & (1 << VIR_DOMAIN_FEATURE_PAE))
+            allocStringMap(&strings, (char *)"pae", (char *)"true");
+    }
+    if (strings != NULL)
+        (*record)->platform = strings;
+
+    (*record)->vcpus_params = xen_string_string_map_alloc(0);
+    (*record)->other_config = xen_string_string_map_alloc(0);
+    (*record)->last_boot_cpu_flags = xen_string_string_map_alloc(0);
+    (*record)->xenstore_data = xen_string_string_map_alloc(0);
+    (*record)->hvm_shadow_multiplier = 1.000;
+    if (!xen_vm_create(((struct _xenapiPrivate *)(conn->privateData))->session,
+                        vm, *record)) {
+        xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL);
+        return -1;
+    }
+
+    int device_number = 0;
+    char *bridge = NULL, *mac = NULL;
+    int i;
+    for (i = 0; i < def->nnets; i++) {
+        if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
+            if (def->nets[i]->data.bridge.brname)
+                if (!(bridge = strdup(def->nets[i]->data.bridge.brname)))
+                    goto error_cleanup;
+            if (def->nets[i]->mac) {
+                char macStr[VIR_MAC_STRING_BUFLEN];
+                virFormatMacAddr(def->nets[i]->mac, macStr);
+                if (!(mac = strdup(macStr))) {
+                    if (bridge) VIR_FREE(bridge);
+                    goto error_cleanup;
+                }
+            }
+            if (mac != NULL && bridge != NULL) {
+                char device[NETWORK_DEVID_SIZE] = "\0";
+                sprintf(device, "%d", device_number);
+                createVifNetwork(conn, *vm, device, bridge, mac);
+                VIR_FREE(bridge);
+                device_number++;
+            }
+            if (bridge) VIR_FREE(bridge);
+        }
+    }
+    return 0;
+
+  error_cleanup:
+    virReportOOMError();
+    xen_vm_record_free(*record);
+    return -1;
+}
diff --git a/src/xenapi/xenapi_utils.h b/src/xenapi/xenapi_utils.h
new file mode 100644 (file)
index 0000000..c062a1e
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * xenapi_utils.h: Xen API driver -- utils header
+ * Copyright (C) 2009, 2010 Citrix Ltd.
+ *
+ * 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
+ *
+ * Author: Sharadha Prabhakar <sharadha.prabhakar@citrix.com>
+ */
+
+#ifndef __VIR_XENAPI_UTILS__
+# define __VIR_XENAPI_UTILS__
+
+# include <stdint.h>
+# include <libxml/uri.h>
+# include <xen/api/xen_all.h>
+# include "internal.h"
+# include "domain_conf.h"
+
+# define NETWORK_DEVID_SIZE  (12)
+
+typedef uint64_t cpumap_t;
+
+void
+xenSessionFree(xen_session *session);
+
+char *
+xenapiUtil_RequestPassword(virConnectAuthPtr auth, const char *username,
+                           const char *hostname);
+
+int
+xenapiUtil_ParseQuery(virConnectPtr conn, xmlURIPtr uri, int *noVerify);
+
+enum xen_on_normal_exit
+actionShutdownLibvirt2XenapiEnum(enum virDomainLifecycleAction action);
+
+enum xen_on_crash_behaviour
+actionCrashLibvirt2XenapiEnum(enum virDomainLifecycleAction action);
+
+char *
+createXenAPIBootOrderString(int nboot, int *bootDevs);
+
+enum virDomainBootOrder map2LibvirtBootOrder(char c);
+
+enum virDomainLifecycleAction
+xenapiNormalExitEnum2virDomainLifecycle(enum xen_on_normal_exit action);
+
+enum virDomainLifecycleAction
+xenapiCrashExitEnum2virDomainLifecycle(enum xen_on_crash_behaviour action);
+
+void getCpuBitMapfromString(char *mask, unsigned char *cpumap, int maplen);
+
+int getStorageVolumeType(char *type);
+
+char *returnErrorFromSession(xen_session *session);
+
+virDomainState
+mapPowerState(enum xen_vm_power_state state);
+
+char *
+mapDomainPinVcpu(unsigned char *cpumap, int maplen);
+
+int
+createVMRecordFromXml (virConnectPtr conn, virDomainDefPtr defPtr,
+                       xen_vm_record **record, xen_vm *vm);
+
+int
+allocStringMap (xen_string_string_map **strings, char *key, char *val);
+
+int
+createVifNetwork(virConnectPtr conn, xen_vm vm, char *device,
+                 char *bridge, char *mac);
+
+#endif /* __VIR_XENAPI_UTILS__ */