]> xenbits.xensource.com Git - libvirt.git/commitdiff
Move xen driver code into src/xen/ directory
authorDaniel P. Berrange <berrange@redhat.com>
Tue, 15 Sep 2009 15:38:33 +0000 (16:38 +0100)
committerDaniel P. Berrange <berrange@redhat.com>
Mon, 21 Sep 2009 13:41:42 +0000 (14:41 +0100)
* src/Makefile.am, src/proxy_internal.c, src/proxy_internal.h
  src/sexpr.c, src/sexpr.h, src/xen_unified.c, src/xen_unified.h,
  src/xen_internal.c, src/xen_internal.h, src/xen_inotify.c,
  src/xen_inotify.h, src/xend_internal.c, src/xend_internal.h,
  src/xm_internal.c, src/xm_internal.h, src/xs_internal.c,
  src/xs_internal.h: Move to src/xen/ directory
* proxy/Makefile.am, proxy/libvirt_proxy.c, src/Makefile.am,
  src/libvirt.c, tests/sexpr2xmltest.c, tests/statstest.c,
  tests/xencapstest.c, tests/xmconfigtest.c, tests/xml2sexprtest.c:
  Adapt to changed xen location
* src/stats_linux.h, src/stats_linux.c: Remove xen specific block
  stats APIs
* src/qemu_driver.c, src/uml_driver.c: Add missing sys/un.h include
  uncovered after change to stats_linux.h
* src/xen/block_stats.h, src/xen/block_stats.c: Add xen specific
  block stats APIs

47 files changed:
proxy/Makefile.am
proxy/libvirt_proxy.c
src/Makefile.am
src/libvirt.c
src/proxy_internal.c [deleted file]
src/proxy_internal.h [deleted file]
src/qemu_driver.c
src/sexpr.c [deleted file]
src/sexpr.h [deleted file]
src/stats_linux.c
src/stats_linux.h
src/uml_driver.c
src/xen/block_stats.c [new file with mode: 0644]
src/xen/block_stats.h [new file with mode: 0644]
src/xen/proxy_internal.c [new file with mode: 0644]
src/xen/proxy_internal.h [new file with mode: 0644]
src/xen/sexpr.c [new file with mode: 0644]
src/xen/sexpr.h [new file with mode: 0644]
src/xen/xen_driver.c [new file with mode: 0644]
src/xen/xen_driver.h [new file with mode: 0644]
src/xen/xen_hypervisor.c [new file with mode: 0644]
src/xen/xen_hypervisor.h [new file with mode: 0644]
src/xen/xen_inotify.c [new file with mode: 0644]
src/xen/xen_inotify.h [new file with mode: 0644]
src/xen/xend_internal.c [new file with mode: 0644]
src/xen/xend_internal.h [new file with mode: 0644]
src/xen/xm_internal.c [new file with mode: 0644]
src/xen/xm_internal.h [new file with mode: 0644]
src/xen/xs_internal.c [new file with mode: 0644]
src/xen/xs_internal.h [new file with mode: 0644]
src/xen_inotify.c [deleted file]
src/xen_inotify.h [deleted file]
src/xen_internal.c [deleted file]
src/xen_internal.h [deleted file]
src/xen_unified.c [deleted file]
src/xen_unified.h [deleted file]
src/xend_internal.c [deleted file]
src/xend_internal.h [deleted file]
src/xm_internal.c [deleted file]
src/xm_internal.h [deleted file]
src/xs_internal.c [deleted file]
src/xs_internal.h [deleted file]
tests/sexpr2xmltest.c
tests/statstest.c
tests/xencapstest.c
tests/xmconfigtest.c
tests/xml2sexprtest.c

index 48678c3bab956fc5d18b1161fb7d217738b79b47..e92333ae1050a8ac0558935db2945d0d71f7d1da 100644 (file)
@@ -3,17 +3,17 @@
 if WITH_PROXY
 INCLUDES = -I$(top_srcdir)/gnulib/lib -I../gnulib/lib \
            -I$(top_builddir)/include -I@top_srcdir@/include \
-          -I@top_srcdir@/proxy -I@top_srcdir@/src @LIBXML_CFLAGS@ \
+          -I@top_srcdir@/proxy -I@top_srcdir@/src -I@top_srcdir@/src/xen @LIBXML_CFLAGS@ \
           -DPROXY  -DLOCALEBASEDIR=\""$(datadir)/locale"\" \
            -DGETTEXT_PACKAGE=\"$(PACKAGE)\" $(WARN_CFLAGS) $(XEN_CFLAGS)
 
 libexec_PROGRAMS = libvirt_proxy
 
-libvirt_proxy_SOURCES = libvirt_proxy.c @top_srcdir@/src/xend_internal.c \
-           @top_srcdir@/src/xen_internal.c @top_srcdir@/src/virterror.c \
-           @top_srcdir@/src/sexpr.c  \
+libvirt_proxy_SOURCES = libvirt_proxy.c @top_srcdir@/src/xen/xend_internal.c \
+           @top_srcdir@/src/xen/xen_hypervisor.c @top_srcdir@/src/virterror.c \
+           @top_srcdir@/src/xen/sexpr.c  \
            @top_srcdir@/src/threads.c  \
-            @top_srcdir@/src/xs_internal.c @top_srcdir@/src/buf.c \
+            @top_srcdir@/src/xen/xs_internal.c @top_srcdir@/src/buf.c \
             @top_srcdir@/src/capabilities.c \
             @top_srcdir@/src/memory.c \
             @top_srcdir@/src/storage_encryption_conf.c \
index e008a7f4be107c4fc728dbbed372099d87b23a3e..aa20d2850feae9176f5cc6b6ba8a308518756359 100644 (file)
 #include "datatypes.h"
 #include "proxy_internal.h"
 #include "util.h"
-#include "xen_internal.h"
+#include "xen_hypervisor.h"
 #include "xend_internal.h"
 #include "xs_internal.h"
-#include "xen_unified.h"
+#include "xen_driver.h"
 
 static int fdServer = -1;
 static int debug = 0;
index b1d01ba42fc2ca2ad52fbdc3cab1416e8ee7045b..52f0c24bf8ab59a2f1d86695c791a6bb91b3db9c 100644 (file)
@@ -7,7 +7,6 @@ INCLUDES = \
           -I@top_srcdir@/daemon \
           $(LIBXML_CFLAGS) \
           $(LIBSSH2_CFLAGS) \
-          $(XEN_CFLAGS) \
           $(SELINUX_CFLAGS) \
           $(DRIVER_MODULE_CFLAGS) \
           -DLIBDIR=\""$(libdir)"\" \
@@ -111,15 +110,16 @@ TEST_DRIVER_SOURCES =                                             \
 
 # Now the Hypervisor specific drivers
 XEN_DRIVER_SOURCES =                                           \
-               proxy_internal.c proxy_internal.h               \
-               sexpr.c sexpr.h                                 \
-               xen_internal.c xen_internal.h                   \
-               xen_unified.c xen_unified.h                     \
-               xend_internal.c xend_internal.h                 \
-               xm_internal.c xm_internal.h                     \
-               xs_internal.c xs_internal.h
+               xen/proxy_internal.c xen/proxy_internal.h       \
+               xen/sexpr.c xen/sexpr.h                         \
+               xen/block_stats.c xen/block_stats.h             \
+               xen/xen_hypervisor.c xen/xen_hypervisor.h       \
+               xen/xen_driver.c xen/xen_driver.h               \
+               xen/xend_internal.c xen/xend_internal.h         \
+               xen/xm_internal.c xen/xm_internal.h             \
+               xen/xs_internal.c xen/xs_internal.h
 if WITH_XEN_INOTIFY
-XEN_DRIVER_SOURCES += xen_inotify.c xen_inotify.h
+XEN_DRIVER_SOURCES += xen/xen_inotify.c xen/xen_inotify.h
 endif
 
 LXC_DRIVER_SOURCES =                                           \
@@ -261,8 +261,8 @@ libvirt_driver_la_SOURCES =                                 \
                $(NODE_DEVICE_CONF_SOURCES)                     \
                $(SECRET_CONF_SOURCES)
 
-libvirt_driver_la_CFLAGS = $(XEN_CFLAGS) $(NUMACTL_CFLAGS)
-libvirt_driver_la_LDFLAGS = $(XEN_LIBS) $(NUMACTL_LIBS)
+libvirt_driver_la_CFLAGS = $(NUMACTL_CFLAGS)
+libvirt_driver_la_LDFLAGS = $(NUMACTL_LIBS)
 
 USED_SYM_FILES = libvirt_private.syms
 
index 4a11688312021f7a635f3e38f349cd1affdb39e7..1139d8bc8f8fad370421d44b16a3a658b1d927bf 100644 (file)
@@ -47,7 +47,7 @@
 #include "test.h"
 #endif
 #ifdef WITH_XEN
-#include "xen_unified.h"
+#include "xen/xen_driver.h"
 #endif
 #ifdef WITH_REMOTE
 #include "remote_internal.h"
diff --git a/src/proxy_internal.c b/src/proxy_internal.c
deleted file mode 100644 (file)
index 5b92ad8..0000000
+++ /dev/null
@@ -1,1049 +0,0 @@
-/*
- * proxy_client.c: client side of the communication with the libvirt proxy.
- *
- * Copyright (C) 2006, 2008, 2009 Red Hat, Inc.
- *
- * See COPYING.LIB for the License of this software
- *
- * Daniel Veillard <veillard@redhat.com>
- */
-
-#include <config.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/poll.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/wait.h>
-#include <string.h>
-
-#include "virterror_internal.h"
-#include "logging.h"
-#include "datatypes.h"
-#include "driver.h"
-#include "proxy_internal.h"
-#include "util.h"
-#include "xen_unified.h"
-#include "memory.h"
-
-#define STANDALONE
-
-#define VIR_FROM_THIS VIR_FROM_PROXY
-
-static int xenProxyClose(virConnectPtr conn);
-static virDrvOpenStatus xenProxyOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags);
-static int xenProxyGetVersion(virConnectPtr conn, unsigned long *hvVer);
-static int xenProxyNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info);
-static char *xenProxyGetCapabilities(virConnectPtr conn);
-static int xenProxyNumOfDomains(virConnectPtr conn);
-static unsigned long xenProxyDomainGetMaxMemory(virDomainPtr domain);
-static int xenProxyDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info);
-static char *xenProxyDomainGetOSType(virDomainPtr domain);
-
-struct xenUnifiedDriver xenProxyDriver = {
-    xenProxyOpen, /* open */
-    xenProxyClose, /* close */
-    xenProxyGetVersion, /* version */
-    NULL, /* hostname */
-    xenProxyNodeGetInfo, /* nodeGetInfo */
-    xenProxyGetCapabilities, /* getCapabilities */
-    xenProxyListDomains, /* listDomains */
-    xenProxyNumOfDomains, /* numOfDomains */
-    NULL, /* domainCreateXML */
-    NULL, /* domainSuspend */
-    NULL, /* domainResume */
-    NULL, /* domainShutdown */
-    NULL, /* domainReboot */
-    NULL, /* domainDestroy */
-    xenProxyDomainGetOSType, /* domainGetOSType */
-    xenProxyDomainGetMaxMemory, /* domainGetMaxMemory */
-    NULL, /* domainSetMaxMemory */
-    NULL, /* domainSetMemory */
-    xenProxyDomainGetInfo, /* domainGetInfo */
-    NULL, /* domainSave */
-    NULL, /* domainRestore */
-    NULL, /* domainCoreDump */
-    NULL, /* domainSetVcpus */
-    NULL, /* domainPinVcpu */
-    NULL, /* domainGetVcpus */
-    NULL, /* domainGetMaxVcpus */
-    NULL, /* listDefinedDomains */
-    NULL, /* numOfDefinedDomains */
-    NULL, /* domainCreate */
-    NULL, /* domainDefineXML */
-    NULL, /* domainUndefine */
-    NULL, /* domainAttachDevice */
-    NULL, /* domainDetachDevice */
-    NULL, /* domainGetAutostart */
-    NULL, /* domainSetAutostart */
-    NULL, /* domainGetSchedulerType */
-    NULL, /* domainGetSchedulerParameters */
-    NULL, /* domainSetSchedulerParameters */
-};
-
-
-/************************************************************************
- *                                                                     *
- *                     Error handling                                  *
- *                                                                     *
- ************************************************************************/
-
-#define virProxyError(conn, code, fmt...)                                    \
-        virReportErrorHelper(conn, VIR_FROM_PROXY, code, __FILE__,         \
-                               __FUNCTION__, __LINE__, fmt)
-
-/************************************************************************
- *                                                                     *
- *     Automatic startup of the proxy server if it is not running      *
- *                                                                     *
- ************************************************************************/
-/**
- * virProxyFindServerPath:
- *
- * Tries to find the path to the gam_server binary.
- *
- * Returns path on success or NULL in case of error.
- */
-static const char *
-virProxyFindServerPath(void)
-{
-    static const char *serverPaths[] = {
-        BINDIR "/libvirt_proxy",
-        "/usr/bin/libvirt_proxy_dbg",
-        NULL
-    };
-    int i;
-    const char *debugProxy = getenv("LIBVIRT_DEBUG_PROXY");
-
-    if (debugProxy)
-        return(debugProxy);
-
-    for (i = 0; serverPaths[i]; i++) {
-        if (access(serverPaths[i], X_OK | R_OK) == 0) {
-            return serverPaths[i];
-        }
-    }
-    return NULL;
-}
-
-/**
- * virProxyForkServer:
- *
- * Forks and try to launch the proxy server processing the requests for
- * libvirt when communicating with Xen.
- *
- * Returns 0 in case of success or -1 in case of detected error.
- */
-static int
-virProxyForkServer(void)
-{
-    const char *proxyPath = virProxyFindServerPath();
-    pid_t pid;
-    const char *proxyarg[2];
-
-    if (!proxyPath) {
-        VIR_WARN0("failed to find libvirt_proxy\n");
-        return(-1);
-    }
-
-    VIR_DEBUG("Asking to launch %s\n", proxyPath);
-
-    proxyarg[0] = proxyPath;
-    proxyarg[1] = NULL;
-
-    if (virExecDaemonize(NULL, proxyarg, NULL, NULL,
-                         &pid, -1, NULL, NULL, 0,
-                         NULL, NULL, NULL) < 0)
-        VIR_ERROR0("Failed to fork libvirt_proxy\n");
-
-    return (0);
-}
-
-/************************************************************************
- *                                                                     *
- *             Processing of client sockets                            *
- *                                                                     *
- ************************************************************************/
-
-/**
- * virProxyOpenClientSocket:
- * @path: the filename for the socket
- *
- * try to connect to the socket open by libvirt_proxy
- *
- * Returns the associated file descriptor or -1 in case of failure
- */
-static int
-virProxyOpenClientSocket(const char *path) {
-    int fd;
-    struct sockaddr_un addr;
-    int trials = 0;
-
-retry:
-    fd = socket(PF_UNIX, SOCK_STREAM, 0);
-    if (fd < 0) {
-        return(-1);
-    }
-
-    /*
-     * Abstract socket do not hit the filesystem, way more secure and
-     * guaranteed to be atomic
-     */
-    memset(&addr, 0, sizeof(addr));
-    addr.sun_family = AF_UNIX;
-    addr.sun_path[0] = '\0';
-    strncpy(&addr.sun_path[1], path, (sizeof(addr) - 4) - 2);
-
-    /*
-     * now bind the socket to that address and listen on it
-     */
-    if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-        close(fd);
-        if (trials < 3) {
-            if (virProxyForkServer() < 0)
-                return(-1);
-            trials++;
-            usleep(5000 * trials * trials);
-            goto retry;
-        }
-        return (-1);
-    }
-
-    DEBUG("connected to unix socket %s via %d\n", path, fd);
-
-    return (fd);
-}
-
-/**
- * virProxyCloseSocket:
- * @priv: the Xen proxy data
- *
- * Close the socket from that client. The caller must
- * hold the lock on 'priv' before calling
- *
- * Returns 0 in case of success and -1 in case of error
- */
-static int
-virProxyCloseSocket(xenUnifiedPrivatePtr priv) {
-    int ret;
-
-    if (priv->proxy < 0)
-        return(-1);
-
-    ret = close(priv->proxy);
-    if (ret != 0)
-        VIR_WARN(_("Failed to close socket %d\n"), priv->proxy);
-    else
-        VIR_DEBUG("Closed socket %d\n", priv->proxy);
-    priv->proxy = -1;
-    return(ret);
-}
-
-/**
- * virProxyReadClientSocket:
- * @fd: the socket
- * @buffer: the target memory area
- * @len: the length in bytes
- *
- * Process a read from a client socket
- *
- * Returns the number of byte read or -1 in case of error.
- */
-static int
-virProxyReadClientSocket(int fd, char *buffer, int len) {
-    int ret;
-
-    if ((fd < 0) || (buffer == NULL) || (len < 0))
-        return(-1);
-
-retry:
-    ret = read(fd, buffer, len);
-    if (ret < 0) {
-        if (errno == EINTR) {
-            VIR_DEBUG("read socket %d interrupted\n", fd);
-            goto retry;
-        }
-        VIR_WARN("Failed to read socket %d\n", fd);
-        return(-1);
-    }
-
-    VIR_DEBUG("read %d bytes from socket %d\n",
-              ret, fd);
-    return(ret);
-}
-
-/**
- * virProxyWriteClientSocket:
- * @fd: the socket
- * @data: the data
- * @len: the length of data in bytes
- *
- * Process a read from a client socket
- */
-static int
-virProxyWriteClientSocket(int fd, const char *data, int len) {
-    int ret;
-
-    if ((fd < 0) || (data == NULL) || (len < 0))
-        return(-1);
-
-    ret = safewrite(fd, data, len);
-    if (ret < 0) {
-        VIR_WARN(_("Failed to write to socket %d\n"), fd);
-        return(-1);
-    }
-    VIR_DEBUG("wrote %d bytes to socket %d\n",
-              len, fd);
-
-    return(0);
-}
-
-/************************************************************************
- *                                                                     *
- *                     Proxy commands processing                       *
- *                                                                     *
- ************************************************************************/
-
-/**
- * xenProxyClose:
- * @conn: pointer to the hypervisor connection
- *
- * Shutdown the Xen proxy communication layer
- */
-static int
-xenProxyClose(virConnectPtr conn)
-{
-    xenUnifiedPrivatePtr priv;
-
-    if (conn == NULL) {
-        virProxyError (NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return -1;
-    }
-
-    priv = (xenUnifiedPrivatePtr) conn->privateData;
-    if (!priv) {
-        virProxyError (NULL, VIR_ERR_INTERNAL_ERROR, __FUNCTION__);
-        return -1;
-    }
-
-    xenUnifiedLock(priv);
-    virProxyCloseSocket (priv);
-    xenUnifiedUnlock(priv);
-
-    return 0;
-}
-
-static int
-xenProxyCommand(virConnectPtr conn, virProxyPacketPtr request,
-                virProxyFullPacketPtr answer, int quiet) {
-    static int serial = 0;
-    int ret;
-    virProxyPacketPtr res = NULL;
-    xenUnifiedPrivatePtr priv;
-
-    if (conn == NULL) {
-        virProxyError (NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return -1;
-    }
-
-    priv = (xenUnifiedPrivatePtr) conn->privateData;
-    if (!priv) {
-        virProxyError (NULL, VIR_ERR_INTERNAL_ERROR, __FUNCTION__);
-        return -1;
-    }
-
-    xenUnifiedLock(priv);
-
-    /* Fail silently. */
-    if (priv->proxy == -1)
-        goto error;
-
-    /*
-     * normal communication serial numbers are in 0..4095
-     */
-    ++serial;
-    if (serial >= 4096)
-        serial = 0;
-    request->version = PROXY_PROTO_VERSION;
-    request->serial = serial;
-    ret  = virProxyWriteClientSocket(priv->proxy, (const char *) request,
-                                     request->len);
-    if (ret < 0) {
-        if (!quiet)
-            virReportSystemError(conn, errno, "%s",
-                                 _("failed to write proxy request"));
-        goto error;
-    }
-retry:
-    if (answer == NULL) {
-        /* read in situ */
-        ret  = virProxyReadClientSocket(priv->proxy, (char *) request,
-                                        sizeof(virProxyPacket));
-        if (ret < 0) {
-            if (!quiet)
-                virReportSystemError(conn, errno, "%s",
-                                     _("failed to read proxy reply"));
-            goto error;
-        }
-        if (ret != sizeof(virProxyPacket)) {
-            virProxyError(conn, VIR_ERR_INTERNAL_ERROR,
-                          _("Communication error with proxy: got %d bytes of %d\n"),
-                          ret, (int) sizeof(virProxyPacket));
-            goto error;
-        }
-        res = request;
-        if (res->len != sizeof(virProxyPacket)) {
-            virProxyError(conn, VIR_ERR_INTERNAL_ERROR,
-                          _("Communication error with proxy: expected %d bytes got %d\n"),
-                          (int) sizeof(virProxyPacket), res->len);
-            goto error;
-        }
-    } else {
-        /* read in packet provided */
-        ret  = virProxyReadClientSocket(priv->proxy, (char *) answer,
-                                        sizeof(virProxyPacket));
-        if (ret < 0) {
-            if (!quiet)
-                virReportSystemError(conn, errno, "%s",
-                                     _("failed to read proxy reply"));
-            goto error;
-        }
-        if (ret != sizeof(virProxyPacket)) {
-            virProxyError(conn, VIR_ERR_INTERNAL_ERROR,
-                          _("Communication error with proxy: got %d bytes of %d\n"),
-                          ret, (int) sizeof(virProxyPacket));
-            goto error;
-        }
-        res = (virProxyPacketPtr) answer;
-        if ((res->len < sizeof(virProxyPacket)) ||
-            (res->len > sizeof(virProxyFullPacket))) {
-            virProxyError(conn, VIR_ERR_INTERNAL_ERROR,
-                          _("Communication error with proxy: got %d bytes packet\n"),
-                          res->len);
-            goto error;
-        }
-        if (res->len > sizeof(virProxyPacket)) {
-            ret  = virProxyReadClientSocket(priv->proxy,
-                                   (char *) &(answer->extra.arg[0]),
-                                            res->len - ret);
-            if (ret != (int) (res->len - sizeof(virProxyPacket))) {
-                virProxyError(conn, VIR_ERR_INTERNAL_ERROR,
-                              _("Communication error with proxy: got %d bytes of %d\n"),
-                              ret, (int) sizeof(virProxyPacket));
-                goto error;
-            }
-        }
-    }
-    /*
-     * do more checks on the incoming packet.
-     */
-    if ((res == NULL) || (res->version != PROXY_PROTO_VERSION) ||
-        (res->len < sizeof(virProxyPacket))) {
-        virProxyError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
-                      _("Communication error with proxy: malformed packet\n"));
-        goto error;
-    }
-    if (res->serial != serial) {
-        VIR_WARN(_("got asynchronous packet number %d\n"), res->serial);
-        goto retry;
-    }
-
-    xenUnifiedUnlock(priv);
-    return 0;
-
-error:
-    virProxyCloseSocket(priv);
-    xenUnifiedUnlock(priv);
-    return -1;
-}
-
-/**
- * xenProxyOpen:
- * @conn: pointer to the hypervisor connection
- * @name: URL for the target, NULL for local
- * @flags: combination of virDrvOpenFlag(s)
- *
- * Try to initialize the Xen proxy communication layer
- * This can be opened only for a read-only kind of access
- *
- * Returns 0 in case of success, and -1 in case of failure
- */
-virDrvOpenStatus
-xenProxyOpen(virConnectPtr conn,
-             virConnectAuthPtr auth ATTRIBUTE_UNUSED,
-             int flags)
-{
-    virProxyPacket req;
-    int ret;
-    int fd;
-    xenUnifiedPrivatePtr priv;
-
-    if (!(flags & VIR_CONNECT_RO))
-        return(-1);
-
-    priv = (xenUnifiedPrivatePtr) conn->privateData;
-    priv->proxy = -1;
-
-    fd = virProxyOpenClientSocket(PROXY_SOCKET_PATH);
-    if (fd < 0) {
-            virProxyError(NULL, VIR_ERR_NO_XEN, PROXY_SOCKET_PATH);
-        return(-1);
-    }
-    priv->proxy = fd;
-
-    memset(&req, 0, sizeof(req));
-    req.command = VIR_PROXY_NONE;
-    req.len = sizeof(req);
-    ret = xenProxyCommand(conn, &req, NULL, 1);
-    if ((ret < 0) || (req.command != VIR_PROXY_NONE)) {
-            virProxyError(NULL, VIR_ERR_OPERATION_FAILED, __FUNCTION__);
-        return(-1);
-    }
-    return(0);
-}
-
-/************************************************************************
- *                                                                     *
- *                     Driver entry points                             *
- *                                                                     *
- ************************************************************************/
-
-/**
- * xenProxyGetVersion:
- * @conn: pointer to the Xen Daemon block
- * @hvVer: return value for the version of the running hypervisor (OUT)
- *
- * Get the version level of the Hypervisor running.
- *
- * Returns -1 in case of error, 0 otherwise. if the version can't be
- *    extracted by lack of capacities returns 0 and @hvVer is 0, otherwise
- *    @hvVer value is major * 1,000,000 + minor * 1,000 + release
- */
-static int
-xenProxyGetVersion(virConnectPtr conn, unsigned long *hvVer)
-{
-    virProxyPacket req;
-    int ret;
-
-    if (!VIR_IS_CONNECT(conn)) {
-        virProxyError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return (-1);
-    }
-    if (hvVer == NULL) {
-        virProxyError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
-    }
-    memset(&req, 0, sizeof(req));
-    req.command = VIR_PROXY_VERSION;
-    req.len = sizeof(req);
-    ret = xenProxyCommand(conn, &req, NULL, 0);
-    if (ret < 0) {
-        return(-1);
-    }
-    *hvVer = req.data.larg;
-    return(0);
-}
-
-/**
- * xenProxyListDomains:
- * @conn: pointer to the hypervisor connection
- * @ids: array to collect the list of IDs of active domains
- * @maxids: size of @ids
- *
- * Collect the list of active domains, and store their ID in @maxids
- *
- * Returns the number of domain found or -1 in case of error
- */
-int
-xenProxyListDomains(virConnectPtr conn, int *ids, int maxids)
-{
-    virProxyPacket req;
-    virProxyFullPacket ans;
-    int ret;
-    int nb;
-
-    if (!VIR_IS_CONNECT(conn)) {
-        virProxyError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return (-1);
-    }
-    if ((ids == NULL) || (maxids <= 0)) {
-        virProxyError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
-    }
-    memset(&req, 0, sizeof(req));
-    req.command = VIR_PROXY_LIST;
-    req.len = sizeof(req);
-    ret = xenProxyCommand(conn, &req, &ans, 0);
-    if (ret < 0) {
-        return(-1);
-    }
-    nb = ans.data.arg;
-    if ((nb > 1020) || (nb <= 0) ||
-        (ans.len <= sizeof(virProxyPacket)) ||
-        (ans.len > sizeof(virProxyFullPacket))) {
-        virProxyError(conn, VIR_ERR_OPERATION_FAILED, __FUNCTION__);
-        return(-1);
-    }
-    if (nb > maxids)
-        nb = maxids;
-    memmove(ids, &ans.extra.arg[0], nb * sizeof(int));
-
-    return(nb);
-}
-
-/**
- * xenProxyNumOfDomains:
- * @conn: pointer to the hypervisor connection
- *
- * Provides the number of active domains.
- *
- * Returns the number of domain found or -1 in case of error
- */
-static int
-xenProxyNumOfDomains(virConnectPtr conn)
-{
-    virProxyPacket req;
-    int ret;
-
-    if (!VIR_IS_CONNECT(conn)) {
-        virProxyError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return (-1);
-    }
-    memset(&req, 0, sizeof(req));
-    req.command = VIR_PROXY_NUM_DOMAIN;
-    req.len = sizeof(req);
-    ret = xenProxyCommand(conn, &req, NULL, 0);
-    if (ret < 0) {
-        return(-1);
-    }
-    return(req.data.arg);
-}
-
-
-/**
- * xenProxyDomainGetDomMaxMemory:
- * @conn: pointer to the hypervisor connection
- * @id: the domain ID number
- *
- * Ask the Xen Daemon for the maximum memory allowed for a domain
- *
- * Returns the memory size in kilobytes or 0 in case of error.
- */
-static unsigned long
-xenProxyDomainGetDomMaxMemory(virConnectPtr conn, int id)
-{
-    virProxyPacket req;
-    int ret;
-
-    if (!VIR_IS_CONNECT(conn)) {
-        virProxyError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return (0);
-    }
-    memset(&req, 0, sizeof(req));
-    req.command = VIR_PROXY_MAX_MEMORY;
-    req.data.arg = id;
-    req.len = sizeof(req);
-    ret = xenProxyCommand(conn, &req, NULL, 0);
-    if (ret < 0) {
-        return(0);
-    }
-    return(req.data.larg);
-}
-
-/**
- * xenProxyDomainGetMaxMemory:
- * @domain: pointer to the domain block
- *
- * Ask the Xen Daemon for the maximum memory allowed for a domain
- *
- * Returns the memory size in kilobytes or 0 in case of error.
- */
-static unsigned long
-xenProxyDomainGetMaxMemory(virDomainPtr domain)
-{
-    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
-        if (domain == NULL)
-            virProxyError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
-        else
-            virProxyError(domain->conn, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
-        return (0);
-    }
-    if (domain->id < 0)
-        return (0);
-    return(xenProxyDomainGetDomMaxMemory(domain->conn, domain->id));
-}
-
-/**
- * xenProxyDomainGetInfo:
- * @domain: a domain object
- * @info: pointer to a virDomainInfo structure allocated by the user
- *
- * This method looks up information about a domain and update the
- * information block provided.
- *
- * Returns 0 in case of success, -1 in case of error
- */
-static int
-xenProxyDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
-{
-    virProxyPacket req;
-    virProxyFullPacket ans;
-    int ret;
-
-    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
-        if (domain == NULL)
-            virProxyError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
-        else
-            virProxyError(domain->conn, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
-        return (-1);
-    }
-    if (domain->id < 0)
-        return (-1);
-    if (info == NULL) {
-        virProxyError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
-    }
-    memset(&req, 0, sizeof(req));
-    req.command = VIR_PROXY_DOMAIN_INFO;
-    req.data.arg = domain->id;
-    req.len = sizeof(req);
-    ret = xenProxyCommand(domain->conn, &req, &ans, 0);
-    if (ret < 0) {
-        return(-1);
-    }
-    if (ans.len != sizeof(virProxyPacket) + sizeof(virDomainInfo)) {
-        virProxyError(domain->conn, VIR_ERR_OPERATION_FAILED, __FUNCTION__);
-        return (-1);
-    }
-    memmove(info, &ans.extra.dinfo, sizeof(virDomainInfo));
-
-    return(0);
-}
-
-/**
- * xenProxyLookupByID:
- * @conn: pointer to the hypervisor connection
- * @id: the domain ID number
- *
- * Try to find a domain based on the hypervisor ID number
- *
- * Returns a new domain object or NULL in case of failure
- */
-virDomainPtr
-xenProxyLookupByID(virConnectPtr conn, int id)
-{
-    virProxyPacket req;
-    virProxyFullPacket ans;
-    unsigned char uuid[VIR_UUID_BUFLEN];
-    const char *name;
-    int ret;
-    virDomainPtr res;
-
-    if (!VIR_IS_CONNECT(conn)) {
-        virProxyError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return (NULL);
-    }
-    if (id < 0) {
-        virProxyError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (NULL);
-    }
-    memset(&req, 0, sizeof(req));
-    req.command = VIR_PROXY_LOOKUP_ID;
-    req.data.arg = id;
-    req.len = sizeof(req);
-    ret = xenProxyCommand(conn, &req, &ans, 0);
-    if (ret < 0) {
-        return(NULL);
-    }
-    if (ans.data.arg == -1) {
-        return(NULL);
-    }
-    memcpy(uuid, &ans.extra.str[0], VIR_UUID_BUFLEN);
-    name = &ans.extra.str[VIR_UUID_BUFLEN];
-    res = virGetDomain(conn, name, uuid);
-        if (res) res->id = id;
-    return(res);
-}
-
-/**
- * xenProxyLookupByUUID:
- * @conn: pointer to the hypervisor connection
- * @uuid: the raw UUID for the domain
- *
- * Try to lookup a domain on xend based on its UUID.
- *
- * Returns a new domain object or NULL in case of failure
- */
-virDomainPtr
-xenProxyLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
-{
-    virProxyFullPacket req;
-    const char *name;
-    int ret;
-    virDomainPtr res;
-
-    if (!VIR_IS_CONNECT(conn)) {
-        virProxyError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return (NULL);
-    }
-    if (uuid == NULL) {
-        virProxyError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (NULL);
-    }
-    memset(&req, 0, sizeof(virProxyPacket));
-    req.command = VIR_PROXY_LOOKUP_UUID;
-    req.len = sizeof(virProxyPacket) + VIR_UUID_BUFLEN;
-    memcpy(&req.extra.str[0], uuid, VIR_UUID_BUFLEN);
-
-    ret = xenProxyCommand(conn, (virProxyPacketPtr) &req, &req, 0);
-    if (ret < 0) {
-        return(NULL);
-    }
-    if (req.data.arg == -1) {
-        return(NULL);
-    }
-    name = &req.extra.str[0];
-    res = virGetDomain(conn, name, uuid);
-        if (res) res->id = req.data.arg;
-    return(res);
-}
-
-/**
- * xenProxyLookupByName:
- * @conn: A xend instance
- * @name: The name of the domain
- *
- * This method looks up information about a domain based on its name
- *
- * Returns a new domain object or NULL in case of failure
- */
-virDomainPtr
-xenProxyLookupByName(virConnectPtr conn, const char *name)
-{
-    virProxyFullPacket req;
-    int ret, len;
-    virDomainPtr res;
-
-    if (!VIR_IS_CONNECT(conn)) {
-        virProxyError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return (NULL);
-    }
-    if (name == NULL) {
-        virProxyError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (NULL);
-    }
-    len = strlen(name);
-    if (len > 1000) {
-        virProxyError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (NULL);
-    }
-    memset(&req, 0, sizeof(virProxyPacket));
-    req.command = VIR_PROXY_LOOKUP_NAME;
-    req.len = sizeof(virProxyPacket) + len + 1;
-    strcpy(&req.extra.str[0], name);
-    ret = xenProxyCommand(conn, (virProxyPacketPtr) &req, &req, 0);
-    if (ret < 0) {
-        return(NULL);
-    }
-    if (req.data.arg == -1) {
-        return(NULL);
-    }
-    res = virGetDomain(conn, name, (const unsigned char *)&req.extra.str[0]);
-        if (res) res->id = req.data.arg;
-    return(res);
-}
-
-/**
- * xenProxyNodeGetInfo:
- * @conn: pointer to the Xen Daemon block
- * @info: pointer to a virNodeInfo structure allocated by the user
- *
- * Extract hardware information about the node.
- *
- * Returns 0 in case of success and -1 in case of failure.
- */
-static int
-xenProxyNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info) {
-    virProxyPacket req;
-    virProxyFullPacket ans;
-    int ret;
-
-    if (!VIR_IS_CONNECT(conn)) {
-        virProxyError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return (-1);
-    }
-    if (info == NULL) {
-        virProxyError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
-    }
-    memset(&req, 0, sizeof(req));
-    req.command = VIR_PROXY_NODE_INFO;
-    req.data.arg = 0;
-    req.len = sizeof(req);
-    ret = xenProxyCommand(conn, &req, &ans, 0);
-    if (ret < 0) {
-        return(-1);
-    }
-    if (ans.data.arg == -1) {
-        return(-1);
-    }
-    if (ans.len != sizeof(virProxyPacket) + sizeof(virNodeInfo)) {
-        return(-1);
-    }
-    memcpy(info, &ans.extra.ninfo, sizeof(virNodeInfo));
-    return(0);
-}
-
-/**
- * xenProxyGetCapabilities:
- * @conn: pointer to the Xen Daemon block
- *
- * Extract capabilities of the hypervisor.
- *
- * Returns capabilities in case of success (freed by caller)
- * and NULL in case of failure.
- */
-static char *
-xenProxyGetCapabilities (virConnectPtr conn)
-{
-    virProxyPacket req;
-    virProxyFullPacket ans;
-    int ret, xmllen;
-    char *xml;
-
-    if (!VIR_IS_CONNECT(conn)) {
-        virProxyError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return NULL;
-    }
-    memset(&req, 0, sizeof(req));
-    req.command = VIR_PROXY_GET_CAPABILITIES;
-    req.data.arg = 0;
-    req.len = sizeof(req);
-    ret = xenProxyCommand(conn, &req, &ans, 0);
-    if (ret < 0) {
-        return NULL;
-    }
-    if (ans.data.arg == -1)
-        return NULL;
-    if (ans.len <= sizeof(virProxyPacket)) {
-        virProxyError(conn, VIR_ERR_OPERATION_FAILED, __FUNCTION__);
-        return NULL;
-    }
-
-    xmllen = ans.len - sizeof (virProxyPacket);
-    if (VIR_ALLOC_N(xml, xmllen+1) < 0) {
-        virReportOOMError (conn);
-        return NULL;
-    }
-    memmove (xml, ans.extra.str, xmllen);
-    xml[xmllen] = '\0';
-
-    return xml;
-}
-
-/**
- * xenProxyDomainDumpXML:
- * @domain: a domain object
- * @flags: xml generation flags
- *
- * This method generates an XML description of a domain.
- *
- * Returns the XML document on success, NULL otherwise.
- */
-char *
-xenProxyDomainDumpXML(virDomainPtr domain, int flags ATTRIBUTE_UNUSED)
-{
-    virProxyPacket req;
-    virProxyFullPacket ans;
-    int ret;
-    int xmllen;
-    char *xml;
-
-    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
-        if (domain == NULL)
-            virProxyError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
-        else
-            virProxyError(domain->conn, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
-        return (NULL);
-    }
-    if (domain->id < 0)
-        return (NULL);
-    memset(&req, 0, sizeof(req));
-    req.command = VIR_PROXY_DOMAIN_XML;
-    req.data.arg = domain->id;
-    req.len = sizeof(req);
-    ret = xenProxyCommand(domain->conn, &req, &ans, 0);
-    if (ret < 0) {
-        return(NULL);
-    }
-    if (ans.len <= sizeof(virProxyPacket)) {
-        virProxyError(domain->conn, VIR_ERR_OPERATION_FAILED, __FUNCTION__);
-        return (NULL);
-    }
-    xmllen = ans.len - sizeof(virProxyPacket);
-    if (VIR_ALLOC_N(xml, xmllen+1) < 0) {
-        virReportOOMError(domain->conn);
-        return NULL;
-    }
-    memmove(xml, &ans.extra.dinfo, xmllen);
-    xml[xmllen] = '\0';
-
-    return(xml);
-}
-
-/**
- * xenProxyDomainGetOSType:
- * @domain: a domain object
- *
- * Get the type of domain operation system.
- *
- * Returns the new string or NULL in case of error, the string must be
- *         freed by the caller.
- */
-static char *
-xenProxyDomainGetOSType(virDomainPtr domain)
-{
-    virProxyPacket req;
-    virProxyFullPacket ans;
-    int ret;
-    int oslen;
-    char *ostype;
-
-    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
-        if (domain == NULL)
-            virProxyError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
-        else
-            virProxyError(domain->conn, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
-        return (NULL);
-    }
-    memset(&req, 0, sizeof(req));
-    req.command = VIR_PROXY_DOMAIN_OSTYPE;
-    req.data.arg = domain->id;
-    req.len = sizeof(req);
-    ret = xenProxyCommand(domain->conn, &req, &ans, 0);
-    if (ret < 0) {
-        return(NULL);
-    }
-    if ((ans.len == sizeof(virProxyPacket)) && (ans.data.arg < 0)) {
-        return(NULL);
-    }
-
-    if (ans.len <= sizeof(virProxyPacket)) {
-        virProxyError(domain->conn, VIR_ERR_OPERATION_FAILED, __FUNCTION__);
-        return (NULL);
-    }
-    oslen = ans.len - sizeof(virProxyPacket);
-    if (VIR_ALLOC_N(ostype, oslen+1) < 0) {
-        virReportOOMError(domain->conn);
-        return NULL;
-    }
-    memmove(ostype, &ans.extra.dinfo, oslen);
-    ostype[oslen] = '\0';
-
-    return(ostype);
-}
diff --git a/src/proxy_internal.h b/src/proxy_internal.h
deleted file mode 100644 (file)
index 185fa67..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * proxy.h: common definitions for proxy usage
- *
- * Copyright (C) 2006 Red Hat, Inc.
- *
- * See COPYING.LIB for the License of this software
- *
- * Daniel Veillard <veillard@redhat.com>
- */
-
-
-#ifndef __LIBVIR_PROXY_H__
-#define __LIBVIR_PROXY_H__
-
-#include "internal.h"
-
-#define PROXY_SOCKET_PATH "/tmp/livirt_proxy_conn"
-#define PROXY_PROTO_VERSION 1
-
-/*
- * the command allowed though the proxy
- */
-typedef enum {
-        VIR_PROXY_NONE = 0,
-        VIR_PROXY_VERSION = 1,
-        VIR_PROXY_NODE_INFO = 2,
-        VIR_PROXY_LIST = 3,
-        VIR_PROXY_NUM_DOMAIN = 4,
-        VIR_PROXY_LOOKUP_ID = 5,
-        VIR_PROXY_LOOKUP_UUID = 6,
-        VIR_PROXY_LOOKUP_NAME = 7,
-        VIR_PROXY_MAX_MEMORY = 8,
-        VIR_PROXY_DOMAIN_INFO = 9,
-        VIR_PROXY_DOMAIN_XML = 10,
-        VIR_PROXY_DOMAIN_OSTYPE = 11,
-    VIR_PROXY_GET_CAPABILITIES = 12
-} virProxyCommand;
-
-/*
- * structure used by the client to make a request to the proxy
- * and by the proxy when answering the client.
- * the size may not be fixed, it's passed as len.
- */
-struct _virProxyPacket {
-    unsigned short version;    /* version of the proxy protocol */
-    unsigned short command;    /* command number a virProxyCommand */
-    unsigned short serial;     /* command serial number */
-    unsigned short len;                /* the length of the request */
-    union {
-        char       string[8];  /* string data */
-        int        arg;                /* or int argument */
-        long       larg;       /* or long argument */
-    } data;
-};
-typedef struct _virProxyPacket virProxyPacket;
-typedef  virProxyPacket *virProxyPacketPtr;
-
-/*
- * If there is extra data sent from the proxy to the client,
- * they are appended after the packet.
- * the size may not be fixed, it's passed as len and includes the
- * extra data.
- */
-struct _virProxyFullPacket {
-    unsigned short version;    /* version of the proxy protocol */
-    unsigned short command;    /* command number a virProxyCommand */
-    unsigned short serial;     /* command serial number */
-    unsigned short len;                /* the length of the request */
-    union {
-        char       string[8];  /* string data */
-        int        arg;                /* or int argument */
-        long       larg;       /* or long argument */
-    } data;
-    /* that should be aligned on a 16bytes boundary */
-    union {
-        char       str[4080];   /* extra char array */
-        int        arg[1020];   /* extra int array */
-        virDomainInfo dinfo;   /* domain information */
-        virNodeInfo   ninfo;   /* node information */
-    } extra;
-};
-typedef struct _virProxyFullPacket virProxyFullPacket;
-typedef  virProxyFullPacket *virProxyFullPacketPtr;
-
-/* xen_unified makes direct calls or indirect calls through here. */
-extern struct xenUnifiedDriver xenProxyDriver;
-extern int xenProxyInit (void);
-
-extern virDomainPtr xenProxyLookupByID(virConnectPtr conn, int id);
-extern virDomainPtr xenProxyLookupByUUID(virConnectPtr conn,
-                                         const unsigned char *uuid);
-extern virDomainPtr xenProxyLookupByName(virConnectPtr conn,
-                                         const char *domname);
-
-extern char *       xenProxyDomainDumpXML(virDomainPtr domain,
-                                          int flags);
-extern int          xenProxyListDomains(virConnectPtr conn, int *ids,
-                                        int maxids);
-#endif /* __LIBVIR_PROXY_H__ */
index 2ddcdc0f6e4d6af910d5618d9e851c82aee0842e..068b0642f3f2861956b3ece84900d7b0ef999b6b 100644 (file)
@@ -44,6 +44,7 @@
 #include <stdio.h>
 #include <sys/wait.h>
 #include <sys/ioctl.h>
+#include <sys/un.h>
 
 #if HAVE_SCHED_H
 #include <sched.h>
diff --git a/src/sexpr.c b/src/sexpr.c
deleted file mode 100644 (file)
index 81cb49f..0000000
+++ /dev/null
@@ -1,577 +0,0 @@
-/*
- * sexpr.c : S-Expression routines to communicate with the Xen Daemon
- *
- * Copyright (C) 2005
- *
- *      Anthony Liguori <aliguori@us.ibm.com>
- *
- *  This file is subject to the terms and conditions of the GNU Lesser General
- *  Public License. See the file COPYING.LIB in the main directory of this
- *  archive for more details.
- */
-
-#include <config.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "c-ctype.h"
-#include <errno.h>
-
-#include "virterror_internal.h"
-#include "sexpr.h"
-#include "util.h"
-#include "memory.h"
-
-#define VIR_FROM_THIS VIR_FROM_SEXPR
-
-#define virSexprError(code, fmt...)                                          \
-        virReportErrorHelper(NULL, VIR_FROM_SEXPR, code, __FILE__,         \
-                               __FUNCTION__, __LINE__, fmt)
-
-/**
- * sexpr_new:
- *
- * Create a new S-Expression
- *
- * Returns the new node or NULL in case of memory allocation error
- */
-static struct sexpr *
-sexpr_new(void)
-{
-    struct sexpr *ret;
-
-    if (VIR_ALLOC(ret) < 0) {
-        virReportOOMError(NULL);
-        return (NULL);
-    }
-    ret->kind = SEXPR_NIL;
-    return ret;
-}
-
-/**
- * sexpr_free:
- * @sexpr: the S-Expression pointer
- *
- * Free an S-Expression
- */
-void
-sexpr_free(struct sexpr *sexpr)
-{
-    int serrno = errno;
-
-    if (sexpr == NULL) {
-        return;
-    }
-
-    switch (sexpr->kind) {
-        case SEXPR_CONS:
-            sexpr_free(sexpr->u.s.car);
-            sexpr_free(sexpr->u.s.cdr);
-            break;
-        case SEXPR_VALUE:
-            VIR_FREE(sexpr->u.value);
-            break;
-        case SEXPR_NIL:
-            break;
-    }
-
-    VIR_FREE(sexpr);
-
-    errno = serrno;
-}
-
-/**
- * sexpr_nil:
- *
- * Provide a NIL S-Expression (the pointer is not shared so NIL equality
- * testing won't work at the pointer level).
- *
- * Returns a new NIL S-Expression of NULL in case of error.
- */
-struct sexpr *
-sexpr_nil(void)
-{
-    return sexpr_new();
-}
-
-/**
- * sexpr_string:
- * @str:  the input string, assumed to be UTF-8
- * @len:  the length in bytes of the input
- *
- * Parse the input S-Expression and return a pointer to the result
- *
- * Returns the S-Expression pointer or NULL in case of error
- */
-struct sexpr *
-sexpr_string(const char *str, ssize_t len)
-{
-    struct sexpr *ret = sexpr_new();
-
-    if (ret == NULL)
-        return ret;
-    ret->kind = SEXPR_VALUE;
-    if (len > 0) {
-        ret->u.value = strndup(str, len);
-    } else {
-        ret->u.value = strdup(str);
-    }
-
-    if (ret->u.value == NULL) {
-        return NULL;
-    }
-
-    return ret;
-}
-
-/**
- * sexpr_cons:
- * @car: the left operand
- * @cdr: the right operand
- *
- * Implement the CONS operation assembling 2 existing S-Expressions.
- * Note that in case of error the input data are not freed.
- *
- * Returns the resulting S-Expression pointer or NULL in case of error.
- */
-struct sexpr *
-sexpr_cons(const struct sexpr *car, const struct sexpr *cdr)
-{
-    struct sexpr *ret = sexpr_new();
-
-    if (ret == NULL)
-        return ret;
-    ret->kind = SEXPR_CONS;
-    ret->u.s.car = (struct sexpr *) car;
-    ret->u.s.cdr = (struct sexpr *) cdr;
-
-    return ret;
-}
-
-/**
- * append:
- * @lst: an existing list
- * @value: the value
- *
- * Internal operation appending a value at the end of an existing list
- */
-static int
-append(struct sexpr *lst, const struct sexpr *value)
-{
-    struct sexpr *nil = sexpr_nil();
-
-    if (nil == NULL)
-        return -1;
-
-    while (lst->kind != SEXPR_NIL) {
-        lst = lst->u.s.cdr;
-    }
-
-    lst->kind = SEXPR_CONS;
-    lst->u.s.car = (struct sexpr *) value;
-    lst->u.s.cdr = nil;
-
-    return 0;
-}
-
-/**
- * @lst: an existing list
- * @value: the value
- *
- * Append a value at the end of an existing list
- *
- * Returns lst or NULL in case of error
- */
-struct sexpr *
-sexpr_append(struct sexpr *lst, const struct sexpr *value)
-{
-    if (lst == NULL)
-        return (NULL);
-    if (value == NULL)
-        return (lst);
-    if (append(lst, value) < 0)
-        return (NULL);
-    return (lst);
-}
-
-/**
- * sexpr2string:
- * @sexpr: an S-Expression pointer
- * @buffer: the output buffer
- * @n_buffer: the size of the buffer in bytes
- *
- * Serialize the S-Expression in the buffer.
- * Note that the output may be truncated if @n_buffer is too small
- * resulting in an unparseable value.
- *
- * Returns the number of bytes used by the serialization in the buffer or
- *         0 in case of error.
- */
-size_t
-sexpr2string(const struct sexpr * sexpr, char *buffer, size_t n_buffer)
-{
-    size_t ret = 0, tmp;
-
-    if ((sexpr == NULL) || (buffer == NULL) || (n_buffer <= 0))
-        return (0);
-
-    switch (sexpr->kind) {
-        case SEXPR_CONS:
-            tmp = snprintf(buffer + ret, n_buffer - ret, "(");
-            if (tmp == 0)
-                goto error;
-            ret += tmp;
-            tmp = sexpr2string(sexpr->u.s.car, buffer + ret, n_buffer - ret);
-            if (tmp == 0)
-                goto error;
-            ret += tmp;
-            while (sexpr->u.s.cdr->kind != SEXPR_NIL) {
-                sexpr = sexpr->u.s.cdr;
-                tmp = snprintf(buffer + ret, n_buffer - ret, " ");
-                if (tmp == 0)
-                    goto error;
-                ret += tmp;
-                tmp =
-                    sexpr2string(sexpr->u.s.car, buffer + ret, n_buffer - ret);
-                if (tmp == 0)
-                    goto error;
-                ret += tmp;
-            }
-            tmp = snprintf(buffer + ret, n_buffer - ret, ")");
-            if (tmp == 0)
-                goto error;
-            ret += tmp;
-            break;
-        case SEXPR_VALUE:
-            if (strchr(sexpr->u.value, ' '))
-                tmp = snprintf(buffer + ret, n_buffer - ret, "'%s'",
-                               sexpr->u.value);
-            else
-                tmp = snprintf(buffer + ret, n_buffer - ret, "%s",
-                               sexpr->u.value);
-            if (tmp == 0)
-                goto error;
-            ret += tmp;
-            break;
-        case SEXPR_NIL:
-            tmp = snprintf(buffer + ret, n_buffer - ret, "()");
-            if (tmp == 0)
-                goto error;
-            ret += tmp;
-            break;
-        default:
-            goto error;
-    }
-
-    return (ret);
-  error:
-    buffer[n_buffer - 1] = 0;
-    virSexprError(VIR_ERR_SEXPR_SERIAL, "%s", buffer);
-    return (0);
-}
-
-#define IS_SPACE(c) ((c == 0x20) || (c == 0x9) || (c == 0xD) || (c == 0xA))
-
-static const char *
-trim(const char *string)
-{
-    while (IS_SPACE(*string))
-        string++;
-    return (string);
-}
-
-/**
- * _string2sexpr:
- * @buffer: a zero terminated buffer containing an S-Expression in UTF-8
- * @end: pointer to an index in the buffer for the already parsed bytes
- *
- * Internal routine implementing the parse of S-Expression
- * Note that failure in this function is catastrophic.  If it returns
- * NULL, you've leaked memory and you're currently OOM.  It will always
- * parse an SEXPR given a buffer
- *
- * Returns a pointer to the resulting parsed S-Expression, or NULL in case of
- *         hard error.
- */
-static struct sexpr *
-_string2sexpr(const char *buffer, size_t * end)
-{
-    const char *ptr = buffer + *end;
-    struct sexpr *ret = sexpr_new();
-
-    if (ret == NULL)
-        return NULL;
-
-    ptr = trim(ptr);
-
-    if (ptr[0] == '(') {
-        ret->kind = SEXPR_NIL;
-
-        ptr = trim(ptr + 1);
-        while (*ptr && *ptr != ')') {
-            struct sexpr *tmp;
-            size_t tmp_len = 0;
-
-            tmp = _string2sexpr(ptr, &tmp_len);
-            if (tmp == NULL)
-                goto error;
-            if (append(ret, tmp) < 0) {
-                sexpr_free(tmp);
-                goto error;
-            }
-#if 0
-            if (0) {
-                char buf[4096];
-
-                sexpr2string(ret, buf, sizeof(buf));
-                printf("%s\n", buffer);
-            }
-#endif
-            ptr = trim(ptr + tmp_len);
-        }
-
-        if (*ptr == ')') {
-            ptr++;
-        }
-    } else {
-        const char *start;
-
-        if (*ptr == '\'') {
-            ptr++;
-            start = ptr;
-
-            while (*ptr && *ptr != '\'') {
-                if (*ptr == '\\' && ptr[1])
-                    ptr++;
-                ptr++;
-            }
-
-            ret->u.value = strndup(start, ptr - start);
-            if (ret->u.value == NULL) {
-                virReportOOMError(NULL);
-                goto error;
-            }
-
-            if (*ptr == '\'')
-                ptr++;
-        } else {
-            start = ptr;
-
-            while (*ptr && !c_isspace(*ptr)
-                   && *ptr != ')' && *ptr != '(') {
-                ptr++;
-            }
-
-            ret->u.value = strndup(start, ptr - start);
-            if (ret->u.value == NULL) {
-                virReportOOMError(NULL);
-                goto error;
-            }
-        }
-
-        ret->kind = SEXPR_VALUE;
-        if (ret->u.value == NULL)
-            goto error;
-    }
-
-    *end = ptr - buffer;
-
-    return ret;
-
-  error:
-    sexpr_free(ret);
-    return (NULL);
-}
-
-/**
- * string2sexpr:
- * @buffer: a zero terminated buffer containing an S-Expression in UTF-8
- *
- * Parse the S-Expression in the buffer.
- * Note that failure in this function is catastrophic.  If it returns
- * NULL, you've leaked memory and you're currently OOM.  It will always
- * parse an SEXPR given a buffer
- *
- * Returns a pointer to the resulting parsed S-Expression, or NULL in case of
- *         hard error.
- */
-struct sexpr *
-string2sexpr(const char *buffer)
-{
-    size_t dummy = 0;
-
-    return _string2sexpr(buffer, &dummy);
-}
-
-
-/**
- * sexpr_lookup_key:
- * @sexpr: a pointer to a parsed S-Expression
- * @node: a path for the sub expression to lookup in the S-Expression
- *
- * Search a sub expression in the S-Expression based on its path
- * Returns the key node, rather than the data node.
- * NOTE: path are limited to 4096 bytes.
- *
- * Returns the pointer to the sub expression or NULL if not found.
- */
-static struct sexpr *
-sexpr_lookup_key(const struct sexpr *sexpr, const char *node)
-{
-    char buffer[4096], *ptr, *token;
-
-    if ((node == NULL) || (sexpr == NULL))
-        return (NULL);
-
-    snprintf(buffer, sizeof(buffer), "%s", node);
-
-    ptr = buffer;
-    token = strsep(&ptr, "/");
-
-    if (sexpr->kind != SEXPR_CONS || sexpr->u.s.car->kind != SEXPR_VALUE) {
-        return NULL;
-    }
-
-    if (STRNEQ(sexpr->u.s.car->u.value, token)) {
-        return NULL;
-    }
-
-    for (token = strsep(&ptr, "/"); token; token = strsep(&ptr, "/")) {
-        const struct sexpr *i;
-
-        if (token == NULL)
-            continue;
-
-        sexpr = sexpr->u.s.cdr;
-        for (i = sexpr; i->kind != SEXPR_NIL; i = i->u.s.cdr) {
-            if (i->kind != SEXPR_CONS ||
-                i->u.s.car->kind != SEXPR_CONS ||
-                i->u.s.car->u.s.car->kind != SEXPR_VALUE) {
-                continue;
-            }
-
-            if (STREQ(i->u.s.car->u.s.car->u.value, token)) {
-                sexpr = i->u.s.car;
-                break;
-            }
-        }
-
-        if (i->kind == SEXPR_NIL) {
-            break;
-        }
-    }
-
-    if (token != NULL) {
-        return NULL;
-    }
-
-    return (struct sexpr *) sexpr;
-}
-
-/**
- * sexpr_lookup:
- * @sexpr: a pointer to a parsed S-Expression
- * @node: a path for the sub expression to lookup in the S-Expression
- *
- * Search a sub expression in the S-Expression based on its path.
- * NOTE: path are limited to 4096 bytes.
- *
- * Returns the pointer to the sub expression or NULL if not found.
- */
-struct sexpr *
-sexpr_lookup(const struct sexpr *sexpr, const char *node)
-{
-    struct sexpr *s = sexpr_lookup_key(sexpr, node);
-
-    if (s == NULL)
-        return NULL;
-
-    if (s->kind != SEXPR_CONS || s->u.s.cdr->kind != SEXPR_CONS)
-        return NULL;
-
-    return s->u.s.cdr;
-}
-
-/**
- * sexpr_has:
- * @sexpr: a pointer to a parsed S-Expression
- * @node: a path for the sub expression to lookup in the S-Expression
- *
- * Search a sub expression in the S-Expression based on its path.
- * NOTE: path are limited to 4096 bytes.
- * NB, even if the key was found sexpr_lookup may return NULL if
- * the corresponding value was empty
- *
- * Returns true if the key was found, false otherwise
- */
-int
-sexpr_has(const struct sexpr *sexpr, const char *node)
-{
-    struct sexpr *s = sexpr_lookup_key(sexpr, node);
-
-    if (s == NULL)
-        return 0;
-
-    if (s->kind != SEXPR_CONS)
-        return 0;
-
-    return 1;
-}
-
-/**
- * sexpr_node:
- * @sexpr: a pointer to a parsed S-Expression
- * @node: a path for the node to lookup in the S-Expression
- *
- * Search a node value in the S-Expression based on its path
- * NOTE: path are limited to 4096 bytes.
- *
- * Returns the value of the node or NULL if not found.
- */
-const char *
-sexpr_node(const struct sexpr *sexpr, const char *node)
-{
-    struct sexpr *n = sexpr_lookup(sexpr, node);
-
-    return (n && n->u.s.car->kind == SEXPR_VALUE) ? n->u.s.car->u.value : NULL;
-}
-
-int sexpr_node_copy(const struct sexpr *sexpr, const char *node, char **dst)
-{
-    const char *val = sexpr_node(sexpr, node);
-
-    if (val) {
-        *dst = strdup(val);
-        if (!(*dst))
-            return -1;
-    } else {
-        *dst = NULL;
-    }
-    return 0;
-}
-
-
-/**
- * sexpr_fmt_node:
- * @sexpr: a pointer to a parsed S-Expression
- * @fmt: a path for the node to lookup in the S-Expression
- * @... extra data to build the path
- *
- * Search a node value in the S-Expression based on its path
- * NOTE: path are limited to 4096 bytes.
- *
- * Returns the value of the node or NULL if not found.
- */
-const char *
-sexpr_fmt_node(const struct sexpr *sexpr, const char *fmt, ...)
-{
-    va_list ap;
-    char node[4096];
-
-    va_start(ap, fmt);
-    vsnprintf(node, sizeof(node), fmt, ap);
-    va_end(ap);
-
-    return sexpr_node(sexpr, node);
-}
diff --git a/src/sexpr.h b/src/sexpr.h
deleted file mode 100644 (file)
index 1d9adaa..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * sexpr.h : S-Expression interfaces needed to communicate with the Xen Daemon
- *
- * Copyright (C) 2005
- *
- *      Anthony Liguori <aliguori@us.ibm.com>
- *
- *  This file is subject to the terms and conditions of the GNU Lesser General
- *  Public License. See the file COPYING.LIB in the main directory of this
- *  archive for more details.
- */
-
-#ifndef _LIBVIR_SEXPR_H_
-#define _LIBVIR_SEXPR_H_
-
-#include "internal.h"
-
-#include <sys/types.h>
-
-enum sexpr_type {
-    SEXPR_NIL,
-    SEXPR_CONS,
-    SEXPR_VALUE,
-};
-
-struct sexpr {
-    enum sexpr_type kind;
-    union {
-        struct {
-            struct sexpr *car;
-            struct sexpr *cdr;
-        } s;
-        char *value;
-    } u;
-};
-
-/* conversion to/from strings */
-size_t sexpr2string(const struct sexpr *sexpr, char *buffer, size_t n_buffer);
-struct sexpr *string2sexpr(const char *buffer);
-
-/* constructors and destructors */
-struct sexpr *sexpr_nil(void);
-struct sexpr *sexpr_string(const char *str, ssize_t len);
-struct sexpr *sexpr_cons(const struct sexpr *car, const struct sexpr *cdr);
-struct sexpr *sexpr_append(struct sexpr *lst, const struct sexpr *item);
-void sexpr_free(struct sexpr *sexpr);
-
-/* lookup in S-Expressions */
-const char *sexpr_node(const struct sexpr *sexpr, const char *node);
-int sexpr_node_copy(const struct sexpr *sexpr, const char *node, char **dst);
-const char *sexpr_fmt_node(const struct sexpr *sexpr, const char *fmt, ...)
-  ATTRIBUTE_FMT_PRINTF(2,3);
-struct sexpr *sexpr_lookup(const struct sexpr *sexpr, const char *node);
-int sexpr_has(const struct sexpr *sexpr, const char *node);
-#endif
index eccda9466a7701f0a50aca24e09f221ac7f3d783..7d8a5f9e0ade7e7fa65e48f6de87196e30151443 100644 (file)
 #include <unistd.h>
 #include <regex.h>
 
-#ifdef WITH_XEN
-#include <xs.h>
-#endif
-
 #include "virterror_internal.h"
 #include "datatypes.h"
 #include "util.h"
-#include "xen_unified.h"
 #include "stats_linux.h"
 #include "memory.h"
 
@@ -63,315 +58,6 @@ statsErrorFunc (virConnectPtr conn,
                     value);
 }
 
-#ifdef WITH_XEN
-/*-------------------- Xen: block stats --------------------*/
-
-#include <linux/major.h>
-
-/* This is normally defined in <linux/major.h> but previously we
- * hard-coded it.  So if it's not defined, hard-code again.
- */
-#ifndef XENVBD_MAJOR
-#define XENVBD_MAJOR 202
-#endif
-
-static int
-xstrtoint64 (char const *s, int base, int64_t *result)
-{
-    long long int lli;
-    char *p;
-
-    errno = 0;
-    lli = strtoll (s, &p, base);
-    if (errno || !(*p == 0 || *p == '\n') || p == s || (int64_t) lli != lli)
-        return -1;
-    *result = lli;
-    return 0;
-}
-
-static int64_t
-read_stat (const char *path)
-{
-    char str[64];
-    int64_t r;
-    int i;
-    FILE *fp;
-
-    fp = fopen (path, "r");
-    if (!fp)
-      return -1;
-
-    /* read, but don't bail out before closing */
-    i = fread (str, 1, sizeof str - 1, fp);
-
-    if (fclose (fp) != 0        /* disk error */
-        || i < 1)               /* ensure we read at least one byte */
-        return -1;
-
-    str[i] = '\0';              /* make sure the string is nul-terminated */
-    if (xstrtoint64 (str, 10, &r) == -1)
-        return -1;
-
-    return r;
-}
-
-static int64_t
-read_bd_stat (int device, int domid, const char *str)
-{
-    char path[PATH_MAX];
-    int64_t r;
-
-    snprintf (path, sizeof path,
-              "/sys/devices/xen-backend/vbd-%d-%d/statistics/%s",
-              domid, device, str);
-    r = read_stat (path);
-    if (r >= 0) return r;
-
-    snprintf (path, sizeof path,
-              "/sys/devices/xen-backend/tap-%d-%d/statistics/%s",
-              domid, device, str);
-    r = read_stat (path);
-    return r;
-}
-
-/* In Xenstore, /local/domain/0/backend/vbd/<domid>/<device>/state,
- * if available, must be XenbusStateConnected (= 4), otherwise there
- * is no connected device.
- */
-static int
-check_bd_connected (xenUnifiedPrivatePtr priv, int device, int domid)
-{
-    char s[256], *rs;
-    int r;
-    unsigned len = 0;
-
-    /* This code assumes we're connected if we can't get to
-     * xenstore, etc.
-     */
-    if (!priv->xshandle) return 1;
-    snprintf (s, sizeof s, "/local/domain/0/backend/vbd/%d/%d/state",
-              domid, device);
-    s[sizeof s - 1] = '\0';
-
-    rs = xs_read (priv->xshandle, 0, s, &len);
-    if (!rs) return 1;
-    if (len == 0) {
-        /* Hmmm ... we can get to xenstore but it returns an empty
-         * string instead of an error.  Assume it's not connected
-         * in this case.
-         */
-        free (rs);
-        return 0;
-    }
-
-    r = STREQ (rs, "4");
-    free (rs);
-    return r;
-}
-
-static int
-read_bd_stats (virConnectPtr conn, xenUnifiedPrivatePtr priv,
-               int device, int domid, struct _virDomainBlockStats *stats)
-{
-    stats->rd_req   = read_bd_stat (device, domid, "rd_req");
-    stats->rd_bytes = read_bd_stat (device, domid, "rd_sect");
-    stats->wr_req   = read_bd_stat (device, domid, "wr_req");
-    stats->wr_bytes = read_bd_stat (device, domid, "wr_sect");
-    stats->errs     = read_bd_stat (device, domid, "oo_req");
-
-    /* None of the files were found - it's likely that this version
-     * of Xen is an old one which just doesn't support stats collection.
-     */
-    if (stats->rd_req == -1 && stats->rd_bytes == -1 &&
-        stats->wr_req == -1 && stats->wr_bytes == -1 &&
-        stats->errs == -1) {
-        statsErrorFunc (conn, VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
-                        "Failed to read any block statistics", domid);
-        return -1;
-    }
-
-    /* If stats are all zero then either there really isn't any block
-     * device activity, or there is no connected front end device
-     * in which case there are no stats.
-     */
-    if (stats->rd_req == 0 && stats->rd_bytes == 0 &&
-        stats->wr_req == 0 && stats->wr_bytes == 0 &&
-        stats->errs == 0 &&
-        !check_bd_connected (priv, device, domid)) {
-        statsErrorFunc (conn, VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
-                        "Frontend block device not connected", domid);
-        return -1;
-    }
-
-    /* 'Bytes' was really sectors when we read it.  Scale up by
-     * an assumed sector size.
-     */
-    if (stats->rd_bytes > 0) {
-        if (stats->rd_bytes >= ((unsigned long long)1)<<(63-9)) {
-            statsErrorFunc (conn, VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
-                            "stats->rd_bytes would overflow 64 bit counter",
-                            domid);
-            return -1;
-        }
-        stats->rd_bytes *= 512;
-    }
-    if (stats->wr_bytes > 0) {
-        if (stats->wr_bytes >= ((unsigned long long)1)<<(63-9)) {
-            statsErrorFunc (conn, VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
-                            "stats->wr_bytes would overflow 64 bit counter",
-                            domid);
-            return -1;
-        }
-        stats->wr_bytes *= 512;
-    }
-
-    return 0;
-}
-
-static int
-disk_re_match(const char *regex, const char *path, int *part)
-{
-    regex_t myreg;
-    int err;
-    int retval;
-    regmatch_t pmatch[3];
-
-    retval = 0;
-
-    err = regcomp(&myreg, regex, REG_EXTENDED);
-    if (err != 0)
-        return 0;
-
-    err = regexec(&myreg, path, 3, pmatch, 0);
-
-    if (err == 0) {
-        /* OK, we have a match; see if we have a partition */
-        *part = 0;
-        retval = 1;
-        if (pmatch[1].rm_so != -1) {
-            if (virStrToLong_i(path + pmatch[1].rm_so, NULL, 10, part) < 0)
-                retval = 0;
-        }
-    }
-
-    regfree(&myreg);
-
-    return retval;
-}
-
-int
-xenLinuxDomainDeviceID(virConnectPtr conn, int domid, const char *path)
-{
-    int major, minor;
-    int part;
-    int retval;
-    char *mod_path;
-
-    int const scsi_majors[] = { SCSI_DISK0_MAJOR, SCSI_DISK1_MAJOR,
-                                SCSI_DISK2_MAJOR, SCSI_DISK3_MAJOR,
-                                SCSI_DISK4_MAJOR, SCSI_DISK5_MAJOR,
-                                SCSI_DISK6_MAJOR, SCSI_DISK7_MAJOR,
-                                SCSI_DISK8_MAJOR, SCSI_DISK9_MAJOR,
-                                SCSI_DISK10_MAJOR, SCSI_DISK11_MAJOR,
-                                SCSI_DISK12_MAJOR, SCSI_DISK13_MAJOR,
-                                SCSI_DISK14_MAJOR, SCSI_DISK15_MAJOR };
-    int const ide_majors[] = { IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR,
-                               IDE4_MAJOR, IDE5_MAJOR, IDE6_MAJOR, IDE7_MAJOR,
-                               IDE8_MAJOR, IDE9_MAJOR };
-
-    /*
-     * Possible block device majors & partition ranges. This
-     * matches the ranges supported in Xend xen/util/blkif.py
-     *
-     * hdNM:  N=a-t, M=1-63, major={IDE0_MAJOR -> IDE9_MAJOR}
-     * sdNM:  N=a-z,aa-iv, M=1-15, major={SCSI_DISK0_MAJOR -> SCSI_DISK15_MAJOR}
-     * xvdNM: N=a-p M=1-15, major=XENVBD_MAJOR
-     * xvdNM: N=q-z,aa-iz M=1-15, major=(1<<28)
-     *
-     * The path for statistics will be
-     *
-     * /sys/devices/xen-backend/(vbd|tap)-{domid}-{devid}/statistics/{...}
-     */
-
-    if (strlen(path) >= 5 && STRPREFIX(path, "/dev/"))
-        retval = virAsprintf(&mod_path, "%s", path);
-    else
-        retval = virAsprintf(&mod_path, "/dev/%s", path);
-
-    if (retval < 0) {
-        virReportOOMError (conn);
-        return -1;
-    }
-
-    retval = -1;
-
-    if (disk_re_match("/dev/sd[a-z]([1-9]|1[0-5])?$", mod_path, &part)) {
-        major = scsi_majors[(mod_path[7] - 'a') / 16];
-        minor = ((mod_path[7] - 'a') % 16) * 16 + part;
-        retval = major * 256 + minor;
-    }
-    else if (disk_re_match("/dev/sd[a-h][a-z]([1-9]|1[0-5])?$",
-                           mod_path, &part) ||
-             disk_re_match("/dev/sdi[a-v]([1-9]|1[0-5])?$",
-                           mod_path, &part)) {
-        major = scsi_majors[((mod_path[7] - 'a' + 1) * 26 + (mod_path[8] - 'a')) / 16];
-        minor = (((mod_path[7] - 'a' + 1) * 26 + (mod_path[8] - 'a')) % 16)
-            * 16 + part;
-        retval = major * 256 + minor;
-    }
-    else if (disk_re_match("/dev/hd[a-t]([1-9]|[1-5][0-9]|6[0-3])?$",
-                           mod_path, &part)) {
-        major = ide_majors[(mod_path[7] - 'a') / 2];
-        minor = ((mod_path[7] - 'a') % 2) * 64 + part;
-        retval = major * 256 + minor;
-    }
-    else if (disk_re_match("/dev/xvd[a-p]([1-9]|1[0-5])?$", mod_path, &part))
-        retval = (202 << 8) + ((mod_path[8] - 'a') << 4) + part;
-    else if (disk_re_match("/dev/xvd[q-z]([1-9]|1[0-5])?$", mod_path, &part))
-        retval = (1 << 28) + ((mod_path[8] - 'a') << 8) + part;
-    else if (disk_re_match("/dev/xvd[a-i][a-z]([1-9]|1[0-5])?$",
-                           mod_path, &part))
-        retval = (1 << 28) + (((mod_path[8] - 'a' + 1) * 26 + (mod_path[9] - 'a')) << 8) + part;
-    /*
-     * OK, we've now checked the common case (things that work); check the
-     * beginning of the strings for better error messages
-     */
-    else if (strlen(mod_path) >= 7 && STRPREFIX(mod_path, "/dev/sd"))
-        statsErrorFunc (conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
-                        "invalid path, device names must be in the range sda[1-15] - sdiv[1-15]",
-                        domid);
-    else if (strlen(mod_path) >= 7 && STRPREFIX(mod_path, "/dev/hd"))
-        statsErrorFunc (conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
-                        "invalid path, device names must be in the range hda[1-63] - hdt[1-63]",
-                        domid);
-    else if (strlen(mod_path) >= 8 && STRPREFIX(mod_path, "/dev/xvd"))
-        statsErrorFunc (conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
-                        "invalid path, device names must be in the range xvda[1-15] - xvdiz[1-15]",
-                        domid);
-    else
-        statsErrorFunc (conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
-                        "unsupported path, use xvdN, hdN, or sdN", domid);
-
-    VIR_FREE(mod_path);
-
-    return retval;
-}
-
-int
-xenLinuxDomainBlockStats (xenUnifiedPrivatePtr priv,
-                          virDomainPtr dom,
-                          const char *path,
-                          struct _virDomainBlockStats *stats)
-{
-    int device = xenLinuxDomainDeviceID(dom->conn, dom->id, path);
-
-    if (device < 0)
-        return -1;
-
-    return read_bd_stats (dom->conn, priv, device, dom->id, stats);
-}
-
-#endif /* WITH_XEN */
 
 /*-------------------- interface stats --------------------*/
 /* Just reads the named interface, so not Xen or QEMU-specific.
index 076ccd7c8a649e3eb5475e90d4f2aa9398a94d68..033a50b64399c55f23519169d00639423b2ae894 100644 (file)
 
 #ifdef __linux__
 
-#include "xen_unified.h"
+#include "internal.h"
 
-extern int xenLinuxDomainBlockStats (xenUnifiedPrivatePtr priv,
-                                     virDomainPtr dom, const char *path,
-                                     struct _virDomainBlockStats *stats);
 extern int linuxDomainInterfaceStats (virConnectPtr conn, const char *path,
                                       struct _virDomainInterfaceStats *stats);
 
-extern int xenLinuxDomainDeviceID(virConnectPtr conn, int domid, const char *dev);
-
 #endif /* __linux__ */
 
 #endif /* __STATS_LINUX_H__ */
index a2b949551d41206096852878776e4aa1e10b9b1e..c2898f72cbfb11cf2fc1f18fc624cd1b2b0344a2 100644 (file)
@@ -44,6 +44,7 @@
 #include <sys/wait.h>
 #include <sys/ioctl.h>
 #include <sys/inotify.h>
+#include <sys/un.h>
 
 #include "uml_driver.h"
 #include "uml_conf.h"
diff --git a/src/xen/block_stats.c b/src/xen/block_stats.c
new file mode 100644 (file)
index 0000000..73b94c1
--- /dev/null
@@ -0,0 +1,370 @@
+/*
+ * Linux block and network stats.
+ *
+ * Copyright (C) 2007-2009 Red Hat, Inc.
+ *
+ * See COPYING.LIB for the License of this software
+ *
+ * Richard W.M. Jones <rjones@redhat.com>
+ */
+
+#include <config.h>
+
+/* This file only applies on Linux. */
+#ifdef __linux__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <regex.h>
+
+#include <xs.h>
+
+#include "virterror_internal.h"
+#include "datatypes.h"
+#include "util.h"
+#include "block_stats.h"
+#include "memory.h"
+
+#define VIR_FROM_THIS VIR_FROM_STATS_LINUX
+
+/**
+ * statsErrorFunc:
+ * @conn: the connection
+ * @error: the error number
+ * @func: the function failing
+ * @info: extra information string
+ * @value: extra information number
+ *
+ * Handle a stats error.
+ */
+static void
+statsErrorFunc (virConnectPtr conn,
+                virErrorNumber error, const char *func, const char *info,
+                int value)
+{
+    char fullinfo[1000];
+    const char *errmsg;
+
+    errmsg = virErrorMsg(error, info);
+    if (func != NULL) {
+        snprintf(fullinfo, sizeof (fullinfo) - 1, "%s: %s", func, info);
+        fullinfo[sizeof (fullinfo) - 1] = 0;
+        info = fullinfo;
+    }
+    virRaiseError(conn, NULL, NULL, VIR_FROM_STATS_LINUX, error,
+                    VIR_ERR_ERROR,
+                    errmsg, info, NULL, value, 0, errmsg, info,
+                    value);
+}
+
+/*-------------------- Xen: block stats --------------------*/
+
+#include <linux/major.h>
+
+/* This is normally defined in <linux/major.h> but previously we
+ * hard-coded it.  So if it's not defined, hard-code again.
+ */
+#ifndef XENVBD_MAJOR
+#define XENVBD_MAJOR 202
+#endif
+
+static int
+xstrtoint64 (char const *s, int base, int64_t *result)
+{
+    long long int lli;
+    char *p;
+
+    errno = 0;
+    lli = strtoll (s, &p, base);
+    if (errno || !(*p == 0 || *p == '\n') || p == s || (int64_t) lli != lli)
+        return -1;
+    *result = lli;
+    return 0;
+}
+
+static int64_t
+read_stat (const char *path)
+{
+    char str[64];
+    int64_t r;
+    int i;
+    FILE *fp;
+
+    fp = fopen (path, "r");
+    if (!fp)
+      return -1;
+
+    /* read, but don't bail out before closing */
+    i = fread (str, 1, sizeof str - 1, fp);
+
+    if (fclose (fp) != 0        /* disk error */
+        || i < 1)               /* ensure we read at least one byte */
+        return -1;
+
+    str[i] = '\0';              /* make sure the string is nul-terminated */
+    if (xstrtoint64 (str, 10, &r) == -1)
+        return -1;
+
+    return r;
+}
+
+static int64_t
+read_bd_stat (int device, int domid, const char *str)
+{
+    char path[PATH_MAX];
+    int64_t r;
+
+    snprintf (path, sizeof path,
+              "/sys/devices/xen-backend/vbd-%d-%d/statistics/%s",
+              domid, device, str);
+    r = read_stat (path);
+    if (r >= 0) return r;
+
+    snprintf (path, sizeof path,
+              "/sys/devices/xen-backend/tap-%d-%d/statistics/%s",
+              domid, device, str);
+    r = read_stat (path);
+    return r;
+}
+
+/* In Xenstore, /local/domain/0/backend/vbd/<domid>/<device>/state,
+ * if available, must be XenbusStateConnected (= 4), otherwise there
+ * is no connected device.
+ */
+static int
+check_bd_connected (xenUnifiedPrivatePtr priv, int device, int domid)
+{
+    char s[256], *rs;
+    int r;
+    unsigned len = 0;
+
+    /* This code assumes we're connected if we can't get to
+     * xenstore, etc.
+     */
+    if (!priv->xshandle) return 1;
+    snprintf (s, sizeof s, "/local/domain/0/backend/vbd/%d/%d/state",
+              domid, device);
+    s[sizeof s - 1] = '\0';
+
+    rs = xs_read (priv->xshandle, 0, s, &len);
+    if (!rs) return 1;
+    if (len == 0) {
+        /* Hmmm ... we can get to xenstore but it returns an empty
+         * string instead of an error.  Assume it's not connected
+         * in this case.
+         */
+        free (rs);
+        return 0;
+    }
+
+    r = STREQ (rs, "4");
+    free (rs);
+    return r;
+}
+
+static int
+read_bd_stats (virConnectPtr conn, xenUnifiedPrivatePtr priv,
+               int device, int domid, struct _virDomainBlockStats *stats)
+{
+    stats->rd_req   = read_bd_stat (device, domid, "rd_req");
+    stats->rd_bytes = read_bd_stat (device, domid, "rd_sect");
+    stats->wr_req   = read_bd_stat (device, domid, "wr_req");
+    stats->wr_bytes = read_bd_stat (device, domid, "wr_sect");
+    stats->errs     = read_bd_stat (device, domid, "oo_req");
+
+    /* None of the files were found - it's likely that this version
+     * of Xen is an old one which just doesn't support stats collection.
+     */
+    if (stats->rd_req == -1 && stats->rd_bytes == -1 &&
+        stats->wr_req == -1 && stats->wr_bytes == -1 &&
+        stats->errs == -1) {
+        statsErrorFunc (conn, VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
+                        "Failed to read any block statistics", domid);
+        return -1;
+    }
+
+    /* If stats are all zero then either there really isn't any block
+     * device activity, or there is no connected front end device
+     * in which case there are no stats.
+     */
+    if (stats->rd_req == 0 && stats->rd_bytes == 0 &&
+        stats->wr_req == 0 && stats->wr_bytes == 0 &&
+        stats->errs == 0 &&
+        !check_bd_connected (priv, device, domid)) {
+        statsErrorFunc (conn, VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
+                        "Frontend block device not connected", domid);
+        return -1;
+    }
+
+    /* 'Bytes' was really sectors when we read it.  Scale up by
+     * an assumed sector size.
+     */
+    if (stats->rd_bytes > 0) {
+        if (stats->rd_bytes >= ((unsigned long long)1)<<(63-9)) {
+            statsErrorFunc (conn, VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
+                            "stats->rd_bytes would overflow 64 bit counter",
+                            domid);
+            return -1;
+        }
+        stats->rd_bytes *= 512;
+    }
+    if (stats->wr_bytes > 0) {
+        if (stats->wr_bytes >= ((unsigned long long)1)<<(63-9)) {
+            statsErrorFunc (conn, VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
+                            "stats->wr_bytes would overflow 64 bit counter",
+                            domid);
+            return -1;
+        }
+        stats->wr_bytes *= 512;
+    }
+
+    return 0;
+}
+
+static int
+disk_re_match(const char *regex, const char *path, int *part)
+{
+    regex_t myreg;
+    int err;
+    int retval;
+    regmatch_t pmatch[3];
+
+    retval = 0;
+
+    err = regcomp(&myreg, regex, REG_EXTENDED);
+    if (err != 0)
+        return 0;
+
+    err = regexec(&myreg, path, 3, pmatch, 0);
+
+    if (err == 0) {
+        /* OK, we have a match; see if we have a partition */
+        *part = 0;
+        retval = 1;
+        if (pmatch[1].rm_so != -1) {
+            if (virStrToLong_i(path + pmatch[1].rm_so, NULL, 10, part) < 0)
+                retval = 0;
+        }
+    }
+
+    regfree(&myreg);
+
+    return retval;
+}
+
+int
+xenLinuxDomainDeviceID(virConnectPtr conn, int domid, const char *path)
+{
+    int major, minor;
+    int part;
+    int retval;
+    char *mod_path;
+
+    int const scsi_majors[] = { SCSI_DISK0_MAJOR, SCSI_DISK1_MAJOR,
+                                SCSI_DISK2_MAJOR, SCSI_DISK3_MAJOR,
+                                SCSI_DISK4_MAJOR, SCSI_DISK5_MAJOR,
+                                SCSI_DISK6_MAJOR, SCSI_DISK7_MAJOR,
+                                SCSI_DISK8_MAJOR, SCSI_DISK9_MAJOR,
+                                SCSI_DISK10_MAJOR, SCSI_DISK11_MAJOR,
+                                SCSI_DISK12_MAJOR, SCSI_DISK13_MAJOR,
+                                SCSI_DISK14_MAJOR, SCSI_DISK15_MAJOR };
+    int const ide_majors[] = { IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR,
+                               IDE4_MAJOR, IDE5_MAJOR, IDE6_MAJOR, IDE7_MAJOR,
+                               IDE8_MAJOR, IDE9_MAJOR };
+
+    /*
+     * Possible block device majors & partition ranges. This
+     * matches the ranges supported in Xend xen/util/blkif.py
+     *
+     * hdNM:  N=a-t, M=1-63, major={IDE0_MAJOR -> IDE9_MAJOR}
+     * sdNM:  N=a-z,aa-iv, M=1-15, major={SCSI_DISK0_MAJOR -> SCSI_DISK15_MAJOR}
+     * xvdNM: N=a-p M=1-15, major=XENVBD_MAJOR
+     * xvdNM: N=q-z,aa-iz M=1-15, major=(1<<28)
+     *
+     * The path for statistics will be
+     *
+     * /sys/devices/xen-backend/(vbd|tap)-{domid}-{devid}/statistics/{...}
+     */
+
+    if (strlen(path) >= 5 && STRPREFIX(path, "/dev/"))
+        retval = virAsprintf(&mod_path, "%s", path);
+    else
+        retval = virAsprintf(&mod_path, "/dev/%s", path);
+
+    if (retval < 0) {
+        virReportOOMError (conn);
+        return -1;
+    }
+
+    retval = -1;
+
+    if (disk_re_match("/dev/sd[a-z]([1-9]|1[0-5])?$", mod_path, &part)) {
+        major = scsi_majors[(mod_path[7] - 'a') / 16];
+        minor = ((mod_path[7] - 'a') % 16) * 16 + part;
+        retval = major * 256 + minor;
+    }
+    else if (disk_re_match("/dev/sd[a-h][a-z]([1-9]|1[0-5])?$",
+                           mod_path, &part) ||
+             disk_re_match("/dev/sdi[a-v]([1-9]|1[0-5])?$",
+                           mod_path, &part)) {
+        major = scsi_majors[((mod_path[7] - 'a' + 1) * 26 + (mod_path[8] - 'a')) / 16];
+        minor = (((mod_path[7] - 'a' + 1) * 26 + (mod_path[8] - 'a')) % 16)
+            * 16 + part;
+        retval = major * 256 + minor;
+    }
+    else if (disk_re_match("/dev/hd[a-t]([1-9]|[1-5][0-9]|6[0-3])?$",
+                           mod_path, &part)) {
+        major = ide_majors[(mod_path[7] - 'a') / 2];
+        minor = ((mod_path[7] - 'a') % 2) * 64 + part;
+        retval = major * 256 + minor;
+    }
+    else if (disk_re_match("/dev/xvd[a-p]([1-9]|1[0-5])?$", mod_path, &part))
+        retval = (202 << 8) + ((mod_path[8] - 'a') << 4) + part;
+    else if (disk_re_match("/dev/xvd[q-z]([1-9]|1[0-5])?$", mod_path, &part))
+        retval = (1 << 28) + ((mod_path[8] - 'a') << 8) + part;
+    else if (disk_re_match("/dev/xvd[a-i][a-z]([1-9]|1[0-5])?$",
+                           mod_path, &part))
+        retval = (1 << 28) + (((mod_path[8] - 'a' + 1) * 26 + (mod_path[9] - 'a')) << 8) + part;
+    /*
+     * OK, we've now checked the common case (things that work); check the
+     * beginning of the strings for better error messages
+     */
+    else if (strlen(mod_path) >= 7 && STRPREFIX(mod_path, "/dev/sd"))
+        statsErrorFunc (conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
+                        "invalid path, device names must be in the range sda[1-15] - sdiv[1-15]",
+                        domid);
+    else if (strlen(mod_path) >= 7 && STRPREFIX(mod_path, "/dev/hd"))
+        statsErrorFunc (conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
+                        "invalid path, device names must be in the range hda[1-63] - hdt[1-63]",
+                        domid);
+    else if (strlen(mod_path) >= 8 && STRPREFIX(mod_path, "/dev/xvd"))
+        statsErrorFunc (conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
+                        "invalid path, device names must be in the range xvda[1-15] - xvdiz[1-15]",
+                        domid);
+    else
+        statsErrorFunc (conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
+                        "unsupported path, use xvdN, hdN, or sdN", domid);
+
+    VIR_FREE(mod_path);
+
+    return retval;
+}
+
+int
+xenLinuxDomainBlockStats (xenUnifiedPrivatePtr priv,
+                          virDomainPtr dom,
+                          const char *path,
+                          struct _virDomainBlockStats *stats)
+{
+    int device = xenLinuxDomainDeviceID(dom->conn, dom->id, path);
+
+    if (device < 0)
+        return -1;
+
+    return read_bd_stats (dom->conn, priv, device, dom->id, stats);
+}
+
+#endif /* __linux__ */
diff --git a/src/xen/block_stats.h b/src/xen/block_stats.h
new file mode 100644 (file)
index 0000000..e29c0b5
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Linux block and network stats.
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ *
+ * See COPYING.LIB for the License of this software
+ *
+ * Richard W.M. Jones <rjones@redhat.com>
+ */
+
+#ifndef __BLOCK_STATS_H__
+#define __BLOCK_STATS_H__
+
+#ifdef __linux__
+
+#include "xen_driver.h"
+
+extern int xenLinuxDomainBlockStats (xenUnifiedPrivatePtr priv,
+                                     virDomainPtr dom, const char *path,
+                                     struct _virDomainBlockStats *stats);
+
+extern int xenLinuxDomainDeviceID(virConnectPtr conn, int domid, const char *dev);
+
+#endif /* __linux__ */
+
+#endif /* __STATS_LINUX_H__ */
diff --git a/src/xen/proxy_internal.c b/src/xen/proxy_internal.c
new file mode 100644 (file)
index 0000000..49127d7
--- /dev/null
@@ -0,0 +1,1049 @@
+/*
+ * proxy_client.c: client side of the communication with the libvirt proxy.
+ *
+ * Copyright (C) 2006, 2008, 2009 Red Hat, Inc.
+ *
+ * See COPYING.LIB for the License of this software
+ *
+ * Daniel Veillard <veillard@redhat.com>
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/wait.h>
+#include <string.h>
+
+#include "virterror_internal.h"
+#include "logging.h"
+#include "datatypes.h"
+#include "driver.h"
+#include "proxy_internal.h"
+#include "util.h"
+#include "xen_driver.h"
+#include "memory.h"
+
+#define STANDALONE
+
+#define VIR_FROM_THIS VIR_FROM_PROXY
+
+static int xenProxyClose(virConnectPtr conn);
+static virDrvOpenStatus xenProxyOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags);
+static int xenProxyGetVersion(virConnectPtr conn, unsigned long *hvVer);
+static int xenProxyNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info);
+static char *xenProxyGetCapabilities(virConnectPtr conn);
+static int xenProxyNumOfDomains(virConnectPtr conn);
+static unsigned long xenProxyDomainGetMaxMemory(virDomainPtr domain);
+static int xenProxyDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info);
+static char *xenProxyDomainGetOSType(virDomainPtr domain);
+
+struct xenUnifiedDriver xenProxyDriver = {
+    xenProxyOpen, /* open */
+    xenProxyClose, /* close */
+    xenProxyGetVersion, /* version */
+    NULL, /* hostname */
+    xenProxyNodeGetInfo, /* nodeGetInfo */
+    xenProxyGetCapabilities, /* getCapabilities */
+    xenProxyListDomains, /* listDomains */
+    xenProxyNumOfDomains, /* numOfDomains */
+    NULL, /* domainCreateXML */
+    NULL, /* domainSuspend */
+    NULL, /* domainResume */
+    NULL, /* domainShutdown */
+    NULL, /* domainReboot */
+    NULL, /* domainDestroy */
+    xenProxyDomainGetOSType, /* domainGetOSType */
+    xenProxyDomainGetMaxMemory, /* domainGetMaxMemory */
+    NULL, /* domainSetMaxMemory */
+    NULL, /* domainSetMemory */
+    xenProxyDomainGetInfo, /* domainGetInfo */
+    NULL, /* domainSave */
+    NULL, /* domainRestore */
+    NULL, /* domainCoreDump */
+    NULL, /* domainSetVcpus */
+    NULL, /* domainPinVcpu */
+    NULL, /* domainGetVcpus */
+    NULL, /* domainGetMaxVcpus */
+    NULL, /* listDefinedDomains */
+    NULL, /* numOfDefinedDomains */
+    NULL, /* domainCreate */
+    NULL, /* domainDefineXML */
+    NULL, /* domainUndefine */
+    NULL, /* domainAttachDevice */
+    NULL, /* domainDetachDevice */
+    NULL, /* domainGetAutostart */
+    NULL, /* domainSetAutostart */
+    NULL, /* domainGetSchedulerType */
+    NULL, /* domainGetSchedulerParameters */
+    NULL, /* domainSetSchedulerParameters */
+};
+
+
+/************************************************************************
+ *                                                                     *
+ *                     Error handling                                  *
+ *                                                                     *
+ ************************************************************************/
+
+#define virProxyError(conn, code, fmt...)                                    \
+        virReportErrorHelper(conn, VIR_FROM_PROXY, code, __FILE__,         \
+                               __FUNCTION__, __LINE__, fmt)
+
+/************************************************************************
+ *                                                                     *
+ *     Automatic startup of the proxy server if it is not running      *
+ *                                                                     *
+ ************************************************************************/
+/**
+ * virProxyFindServerPath:
+ *
+ * Tries to find the path to the gam_server binary.
+ *
+ * Returns path on success or NULL in case of error.
+ */
+static const char *
+virProxyFindServerPath(void)
+{
+    static const char *serverPaths[] = {
+        BINDIR "/libvirt_proxy",
+        "/usr/bin/libvirt_proxy_dbg",
+        NULL
+    };
+    int i;
+    const char *debugProxy = getenv("LIBVIRT_DEBUG_PROXY");
+
+    if (debugProxy)
+        return(debugProxy);
+
+    for (i = 0; serverPaths[i]; i++) {
+        if (access(serverPaths[i], X_OK | R_OK) == 0) {
+            return serverPaths[i];
+        }
+    }
+    return NULL;
+}
+
+/**
+ * virProxyForkServer:
+ *
+ * Forks and try to launch the proxy server processing the requests for
+ * libvirt when communicating with Xen.
+ *
+ * Returns 0 in case of success or -1 in case of detected error.
+ */
+static int
+virProxyForkServer(void)
+{
+    const char *proxyPath = virProxyFindServerPath();
+    pid_t pid;
+    const char *proxyarg[2];
+
+    if (!proxyPath) {
+        VIR_WARN0("failed to find libvirt_proxy\n");
+        return(-1);
+    }
+
+    VIR_DEBUG("Asking to launch %s\n", proxyPath);
+
+    proxyarg[0] = proxyPath;
+    proxyarg[1] = NULL;
+
+    if (virExecDaemonize(NULL, proxyarg, NULL, NULL,
+                         &pid, -1, NULL, NULL, 0,
+                         NULL, NULL, NULL) < 0)
+        VIR_ERROR0("Failed to fork libvirt_proxy\n");
+
+    return (0);
+}
+
+/************************************************************************
+ *                                                                     *
+ *             Processing of client sockets                            *
+ *                                                                     *
+ ************************************************************************/
+
+/**
+ * virProxyOpenClientSocket:
+ * @path: the filename for the socket
+ *
+ * try to connect to the socket open by libvirt_proxy
+ *
+ * Returns the associated file descriptor or -1 in case of failure
+ */
+static int
+virProxyOpenClientSocket(const char *path) {
+    int fd;
+    struct sockaddr_un addr;
+    int trials = 0;
+
+retry:
+    fd = socket(PF_UNIX, SOCK_STREAM, 0);
+    if (fd < 0) {
+        return(-1);
+    }
+
+    /*
+     * Abstract socket do not hit the filesystem, way more secure and
+     * guaranteed to be atomic
+     */
+    memset(&addr, 0, sizeof(addr));
+    addr.sun_family = AF_UNIX;
+    addr.sun_path[0] = '\0';
+    strncpy(&addr.sun_path[1], path, (sizeof(addr) - 4) - 2);
+
+    /*
+     * now bind the socket to that address and listen on it
+     */
+    if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+        close(fd);
+        if (trials < 3) {
+            if (virProxyForkServer() < 0)
+                return(-1);
+            trials++;
+            usleep(5000 * trials * trials);
+            goto retry;
+        }
+        return (-1);
+    }
+
+    DEBUG("connected to unix socket %s via %d\n", path, fd);
+
+    return (fd);
+}
+
+/**
+ * virProxyCloseSocket:
+ * @priv: the Xen proxy data
+ *
+ * Close the socket from that client. The caller must
+ * hold the lock on 'priv' before calling
+ *
+ * Returns 0 in case of success and -1 in case of error
+ */
+static int
+virProxyCloseSocket(xenUnifiedPrivatePtr priv) {
+    int ret;
+
+    if (priv->proxy < 0)
+        return(-1);
+
+    ret = close(priv->proxy);
+    if (ret != 0)
+        VIR_WARN(_("Failed to close socket %d\n"), priv->proxy);
+    else
+        VIR_DEBUG("Closed socket %d\n", priv->proxy);
+    priv->proxy = -1;
+    return(ret);
+}
+
+/**
+ * virProxyReadClientSocket:
+ * @fd: the socket
+ * @buffer: the target memory area
+ * @len: the length in bytes
+ *
+ * Process a read from a client socket
+ *
+ * Returns the number of byte read or -1 in case of error.
+ */
+static int
+virProxyReadClientSocket(int fd, char *buffer, int len) {
+    int ret;
+
+    if ((fd < 0) || (buffer == NULL) || (len < 0))
+        return(-1);
+
+retry:
+    ret = read(fd, buffer, len);
+    if (ret < 0) {
+        if (errno == EINTR) {
+            VIR_DEBUG("read socket %d interrupted\n", fd);
+            goto retry;
+        }
+        VIR_WARN("Failed to read socket %d\n", fd);
+        return(-1);
+    }
+
+    VIR_DEBUG("read %d bytes from socket %d\n",
+              ret, fd);
+    return(ret);
+}
+
+/**
+ * virProxyWriteClientSocket:
+ * @fd: the socket
+ * @data: the data
+ * @len: the length of data in bytes
+ *
+ * Process a read from a client socket
+ */
+static int
+virProxyWriteClientSocket(int fd, const char *data, int len) {
+    int ret;
+
+    if ((fd < 0) || (data == NULL) || (len < 0))
+        return(-1);
+
+    ret = safewrite(fd, data, len);
+    if (ret < 0) {
+        VIR_WARN(_("Failed to write to socket %d\n"), fd);
+        return(-1);
+    }
+    VIR_DEBUG("wrote %d bytes to socket %d\n",
+              len, fd);
+
+    return(0);
+}
+
+/************************************************************************
+ *                                                                     *
+ *                     Proxy commands processing                       *
+ *                                                                     *
+ ************************************************************************/
+
+/**
+ * xenProxyClose:
+ * @conn: pointer to the hypervisor connection
+ *
+ * Shutdown the Xen proxy communication layer
+ */
+static int
+xenProxyClose(virConnectPtr conn)
+{
+    xenUnifiedPrivatePtr priv;
+
+    if (conn == NULL) {
+        virProxyError (NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return -1;
+    }
+
+    priv = (xenUnifiedPrivatePtr) conn->privateData;
+    if (!priv) {
+        virProxyError (NULL, VIR_ERR_INTERNAL_ERROR, __FUNCTION__);
+        return -1;
+    }
+
+    xenUnifiedLock(priv);
+    virProxyCloseSocket (priv);
+    xenUnifiedUnlock(priv);
+
+    return 0;
+}
+
+static int
+xenProxyCommand(virConnectPtr conn, virProxyPacketPtr request,
+                virProxyFullPacketPtr answer, int quiet) {
+    static int serial = 0;
+    int ret;
+    virProxyPacketPtr res = NULL;
+    xenUnifiedPrivatePtr priv;
+
+    if (conn == NULL) {
+        virProxyError (NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return -1;
+    }
+
+    priv = (xenUnifiedPrivatePtr) conn->privateData;
+    if (!priv) {
+        virProxyError (NULL, VIR_ERR_INTERNAL_ERROR, __FUNCTION__);
+        return -1;
+    }
+
+    xenUnifiedLock(priv);
+
+    /* Fail silently. */
+    if (priv->proxy == -1)
+        goto error;
+
+    /*
+     * normal communication serial numbers are in 0..4095
+     */
+    ++serial;
+    if (serial >= 4096)
+        serial = 0;
+    request->version = PROXY_PROTO_VERSION;
+    request->serial = serial;
+    ret  = virProxyWriteClientSocket(priv->proxy, (const char *) request,
+                                     request->len);
+    if (ret < 0) {
+        if (!quiet)
+            virReportSystemError(conn, errno, "%s",
+                                 _("failed to write proxy request"));
+        goto error;
+    }
+retry:
+    if (answer == NULL) {
+        /* read in situ */
+        ret  = virProxyReadClientSocket(priv->proxy, (char *) request,
+                                        sizeof(virProxyPacket));
+        if (ret < 0) {
+            if (!quiet)
+                virReportSystemError(conn, errno, "%s",
+                                     _("failed to read proxy reply"));
+            goto error;
+        }
+        if (ret != sizeof(virProxyPacket)) {
+            virProxyError(conn, VIR_ERR_INTERNAL_ERROR,
+                          _("Communication error with proxy: got %d bytes of %d\n"),
+                          ret, (int) sizeof(virProxyPacket));
+            goto error;
+        }
+        res = request;
+        if (res->len != sizeof(virProxyPacket)) {
+            virProxyError(conn, VIR_ERR_INTERNAL_ERROR,
+                          _("Communication error with proxy: expected %d bytes got %d\n"),
+                          (int) sizeof(virProxyPacket), res->len);
+            goto error;
+        }
+    } else {
+        /* read in packet provided */
+        ret  = virProxyReadClientSocket(priv->proxy, (char *) answer,
+                                        sizeof(virProxyPacket));
+        if (ret < 0) {
+            if (!quiet)
+                virReportSystemError(conn, errno, "%s",
+                                     _("failed to read proxy reply"));
+            goto error;
+        }
+        if (ret != sizeof(virProxyPacket)) {
+            virProxyError(conn, VIR_ERR_INTERNAL_ERROR,
+                          _("Communication error with proxy: got %d bytes of %d\n"),
+                          ret, (int) sizeof(virProxyPacket));
+            goto error;
+        }
+        res = (virProxyPacketPtr) answer;
+        if ((res->len < sizeof(virProxyPacket)) ||
+            (res->len > sizeof(virProxyFullPacket))) {
+            virProxyError(conn, VIR_ERR_INTERNAL_ERROR,
+                          _("Communication error with proxy: got %d bytes packet\n"),
+                          res->len);
+            goto error;
+        }
+        if (res->len > sizeof(virProxyPacket)) {
+            ret  = virProxyReadClientSocket(priv->proxy,
+                                   (char *) &(answer->extra.arg[0]),
+                                            res->len - ret);
+            if (ret != (int) (res->len - sizeof(virProxyPacket))) {
+                virProxyError(conn, VIR_ERR_INTERNAL_ERROR,
+                              _("Communication error with proxy: got %d bytes of %d\n"),
+                              ret, (int) sizeof(virProxyPacket));
+                goto error;
+            }
+        }
+    }
+    /*
+     * do more checks on the incoming packet.
+     */
+    if ((res == NULL) || (res->version != PROXY_PROTO_VERSION) ||
+        (res->len < sizeof(virProxyPacket))) {
+        virProxyError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
+                      _("Communication error with proxy: malformed packet\n"));
+        goto error;
+    }
+    if (res->serial != serial) {
+        VIR_WARN(_("got asynchronous packet number %d\n"), res->serial);
+        goto retry;
+    }
+
+    xenUnifiedUnlock(priv);
+    return 0;
+
+error:
+    virProxyCloseSocket(priv);
+    xenUnifiedUnlock(priv);
+    return -1;
+}
+
+/**
+ * xenProxyOpen:
+ * @conn: pointer to the hypervisor connection
+ * @name: URL for the target, NULL for local
+ * @flags: combination of virDrvOpenFlag(s)
+ *
+ * Try to initialize the Xen proxy communication layer
+ * This can be opened only for a read-only kind of access
+ *
+ * Returns 0 in case of success, and -1 in case of failure
+ */
+virDrvOpenStatus
+xenProxyOpen(virConnectPtr conn,
+             virConnectAuthPtr auth ATTRIBUTE_UNUSED,
+             int flags)
+{
+    virProxyPacket req;
+    int ret;
+    int fd;
+    xenUnifiedPrivatePtr priv;
+
+    if (!(flags & VIR_CONNECT_RO))
+        return(-1);
+
+    priv = (xenUnifiedPrivatePtr) conn->privateData;
+    priv->proxy = -1;
+
+    fd = virProxyOpenClientSocket(PROXY_SOCKET_PATH);
+    if (fd < 0) {
+            virProxyError(NULL, VIR_ERR_NO_XEN, PROXY_SOCKET_PATH);
+        return(-1);
+    }
+    priv->proxy = fd;
+
+    memset(&req, 0, sizeof(req));
+    req.command = VIR_PROXY_NONE;
+    req.len = sizeof(req);
+    ret = xenProxyCommand(conn, &req, NULL, 1);
+    if ((ret < 0) || (req.command != VIR_PROXY_NONE)) {
+            virProxyError(NULL, VIR_ERR_OPERATION_FAILED, __FUNCTION__);
+        return(-1);
+    }
+    return(0);
+}
+
+/************************************************************************
+ *                                                                     *
+ *                     Driver entry points                             *
+ *                                                                     *
+ ************************************************************************/
+
+/**
+ * xenProxyGetVersion:
+ * @conn: pointer to the Xen Daemon block
+ * @hvVer: return value for the version of the running hypervisor (OUT)
+ *
+ * Get the version level of the Hypervisor running.
+ *
+ * Returns -1 in case of error, 0 otherwise. if the version can't be
+ *    extracted by lack of capacities returns 0 and @hvVer is 0, otherwise
+ *    @hvVer value is major * 1,000,000 + minor * 1,000 + release
+ */
+static int
+xenProxyGetVersion(virConnectPtr conn, unsigned long *hvVer)
+{
+    virProxyPacket req;
+    int ret;
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virProxyError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (-1);
+    }
+    if (hvVer == NULL) {
+        virProxyError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (-1);
+    }
+    memset(&req, 0, sizeof(req));
+    req.command = VIR_PROXY_VERSION;
+    req.len = sizeof(req);
+    ret = xenProxyCommand(conn, &req, NULL, 0);
+    if (ret < 0) {
+        return(-1);
+    }
+    *hvVer = req.data.larg;
+    return(0);
+}
+
+/**
+ * xenProxyListDomains:
+ * @conn: pointer to the hypervisor connection
+ * @ids: array to collect the list of IDs of active domains
+ * @maxids: size of @ids
+ *
+ * Collect the list of active domains, and store their ID in @maxids
+ *
+ * Returns the number of domain found or -1 in case of error
+ */
+int
+xenProxyListDomains(virConnectPtr conn, int *ids, int maxids)
+{
+    virProxyPacket req;
+    virProxyFullPacket ans;
+    int ret;
+    int nb;
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virProxyError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (-1);
+    }
+    if ((ids == NULL) || (maxids <= 0)) {
+        virProxyError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (-1);
+    }
+    memset(&req, 0, sizeof(req));
+    req.command = VIR_PROXY_LIST;
+    req.len = sizeof(req);
+    ret = xenProxyCommand(conn, &req, &ans, 0);
+    if (ret < 0) {
+        return(-1);
+    }
+    nb = ans.data.arg;
+    if ((nb > 1020) || (nb <= 0) ||
+        (ans.len <= sizeof(virProxyPacket)) ||
+        (ans.len > sizeof(virProxyFullPacket))) {
+        virProxyError(conn, VIR_ERR_OPERATION_FAILED, __FUNCTION__);
+        return(-1);
+    }
+    if (nb > maxids)
+        nb = maxids;
+    memmove(ids, &ans.extra.arg[0], nb * sizeof(int));
+
+    return(nb);
+}
+
+/**
+ * xenProxyNumOfDomains:
+ * @conn: pointer to the hypervisor connection
+ *
+ * Provides the number of active domains.
+ *
+ * Returns the number of domain found or -1 in case of error
+ */
+static int
+xenProxyNumOfDomains(virConnectPtr conn)
+{
+    virProxyPacket req;
+    int ret;
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virProxyError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (-1);
+    }
+    memset(&req, 0, sizeof(req));
+    req.command = VIR_PROXY_NUM_DOMAIN;
+    req.len = sizeof(req);
+    ret = xenProxyCommand(conn, &req, NULL, 0);
+    if (ret < 0) {
+        return(-1);
+    }
+    return(req.data.arg);
+}
+
+
+/**
+ * xenProxyDomainGetDomMaxMemory:
+ * @conn: pointer to the hypervisor connection
+ * @id: the domain ID number
+ *
+ * Ask the Xen Daemon for the maximum memory allowed for a domain
+ *
+ * Returns the memory size in kilobytes or 0 in case of error.
+ */
+static unsigned long
+xenProxyDomainGetDomMaxMemory(virConnectPtr conn, int id)
+{
+    virProxyPacket req;
+    int ret;
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virProxyError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (0);
+    }
+    memset(&req, 0, sizeof(req));
+    req.command = VIR_PROXY_MAX_MEMORY;
+    req.data.arg = id;
+    req.len = sizeof(req);
+    ret = xenProxyCommand(conn, &req, NULL, 0);
+    if (ret < 0) {
+        return(0);
+    }
+    return(req.data.larg);
+}
+
+/**
+ * xenProxyDomainGetMaxMemory:
+ * @domain: pointer to the domain block
+ *
+ * Ask the Xen Daemon for the maximum memory allowed for a domain
+ *
+ * Returns the memory size in kilobytes or 0 in case of error.
+ */
+static unsigned long
+xenProxyDomainGetMaxMemory(virDomainPtr domain)
+{
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+        if (domain == NULL)
+            virProxyError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        else
+            virProxyError(domain->conn, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return (0);
+    }
+    if (domain->id < 0)
+        return (0);
+    return(xenProxyDomainGetDomMaxMemory(domain->conn, domain->id));
+}
+
+/**
+ * xenProxyDomainGetInfo:
+ * @domain: a domain object
+ * @info: pointer to a virDomainInfo structure allocated by the user
+ *
+ * This method looks up information about a domain and update the
+ * information block provided.
+ *
+ * Returns 0 in case of success, -1 in case of error
+ */
+static int
+xenProxyDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
+{
+    virProxyPacket req;
+    virProxyFullPacket ans;
+    int ret;
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+        if (domain == NULL)
+            virProxyError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        else
+            virProxyError(domain->conn, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return (-1);
+    }
+    if (domain->id < 0)
+        return (-1);
+    if (info == NULL) {
+        virProxyError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (-1);
+    }
+    memset(&req, 0, sizeof(req));
+    req.command = VIR_PROXY_DOMAIN_INFO;
+    req.data.arg = domain->id;
+    req.len = sizeof(req);
+    ret = xenProxyCommand(domain->conn, &req, &ans, 0);
+    if (ret < 0) {
+        return(-1);
+    }
+    if (ans.len != sizeof(virProxyPacket) + sizeof(virDomainInfo)) {
+        virProxyError(domain->conn, VIR_ERR_OPERATION_FAILED, __FUNCTION__);
+        return (-1);
+    }
+    memmove(info, &ans.extra.dinfo, sizeof(virDomainInfo));
+
+    return(0);
+}
+
+/**
+ * xenProxyLookupByID:
+ * @conn: pointer to the hypervisor connection
+ * @id: the domain ID number
+ *
+ * Try to find a domain based on the hypervisor ID number
+ *
+ * Returns a new domain object or NULL in case of failure
+ */
+virDomainPtr
+xenProxyLookupByID(virConnectPtr conn, int id)
+{
+    virProxyPacket req;
+    virProxyFullPacket ans;
+    unsigned char uuid[VIR_UUID_BUFLEN];
+    const char *name;
+    int ret;
+    virDomainPtr res;
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virProxyError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (NULL);
+    }
+    if (id < 0) {
+        virProxyError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (NULL);
+    }
+    memset(&req, 0, sizeof(req));
+    req.command = VIR_PROXY_LOOKUP_ID;
+    req.data.arg = id;
+    req.len = sizeof(req);
+    ret = xenProxyCommand(conn, &req, &ans, 0);
+    if (ret < 0) {
+        return(NULL);
+    }
+    if (ans.data.arg == -1) {
+        return(NULL);
+    }
+    memcpy(uuid, &ans.extra.str[0], VIR_UUID_BUFLEN);
+    name = &ans.extra.str[VIR_UUID_BUFLEN];
+    res = virGetDomain(conn, name, uuid);
+        if (res) res->id = id;
+    return(res);
+}
+
+/**
+ * xenProxyLookupByUUID:
+ * @conn: pointer to the hypervisor connection
+ * @uuid: the raw UUID for the domain
+ *
+ * Try to lookup a domain on xend based on its UUID.
+ *
+ * Returns a new domain object or NULL in case of failure
+ */
+virDomainPtr
+xenProxyLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
+{
+    virProxyFullPacket req;
+    const char *name;
+    int ret;
+    virDomainPtr res;
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virProxyError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (NULL);
+    }
+    if (uuid == NULL) {
+        virProxyError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (NULL);
+    }
+    memset(&req, 0, sizeof(virProxyPacket));
+    req.command = VIR_PROXY_LOOKUP_UUID;
+    req.len = sizeof(virProxyPacket) + VIR_UUID_BUFLEN;
+    memcpy(&req.extra.str[0], uuid, VIR_UUID_BUFLEN);
+
+    ret = xenProxyCommand(conn, (virProxyPacketPtr) &req, &req, 0);
+    if (ret < 0) {
+        return(NULL);
+    }
+    if (req.data.arg == -1) {
+        return(NULL);
+    }
+    name = &req.extra.str[0];
+    res = virGetDomain(conn, name, uuid);
+        if (res) res->id = req.data.arg;
+    return(res);
+}
+
+/**
+ * xenProxyLookupByName:
+ * @conn: A xend instance
+ * @name: The name of the domain
+ *
+ * This method looks up information about a domain based on its name
+ *
+ * Returns a new domain object or NULL in case of failure
+ */
+virDomainPtr
+xenProxyLookupByName(virConnectPtr conn, const char *name)
+{
+    virProxyFullPacket req;
+    int ret, len;
+    virDomainPtr res;
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virProxyError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (NULL);
+    }
+    if (name == NULL) {
+        virProxyError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (NULL);
+    }
+    len = strlen(name);
+    if (len > 1000) {
+        virProxyError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (NULL);
+    }
+    memset(&req, 0, sizeof(virProxyPacket));
+    req.command = VIR_PROXY_LOOKUP_NAME;
+    req.len = sizeof(virProxyPacket) + len + 1;
+    strcpy(&req.extra.str[0], name);
+    ret = xenProxyCommand(conn, (virProxyPacketPtr) &req, &req, 0);
+    if (ret < 0) {
+        return(NULL);
+    }
+    if (req.data.arg == -1) {
+        return(NULL);
+    }
+    res = virGetDomain(conn, name, (const unsigned char *)&req.extra.str[0]);
+        if (res) res->id = req.data.arg;
+    return(res);
+}
+
+/**
+ * xenProxyNodeGetInfo:
+ * @conn: pointer to the Xen Daemon block
+ * @info: pointer to a virNodeInfo structure allocated by the user
+ *
+ * Extract hardware information about the node.
+ *
+ * Returns 0 in case of success and -1 in case of failure.
+ */
+static int
+xenProxyNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info) {
+    virProxyPacket req;
+    virProxyFullPacket ans;
+    int ret;
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virProxyError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (-1);
+    }
+    if (info == NULL) {
+        virProxyError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (-1);
+    }
+    memset(&req, 0, sizeof(req));
+    req.command = VIR_PROXY_NODE_INFO;
+    req.data.arg = 0;
+    req.len = sizeof(req);
+    ret = xenProxyCommand(conn, &req, &ans, 0);
+    if (ret < 0) {
+        return(-1);
+    }
+    if (ans.data.arg == -1) {
+        return(-1);
+    }
+    if (ans.len != sizeof(virProxyPacket) + sizeof(virNodeInfo)) {
+        return(-1);
+    }
+    memcpy(info, &ans.extra.ninfo, sizeof(virNodeInfo));
+    return(0);
+}
+
+/**
+ * xenProxyGetCapabilities:
+ * @conn: pointer to the Xen Daemon block
+ *
+ * Extract capabilities of the hypervisor.
+ *
+ * Returns capabilities in case of success (freed by caller)
+ * and NULL in case of failure.
+ */
+static char *
+xenProxyGetCapabilities (virConnectPtr conn)
+{
+    virProxyPacket req;
+    virProxyFullPacket ans;
+    int ret, xmllen;
+    char *xml;
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virProxyError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return NULL;
+    }
+    memset(&req, 0, sizeof(req));
+    req.command = VIR_PROXY_GET_CAPABILITIES;
+    req.data.arg = 0;
+    req.len = sizeof(req);
+    ret = xenProxyCommand(conn, &req, &ans, 0);
+    if (ret < 0) {
+        return NULL;
+    }
+    if (ans.data.arg == -1)
+        return NULL;
+    if (ans.len <= sizeof(virProxyPacket)) {
+        virProxyError(conn, VIR_ERR_OPERATION_FAILED, __FUNCTION__);
+        return NULL;
+    }
+
+    xmllen = ans.len - sizeof (virProxyPacket);
+    if (VIR_ALLOC_N(xml, xmllen+1) < 0) {
+        virReportOOMError (conn);
+        return NULL;
+    }
+    memmove (xml, ans.extra.str, xmllen);
+    xml[xmllen] = '\0';
+
+    return xml;
+}
+
+/**
+ * xenProxyDomainDumpXML:
+ * @domain: a domain object
+ * @flags: xml generation flags
+ *
+ * This method generates an XML description of a domain.
+ *
+ * Returns the XML document on success, NULL otherwise.
+ */
+char *
+xenProxyDomainDumpXML(virDomainPtr domain, int flags ATTRIBUTE_UNUSED)
+{
+    virProxyPacket req;
+    virProxyFullPacket ans;
+    int ret;
+    int xmllen;
+    char *xml;
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+        if (domain == NULL)
+            virProxyError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        else
+            virProxyError(domain->conn, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return (NULL);
+    }
+    if (domain->id < 0)
+        return (NULL);
+    memset(&req, 0, sizeof(req));
+    req.command = VIR_PROXY_DOMAIN_XML;
+    req.data.arg = domain->id;
+    req.len = sizeof(req);
+    ret = xenProxyCommand(domain->conn, &req, &ans, 0);
+    if (ret < 0) {
+        return(NULL);
+    }
+    if (ans.len <= sizeof(virProxyPacket)) {
+        virProxyError(domain->conn, VIR_ERR_OPERATION_FAILED, __FUNCTION__);
+        return (NULL);
+    }
+    xmllen = ans.len - sizeof(virProxyPacket);
+    if (VIR_ALLOC_N(xml, xmllen+1) < 0) {
+        virReportOOMError(domain->conn);
+        return NULL;
+    }
+    memmove(xml, &ans.extra.dinfo, xmllen);
+    xml[xmllen] = '\0';
+
+    return(xml);
+}
+
+/**
+ * xenProxyDomainGetOSType:
+ * @domain: a domain object
+ *
+ * Get the type of domain operation system.
+ *
+ * Returns the new string or NULL in case of error, the string must be
+ *         freed by the caller.
+ */
+static char *
+xenProxyDomainGetOSType(virDomainPtr domain)
+{
+    virProxyPacket req;
+    virProxyFullPacket ans;
+    int ret;
+    int oslen;
+    char *ostype;
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+        if (domain == NULL)
+            virProxyError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        else
+            virProxyError(domain->conn, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return (NULL);
+    }
+    memset(&req, 0, sizeof(req));
+    req.command = VIR_PROXY_DOMAIN_OSTYPE;
+    req.data.arg = domain->id;
+    req.len = sizeof(req);
+    ret = xenProxyCommand(domain->conn, &req, &ans, 0);
+    if (ret < 0) {
+        return(NULL);
+    }
+    if ((ans.len == sizeof(virProxyPacket)) && (ans.data.arg < 0)) {
+        return(NULL);
+    }
+
+    if (ans.len <= sizeof(virProxyPacket)) {
+        virProxyError(domain->conn, VIR_ERR_OPERATION_FAILED, __FUNCTION__);
+        return (NULL);
+    }
+    oslen = ans.len - sizeof(virProxyPacket);
+    if (VIR_ALLOC_N(ostype, oslen+1) < 0) {
+        virReportOOMError(domain->conn);
+        return NULL;
+    }
+    memmove(ostype, &ans.extra.dinfo, oslen);
+    ostype[oslen] = '\0';
+
+    return(ostype);
+}
diff --git a/src/xen/proxy_internal.h b/src/xen/proxy_internal.h
new file mode 100644 (file)
index 0000000..185fa67
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * proxy.h: common definitions for proxy usage
+ *
+ * Copyright (C) 2006 Red Hat, Inc.
+ *
+ * See COPYING.LIB for the License of this software
+ *
+ * Daniel Veillard <veillard@redhat.com>
+ */
+
+
+#ifndef __LIBVIR_PROXY_H__
+#define __LIBVIR_PROXY_H__
+
+#include "internal.h"
+
+#define PROXY_SOCKET_PATH "/tmp/livirt_proxy_conn"
+#define PROXY_PROTO_VERSION 1
+
+/*
+ * the command allowed though the proxy
+ */
+typedef enum {
+        VIR_PROXY_NONE = 0,
+        VIR_PROXY_VERSION = 1,
+        VIR_PROXY_NODE_INFO = 2,
+        VIR_PROXY_LIST = 3,
+        VIR_PROXY_NUM_DOMAIN = 4,
+        VIR_PROXY_LOOKUP_ID = 5,
+        VIR_PROXY_LOOKUP_UUID = 6,
+        VIR_PROXY_LOOKUP_NAME = 7,
+        VIR_PROXY_MAX_MEMORY = 8,
+        VIR_PROXY_DOMAIN_INFO = 9,
+        VIR_PROXY_DOMAIN_XML = 10,
+        VIR_PROXY_DOMAIN_OSTYPE = 11,
+    VIR_PROXY_GET_CAPABILITIES = 12
+} virProxyCommand;
+
+/*
+ * structure used by the client to make a request to the proxy
+ * and by the proxy when answering the client.
+ * the size may not be fixed, it's passed as len.
+ */
+struct _virProxyPacket {
+    unsigned short version;    /* version of the proxy protocol */
+    unsigned short command;    /* command number a virProxyCommand */
+    unsigned short serial;     /* command serial number */
+    unsigned short len;                /* the length of the request */
+    union {
+        char       string[8];  /* string data */
+        int        arg;                /* or int argument */
+        long       larg;       /* or long argument */
+    } data;
+};
+typedef struct _virProxyPacket virProxyPacket;
+typedef  virProxyPacket *virProxyPacketPtr;
+
+/*
+ * If there is extra data sent from the proxy to the client,
+ * they are appended after the packet.
+ * the size may not be fixed, it's passed as len and includes the
+ * extra data.
+ */
+struct _virProxyFullPacket {
+    unsigned short version;    /* version of the proxy protocol */
+    unsigned short command;    /* command number a virProxyCommand */
+    unsigned short serial;     /* command serial number */
+    unsigned short len;                /* the length of the request */
+    union {
+        char       string[8];  /* string data */
+        int        arg;                /* or int argument */
+        long       larg;       /* or long argument */
+    } data;
+    /* that should be aligned on a 16bytes boundary */
+    union {
+        char       str[4080];   /* extra char array */
+        int        arg[1020];   /* extra int array */
+        virDomainInfo dinfo;   /* domain information */
+        virNodeInfo   ninfo;   /* node information */
+    } extra;
+};
+typedef struct _virProxyFullPacket virProxyFullPacket;
+typedef  virProxyFullPacket *virProxyFullPacketPtr;
+
+/* xen_unified makes direct calls or indirect calls through here. */
+extern struct xenUnifiedDriver xenProxyDriver;
+extern int xenProxyInit (void);
+
+extern virDomainPtr xenProxyLookupByID(virConnectPtr conn, int id);
+extern virDomainPtr xenProxyLookupByUUID(virConnectPtr conn,
+                                         const unsigned char *uuid);
+extern virDomainPtr xenProxyLookupByName(virConnectPtr conn,
+                                         const char *domname);
+
+extern char *       xenProxyDomainDumpXML(virDomainPtr domain,
+                                          int flags);
+extern int          xenProxyListDomains(virConnectPtr conn, int *ids,
+                                        int maxids);
+#endif /* __LIBVIR_PROXY_H__ */
diff --git a/src/xen/sexpr.c b/src/xen/sexpr.c
new file mode 100644 (file)
index 0000000..81cb49f
--- /dev/null
@@ -0,0 +1,577 @@
+/*
+ * sexpr.c : S-Expression routines to communicate with the Xen Daemon
+ *
+ * Copyright (C) 2005
+ *
+ *      Anthony Liguori <aliguori@us.ibm.com>
+ *
+ *  This file is subject to the terms and conditions of the GNU Lesser General
+ *  Public License. See the file COPYING.LIB in the main directory of this
+ *  archive for more details.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "c-ctype.h"
+#include <errno.h>
+
+#include "virterror_internal.h"
+#include "sexpr.h"
+#include "util.h"
+#include "memory.h"
+
+#define VIR_FROM_THIS VIR_FROM_SEXPR
+
+#define virSexprError(code, fmt...)                                          \
+        virReportErrorHelper(NULL, VIR_FROM_SEXPR, code, __FILE__,         \
+                               __FUNCTION__, __LINE__, fmt)
+
+/**
+ * sexpr_new:
+ *
+ * Create a new S-Expression
+ *
+ * Returns the new node or NULL in case of memory allocation error
+ */
+static struct sexpr *
+sexpr_new(void)
+{
+    struct sexpr *ret;
+
+    if (VIR_ALLOC(ret) < 0) {
+        virReportOOMError(NULL);
+        return (NULL);
+    }
+    ret->kind = SEXPR_NIL;
+    return ret;
+}
+
+/**
+ * sexpr_free:
+ * @sexpr: the S-Expression pointer
+ *
+ * Free an S-Expression
+ */
+void
+sexpr_free(struct sexpr *sexpr)
+{
+    int serrno = errno;
+
+    if (sexpr == NULL) {
+        return;
+    }
+
+    switch (sexpr->kind) {
+        case SEXPR_CONS:
+            sexpr_free(sexpr->u.s.car);
+            sexpr_free(sexpr->u.s.cdr);
+            break;
+        case SEXPR_VALUE:
+            VIR_FREE(sexpr->u.value);
+            break;
+        case SEXPR_NIL:
+            break;
+    }
+
+    VIR_FREE(sexpr);
+
+    errno = serrno;
+}
+
+/**
+ * sexpr_nil:
+ *
+ * Provide a NIL S-Expression (the pointer is not shared so NIL equality
+ * testing won't work at the pointer level).
+ *
+ * Returns a new NIL S-Expression of NULL in case of error.
+ */
+struct sexpr *
+sexpr_nil(void)
+{
+    return sexpr_new();
+}
+
+/**
+ * sexpr_string:
+ * @str:  the input string, assumed to be UTF-8
+ * @len:  the length in bytes of the input
+ *
+ * Parse the input S-Expression and return a pointer to the result
+ *
+ * Returns the S-Expression pointer or NULL in case of error
+ */
+struct sexpr *
+sexpr_string(const char *str, ssize_t len)
+{
+    struct sexpr *ret = sexpr_new();
+
+    if (ret == NULL)
+        return ret;
+    ret->kind = SEXPR_VALUE;
+    if (len > 0) {
+        ret->u.value = strndup(str, len);
+    } else {
+        ret->u.value = strdup(str);
+    }
+
+    if (ret->u.value == NULL) {
+        return NULL;
+    }
+
+    return ret;
+}
+
+/**
+ * sexpr_cons:
+ * @car: the left operand
+ * @cdr: the right operand
+ *
+ * Implement the CONS operation assembling 2 existing S-Expressions.
+ * Note that in case of error the input data are not freed.
+ *
+ * Returns the resulting S-Expression pointer or NULL in case of error.
+ */
+struct sexpr *
+sexpr_cons(const struct sexpr *car, const struct sexpr *cdr)
+{
+    struct sexpr *ret = sexpr_new();
+
+    if (ret == NULL)
+        return ret;
+    ret->kind = SEXPR_CONS;
+    ret->u.s.car = (struct sexpr *) car;
+    ret->u.s.cdr = (struct sexpr *) cdr;
+
+    return ret;
+}
+
+/**
+ * append:
+ * @lst: an existing list
+ * @value: the value
+ *
+ * Internal operation appending a value at the end of an existing list
+ */
+static int
+append(struct sexpr *lst, const struct sexpr *value)
+{
+    struct sexpr *nil = sexpr_nil();
+
+    if (nil == NULL)
+        return -1;
+
+    while (lst->kind != SEXPR_NIL) {
+        lst = lst->u.s.cdr;
+    }
+
+    lst->kind = SEXPR_CONS;
+    lst->u.s.car = (struct sexpr *) value;
+    lst->u.s.cdr = nil;
+
+    return 0;
+}
+
+/**
+ * @lst: an existing list
+ * @value: the value
+ *
+ * Append a value at the end of an existing list
+ *
+ * Returns lst or NULL in case of error
+ */
+struct sexpr *
+sexpr_append(struct sexpr *lst, const struct sexpr *value)
+{
+    if (lst == NULL)
+        return (NULL);
+    if (value == NULL)
+        return (lst);
+    if (append(lst, value) < 0)
+        return (NULL);
+    return (lst);
+}
+
+/**
+ * sexpr2string:
+ * @sexpr: an S-Expression pointer
+ * @buffer: the output buffer
+ * @n_buffer: the size of the buffer in bytes
+ *
+ * Serialize the S-Expression in the buffer.
+ * Note that the output may be truncated if @n_buffer is too small
+ * resulting in an unparseable value.
+ *
+ * Returns the number of bytes used by the serialization in the buffer or
+ *         0 in case of error.
+ */
+size_t
+sexpr2string(const struct sexpr * sexpr, char *buffer, size_t n_buffer)
+{
+    size_t ret = 0, tmp;
+
+    if ((sexpr == NULL) || (buffer == NULL) || (n_buffer <= 0))
+        return (0);
+
+    switch (sexpr->kind) {
+        case SEXPR_CONS:
+            tmp = snprintf(buffer + ret, n_buffer - ret, "(");
+            if (tmp == 0)
+                goto error;
+            ret += tmp;
+            tmp = sexpr2string(sexpr->u.s.car, buffer + ret, n_buffer - ret);
+            if (tmp == 0)
+                goto error;
+            ret += tmp;
+            while (sexpr->u.s.cdr->kind != SEXPR_NIL) {
+                sexpr = sexpr->u.s.cdr;
+                tmp = snprintf(buffer + ret, n_buffer - ret, " ");
+                if (tmp == 0)
+                    goto error;
+                ret += tmp;
+                tmp =
+                    sexpr2string(sexpr->u.s.car, buffer + ret, n_buffer - ret);
+                if (tmp == 0)
+                    goto error;
+                ret += tmp;
+            }
+            tmp = snprintf(buffer + ret, n_buffer - ret, ")");
+            if (tmp == 0)
+                goto error;
+            ret += tmp;
+            break;
+        case SEXPR_VALUE:
+            if (strchr(sexpr->u.value, ' '))
+                tmp = snprintf(buffer + ret, n_buffer - ret, "'%s'",
+                               sexpr->u.value);
+            else
+                tmp = snprintf(buffer + ret, n_buffer - ret, "%s",
+                               sexpr->u.value);
+            if (tmp == 0)
+                goto error;
+            ret += tmp;
+            break;
+        case SEXPR_NIL:
+            tmp = snprintf(buffer + ret, n_buffer - ret, "()");
+            if (tmp == 0)
+                goto error;
+            ret += tmp;
+            break;
+        default:
+            goto error;
+    }
+
+    return (ret);
+  error:
+    buffer[n_buffer - 1] = 0;
+    virSexprError(VIR_ERR_SEXPR_SERIAL, "%s", buffer);
+    return (0);
+}
+
+#define IS_SPACE(c) ((c == 0x20) || (c == 0x9) || (c == 0xD) || (c == 0xA))
+
+static const char *
+trim(const char *string)
+{
+    while (IS_SPACE(*string))
+        string++;
+    return (string);
+}
+
+/**
+ * _string2sexpr:
+ * @buffer: a zero terminated buffer containing an S-Expression in UTF-8
+ * @end: pointer to an index in the buffer for the already parsed bytes
+ *
+ * Internal routine implementing the parse of S-Expression
+ * Note that failure in this function is catastrophic.  If it returns
+ * NULL, you've leaked memory and you're currently OOM.  It will always
+ * parse an SEXPR given a buffer
+ *
+ * Returns a pointer to the resulting parsed S-Expression, or NULL in case of
+ *         hard error.
+ */
+static struct sexpr *
+_string2sexpr(const char *buffer, size_t * end)
+{
+    const char *ptr = buffer + *end;
+    struct sexpr *ret = sexpr_new();
+
+    if (ret == NULL)
+        return NULL;
+
+    ptr = trim(ptr);
+
+    if (ptr[0] == '(') {
+        ret->kind = SEXPR_NIL;
+
+        ptr = trim(ptr + 1);
+        while (*ptr && *ptr != ')') {
+            struct sexpr *tmp;
+            size_t tmp_len = 0;
+
+            tmp = _string2sexpr(ptr, &tmp_len);
+            if (tmp == NULL)
+                goto error;
+            if (append(ret, tmp) < 0) {
+                sexpr_free(tmp);
+                goto error;
+            }
+#if 0
+            if (0) {
+                char buf[4096];
+
+                sexpr2string(ret, buf, sizeof(buf));
+                printf("%s\n", buffer);
+            }
+#endif
+            ptr = trim(ptr + tmp_len);
+        }
+
+        if (*ptr == ')') {
+            ptr++;
+        }
+    } else {
+        const char *start;
+
+        if (*ptr == '\'') {
+            ptr++;
+            start = ptr;
+
+            while (*ptr && *ptr != '\'') {
+                if (*ptr == '\\' && ptr[1])
+                    ptr++;
+                ptr++;
+            }
+
+            ret->u.value = strndup(start, ptr - start);
+            if (ret->u.value == NULL) {
+                virReportOOMError(NULL);
+                goto error;
+            }
+
+            if (*ptr == '\'')
+                ptr++;
+        } else {
+            start = ptr;
+
+            while (*ptr && !c_isspace(*ptr)
+                   && *ptr != ')' && *ptr != '(') {
+                ptr++;
+            }
+
+            ret->u.value = strndup(start, ptr - start);
+            if (ret->u.value == NULL) {
+                virReportOOMError(NULL);
+                goto error;
+            }
+        }
+
+        ret->kind = SEXPR_VALUE;
+        if (ret->u.value == NULL)
+            goto error;
+    }
+
+    *end = ptr - buffer;
+
+    return ret;
+
+  error:
+    sexpr_free(ret);
+    return (NULL);
+}
+
+/**
+ * string2sexpr:
+ * @buffer: a zero terminated buffer containing an S-Expression in UTF-8
+ *
+ * Parse the S-Expression in the buffer.
+ * Note that failure in this function is catastrophic.  If it returns
+ * NULL, you've leaked memory and you're currently OOM.  It will always
+ * parse an SEXPR given a buffer
+ *
+ * Returns a pointer to the resulting parsed S-Expression, or NULL in case of
+ *         hard error.
+ */
+struct sexpr *
+string2sexpr(const char *buffer)
+{
+    size_t dummy = 0;
+
+    return _string2sexpr(buffer, &dummy);
+}
+
+
+/**
+ * sexpr_lookup_key:
+ * @sexpr: a pointer to a parsed S-Expression
+ * @node: a path for the sub expression to lookup in the S-Expression
+ *
+ * Search a sub expression in the S-Expression based on its path
+ * Returns the key node, rather than the data node.
+ * NOTE: path are limited to 4096 bytes.
+ *
+ * Returns the pointer to the sub expression or NULL if not found.
+ */
+static struct sexpr *
+sexpr_lookup_key(const struct sexpr *sexpr, const char *node)
+{
+    char buffer[4096], *ptr, *token;
+
+    if ((node == NULL) || (sexpr == NULL))
+        return (NULL);
+
+    snprintf(buffer, sizeof(buffer), "%s", node);
+
+    ptr = buffer;
+    token = strsep(&ptr, "/");
+
+    if (sexpr->kind != SEXPR_CONS || sexpr->u.s.car->kind != SEXPR_VALUE) {
+        return NULL;
+    }
+
+    if (STRNEQ(sexpr->u.s.car->u.value, token)) {
+        return NULL;
+    }
+
+    for (token = strsep(&ptr, "/"); token; token = strsep(&ptr, "/")) {
+        const struct sexpr *i;
+
+        if (token == NULL)
+            continue;
+
+        sexpr = sexpr->u.s.cdr;
+        for (i = sexpr; i->kind != SEXPR_NIL; i = i->u.s.cdr) {
+            if (i->kind != SEXPR_CONS ||
+                i->u.s.car->kind != SEXPR_CONS ||
+                i->u.s.car->u.s.car->kind != SEXPR_VALUE) {
+                continue;
+            }
+
+            if (STREQ(i->u.s.car->u.s.car->u.value, token)) {
+                sexpr = i->u.s.car;
+                break;
+            }
+        }
+
+        if (i->kind == SEXPR_NIL) {
+            break;
+        }
+    }
+
+    if (token != NULL) {
+        return NULL;
+    }
+
+    return (struct sexpr *) sexpr;
+}
+
+/**
+ * sexpr_lookup:
+ * @sexpr: a pointer to a parsed S-Expression
+ * @node: a path for the sub expression to lookup in the S-Expression
+ *
+ * Search a sub expression in the S-Expression based on its path.
+ * NOTE: path are limited to 4096 bytes.
+ *
+ * Returns the pointer to the sub expression or NULL if not found.
+ */
+struct sexpr *
+sexpr_lookup(const struct sexpr *sexpr, const char *node)
+{
+    struct sexpr *s = sexpr_lookup_key(sexpr, node);
+
+    if (s == NULL)
+        return NULL;
+
+    if (s->kind != SEXPR_CONS || s->u.s.cdr->kind != SEXPR_CONS)
+        return NULL;
+
+    return s->u.s.cdr;
+}
+
+/**
+ * sexpr_has:
+ * @sexpr: a pointer to a parsed S-Expression
+ * @node: a path for the sub expression to lookup in the S-Expression
+ *
+ * Search a sub expression in the S-Expression based on its path.
+ * NOTE: path are limited to 4096 bytes.
+ * NB, even if the key was found sexpr_lookup may return NULL if
+ * the corresponding value was empty
+ *
+ * Returns true if the key was found, false otherwise
+ */
+int
+sexpr_has(const struct sexpr *sexpr, const char *node)
+{
+    struct sexpr *s = sexpr_lookup_key(sexpr, node);
+
+    if (s == NULL)
+        return 0;
+
+    if (s->kind != SEXPR_CONS)
+        return 0;
+
+    return 1;
+}
+
+/**
+ * sexpr_node:
+ * @sexpr: a pointer to a parsed S-Expression
+ * @node: a path for the node to lookup in the S-Expression
+ *
+ * Search a node value in the S-Expression based on its path
+ * NOTE: path are limited to 4096 bytes.
+ *
+ * Returns the value of the node or NULL if not found.
+ */
+const char *
+sexpr_node(const struct sexpr *sexpr, const char *node)
+{
+    struct sexpr *n = sexpr_lookup(sexpr, node);
+
+    return (n && n->u.s.car->kind == SEXPR_VALUE) ? n->u.s.car->u.value : NULL;
+}
+
+int sexpr_node_copy(const struct sexpr *sexpr, const char *node, char **dst)
+{
+    const char *val = sexpr_node(sexpr, node);
+
+    if (val) {
+        *dst = strdup(val);
+        if (!(*dst))
+            return -1;
+    } else {
+        *dst = NULL;
+    }
+    return 0;
+}
+
+
+/**
+ * sexpr_fmt_node:
+ * @sexpr: a pointer to a parsed S-Expression
+ * @fmt: a path for the node to lookup in the S-Expression
+ * @... extra data to build the path
+ *
+ * Search a node value in the S-Expression based on its path
+ * NOTE: path are limited to 4096 bytes.
+ *
+ * Returns the value of the node or NULL if not found.
+ */
+const char *
+sexpr_fmt_node(const struct sexpr *sexpr, const char *fmt, ...)
+{
+    va_list ap;
+    char node[4096];
+
+    va_start(ap, fmt);
+    vsnprintf(node, sizeof(node), fmt, ap);
+    va_end(ap);
+
+    return sexpr_node(sexpr, node);
+}
diff --git a/src/xen/sexpr.h b/src/xen/sexpr.h
new file mode 100644 (file)
index 0000000..1d9adaa
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * sexpr.h : S-Expression interfaces needed to communicate with the Xen Daemon
+ *
+ * Copyright (C) 2005
+ *
+ *      Anthony Liguori <aliguori@us.ibm.com>
+ *
+ *  This file is subject to the terms and conditions of the GNU Lesser General
+ *  Public License. See the file COPYING.LIB in the main directory of this
+ *  archive for more details.
+ */
+
+#ifndef _LIBVIR_SEXPR_H_
+#define _LIBVIR_SEXPR_H_
+
+#include "internal.h"
+
+#include <sys/types.h>
+
+enum sexpr_type {
+    SEXPR_NIL,
+    SEXPR_CONS,
+    SEXPR_VALUE,
+};
+
+struct sexpr {
+    enum sexpr_type kind;
+    union {
+        struct {
+            struct sexpr *car;
+            struct sexpr *cdr;
+        } s;
+        char *value;
+    } u;
+};
+
+/* conversion to/from strings */
+size_t sexpr2string(const struct sexpr *sexpr, char *buffer, size_t n_buffer);
+struct sexpr *string2sexpr(const char *buffer);
+
+/* constructors and destructors */
+struct sexpr *sexpr_nil(void);
+struct sexpr *sexpr_string(const char *str, ssize_t len);
+struct sexpr *sexpr_cons(const struct sexpr *car, const struct sexpr *cdr);
+struct sexpr *sexpr_append(struct sexpr *lst, const struct sexpr *item);
+void sexpr_free(struct sexpr *sexpr);
+
+/* lookup in S-Expressions */
+const char *sexpr_node(const struct sexpr *sexpr, const char *node);
+int sexpr_node_copy(const struct sexpr *sexpr, const char *node, char **dst);
+const char *sexpr_fmt_node(const struct sexpr *sexpr, const char *fmt, ...)
+  ATTRIBUTE_FMT_PRINTF(2,3);
+struct sexpr *sexpr_lookup(const struct sexpr *sexpr, const char *node);
+int sexpr_has(const struct sexpr *sexpr, const char *node);
+#endif
diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c
new file mode 100644 (file)
index 0000000..3dd0237
--- /dev/null
@@ -0,0 +1,1917 @@
+/*
+ * xen_driver.c: Unified Xen driver.
+ *
+ * Copyright (C) 2007, 2008, 2009 Red Hat, Inc.
+ *
+ * See COPYING.LIB for the License of this software
+ *
+ * Richard W.M. Jones <rjones@redhat.com>
+ */
+
+#include <config.h>
+
+/* Note:
+ *
+ * This driver provides a unified interface to the five
+ * separate underlying Xen drivers (xen_internal, proxy_internal,
+ * xend_internal, xs_internal and xm_internal).  Historically
+ * the body of libvirt.c handled the five Xen drivers,
+ * and contained Xen-specific code.
+ */
+
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <xen/dom0_ops.h>
+#include <libxml/uri.h>
+
+#include "virterror_internal.h"
+#include "logging.h"
+#include "datatypes.h"
+#include "xen_driver.h"
+
+#include "xen_hypervisor.h"
+#include "proxy_internal.h"
+#include "xend_internal.h"
+#include "xs_internal.h"
+#include "xm_internal.h"
+#if WITH_XEN_INOTIFY
+#include "xen_inotify.h"
+#endif
+#include "xml.h"
+#include "util.h"
+#include "memory.h"
+#include "node_device_conf.h"
+#include "pci.h"
+
+#define VIR_FROM_THIS VIR_FROM_XEN
+
+static int
+xenUnifiedNodeGetInfo (virConnectPtr conn, virNodeInfoPtr info);
+static int
+xenUnifiedDomainGetMaxVcpus (virDomainPtr dom);
+static int
+xenUnifiedDomainGetVcpus (virDomainPtr dom,
+                          virVcpuInfoPtr info, int maxinfo,
+                          unsigned char *cpumaps, int maplen);
+
+/* The five Xen drivers below us. */
+static struct xenUnifiedDriver const * const drivers[XEN_UNIFIED_NR_DRIVERS] = {
+    [XEN_UNIFIED_HYPERVISOR_OFFSET] = &xenHypervisorDriver,
+    [XEN_UNIFIED_PROXY_OFFSET] = &xenProxyDriver,
+    [XEN_UNIFIED_XEND_OFFSET] = &xenDaemonDriver,
+    [XEN_UNIFIED_XS_OFFSET] = &xenStoreDriver,
+    [XEN_UNIFIED_XM_OFFSET] = &xenXMDriver,
+#if WITH_XEN_INOTIFY
+    [XEN_UNIFIED_INOTIFY_OFFSET] = &xenInotifyDriver,
+#endif
+};
+
+static int inside_daemon;
+
+#define xenUnifiedError(conn, code, fmt...)                                  \
+        virReportErrorHelper(conn, VIR_FROM_XEN, code, __FILE__,           \
+                               __FUNCTION__, __LINE__, fmt)
+
+/**
+ * xenNumaInit:
+ * @conn: pointer to the hypervisor connection
+ *
+ * Initializer for previous variables. We currently assume that
+ * the number of physical CPU and the number of NUMA cell is fixed
+ * until reboot which might be false in future Xen implementations.
+ */
+static void
+xenNumaInit(virConnectPtr conn) {
+    virNodeInfo nodeInfo;
+    xenUnifiedPrivatePtr priv;
+    int ret;
+
+    ret = xenUnifiedNodeGetInfo(conn, &nodeInfo);
+    if (ret < 0)
+        return;
+
+    priv = conn->privateData;
+
+    priv->nbNodeCells = nodeInfo.nodes;
+    priv->nbNodeCpus = nodeInfo.cpus;
+}
+
+
+/**
+ * xenDomainUsedCpus:
+ * @dom: the domain
+ *
+ * Analyze which set of CPUs are used by the domain and
+ * return a string providing the ranges.
+ *
+ * Returns the string which needs to be freed by the caller or
+ *         NULL if the domain uses all CPU or in case of error.
+ */
+char *
+xenDomainUsedCpus(virDomainPtr dom)
+{
+    char *res = NULL;
+    int ncpus;
+    int nb_vcpu;
+    char *cpulist = NULL;
+    unsigned char *cpumap = NULL;
+    size_t cpumaplen;
+    int nb = 0;
+    int n, m;
+    virVcpuInfoPtr cpuinfo = NULL;
+    virNodeInfo nodeinfo;
+    xenUnifiedPrivatePtr priv;
+
+    if (!VIR_IS_CONNECTED_DOMAIN(dom))
+        return (NULL);
+
+    priv = dom->conn->privateData;
+
+    if (priv->nbNodeCpus <= 0)
+        return(NULL);
+    nb_vcpu = xenUnifiedDomainGetMaxVcpus(dom);
+    if (nb_vcpu <= 0)
+        return(NULL);
+    if (xenUnifiedNodeGetInfo(dom->conn, &nodeinfo) < 0)
+        return(NULL);
+
+    if (VIR_ALLOC_N(cpulist, priv->nbNodeCpus) < 0)
+        goto done;
+    if (VIR_ALLOC_N(cpuinfo, nb_vcpu) < 0)
+        goto done;
+    cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo));
+    if (xalloc_oversized(nb_vcpu, cpumaplen) ||
+        VIR_ALLOC_N(cpumap, nb_vcpu * cpumaplen) < 0)
+        goto done;
+
+    if ((ncpus = xenUnifiedDomainGetVcpus(dom, cpuinfo, nb_vcpu,
+                                          cpumap, cpumaplen)) >= 0) {
+        for (n = 0 ; n < ncpus ; n++) {
+            for (m = 0 ; m < priv->nbNodeCpus; m++) {
+                if ((cpulist[m] == 0) &&
+                    (VIR_CPU_USABLE(cpumap, cpumaplen, n, m))) {
+                    cpulist[m] = 1;
+                    nb++;
+                    /* if all CPU are used just return NULL */
+                    if (nb == priv->nbNodeCpus)
+                        goto done;
+
+                }
+            }
+        }
+        res = virDomainCpuSetFormat(dom->conn, cpulist, priv->nbNodeCpus);
+    }
+
+done:
+    VIR_FREE(cpulist);
+    VIR_FREE(cpumap);
+    VIR_FREE(cpuinfo);
+    return(res);
+}
+
+#ifdef WITH_LIBVIRTD
+
+static int
+xenInitialize (int privileged ATTRIBUTE_UNUSED)
+{
+    inside_daemon = 1;
+    return 0;
+}
+
+static virStateDriver state_driver = {
+    .initialize = xenInitialize,
+};
+
+#endif
+
+/*----- Dispatch functions. -----*/
+
+/* These dispatch functions follow the model used historically
+ * by libvirt.c -- trying each low-level Xen driver in turn
+ * until one succeeds.  However since we know what low-level
+ * drivers can perform which functions, it is probably better
+ * in future to optimise these dispatch functions to just call
+ * the single function (or small number of appropriate functions)
+ * in the low level drivers directly.
+ */
+
+static int
+xenUnifiedProbe (void)
+{
+#ifdef __linux__
+    if (virFileExists("/proc/xen"))
+        return 1;
+#endif
+#ifdef __sun
+    FILE *fh;
+
+    if (fh = fopen("/dev/xen/domcaps", "r")) {
+        fclose(fh);
+        return 1;
+    }
+#endif
+    return 0;
+}
+
+static virDrvOpenStatus
+xenUnifiedOpen (virConnectPtr conn, virConnectAuthPtr auth, int flags)
+{
+    int i, ret = VIR_DRV_OPEN_DECLINED;
+    xenUnifiedPrivatePtr priv;
+    virDomainEventCallbackListPtr cbList;
+
+#ifdef __sun
+    /*
+     * Only the libvirtd instance can open this driver.
+     * Everything else falls back to the remote driver.
+     */
+    if (!inside_daemon)
+        return VIR_DRV_OPEN_DECLINED;
+#endif
+
+    if (conn->uri == NULL) {
+        if (!xenUnifiedProbe())
+            return VIR_DRV_OPEN_DECLINED;
+
+        conn->uri = xmlParseURI("xen:///");
+        if (!conn->uri) {
+            virReportOOMError (NULL);
+            return VIR_DRV_OPEN_ERROR;
+        }
+    } else {
+        if (conn->uri->scheme) {
+            /* Decline any scheme which isn't "xen://" or "http://". */
+            if (STRCASENEQ(conn->uri->scheme, "xen") &&
+                STRCASENEQ(conn->uri->scheme, "http"))
+                return VIR_DRV_OPEN_DECLINED;
+
+
+            /* Return an error if the path isn't '' or '/' */
+            if (conn->uri->path &&
+                STRNEQ(conn->uri->path, "") &&
+                STRNEQ(conn->uri->path, "/")) {
+                xenUnifiedError(NULL, VIR_ERR_INTERNAL_ERROR,
+                                _("unexpected Xen URI path '%s', try xen:///"),
+                                conn->uri->path);
+                return VIR_DRV_OPEN_ERROR;
+            }
+
+            /* Decline any xen:// URI with a server specified, allowing remote
+             * driver to handle, but keep any http:/// URIs */
+            if (STRCASEEQ(conn->uri->scheme, "xen") &&
+                conn->uri->server)
+                return VIR_DRV_OPEN_DECLINED;
+        } else {
+            /* Special case URI for Xen driver only:
+             *
+             * Treat a plain path as a Xen UNIX socket path, and give
+             * error unless path is absolute
+             */
+            if (!conn->uri->path || conn->uri->path[0] != '/') {
+                xenUnifiedError(NULL, VIR_ERR_INTERNAL_ERROR,
+                                _("unexpected Xen URI path '%s', try ///var/lib/xen/xend-socket"),
+                                NULLSTR(conn->uri->path));
+                return VIR_DRV_OPEN_ERROR;
+            }
+        }
+    }
+
+    /* We now know the URI is definitely for this driver, so beyond
+     * here, don't return DECLINED, always use ERROR */
+
+    /* Allocate per-connection private data. */
+    if (VIR_ALLOC(priv) < 0) {
+        virReportOOMError (NULL);
+        return VIR_DRV_OPEN_ERROR;
+    }
+    if (virMutexInit(&priv->lock) < 0) {
+        xenUnifiedError (NULL, VIR_ERR_INTERNAL_ERROR,
+                         "%s", _("cannot initialise mutex"));
+        VIR_FREE(priv);
+        return VIR_DRV_OPEN_ERROR;
+    }
+
+    /* Allocate callback list */
+    if (VIR_ALLOC(cbList) < 0) {
+        virReportOOMError (NULL);
+        virMutexDestroy(&priv->lock);
+        VIR_FREE(priv);
+        return VIR_DRV_OPEN_ERROR;
+    }
+    conn->privateData = priv;
+
+    priv->domainEventCallbacks = cbList;
+
+    priv->handle = -1;
+    priv->xendConfigVersion = -1;
+    priv->xshandle = NULL;
+    priv->proxy = -1;
+
+
+    /* Hypervisor is only run with privilege & required to succeed */
+    if (xenHavePrivilege()) {
+        DEBUG0("Trying hypervisor sub-driver");
+        if (drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->open(conn, auth, flags) ==
+            VIR_DRV_OPEN_SUCCESS) {
+            DEBUG0("Activated hypervisor sub-driver");
+            priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET] = 1;
+        }
+    }
+
+    /* XenD is required to succeed if privileged.
+     * If it fails as non-root, then the proxy driver may take over
+     */
+    DEBUG0("Trying XenD sub-driver");
+    if (drivers[XEN_UNIFIED_XEND_OFFSET]->open(conn, auth, flags) ==
+        VIR_DRV_OPEN_SUCCESS) {
+        DEBUG0("Activated XenD sub-driver");
+        priv->opened[XEN_UNIFIED_XEND_OFFSET] = 1;
+
+        /* XenD is active, so try the xm & xs drivers too, both requird to
+         * succeed if root, optional otherwise */
+        if (priv->xendConfigVersion <= 2) {
+            DEBUG0("Trying XM sub-driver");
+            if (drivers[XEN_UNIFIED_XM_OFFSET]->open(conn, auth, flags) ==
+                VIR_DRV_OPEN_SUCCESS) {
+                DEBUG0("Activated XM sub-driver");
+                priv->opened[XEN_UNIFIED_XM_OFFSET] = 1;
+            }
+        }
+        DEBUG0("Trying XS sub-driver");
+        if (drivers[XEN_UNIFIED_XS_OFFSET]->open(conn, auth, flags) ==
+            VIR_DRV_OPEN_SUCCESS) {
+            DEBUG0("Activated XS sub-driver");
+            priv->opened[XEN_UNIFIED_XS_OFFSET] = 1;
+        } else {
+            if (xenHavePrivilege())
+                goto fail; /* XS is mandatory when privileged */
+        }
+    } else {
+        if (xenHavePrivilege()) {
+            goto fail; /* XenD is mandatory when privileged */
+        } else {
+#if WITH_PROXY
+            DEBUG0("Trying proxy sub-driver");
+            if (drivers[XEN_UNIFIED_PROXY_OFFSET]->open(conn, auth, flags) ==
+                VIR_DRV_OPEN_SUCCESS) {
+                DEBUG0("Activated proxy sub-driver");
+                priv->opened[XEN_UNIFIED_PROXY_OFFSET] = 1;
+            } else {
+                goto fail; /* Proxy is mandatory if XenD failed */
+            }
+#else
+            DEBUG0("Handing off for remote driver");
+            ret = VIR_DRV_OPEN_DECLINED; /* Let remote_driver try instead */
+            goto clean;
+#endif
+        }
+    }
+
+    xenNumaInit(conn);
+
+    if (!(priv->caps = xenHypervisorMakeCapabilities(conn))) {
+        DEBUG0("Failed to make capabilities");
+        goto fail;
+    }
+
+#if WITH_XEN_INOTIFY
+    if (xenHavePrivilege()) {
+        DEBUG0("Trying Xen inotify sub-driver");
+        if (drivers[XEN_UNIFIED_INOTIFY_OFFSET]->open(conn, auth, flags) ==
+            VIR_DRV_OPEN_SUCCESS) {
+            DEBUG0("Activated Xen inotify sub-driver");
+            priv->opened[XEN_UNIFIED_INOTIFY_OFFSET] = 1;
+        }
+    }
+#endif
+
+    return VIR_DRV_OPEN_SUCCESS;
+
+fail:
+    ret = VIR_DRV_OPEN_ERROR;
+#ifndef WITH_PROXY
+clean:
+#endif
+    DEBUG0("Failed to activate a mandatory sub-driver");
+    for (i = 0 ; i < XEN_UNIFIED_NR_DRIVERS ; i++)
+        if (priv->opened[i]) drivers[i]->close(conn);
+    virMutexDestroy(&priv->lock);
+    VIR_FREE(priv);
+    conn->privateData = NULL;
+    return ret;
+}
+
+#define GET_PRIVATE(conn) \
+    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) (conn)->privateData
+
+static int
+xenUnifiedClose (virConnectPtr conn)
+{
+    GET_PRIVATE(conn);
+    int i;
+
+    virCapabilitiesFree(priv->caps);
+    virDomainEventCallbackListFree(priv->domainEventCallbacks);
+
+    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
+        if (priv->opened[i] && drivers[i]->close)
+            (void) drivers[i]->close (conn);
+
+    virMutexDestroy(&priv->lock);
+    VIR_FREE(conn->privateData);
+
+    return 0;
+}
+
+
+#define HV_VERSION ((DOM0_INTERFACE_VERSION >> 24) * 1000000 +         \
+                    ((DOM0_INTERFACE_VERSION >> 16) & 0xFF) * 1000 +   \
+                    (DOM0_INTERFACE_VERSION & 0xFFFF))
+
+unsigned long xenUnifiedVersion(void)
+{
+    return HV_VERSION;
+}
+
+
+static const char *
+xenUnifiedType (virConnectPtr conn)
+{
+    GET_PRIVATE(conn);
+    int i;
+
+    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
+        if (priv->opened[i])
+            return "Xen";
+
+    return NULL;
+}
+
+/* Which features are supported by this driver? */
+static int
+xenUnifiedSupportsFeature (virConnectPtr conn ATTRIBUTE_UNUSED, int feature)
+{
+    switch (feature) {
+    case VIR_DRV_FEATURE_MIGRATION_V1: return 1;
+    default: return 0;
+    }
+}
+
+static int
+xenUnifiedGetVersion (virConnectPtr conn, unsigned long *hvVer)
+{
+    GET_PRIVATE(conn);
+    int i;
+
+    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
+        if (priv->opened[i] &&
+            drivers[i]->version &&
+            drivers[i]->version (conn, hvVer) == 0)
+            return 0;
+
+    return -1;
+}
+
+/* NB: Even if connected to the proxy, we're still on the
+ * same machine.
+ */
+static char *
+xenUnifiedGetHostname (virConnectPtr conn)
+{
+    char *result;
+
+    result = virGetHostname();
+    if (result == NULL) {
+        virReportSystemError(conn, errno,
+                             "%s", _("cannot lookup hostname"));
+        return NULL;
+    }
+    /* Caller frees this string. */
+    return result;
+}
+
+static int
+xenUnifiedGetMaxVcpus (virConnectPtr conn, const char *type)
+{
+    GET_PRIVATE(conn);
+
+    if (type && STRCASENEQ (type, "Xen")) {
+        xenUnifiedError (conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return -1;
+    }
+
+    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET])
+        return xenHypervisorGetMaxVcpus (conn, type);
+    else {
+        xenUnifiedError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        return -1;
+    }
+}
+
+static int
+xenUnifiedNodeGetInfo (virConnectPtr conn, virNodeInfoPtr info)
+{
+    GET_PRIVATE(conn);
+    int i;
+
+    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
+        if (priv->opened[i] &&
+            drivers[i]->nodeGetInfo &&
+            drivers[i]->nodeGetInfo (conn, info) == 0)
+            return 0;
+
+    return -1;
+}
+
+static char *
+xenUnifiedGetCapabilities (virConnectPtr conn)
+{
+    xenUnifiedPrivatePtr priv = conn->privateData;
+    char *xml;
+
+    if (!(xml = virCapabilitiesFormatXML(priv->caps))) {
+        virReportOOMError(conn);
+        return NULL;
+    }
+
+    return xml;
+}
+
+static int
+xenUnifiedListDomains (virConnectPtr conn, int *ids, int maxids)
+{
+    GET_PRIVATE(conn);
+    int ret;
+
+    /* Try xenstore. */
+    if (priv->opened[XEN_UNIFIED_XS_OFFSET]) {
+        ret = xenStoreListDomains (conn, ids, maxids);
+        if (ret >= 0) return ret;
+    }
+
+    /* Try HV. */
+    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET]) {
+        ret = xenHypervisorListDomains (conn, ids, maxids);
+        if (ret >= 0) return ret;
+    }
+
+    /* Try xend. */
+    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
+        ret = xenDaemonListDomains (conn, ids, maxids);
+        if (ret >= 0) return ret;
+    }
+
+    /* Try proxy. */
+    if (priv->opened[XEN_UNIFIED_PROXY_OFFSET]) {
+        ret = xenProxyListDomains (conn, ids, maxids);
+        if (ret >= 0) return ret;
+    }
+    return -1;
+}
+
+static int
+xenUnifiedNumOfDomains (virConnectPtr conn)
+{
+    GET_PRIVATE(conn);
+    int i, ret;
+
+    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
+        if (priv->opened[i] && drivers[i]->numOfDomains) {
+            ret = drivers[i]->numOfDomains (conn);
+            if (ret >= 0) return ret;
+        }
+
+    return -1;
+}
+
+static virDomainPtr
+xenUnifiedDomainCreateXML (virConnectPtr conn,
+                           const char *xmlDesc, unsigned int flags)
+{
+    GET_PRIVATE(conn);
+    int i;
+    virDomainPtr ret;
+
+    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
+        if (priv->opened[i] && drivers[i]->domainCreateXML) {
+            ret = drivers[i]->domainCreateXML (conn, xmlDesc, flags);
+            if (ret) return ret;
+        }
+
+    return NULL;
+}
+
+/* Assumption made in underlying drivers:
+ * If the domain is "not found" and there is no other error, then
+ * the Lookup* functions return a NULL but do not set virterror.
+ */
+static virDomainPtr
+xenUnifiedDomainLookupByID (virConnectPtr conn, int id)
+{
+    GET_PRIVATE(conn);
+    virDomainPtr ret;
+
+    /* Reset any connection-level errors in virterror first, in case
+     * there is one hanging around from a previous call.
+     */
+    virConnResetLastError (conn);
+
+    /* Try hypervisor/xenstore combo. */
+    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET]) {
+        ret = xenHypervisorLookupDomainByID (conn, id);
+        if (ret || conn->err.code != VIR_ERR_OK)
+            return ret;
+    }
+
+    /* Try proxy. */
+    if (priv->opened[XEN_UNIFIED_PROXY_OFFSET]) {
+        ret = xenProxyLookupByID (conn, id);
+        if (ret || conn->err.code != VIR_ERR_OK)
+            return ret;
+    }
+
+    /* Try xend. */
+    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
+        ret = xenDaemonLookupByID (conn, id);
+        if (ret || conn->err.code != VIR_ERR_OK)
+            return ret;
+    }
+
+    /* Not found. */
+    xenUnifiedError (conn, VIR_ERR_NO_DOMAIN, __FUNCTION__);
+    return NULL;
+}
+
+static virDomainPtr
+xenUnifiedDomainLookupByUUID (virConnectPtr conn,
+                              const unsigned char *uuid)
+{
+    GET_PRIVATE(conn);
+    virDomainPtr ret;
+
+    /* Reset any connection-level errors in virterror first, in case
+     * there is one hanging around from a previous call.
+     */
+    virConnResetLastError (conn);
+
+    /* Try hypervisor/xenstore combo. */
+    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET]) {
+        ret = xenHypervisorLookupDomainByUUID (conn, uuid);
+        if (ret || conn->err.code != VIR_ERR_OK)
+            return ret;
+    }
+
+    /* Try proxy. */
+    if (priv->opened[XEN_UNIFIED_PROXY_OFFSET]) {
+        ret = xenProxyLookupByUUID (conn, uuid);
+        if (ret || conn->err.code != VIR_ERR_OK)
+            return ret;
+    }
+
+    /* Try xend. */
+    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
+        ret = xenDaemonLookupByUUID (conn, uuid);
+        if (ret || conn->err.code != VIR_ERR_OK)
+            return ret;
+    }
+
+    /* Try XM for inactive domains. */
+    if (priv->opened[XEN_UNIFIED_XM_OFFSET]) {
+        ret = xenXMDomainLookupByUUID (conn, uuid);
+        if (ret || conn->err.code != VIR_ERR_OK)
+            return ret;
+    }
+
+    /* Not found. */
+    xenUnifiedError (conn, VIR_ERR_NO_DOMAIN, __FUNCTION__);
+    return NULL;
+}
+
+static virDomainPtr
+xenUnifiedDomainLookupByName (virConnectPtr conn,
+                              const char *name)
+{
+    GET_PRIVATE(conn);
+    virDomainPtr ret;
+
+    /* Reset any connection-level errors in virterror first, in case
+     * there is one hanging around from a previous call.
+     */
+    virConnResetLastError (conn);
+
+    /* Try proxy. */
+    if (priv->opened[XEN_UNIFIED_PROXY_OFFSET]) {
+        ret = xenProxyLookupByName (conn, name);
+        if (ret || conn->err.code != VIR_ERR_OK)
+            return ret;
+    }
+
+    /* Try xend. */
+    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
+        ret = xenDaemonLookupByName (conn, name);
+        if (ret || conn->err.code != VIR_ERR_OK)
+            return ret;
+    }
+
+    /* Try xenstore for inactive domains. */
+    if (priv->opened[XEN_UNIFIED_XS_OFFSET]) {
+        ret = xenStoreLookupByName (conn, name);
+        if (ret || conn->err.code != VIR_ERR_OK)
+            return ret;
+    }
+
+    /* Try XM for inactive domains. */
+    if (priv->opened[XEN_UNIFIED_XM_OFFSET]) {
+        ret = xenXMDomainLookupByName (conn, name);
+        if (ret || conn->err.code != VIR_ERR_OK)
+            return ret;
+    }
+
+    /* Not found. */
+    xenUnifiedError (conn, VIR_ERR_NO_DOMAIN, __FUNCTION__);
+    return NULL;
+}
+
+static int
+xenUnifiedDomainSuspend (virDomainPtr dom)
+{
+    GET_PRIVATE(dom->conn);
+    int i;
+
+    /* Try non-hypervisor methods first, then hypervisor direct method
+     * as a last resort.
+     */
+    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
+        if (i != XEN_UNIFIED_HYPERVISOR_OFFSET &&
+            priv->opened[i] &&
+            drivers[i]->domainSuspend &&
+            drivers[i]->domainSuspend (dom) == 0)
+            return 0;
+
+    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET] &&
+        drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->domainSuspend &&
+        drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->domainSuspend (dom) == 0)
+        return 0;
+
+    return -1;
+}
+
+static int
+xenUnifiedDomainResume (virDomainPtr dom)
+{
+    GET_PRIVATE(dom->conn);
+    int i;
+
+    /* Try non-hypervisor methods first, then hypervisor direct method
+     * as a last resort.
+     */
+    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
+        if (i != XEN_UNIFIED_HYPERVISOR_OFFSET &&
+            priv->opened[i] &&
+            drivers[i]->domainResume &&
+            drivers[i]->domainResume (dom) == 0)
+            return 0;
+
+    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET] &&
+        drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->domainResume &&
+        drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->domainResume (dom) == 0)
+        return 0;
+
+    return -1;
+}
+
+static int
+xenUnifiedDomainShutdown (virDomainPtr dom)
+{
+    GET_PRIVATE(dom->conn);
+    int i;
+
+    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
+        if (priv->opened[i] &&
+            drivers[i]->domainShutdown &&
+            drivers[i]->domainShutdown (dom) == 0)
+            return 0;
+
+    return -1;
+}
+
+static int
+xenUnifiedDomainReboot (virDomainPtr dom, unsigned int flags)
+{
+    GET_PRIVATE(dom->conn);
+    int i;
+
+    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
+        if (priv->opened[i] &&
+            drivers[i]->domainReboot &&
+            drivers[i]->domainReboot (dom, flags) == 0)
+            return 0;
+
+    return -1;
+}
+
+static int
+xenUnifiedDomainDestroy (virDomainPtr dom)
+{
+    GET_PRIVATE(dom->conn);
+    int i;
+
+    /* Try non-hypervisor methods first, then hypervisor direct method
+     * as a last resort.
+     */
+    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
+        if (i != XEN_UNIFIED_HYPERVISOR_OFFSET &&
+            priv->opened[i] &&
+            drivers[i]->domainDestroy &&
+            drivers[i]->domainDestroy (dom) == 0)
+            return 0;
+
+    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET] &&
+        drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->domainDestroy &&
+        drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->domainDestroy (dom) == 0)
+        return 0;
+
+    return -1;
+}
+
+static char *
+xenUnifiedDomainGetOSType (virDomainPtr dom)
+{
+    GET_PRIVATE(dom->conn);
+    int i;
+    char *ret;
+
+    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
+        if (priv->opened[i] && drivers[i]->domainGetOSType) {
+            ret = drivers[i]->domainGetOSType (dom);
+            if (ret) return ret;
+        }
+
+    return NULL;
+}
+
+static unsigned long
+xenUnifiedDomainGetMaxMemory (virDomainPtr dom)
+{
+    GET_PRIVATE(dom->conn);
+    int i;
+    unsigned long ret;
+
+    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
+        if (priv->opened[i] && drivers[i]->domainGetMaxMemory) {
+            ret = drivers[i]->domainGetMaxMemory (dom);
+            if (ret != 0) return ret;
+        }
+
+    return 0;
+}
+
+static int
+xenUnifiedDomainSetMaxMemory (virDomainPtr dom, unsigned long memory)
+{
+    GET_PRIVATE(dom->conn);
+    int i;
+
+    /* Prefer xend for setting max memory */
+    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
+        if (xenDaemonDomainSetMaxMemory (dom, memory) == 0)
+            return 0;
+    }
+
+    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
+        if (i != XEN_UNIFIED_XEND_OFFSET &&
+            priv->opened[i] &&
+            drivers[i]->domainSetMaxMemory &&
+            drivers[i]->domainSetMaxMemory (dom, memory) == 0)
+            return 0;
+
+    return -1;
+}
+
+static int
+xenUnifiedDomainSetMemory (virDomainPtr dom, unsigned long memory)
+{
+    GET_PRIVATE(dom->conn);
+    int i;
+
+    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
+        if (priv->opened[i] &&
+            drivers[i]->domainSetMemory &&
+            drivers[i]->domainSetMemory (dom, memory) == 0)
+            return 0;
+
+    return -1;
+}
+
+static int
+xenUnifiedDomainGetInfo (virDomainPtr dom, virDomainInfoPtr info)
+{
+    GET_PRIVATE(dom->conn);
+    int i;
+
+    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
+        if (priv->opened[i] &&
+            drivers[i]->domainGetInfo &&
+            drivers[i]->domainGetInfo (dom, info) == 0)
+            return 0;
+
+    return -1;
+}
+
+static int
+xenUnifiedDomainSave (virDomainPtr dom, const char *to)
+{
+    GET_PRIVATE(dom->conn);
+    int i;
+
+    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
+        if (priv->opened[i] &&
+            drivers[i]->domainSave &&
+            drivers[i]->domainSave (dom, to) == 0)
+            return 0;
+
+    return -1;
+}
+
+static int
+xenUnifiedDomainRestore (virConnectPtr conn, const char *from)
+{
+    GET_PRIVATE(conn);
+    int i;
+
+    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
+        if (priv->opened[i] &&
+            drivers[i]->domainRestore &&
+            drivers[i]->domainRestore (conn, from) == 0)
+            return 0;
+
+    return -1;
+}
+
+static int
+xenUnifiedDomainCoreDump (virDomainPtr dom, const char *to, int flags)
+{
+    GET_PRIVATE(dom->conn);
+    int i;
+
+    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
+        if (priv->opened[i] &&
+            drivers[i]->domainCoreDump &&
+            drivers[i]->domainCoreDump (dom, to, flags) == 0)
+            return 0;
+
+    return -1;
+}
+
+static int
+xenUnifiedDomainSetVcpus (virDomainPtr dom, unsigned int nvcpus)
+{
+    GET_PRIVATE(dom->conn);
+    int i;
+
+    /* Try non-hypervisor methods first, then hypervisor direct method
+     * as a last resort.
+     */
+    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
+        if (i != XEN_UNIFIED_HYPERVISOR_OFFSET &&
+            priv->opened[i] &&
+            drivers[i]->domainSetVcpus &&
+            drivers[i]->domainSetVcpus (dom, nvcpus) == 0)
+            return 0;
+
+    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET] &&
+        drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->domainSetVcpus &&
+        drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->domainSetVcpus (dom, nvcpus) == 0)
+        return 0;
+
+    return -1;
+}
+
+static int
+xenUnifiedDomainPinVcpu (virDomainPtr dom, unsigned int vcpu,
+                         unsigned char *cpumap, int maplen)
+{
+    GET_PRIVATE(dom->conn);
+    int i;
+
+    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
+        if (priv->opened[i] &&
+            drivers[i]->domainPinVcpu &&
+            drivers[i]->domainPinVcpu (dom, vcpu, cpumap, maplen) == 0)
+            return 0;
+
+    return -1;
+}
+
+static int
+xenUnifiedDomainGetVcpus (virDomainPtr dom,
+                          virVcpuInfoPtr info, int maxinfo,
+                          unsigned char *cpumaps, int maplen)
+{
+    GET_PRIVATE(dom->conn);
+    int i, ret;
+
+    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
+        if (priv->opened[i] && drivers[i]->domainGetVcpus) {
+            ret = drivers[i]->domainGetVcpus (dom, info, maxinfo, cpumaps, maplen);
+            if (ret > 0)
+                return ret;
+        }
+    return -1;
+}
+
+static int
+xenUnifiedDomainGetMaxVcpus (virDomainPtr dom)
+{
+    GET_PRIVATE(dom->conn);
+    int i, ret;
+
+    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
+        if (priv->opened[i] && drivers[i]->domainGetMaxVcpus) {
+            ret = drivers[i]->domainGetMaxVcpus (dom);
+            if (ret != 0) return ret;
+        }
+
+    return -1;
+}
+
+static char *
+xenUnifiedDomainDumpXML (virDomainPtr dom, int flags)
+{
+    GET_PRIVATE(dom->conn);
+
+    if (dom->id == -1 && priv->xendConfigVersion < 3 ) {
+        if (priv->opened[XEN_UNIFIED_XM_OFFSET])
+            return xenXMDomainDumpXML(dom, flags);
+    } else {
+        if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
+            char *cpus, *res;
+            xenUnifiedLock(priv);
+            cpus = xenDomainUsedCpus(dom);
+            xenUnifiedUnlock(priv);
+            res = xenDaemonDomainDumpXML(dom, flags, cpus);
+            VIR_FREE(cpus);
+            return(res);
+        }
+        if (priv->opened[XEN_UNIFIED_PROXY_OFFSET])
+            return xenProxyDomainDumpXML(dom, flags);
+    }
+
+    xenUnifiedError (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return NULL;
+}
+
+
+static char *
+xenUnifiedDomainXMLFromNative(virConnectPtr conn,
+                              const char *format,
+                              const char *config,
+                              unsigned int flags ATTRIBUTE_UNUSED)
+{
+    virDomainDefPtr def = NULL;
+    char *ret = NULL;
+    virConfPtr conf = NULL;
+    GET_PRIVATE(conn);
+
+    if (STRNEQ(format, XEN_CONFIG_FORMAT_XM) &&
+        STRNEQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
+        xenUnifiedError(conn, VIR_ERR_INVALID_ARG,
+                        _("unsupported config type %s"), format);
+        return NULL;
+    }
+
+    if (STREQ(format, XEN_CONFIG_FORMAT_XM)) {
+        conf = virConfReadMem(config, strlen(config), 0);
+        if (!conf)
+            goto cleanup;
+
+        def = xenXMDomainConfigParse(conn, conf);
+    } else if (STREQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
+        def = xenDaemonParseSxprString(conn, config, priv->xendConfigVersion);
+    }
+    if (!def)
+        goto cleanup;
+
+    ret = virDomainDefFormat(conn, def, 0);
+
+cleanup:
+    virDomainDefFree(def);
+    return ret;
+}
+
+
+#define MAX_CONFIG_SIZE (1024 * 65)
+static char *
+xenUnifiedDomainXMLToNative(virConnectPtr conn,
+                            const char *format,
+                            const char *xmlData,
+                            unsigned int flags ATTRIBUTE_UNUSED)
+{
+    virDomainDefPtr def = NULL;
+    char *ret = NULL;
+    virConfPtr conf = NULL;
+    GET_PRIVATE(conn);
+
+    if (STRNEQ(format, XEN_CONFIG_FORMAT_XM) &&
+        STRNEQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
+        xenUnifiedError(conn, VIR_ERR_INVALID_ARG,
+                        _("unsupported config type %s"), format);
+        goto cleanup;
+    }
+
+    if (!(def = virDomainDefParseString(conn,
+                                        priv->caps,
+                                        xmlData,
+                                        0)))
+        goto cleanup;
+
+    if (STREQ(format, XEN_CONFIG_FORMAT_XM)) {
+        int len = MAX_CONFIG_SIZE;
+        conf = xenXMDomainConfigFormat(conn, def);
+        if (!conf)
+            goto cleanup;
+
+        if (VIR_ALLOC_N(ret, len) < 0) {
+            virReportOOMError(conn);
+            goto cleanup;
+        }
+
+        if (virConfWriteMem(ret, &len, conf) < 0) {
+            VIR_FREE(ret);
+            goto cleanup;
+        }
+    } else if (STREQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
+        ret = xenDaemonFormatSxpr(conn, def, priv->xendConfigVersion);
+    }
+
+cleanup:
+    virDomainDefFree(def);
+    if (conf)
+        virConfFree(conf);
+    return ret;
+}
+
+
+static int
+xenUnifiedDomainMigratePrepare (virConnectPtr dconn,
+                                char **cookie,
+                                int *cookielen,
+                                const char *uri_in,
+                                char **uri_out,
+                                unsigned long flags,
+                                const char *dname,
+                                unsigned long resource)
+{
+    GET_PRIVATE(dconn);
+
+    if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
+        return xenDaemonDomainMigratePrepare (dconn, cookie, cookielen,
+                                              uri_in, uri_out,
+                                              flags, dname, resource);
+
+    xenUnifiedError (dconn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+static int
+xenUnifiedDomainMigratePerform (virDomainPtr dom,
+                                const char *cookie,
+                                int cookielen,
+                                const char *uri,
+                                unsigned long flags,
+                                const char *dname,
+                                unsigned long resource)
+{
+    GET_PRIVATE(dom->conn);
+
+    if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
+        return xenDaemonDomainMigratePerform (dom, cookie, cookielen, uri,
+                                              flags, dname, resource);
+
+    xenUnifiedError (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+static virDomainPtr
+xenUnifiedDomainMigrateFinish (virConnectPtr dconn,
+                               const char *dname,
+                               const char *cookie ATTRIBUTE_UNUSED,
+                               int cookielen ATTRIBUTE_UNUSED,
+                               const char *uri ATTRIBUTE_UNUSED,
+                               unsigned long flags ATTRIBUTE_UNUSED)
+{
+    return xenUnifiedDomainLookupByName (dconn, dname);
+}
+
+static int
+xenUnifiedListDefinedDomains (virConnectPtr conn, char **const names,
+                              int maxnames)
+{
+    GET_PRIVATE(conn);
+    int i;
+    int ret;
+
+    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
+        if (priv->opened[i] && drivers[i]->listDefinedDomains) {
+            ret = drivers[i]->listDefinedDomains (conn, names, maxnames);
+            if (ret >= 0) return ret;
+        }
+
+    return -1;
+}
+
+static int
+xenUnifiedNumOfDefinedDomains (virConnectPtr conn)
+{
+    GET_PRIVATE(conn);
+    int i;
+    int ret;
+
+    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
+        if (priv->opened[i] && drivers[i]->numOfDefinedDomains) {
+            ret = drivers[i]->numOfDefinedDomains (conn);
+            if (ret >= 0) return ret;
+        }
+
+    return -1;
+}
+
+static int
+xenUnifiedDomainCreate (virDomainPtr dom)
+{
+    GET_PRIVATE(dom->conn);
+    int i;
+
+    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
+        if (priv->opened[i] && drivers[i]->domainCreate &&
+            drivers[i]->domainCreate (dom) == 0)
+            return 0;
+
+    return -1;
+}
+
+static virDomainPtr
+xenUnifiedDomainDefineXML (virConnectPtr conn, const char *xml)
+{
+    GET_PRIVATE(conn);
+    int i;
+    virDomainPtr ret;
+
+    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
+        if (priv->opened[i] && drivers[i]->domainDefineXML) {
+            ret = drivers[i]->domainDefineXML (conn, xml);
+            if (ret) return ret;
+        }
+
+    return NULL;
+}
+
+static int
+xenUnifiedDomainUndefine (virDomainPtr dom)
+{
+    GET_PRIVATE(dom->conn);
+    int i;
+
+    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
+        if (priv->opened[i] && drivers[i]->domainUndefine &&
+            drivers[i]->domainUndefine (dom) == 0)
+            return 0;
+
+    return -1;
+}
+
+static int
+xenUnifiedDomainAttachDevice (virDomainPtr dom, const char *xml)
+{
+    GET_PRIVATE(dom->conn);
+    int i;
+
+    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
+        if (priv->opened[i] && drivers[i]->domainAttachDevice &&
+            drivers[i]->domainAttachDevice (dom, xml) == 0)
+            return 0;
+
+    return -1;
+}
+
+static int
+xenUnifiedDomainDetachDevice (virDomainPtr dom, const char *xml)
+{
+    GET_PRIVATE(dom->conn);
+    int i;
+
+    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
+        if (priv->opened[i] && drivers[i]->domainDetachDevice &&
+            drivers[i]->domainDetachDevice (dom, xml) == 0)
+            return 0;
+
+    return -1;
+}
+
+static int
+xenUnifiedDomainGetAutostart (virDomainPtr dom, int *autostart)
+{
+    GET_PRIVATE(dom->conn);
+
+    if (priv->xendConfigVersion < 3) {
+        if (priv->opened[XEN_UNIFIED_XM_OFFSET])
+            return xenXMDomainGetAutostart(dom, autostart);
+    } else {
+        if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
+            return xenDaemonDomainGetAutostart(dom, autostart);
+    }
+
+    xenUnifiedError (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+static int
+xenUnifiedDomainSetAutostart (virDomainPtr dom, int autostart)
+{
+    GET_PRIVATE(dom->conn);
+
+    if (priv->xendConfigVersion < 3) {
+        if (priv->opened[XEN_UNIFIED_XM_OFFSET])
+            return xenXMDomainSetAutostart(dom, autostart);
+    } else {
+        if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
+            return xenDaemonDomainSetAutostart(dom, autostart);
+    }
+
+    xenUnifiedError (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+static char *
+xenUnifiedDomainGetSchedulerType (virDomainPtr dom, int *nparams)
+{
+    GET_PRIVATE(dom->conn);
+    int i;
+    char *schedulertype;
+
+    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; i++) {
+        if (priv->opened[i] && drivers[i]->domainGetSchedulerType) {
+            schedulertype = drivers[i]->domainGetSchedulerType (dom, nparams);
+            if (schedulertype != NULL)
+                return(schedulertype);
+        }
+    }
+    return(NULL);
+}
+
+static int
+xenUnifiedDomainGetSchedulerParameters (virDomainPtr dom,
+                    virSchedParameterPtr params, int *nparams)
+{
+    GET_PRIVATE(dom->conn);
+    int i, ret;
+
+    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i) {
+        if (priv->opened[i] && drivers[i]->domainGetSchedulerParameters) {
+           ret = drivers[i]->domainGetSchedulerParameters(dom, params, nparams);
+           if (ret == 0)
+               return(0);
+        }
+    }
+    return(-1);
+}
+
+static int
+xenUnifiedDomainSetSchedulerParameters (virDomainPtr dom,
+                    virSchedParameterPtr params, int nparams)
+{
+    GET_PRIVATE(dom->conn);
+    int i, ret;
+
+    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i) {
+        if (priv->opened[i] && drivers[i]->domainSetSchedulerParameters) {
+           ret = drivers[i]->domainSetSchedulerParameters(dom, params, nparams);
+           if (ret == 0)
+               return 0;
+        }
+    }
+
+    return(-1);
+}
+
+static int
+xenUnifiedDomainBlockStats (virDomainPtr dom, const char *path,
+                            struct _virDomainBlockStats *stats)
+{
+    GET_PRIVATE (dom->conn);
+
+    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET])
+        return xenHypervisorDomainBlockStats (dom, path, stats);
+
+    xenUnifiedError (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+static int
+xenUnifiedDomainInterfaceStats (virDomainPtr dom, const char *path,
+                                struct _virDomainInterfaceStats *stats)
+{
+    GET_PRIVATE (dom->conn);
+
+    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET])
+        return xenHypervisorDomainInterfaceStats (dom, path, stats);
+
+    xenUnifiedError (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+static int
+xenUnifiedDomainBlockPeek (virDomainPtr dom, const char *path,
+                           unsigned long long offset, size_t size,
+                           void *buffer, unsigned int flags ATTRIBUTE_UNUSED)
+{
+    int r;
+    GET_PRIVATE (dom->conn);
+
+    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
+        r = xenDaemonDomainBlockPeek (dom, path, offset, size, buffer);
+        if (r != -2) return r;
+        /* r == -2 means declined, so fall through to XM driver ... */
+    }
+
+    if (priv->opened[XEN_UNIFIED_XM_OFFSET]) {
+        if (xenXMDomainBlockPeek (dom, path, offset, size, buffer) == 0)
+            return 0;
+    }
+
+    xenUnifiedError (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+static int
+xenUnifiedNodeGetCellsFreeMemory (virConnectPtr conn, unsigned long long *freeMems,
+                                  int startCell, int maxCells)
+{
+    GET_PRIVATE (conn);
+
+    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET])
+        return xenHypervisorNodeGetCellsFreeMemory (conn, freeMems,
+                                                    startCell, maxCells);
+
+    xenUnifiedError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+static unsigned long long
+xenUnifiedNodeGetFreeMemory (virConnectPtr conn)
+{
+    unsigned long long freeMem = 0;
+    int ret;
+    GET_PRIVATE (conn);
+
+    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET]) {
+        ret = xenHypervisorNodeGetCellsFreeMemory (conn, &freeMem,
+                                                    -1, 1);
+        if (ret != 1)
+            return (0);
+        return(freeMem);
+    }
+
+    xenUnifiedError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return(0);
+}
+
+static int
+xenUnifiedDomainEventRegister (virConnectPtr conn,
+                               virConnectDomainEventCallback callback,
+                               void *opaque,
+                               void (*freefunc)(void *))
+{
+    GET_PRIVATE (conn);
+
+    int ret;
+    xenUnifiedLock(priv);
+
+    if (priv->xsWatch == -1) {
+        xenUnifiedError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        xenUnifiedUnlock(priv);
+        return -1;
+    }
+
+    ret = virDomainEventCallbackListAdd(conn, priv->domainEventCallbacks,
+                                        callback, opaque, freefunc);
+
+    if (ret == 0)
+        conn->refs++;
+
+    xenUnifiedUnlock(priv);
+    return (ret);
+}
+
+static int
+xenUnifiedDomainEventDeregister (virConnectPtr conn,
+                                 virConnectDomainEventCallback callback)
+{
+    int ret;
+    GET_PRIVATE (conn);
+    xenUnifiedLock(priv);
+
+    if (priv->xsWatch == -1) {
+        xenUnifiedError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        xenUnifiedUnlock(priv);
+        return -1;
+    }
+
+    if (priv->domainEventDispatching)
+        ret = virDomainEventCallbackListMarkDelete(conn, priv->domainEventCallbacks,
+                                                   callback);
+    else
+        ret = virDomainEventCallbackListRemove(conn, priv->domainEventCallbacks,
+                                               callback);
+
+    if (ret == 0)
+        virUnrefConnect(conn);
+
+    xenUnifiedUnlock(priv);
+    return ret;
+}
+
+
+static int
+xenUnifiedNodeDeviceGetPciInfo (virNodeDevicePtr dev,
+                           unsigned *domain,
+                           unsigned *bus,
+                           unsigned *slot,
+                           unsigned *function)
+{
+    virNodeDeviceDefPtr def = NULL;
+    virNodeDevCapsDefPtr cap;
+    char *xml = NULL;
+    int ret = -1;
+
+    xml = virNodeDeviceGetXMLDesc(dev, 0);
+    if (!xml)
+        goto out;
+
+    def = virNodeDeviceDefParseString(dev->conn, xml, EXISTING_DEVICE);
+    if (!def)
+        goto out;
+
+    cap = def->caps;
+    while (cap) {
+        if (cap->type == VIR_NODE_DEV_CAP_PCI_DEV) {
+            *domain   = cap->data.pci_dev.domain;
+            *bus      = cap->data.pci_dev.bus;
+            *slot     = cap->data.pci_dev.slot;
+            *function = cap->data.pci_dev.function;
+            break;
+        }
+
+        cap = cap->next;
+    }
+
+    if (!cap) {
+        xenUnifiedError(dev->conn, VIR_ERR_INVALID_ARG,
+                        _("device %s is not a PCI device"), dev->name);
+        goto out;
+    }
+
+    ret = 0;
+out:
+    virNodeDeviceDefFree(def);
+    VIR_FREE(xml);
+    return ret;
+}
+
+static int
+xenUnifiedNodeDeviceDettach (virNodeDevicePtr dev)
+{
+    pciDevice *pci;
+    unsigned domain, bus, slot, function;
+    int ret = -1;
+
+    if (xenUnifiedNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
+        return -1;
+
+    pci = pciGetDevice(dev->conn, domain, bus, slot, function);
+    if (!pci)
+        return -1;
+
+    if (pciDettachDevice(dev->conn, pci) < 0)
+        goto out;
+
+    ret = 0;
+out:
+    pciFreeDevice(dev->conn, pci);
+    return ret;
+}
+
+static int
+xenUnifiedNodeDeviceReAttach (virNodeDevicePtr dev)
+{
+    pciDevice *pci;
+    unsigned domain, bus, slot, function;
+    int ret = -1;
+
+    if (xenUnifiedNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
+        return -1;
+
+    pci = pciGetDevice(dev->conn, domain, bus, slot, function);
+    if (!pci)
+        return -1;
+
+    if (pciReAttachDevice(dev->conn, pci) < 0)
+        goto out;
+
+    ret = 0;
+out:
+    pciFreeDevice(dev->conn, pci);
+    return ret;
+}
+
+static int
+xenUnifiedNodeDeviceReset (virNodeDevicePtr dev)
+{
+    pciDevice *pci;
+    unsigned domain, bus, slot, function;
+    int ret = -1;
+
+    if (xenUnifiedNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
+        return -1;
+
+    pci = pciGetDevice(dev->conn, domain, bus, slot, function);
+    if (!pci)
+        return -1;
+
+    if (pciResetDevice(dev->conn, pci, NULL) < 0)
+        goto out;
+
+    ret = 0;
+out:
+    pciFreeDevice(dev->conn, pci);
+    return ret;
+}
+
+
+/*----- Register with libvirt.c, and initialise Xen drivers. -----*/
+
+/* The interface which we export upwards to libvirt.c. */
+static virDriver xenUnifiedDriver = {
+    VIR_DRV_XEN_UNIFIED,
+    "Xen",
+    xenUnifiedOpen, /* open */
+    xenUnifiedClose, /* close */
+    xenUnifiedSupportsFeature, /* supports_feature */
+    xenUnifiedType, /* type */
+    xenUnifiedGetVersion, /* version */
+    xenUnifiedGetHostname, /* getHostname */
+    xenUnifiedGetMaxVcpus, /* getMaxVcpus */
+    xenUnifiedNodeGetInfo, /* nodeGetInfo */
+    xenUnifiedGetCapabilities, /* getCapabilities */
+    xenUnifiedListDomains, /* listDomains */
+    xenUnifiedNumOfDomains, /* numOfDomains */
+    xenUnifiedDomainCreateXML, /* domainCreateXML */
+    xenUnifiedDomainLookupByID, /* domainLookupByID */
+    xenUnifiedDomainLookupByUUID, /* domainLookupByUUID */
+    xenUnifiedDomainLookupByName, /* domainLookupByName */
+    xenUnifiedDomainSuspend, /* domainSuspend */
+    xenUnifiedDomainResume, /* domainResume */
+    xenUnifiedDomainShutdown, /* domainShutdown */
+    xenUnifiedDomainReboot, /* domainReboot */
+    xenUnifiedDomainDestroy, /* domainDestroy */
+    xenUnifiedDomainGetOSType, /* domainGetOSType */
+    xenUnifiedDomainGetMaxMemory, /* domainGetMaxMemory */
+    xenUnifiedDomainSetMaxMemory, /* domainSetMaxMemory */
+    xenUnifiedDomainSetMemory, /* domainSetMemory */
+    xenUnifiedDomainGetInfo, /* domainGetInfo */
+    xenUnifiedDomainSave, /* domainSave */
+    xenUnifiedDomainRestore, /* domainRestore */
+    xenUnifiedDomainCoreDump, /* domainCoreDump */
+    xenUnifiedDomainSetVcpus, /* domainSetVcpus */
+    xenUnifiedDomainPinVcpu, /* domainPinVcpu */
+    xenUnifiedDomainGetVcpus, /* domainGetVcpus */
+    xenUnifiedDomainGetMaxVcpus, /* domainGetMaxVcpus */
+    NULL, /* domainGetSecurityLabel */
+    NULL, /* nodeGetSecurityModel */
+    xenUnifiedDomainDumpXML, /* domainDumpXML */
+    xenUnifiedDomainXMLFromNative, /* domainXmlFromNative */
+    xenUnifiedDomainXMLToNative, /* domainXmlToNative */
+    xenUnifiedListDefinedDomains, /* listDefinedDomains */
+    xenUnifiedNumOfDefinedDomains, /* numOfDefinedDomains */
+    xenUnifiedDomainCreate, /* domainCreate */
+    xenUnifiedDomainDefineXML, /* domainDefineXML */
+    xenUnifiedDomainUndefine, /* domainUndefine */
+    xenUnifiedDomainAttachDevice, /* domainAttachDevice */
+    xenUnifiedDomainDetachDevice, /* domainDetachDevice */
+    xenUnifiedDomainGetAutostart, /* domainGetAutostart */
+    xenUnifiedDomainSetAutostart, /* domainSetAutostart */
+    xenUnifiedDomainGetSchedulerType, /* domainGetSchedulerType */
+    xenUnifiedDomainGetSchedulerParameters, /* domainGetSchedulerParameters */
+    xenUnifiedDomainSetSchedulerParameters, /* domainSetSchedulerParameters */
+    xenUnifiedDomainMigratePrepare, /* domainMigratePrepare */
+    xenUnifiedDomainMigratePerform, /* domainMigratePerform */
+    xenUnifiedDomainMigrateFinish, /* domainMigrateFinish */
+    xenUnifiedDomainBlockStats, /* domainBlockStats */
+    xenUnifiedDomainInterfaceStats, /* domainInterfaceStats */
+    xenUnifiedDomainBlockPeek, /* domainBlockPeek */
+    NULL, /* domainMemoryPeek */
+    xenUnifiedNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */
+    xenUnifiedNodeGetFreeMemory, /* getFreeMemory */
+    xenUnifiedDomainEventRegister, /* domainEventRegister */
+    xenUnifiedDomainEventDeregister, /* domainEventDeregister */
+    NULL, /* domainMigratePrepare2 */
+    NULL, /* domainMigrateFinish2 */
+    xenUnifiedNodeDeviceDettach, /* nodeDeviceDettach */
+    xenUnifiedNodeDeviceReAttach, /* nodeDeviceReAttach */
+    xenUnifiedNodeDeviceReset, /* nodeDeviceReset */
+};
+
+/**
+ * xenRegister:
+ *
+ * Register xen related drivers
+ *
+ * Returns the driver priority or -1 in case of error.
+ */
+int
+xenRegister (void)
+{
+    /* Ignore failures here. */
+    (void) xenHypervisorInit ();
+
+#ifdef WITH_LIBVIRTD
+    if (virRegisterStateDriver (&state_driver) == -1) return -1;
+#endif
+
+    return virRegisterDriver (&xenUnifiedDriver);
+}
+
+/**
+ * xenUnifiedDomainInfoListFree:
+ *
+ * Free the Domain Info List
+ */
+void
+xenUnifiedDomainInfoListFree(xenUnifiedDomainInfoListPtr list)
+{
+    int i;
+
+    if (list == NULL)
+        return;
+
+    for (i=0; i<list->count; i++) {
+        VIR_FREE(list->doms[i]->name);
+        VIR_FREE(list->doms[i]);
+    }
+    VIR_FREE(list);
+}
+
+/**
+ * xenUnifiedAddDomainInfo:
+ *
+ * Add name and uuid to the domain info list
+ *
+ * Returns: 0 on success, -1 on failure
+ */
+int
+xenUnifiedAddDomainInfo(xenUnifiedDomainInfoListPtr list,
+                        int id, char *name,
+                        unsigned char *uuid)
+{
+    xenUnifiedDomainInfoPtr info;
+    int n;
+
+    /* check if we already have this callback on our list */
+    for (n=0; n < list->count; n++) {
+        if (STREQ(list->doms[n]->name, name) &&
+            !memcmp(list->doms[n]->uuid, uuid, VIR_UUID_BUFLEN)) {
+            DEBUG0("WARNING: dom already tracked");
+            return -1;
+        }
+    }
+
+    if (VIR_ALLOC(info) < 0)
+        goto memory_error;
+    if (!(info->name = strdup(name)))
+        goto memory_error;
+
+    memcpy(info->uuid, uuid, VIR_UUID_BUFLEN);
+    info->id = id;
+
+    /* Make space on list */
+    n = list->count;
+    if (VIR_REALLOC_N(list->doms, n + 1) < 0) {
+        goto memory_error;
+    }
+
+    list->doms[n] = info;
+    list->count++;
+    return 0;
+memory_error:
+    virReportOOMError (NULL);
+    if (info)
+        VIR_FREE(info->name);
+    VIR_FREE(info);
+    return -1;
+}
+
+/**
+ * xenUnifiedRemoveDomainInfo:
+ *
+ * Removes name and uuid to the domain info list
+ *
+ * Returns: 0 on success, -1 on failure
+ */
+int
+xenUnifiedRemoveDomainInfo(xenUnifiedDomainInfoListPtr list,
+                           int id, char *name,
+                           unsigned char *uuid)
+{
+    int i;
+    for (i = 0 ; i < list->count ; i++) {
+        if( list->doms[i]->id == id &&
+            STREQ(list->doms[i]->name, name) &&
+            !memcmp(list->doms[i]->uuid, uuid, VIR_UUID_BUFLEN)) {
+
+            VIR_FREE(list->doms[i]->name);
+            VIR_FREE(list->doms[i]);
+
+            if (i < (list->count - 1))
+                memmove(list->doms + i,
+                        list->doms + i + 1,
+                        sizeof(*(list->doms)) *
+                                (list->count - (i + 1)));
+
+            if (VIR_REALLOC_N(list->doms,
+                              list->count - 1) < 0) {
+                ; /* Failure to reduce memory allocation isn't fatal */
+            }
+            list->count--;
+
+            return 0;
+        }
+    }
+    return -1;
+}
+
+static void
+xenUnifiedDomainEventDispatchFunc(virConnectPtr conn,
+                                  virDomainEventPtr event,
+                                  virConnectDomainEventCallback cb,
+                                  void *cbopaque,
+                                  void *opaque)
+{
+    xenUnifiedPrivatePtr priv = opaque;
+
+    /*
+     * Release the lock while the callback is running so that
+     * we're re-entrant safe for callback work - the callback
+     * may want to invoke other virt functions & we have already
+     * protected the one piece of state we have - the callback
+     * list
+     */
+    xenUnifiedUnlock(priv);
+    virDomainEventDispatchDefaultFunc(conn, event, cb, cbopaque, NULL);
+    xenUnifiedLock(priv);
+}
+
+/**
+ * xenUnifiedDomainEventDispatch:
+ * @priv: the connection to dispatch events on
+ * @event: the event to dispatch
+ *
+ * Dispatch domain events to registered callbacks
+ *
+ * The caller must hold the lock in 'priv' before invoking
+ *
+ */
+void xenUnifiedDomainEventDispatch (xenUnifiedPrivatePtr priv,
+                                    virDomainEventPtr event)
+{
+    if (!priv)
+        return;
+
+    priv->domainEventDispatching = 1;
+
+    if (priv->domainEventCallbacks) {
+        virDomainEventDispatch(event,
+                               priv->domainEventCallbacks,
+                               xenUnifiedDomainEventDispatchFunc,
+                               priv);
+
+        /* Purge any deleted callbacks */
+        virDomainEventCallbackListPurgeMarked(priv->domainEventCallbacks);
+    }
+
+    virDomainEventFree(event);
+
+    priv->domainEventDispatching = 0;
+}
+
+void xenUnifiedLock(xenUnifiedPrivatePtr priv)
+{
+    virMutexLock(&priv->lock);
+}
+
+void xenUnifiedUnlock(xenUnifiedPrivatePtr priv)
+{
+    virMutexUnlock(&priv->lock);
+}
diff --git a/src/xen/xen_driver.h b/src/xen/xen_driver.h
new file mode 100644 (file)
index 0000000..9cc877b
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * xen_unified.c: Unified Xen driver.
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ *
+ * See COPYING.LIB for the License of this software
+ *
+ * Richard W.M. Jones <rjones@redhat.com>
+ */
+
+#ifndef __VIR_XEN_UNIFIED_H__
+#define __VIR_XEN_UNIFIED_H__
+
+#include "internal.h"
+#include "capabilities.h"
+#include "driver.h"
+#include "domain_conf.h"
+#include "xs_internal.h"
+#if WITH_XEN_INOTIFY
+#include "xen_inotify.h"
+#endif
+#include "domain_event.h"
+#include "hash.h"
+
+#ifndef HAVE_WINSOCK2_H
+#include <sys/un.h>
+#include <netinet/in.h>
+#else
+#include <winsock2.h>
+#endif
+
+extern int xenRegister (void);
+
+#define XEN_UNIFIED_HYPERVISOR_OFFSET 0
+#define XEN_UNIFIED_PROXY_OFFSET 1
+#define XEN_UNIFIED_XEND_OFFSET 2
+#define XEN_UNIFIED_XS_OFFSET 3
+#define XEN_UNIFIED_XM_OFFSET 4
+
+#if WITH_XEN_INOTIFY
+#define XEN_UNIFIED_INOTIFY_OFFSET 5
+#define XEN_UNIFIED_NR_DRIVERS 6
+#else
+#define XEN_UNIFIED_NR_DRIVERS 5
+#endif
+
+#define MIN_XEN_GUEST_SIZE 64  /* 64 megabytes */
+
+#define XEN_CONFIG_FORMAT_XM    "xen-xm"
+#define XEN_CONFIG_FORMAT_SEXPR "xen-sxpr"
+
+/* _xenUnifiedDriver:
+ *
+ * Entry points into the underlying Xen drivers.  This structure
+ * will eventually go away and instead xen unified will make direct
+ * calls to the underlying Xen drivers.
+ *
+ * To reiterate - the goal is to remove elements from this structure
+ * until it is empty, replacing indirect calls through this
+ * structure with direct calls in xen_unified.c.
+ */
+struct xenUnifiedDriver {
+        virDrvOpen                     open;
+        virDrvClose                    close;
+        virDrvGetVersion               version;
+    virDrvGetHostname       getHostname;
+        virDrvNodeGetInfo              nodeGetInfo;
+        virDrvGetCapabilities          getCapabilities;
+        virDrvListDomains              listDomains;
+        virDrvNumOfDomains             numOfDomains;
+        virDrvDomainCreateXML          domainCreateXML;
+        virDrvDomainSuspend            domainSuspend;
+        virDrvDomainResume             domainResume;
+        virDrvDomainShutdown           domainShutdown;
+        virDrvDomainReboot             domainReboot;
+        virDrvDomainDestroy            domainDestroy;
+        virDrvDomainGetOSType          domainGetOSType;
+        virDrvDomainGetMaxMemory       domainGetMaxMemory;
+        virDrvDomainSetMaxMemory       domainSetMaxMemory;
+        virDrvDomainSetMemory          domainSetMemory;
+        virDrvDomainGetInfo            domainGetInfo;
+        virDrvDomainSave               domainSave;
+        virDrvDomainRestore            domainRestore;
+        virDrvDomainCoreDump           domainCoreDump;
+        virDrvDomainSetVcpus           domainSetVcpus;
+        virDrvDomainPinVcpu            domainPinVcpu;
+        virDrvDomainGetVcpus           domainGetVcpus;
+        virDrvDomainGetMaxVcpus                domainGetMaxVcpus;
+        virDrvListDefinedDomains       listDefinedDomains;
+        virDrvNumOfDefinedDomains      numOfDefinedDomains;
+        virDrvDomainCreate             domainCreate;
+        virDrvDomainDefineXML           domainDefineXML;
+        virDrvDomainUndefine            domainUndefine;
+        virDrvDomainAttachDevice       domainAttachDevice;
+        virDrvDomainDetachDevice       domainDetachDevice;
+        virDrvDomainGetAutostart       domainGetAutostart;
+        virDrvDomainSetAutostart       domainSetAutostart;
+        virDrvDomainGetSchedulerType   domainGetSchedulerType;
+        virDrvDomainGetSchedulerParameters domainGetSchedulerParameters;
+        virDrvDomainSetSchedulerParameters domainSetSchedulerParameters;
+};
+
+typedef struct xenXMConfCache *xenXMConfCachePtr;
+typedef struct xenXMConfCache {
+    time_t refreshedAt;
+    char filename[PATH_MAX];
+    virDomainDefPtr def;
+} xenXMConfCache;
+
+/* xenUnifiedDomainInfoPtr:
+ * The minimal state we have about active domains
+ * This is the minmal info necessary to still get a
+ * virDomainPtr when the domain goes away
+ */
+struct _xenUnifiedDomainInfo {
+    int  id;
+    char *name;
+    unsigned char uuid[VIR_UUID_BUFLEN];
+};
+typedef struct _xenUnifiedDomainInfo xenUnifiedDomainInfo;
+typedef xenUnifiedDomainInfo *xenUnifiedDomainInfoPtr;
+
+struct _xenUnifiedDomainInfoList {
+    unsigned int count;
+    xenUnifiedDomainInfoPtr *doms;
+};
+typedef struct _xenUnifiedDomainInfoList xenUnifiedDomainInfoList;
+typedef xenUnifiedDomainInfoList *xenUnifiedDomainInfoListPtr;
+
+/* xenUnifiedPrivatePtr:
+ *
+ * Per-connection private data, stored in conn->privateData.  All Xen
+ * low-level drivers access parts of this structure.
+ */
+struct _xenUnifiedPrivate {
+    virMutex lock;
+
+    /* These initial vars are initialized in Open method
+     * and readonly thereafter, so can be used without
+     * holding the lock
+     */
+    virCapsPtr caps;
+    int handle;                        /* Xen hypervisor handle */
+
+    int xendConfigVersion;      /* XenD config version */
+
+    /* connection to xend */
+    struct sockaddr_storage addr;
+    socklen_t addrlen;
+    int addrfamily;
+    int addrprotocol;
+
+    /* Keep track of the drivers which opened.  We keep a yes/no flag
+     * here for each driver, corresponding to the array drivers in
+     * xen_unified.c.
+     */
+    int opened[XEN_UNIFIED_NR_DRIVERS];
+
+
+    /*
+     * Everything from this point onwards must be protected
+     * by the lock when used
+     */
+
+    struct xs_handle *xshandle; /* handle to talk to the xenstore */
+
+    int proxy;                  /* fd of proxy. */
+
+
+    /* A list of xenstore watches */
+    xenStoreWatchListPtr xsWatchList;
+    int xsWatch;
+    /* A list of active domain name/uuids */
+    xenUnifiedDomainInfoListPtr activeDomainList;
+
+    /* NUMA topology info cache */
+    int nbNodeCells;
+    int nbNodeCpus;
+
+    /* An list of callbacks */
+    virDomainEventCallbackListPtr domainEventCallbacks;
+    int domainEventDispatching;
+
+    /* Location of config files, either /etc
+     * or /var/lib/xen */
+    const char *configDir;
+
+#if WITH_XEN_INOTIFY
+    /* The inotify fd */
+    int inotifyFD;
+    int inotifyWatch;
+
+    int  useXenConfigCache ;
+    xenUnifiedDomainInfoListPtr configInfoList;
+#endif
+
+    /* For the 'xm' driver */
+    /* Primary config file name -> virDomainDef map */
+    virHashTablePtr configCache;
+    /* Domain name to config file name */
+    virHashTablePtr nameConfigMap;
+    /* So we don't refresh too often */
+    time_t lastRefresh;
+};
+
+typedef struct _xenUnifiedPrivate *xenUnifiedPrivatePtr;
+
+char *xenDomainUsedCpus(virDomainPtr dom);
+
+void xenUnifiedDomainInfoListFree(xenUnifiedDomainInfoListPtr info);
+int  xenUnifiedAddDomainInfo(xenUnifiedDomainInfoListPtr info,
+                             int id, char *name,
+                             unsigned char *uuid);
+int  xenUnifiedRemoveDomainInfo(xenUnifiedDomainInfoListPtr info,
+                                int id, char *name,
+                                unsigned char *uuid);
+void xenUnifiedDomainEventDispatch (xenUnifiedPrivatePtr priv,
+                                    virDomainEventPtr event);
+unsigned long xenUnifiedVersion(void);
+
+#ifndef PROXY
+void xenUnifiedLock(xenUnifiedPrivatePtr priv);
+void xenUnifiedUnlock(xenUnifiedPrivatePtr priv);
+#else
+#define xenUnifiedLock(p) do {} while(0)
+#define xenUnifiedUnlock(p) do {} while(0)
+#endif
+
+#endif /* __VIR_XEN_UNIFIED_H__ */
diff --git a/src/xen/xen_hypervisor.c b/src/xen/xen_hypervisor.c
new file mode 100644 (file)
index 0000000..9f3f5fe
--- /dev/null
@@ -0,0 +1,3458 @@
+/*
+ * xen_internal.c: direct access to Xen hypervisor level
+ *
+ * Copyright (C) 2005, 2006, 2007, 2008, 2009 Red Hat, Inc.
+ *
+ * See COPYING.LIB for the License of this software
+ *
+ * Daniel Veillard <veillard@redhat.com>
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+/* required for uint8_t, uint32_t, etc ... */
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <limits.h>
+#include <stdint.h>
+#include <regex.h>
+#include <errno.h>
+#include <sys/utsname.h>
+
+#ifdef __sun
+#include <sys/systeminfo.h>
+
+#include <priv.h>
+
+#ifndef PRIV_XVM_CONTROL
+#define PRIV_XVM_CONTROL ((const char *)"xvm_control")
+#endif
+
+#endif /* __sun */
+
+/* required for dom0_getdomaininfo_t */
+#include <xen/dom0_ops.h>
+#include <xen/version.h>
+#ifdef HAVE_XEN_LINUX_PRIVCMD_H
+#include <xen/linux/privcmd.h>
+#else
+#ifdef HAVE_XEN_SYS_PRIVCMD_H
+#include <xen/sys/privcmd.h>
+#endif
+#endif
+
+/* required for shutdown flags */
+#include <xen/sched.h>
+
+#include "virterror_internal.h"
+#include "logging.h"
+#include "datatypes.h"
+#include "driver.h"
+#include "util.h"
+#include "xen_driver.h"
+#include "xen_hypervisor.h"
+#include "xs_internal.h"
+#include "stats_linux.h"
+#include "block_stats.h"
+#include "xend_internal.h"
+#include "buf.h"
+#include "capabilities.h"
+#include "memory.h"
+
+#define VIR_FROM_THIS VIR_FROM_XEN
+
+/*
+ * so far there is 2 versions of the structures usable for doing
+ * hypervisor calls.
+ */
+/* the old one */
+typedef struct v0_hypercall_struct {
+    unsigned long op;
+    unsigned long arg[5];
+} v0_hypercall_t;
+
+#ifdef __linux__
+#define XEN_V0_IOCTL_HYPERCALL_CMD \
+        _IOC(_IOC_NONE, 'P', 0, sizeof(v0_hypercall_t))
+/* the new one */
+typedef struct v1_hypercall_struct
+{
+    uint64_t op;
+    uint64_t arg[5];
+} v1_hypercall_t;
+#define XEN_V1_IOCTL_HYPERCALL_CMD                  \
+    _IOC(_IOC_NONE, 'P', 0, sizeof(v1_hypercall_t))
+typedef v1_hypercall_t hypercall_t;
+#elif defined(__sun)
+typedef privcmd_hypercall_t hypercall_t;
+#else
+#error "unsupported platform"
+#endif
+
+#ifndef __HYPERVISOR_sysctl
+#define __HYPERVISOR_sysctl 35
+#endif
+#ifndef __HYPERVISOR_domctl
+#define __HYPERVISOR_domctl 36
+#endif
+
+#ifdef WITH_RHEL5_API
+#define SYS_IFACE_MIN_VERS_NUMA 3
+#else
+#define SYS_IFACE_MIN_VERS_NUMA 4
+#endif
+
+static int xen_ioctl_hypercall_cmd = 0;
+static int initialized = 0;
+static int in_init = 0;
+static int hv_version = 0;
+static int hypervisor_version = 2;
+static int sys_interface_version = -1;
+static int dom_interface_version = -1;
+static int kb_per_pages = 0;
+
+/* Regular expressions used by xenHypervisorGetCapabilities, and
+ * compiled once by xenHypervisorInit.  Note that these are POSIX.2
+ * extended regular expressions (regex(7)).
+ */
+static const char *flags_hvm_re = "^flags[[:blank:]]+:.* (vmx|svm)[[:space:]]";
+static regex_t flags_hvm_rec;
+static const char *flags_pae_re = "^flags[[:blank:]]+:.* pae[[:space:]]";
+static regex_t flags_pae_rec;
+static const char *xen_cap_re = "(xen|hvm)-[[:digit:]]+\\.[[:digit:]]+-(x86_32|x86_64|ia64|powerpc64)(p|be)?";
+static regex_t xen_cap_rec;
+
+/*
+ * The content of the structures for a getdomaininfolist system hypercall
+ */
+#ifndef DOMFLAGS_DYING
+#define DOMFLAGS_DYING     (1<<0) /* Domain is scheduled to die.             */
+#define DOMFLAGS_HVM       (1<<1) /* Domain is HVM                           */
+#define DOMFLAGS_SHUTDOWN  (1<<2) /* The guest OS has shut down.             */
+#define DOMFLAGS_PAUSED    (1<<3) /* Currently paused by control software.   */
+#define DOMFLAGS_BLOCKED   (1<<4) /* Currently blocked pending an event.     */
+#define DOMFLAGS_RUNNING   (1<<5) /* Domain is currently running.            */
+#define DOMFLAGS_CPUMASK      255 /* CPU to which this domain is bound.      */
+#define DOMFLAGS_CPUSHIFT       8
+#define DOMFLAGS_SHUTDOWNMASK 255 /* DOMFLAGS_SHUTDOWN guest-supplied code.  */
+#define DOMFLAGS_SHUTDOWNSHIFT 16
+#endif
+
+/*
+ * These flags explain why a system is in the state of "shutdown".  Normally,
+ * They are defined in xen/sched.h
+ */
+#ifndef SHUTDOWN_poweroff
+#define SHUTDOWN_poweroff   0  /* Domain exited normally. Clean up and kill. */
+#define SHUTDOWN_reboot     1  /* Clean up, kill, and then restart.          */
+#define SHUTDOWN_suspend    2  /* Clean up, save suspend info, kill.         */
+#define SHUTDOWN_crash      3  /* Tell controller we've crashed.             */
+#endif
+
+#define XEN_V0_OP_GETDOMAININFOLIST    38
+#define XEN_V1_OP_GETDOMAININFOLIST    38
+#define XEN_V2_OP_GETDOMAININFOLIST    6
+
+struct xen_v0_getdomaininfo {
+    domid_t  domain;   /* the domain number */
+    uint32_t flags;    /* flags, see before */
+    uint64_t tot_pages;        /* total number of pages used */
+    uint64_t max_pages;        /* maximum number of pages allowed */
+    unsigned long shared_info_frame; /* MFN of shared_info struct */
+    uint64_t cpu_time;  /* CPU time used */
+    uint32_t nr_online_vcpus;  /* Number of VCPUs currently online. */
+    uint32_t max_vcpu_id; /* Maximum VCPUID in use by this domain. */
+    uint32_t ssidref;
+    xen_domain_handle_t handle;
+};
+typedef struct xen_v0_getdomaininfo xen_v0_getdomaininfo;
+
+struct xen_v2_getdomaininfo {
+    domid_t  domain;   /* the domain number */
+    uint32_t flags;    /* flags, see before */
+    uint64_t tot_pages;        /* total number of pages used */
+    uint64_t max_pages;        /* maximum number of pages allowed */
+    uint64_t shared_info_frame; /* MFN of shared_info struct */
+    uint64_t cpu_time;  /* CPU time used */
+    uint32_t nr_online_vcpus;  /* Number of VCPUs currently online. */
+    uint32_t max_vcpu_id; /* Maximum VCPUID in use by this domain. */
+    uint32_t ssidref;
+    xen_domain_handle_t handle;
+};
+typedef struct xen_v2_getdomaininfo xen_v2_getdomaininfo;
+
+
+/* As of Hypervisor Call v2,  DomCtl v5 we are now 8-byte aligned
+   even on 32-bit archs when dealing with uint64_t */
+#define ALIGN_64 __attribute__((aligned(8)))
+
+struct xen_v2d5_getdomaininfo {
+    domid_t  domain;   /* the domain number */
+    uint32_t flags;    /* flags, see before */
+    uint64_t tot_pages ALIGN_64;       /* total number of pages used */
+    uint64_t max_pages ALIGN_64;       /* maximum number of pages allowed */
+    uint64_t shared_info_frame ALIGN_64; /* MFN of shared_info struct */
+    uint64_t cpu_time ALIGN_64;  /* CPU time used */
+    uint32_t nr_online_vcpus;  /* Number of VCPUs currently online. */
+    uint32_t max_vcpu_id; /* Maximum VCPUID in use by this domain. */
+    uint32_t ssidref;
+    xen_domain_handle_t handle;
+};
+typedef struct xen_v2d5_getdomaininfo xen_v2d5_getdomaininfo;
+
+union xen_getdomaininfo {
+    struct xen_v0_getdomaininfo v0;
+    struct xen_v2_getdomaininfo v2;
+    struct xen_v2d5_getdomaininfo v2d5;
+};
+typedef union xen_getdomaininfo xen_getdomaininfo;
+
+union xen_getdomaininfolist {
+    struct xen_v0_getdomaininfo *v0;
+    struct xen_v2_getdomaininfo *v2;
+    struct xen_v2d5_getdomaininfo *v2d5;
+};
+typedef union xen_getdomaininfolist xen_getdomaininfolist;
+
+
+struct xen_v2_getschedulerid {
+    uint32_t sched_id; /* Get Scheduler ID from Xen */
+};
+typedef struct xen_v2_getschedulerid xen_v2_getschedulerid;
+
+
+union xen_getschedulerid {
+    struct xen_v2_getschedulerid *v2;
+};
+typedef union xen_getschedulerid xen_getschedulerid;
+
+struct xen_v2s4_availheap {
+    uint32_t min_bitwidth;  /* Smallest address width (zero if don't care). */
+    uint32_t max_bitwidth;  /* Largest address width (zero if don't care). */
+    int32_t  node;          /* NUMA node (-1 for sum across all nodes). */
+    uint64_t avail_bytes;   /* Bytes available in the specified region. */
+};
+
+typedef struct xen_v2s4_availheap  xen_v2s4_availheap;
+
+struct xen_v2s5_availheap {
+    uint32_t min_bitwidth;  /* Smallest address width (zero if don't care). */
+    uint32_t max_bitwidth;  /* Largest address width (zero if don't care). */
+    int32_t  node;          /* NUMA node (-1 for sum across all nodes). */
+    uint64_t avail_bytes ALIGN_64;   /* Bytes available in the specified region. */
+};
+
+typedef struct xen_v2s5_availheap  xen_v2s5_availheap;
+
+
+#define XEN_GETDOMAININFOLIST_ALLOC(domlist, size)                      \
+    (hypervisor_version < 2 ?                                           \
+     (VIR_ALLOC_N(domlist.v0, (size)) == 0) :                           \
+     (dom_interface_version < 5 ?                                       \
+      (VIR_ALLOC_N(domlist.v2, (size)) == 0) :                          \
+      (VIR_ALLOC_N(domlist.v2d5, (size)) == 0)))
+
+#define XEN_GETDOMAININFOLIST_FREE(domlist)            \
+    (hypervisor_version < 2 ?                          \
+     VIR_FREE(domlist.v0) :                            \
+     (dom_interface_version < 5 ?                      \
+      VIR_FREE(domlist.v2) :                           \
+      VIR_FREE(domlist.v2d5)))
+
+#define XEN_GETDOMAININFOLIST_CLEAR(domlist, size)            \
+    (hypervisor_version < 2 ?                                 \
+     memset(domlist.v0, 0, sizeof(*domlist.v0) * size) :      \
+     (dom_interface_version < 5 ?                             \
+      memset(domlist.v2, 0, sizeof(*domlist.v2) * size) :     \
+      memset(domlist.v2d5, 0, sizeof(*domlist.v2d5) * size)))
+
+#define XEN_GETDOMAININFOLIST_DOMAIN(domlist, n)    \
+    (hypervisor_version < 2 ?                       \
+     domlist.v0[n].domain :                         \
+     (dom_interface_version < 5 ?                   \
+      domlist.v2[n].domain :                        \
+      domlist.v2d5[n].domain))
+
+#define XEN_GETDOMAININFOLIST_UUID(domlist, n)      \
+    (hypervisor_version < 2 ?                       \
+     domlist.v0[n].handle :                         \
+     (dom_interface_version < 5 ?                   \
+      domlist.v2[n].handle :                        \
+      domlist.v2d5[n].handle))
+
+#define XEN_GETDOMAININFOLIST_DATA(domlist)        \
+    (hypervisor_version < 2 ?                      \
+     (void*)(domlist->v0) :                        \
+     (dom_interface_version < 5 ?                  \
+      (void*)(domlist->v2) :                       \
+      (void*)(domlist->v2d5)))
+
+#define XEN_GETDOMAININFO_SIZE                     \
+    (hypervisor_version < 2 ?                      \
+     sizeof(xen_v0_getdomaininfo) :                \
+     (dom_interface_version < 5 ?                  \
+      sizeof(xen_v2_getdomaininfo) :               \
+      sizeof(xen_v2d5_getdomaininfo)))
+
+#define XEN_GETDOMAININFO_CLEAR(dominfo)                           \
+    (hypervisor_version < 2 ?                                      \
+     memset(&(dominfo.v0), 0, sizeof(xen_v0_getdomaininfo)) :      \
+     (dom_interface_version < 5 ?                                  \
+      memset(&(dominfo.v2), 0, sizeof(xen_v2_getdomaininfo)) :     \
+      memset(&(dominfo.v2d5), 0, sizeof(xen_v2d5_getdomaininfo))))
+
+#define XEN_GETDOMAININFO_DOMAIN(dominfo)       \
+    (hypervisor_version < 2 ?                   \
+     dominfo.v0.domain :                        \
+     (dom_interface_version < 5 ?               \
+      dominfo.v2.domain :                       \
+      dominfo.v2d5.domain))
+
+#define XEN_GETDOMAININFO_CPUTIME(dominfo)      \
+    (hypervisor_version < 2 ?                   \
+     dominfo.v0.cpu_time :                      \
+     (dom_interface_version < 5 ?               \
+      dominfo.v2.cpu_time :                     \
+      dominfo.v2d5.cpu_time))
+
+#define XEN_GETDOMAININFO_CPUCOUNT(dominfo)     \
+    (hypervisor_version < 2 ?                   \
+     dominfo.v0.nr_online_vcpus :               \
+     (dom_interface_version < 5 ?               \
+      dominfo.v2.nr_online_vcpus :              \
+      dominfo.v2d5.nr_online_vcpus))
+
+#define XEN_GETDOMAININFO_MAXCPUID(dominfo)  \
+    (hypervisor_version < 2 ?                   \
+     dominfo.v0.max_vcpu_id :                   \
+     (dom_interface_version < 5 ?               \
+      dominfo.v2.max_vcpu_id :                  \
+      dominfo.v2d5.max_vcpu_id))
+
+#define XEN_GETDOMAININFO_FLAGS(dominfo)        \
+    (hypervisor_version < 2 ?                   \
+     dominfo.v0.flags :                         \
+     (dom_interface_version < 5 ?               \
+      dominfo.v2.flags :                        \
+      dominfo.v2d5.flags))
+
+#define XEN_GETDOMAININFO_TOT_PAGES(dominfo)    \
+    (hypervisor_version < 2 ?                   \
+     dominfo.v0.tot_pages :                     \
+     (dom_interface_version < 5 ?               \
+      dominfo.v2.tot_pages :                    \
+      dominfo.v2d5.tot_pages))
+
+#define XEN_GETDOMAININFO_MAX_PAGES(dominfo)    \
+    (hypervisor_version < 2 ?                   \
+     dominfo.v0.max_pages :                     \
+     (dom_interface_version < 5 ?               \
+      dominfo.v2.max_pages :                    \
+      dominfo.v2d5.max_pages))
+
+#define XEN_GETDOMAININFO_UUID(dominfo)         \
+    (hypervisor_version < 2 ?                   \
+     dominfo.v0.handle :                        \
+     (dom_interface_version < 5 ?               \
+      dominfo.v2.handle :                       \
+      dominfo.v2d5.handle))
+
+
+static int
+lock_pages(void *addr, size_t len)
+{
+#ifdef __linux__
+        return (mlock(addr, len));
+#elif defined(__sun)
+        return (0);
+#endif
+}
+
+static int
+unlock_pages(void *addr, size_t len)
+{
+#ifdef __linux__
+        return (munlock(addr, len));
+#elif defined(__sun)
+        return (0);
+#endif
+}
+
+
+struct xen_v0_getdomaininfolistop {
+    domid_t   first_domain;
+    uint32_t  max_domains;
+    struct xen_v0_getdomaininfo *buffer;
+    uint32_t  num_domains;
+};
+typedef struct xen_v0_getdomaininfolistop xen_v0_getdomaininfolistop;
+
+
+struct xen_v2_getdomaininfolistop {
+    domid_t   first_domain;
+    uint32_t  max_domains;
+    struct xen_v2_getdomaininfo *buffer;
+    uint32_t  num_domains;
+};
+typedef struct xen_v2_getdomaininfolistop xen_v2_getdomaininfolistop;
+
+/* As of HV version 2, sysctl version 3 the *buffer pointer is 64-bit aligned */
+struct xen_v2s3_getdomaininfolistop {
+    domid_t   first_domain;
+    uint32_t  max_domains;
+#ifdef __BIG_ENDIAN__
+    struct {
+        int __pad[(sizeof (long long) - sizeof (struct xen_v2d5_getdomaininfo *)) / sizeof (int)];
+        struct xen_v2d5_getdomaininfo *v;
+    } buffer;
+#else
+    union {
+        struct xen_v2d5_getdomaininfo *v;
+        uint64_t pad ALIGN_64;
+    } buffer;
+#endif
+    uint32_t  num_domains;
+};
+typedef struct xen_v2s3_getdomaininfolistop xen_v2s3_getdomaininfolistop;
+
+
+
+struct xen_v0_domainop {
+    domid_t   domain;
+};
+typedef struct xen_v0_domainop xen_v0_domainop;
+
+/*
+ * The information for a destroydomain system hypercall
+ */
+#define XEN_V0_OP_DESTROYDOMAIN        9
+#define XEN_V1_OP_DESTROYDOMAIN        9
+#define XEN_V2_OP_DESTROYDOMAIN        2
+
+/*
+ * The information for a pausedomain system hypercall
+ */
+#define XEN_V0_OP_PAUSEDOMAIN  10
+#define XEN_V1_OP_PAUSEDOMAIN  10
+#define XEN_V2_OP_PAUSEDOMAIN  3
+
+/*
+ * The information for an unpausedomain system hypercall
+ */
+#define XEN_V0_OP_UNPAUSEDOMAIN        11
+#define XEN_V1_OP_UNPAUSEDOMAIN        11
+#define XEN_V2_OP_UNPAUSEDOMAIN        4
+
+/*
+ * The information for an setmaxmem system hypercall
+ */
+#define XEN_V0_OP_SETMAXMEM    28
+#define XEN_V1_OP_SETMAXMEM    28
+#define XEN_V2_OP_SETMAXMEM    11
+
+struct xen_v0_setmaxmem {
+    domid_t    domain;
+    uint64_t   maxmem;
+};
+typedef struct xen_v0_setmaxmem xen_v0_setmaxmem;
+typedef struct xen_v0_setmaxmem xen_v1_setmaxmem;
+
+struct xen_v2_setmaxmem {
+    uint64_t   maxmem;
+};
+typedef struct xen_v2_setmaxmem xen_v2_setmaxmem;
+
+struct xen_v2d5_setmaxmem {
+    uint64_t   maxmem ALIGN_64;
+};
+typedef struct xen_v2d5_setmaxmem xen_v2d5_setmaxmem;
+
+/*
+ * The information for an setmaxvcpu system hypercall
+ */
+#define XEN_V0_OP_SETMAXVCPU   41
+#define XEN_V1_OP_SETMAXVCPU   41
+#define XEN_V2_OP_SETMAXVCPU   15
+
+struct xen_v0_setmaxvcpu {
+    domid_t    domain;
+    uint32_t   maxvcpu;
+};
+typedef struct xen_v0_setmaxvcpu xen_v0_setmaxvcpu;
+typedef struct xen_v0_setmaxvcpu xen_v1_setmaxvcpu;
+
+struct xen_v2_setmaxvcpu {
+    uint32_t   maxvcpu;
+};
+typedef struct xen_v2_setmaxvcpu xen_v2_setmaxvcpu;
+
+/*
+ * The information for an setvcpumap system hypercall
+ * Note that between 1 and 2 the limitation to 64 physical CPU was lifted
+ * hence the difference in structures
+ */
+#define XEN_V0_OP_SETVCPUMAP   20
+#define XEN_V1_OP_SETVCPUMAP   20
+#define XEN_V2_OP_SETVCPUMAP   9
+
+struct xen_v0_setvcpumap {
+    domid_t    domain;
+    uint32_t   vcpu;
+    cpumap_t    cpumap;
+};
+typedef struct xen_v0_setvcpumap xen_v0_setvcpumap;
+typedef struct xen_v0_setvcpumap xen_v1_setvcpumap;
+
+struct xen_v2_cpumap {
+    uint8_t    *bitmap;
+    uint32_t    nr_cpus;
+};
+struct xen_v2_setvcpumap {
+    uint32_t   vcpu;
+    struct xen_v2_cpumap cpumap;
+};
+typedef struct xen_v2_setvcpumap xen_v2_setvcpumap;
+
+/* HV version 2, Dom version 5 requires 64-bit alignment */
+struct xen_v2d5_cpumap {
+#ifdef __BIG_ENDIAN__
+    struct {
+        int __pad[(sizeof (long long) - sizeof (uint8_t *)) / sizeof (int)];
+        uint8_t *v;
+    } bitmap;
+#else
+    union {
+        uint8_t    *v;
+        uint64_t   pad ALIGN_64;
+    } bitmap;
+#endif
+    uint32_t    nr_cpus;
+};
+struct xen_v2d5_setvcpumap {
+    uint32_t   vcpu;
+    struct xen_v2d5_cpumap cpumap;
+};
+typedef struct xen_v2d5_setvcpumap xen_v2d5_setvcpumap;
+
+/*
+ * The information for an vcpuinfo system hypercall
+ */
+#define XEN_V0_OP_GETVCPUINFO   43
+#define XEN_V1_OP_GETVCPUINFO  43
+#define XEN_V2_OP_GETVCPUINFO   14
+
+struct xen_v0_vcpuinfo {
+    domid_t    domain;         /* owner's domain */
+    uint32_t   vcpu;           /* the vcpu number */
+    uint8_t    online;         /* seen as on line */
+    uint8_t    blocked;        /* blocked on event */
+    uint8_t    running;        /* scheduled on CPU */
+    uint64_t    cpu_time;      /* nanosecond of CPU used */
+    uint32_t   cpu;            /* current mapping */
+    cpumap_t   cpumap;         /* deprecated in V2 */
+};
+typedef struct xen_v0_vcpuinfo xen_v0_vcpuinfo;
+typedef struct xen_v0_vcpuinfo xen_v1_vcpuinfo;
+
+struct xen_v2_vcpuinfo {
+    uint32_t   vcpu;           /* the vcpu number */
+    uint8_t    online;         /* seen as on line */
+    uint8_t    blocked;        /* blocked on event */
+    uint8_t    running;        /* scheduled on CPU */
+    uint64_t    cpu_time;      /* nanosecond of CPU used */
+    uint32_t   cpu;            /* current mapping */
+};
+typedef struct xen_v2_vcpuinfo xen_v2_vcpuinfo;
+
+struct xen_v2d5_vcpuinfo {
+    uint32_t   vcpu;           /* the vcpu number */
+    uint8_t    online;         /* seen as on line */
+    uint8_t    blocked;        /* blocked on event */
+    uint8_t    running;        /* scheduled on CPU */
+    uint64_t    cpu_time ALIGN_64; /* nanosecond of CPU used */
+    uint32_t   cpu;            /* current mapping */
+};
+typedef struct xen_v2d5_vcpuinfo xen_v2d5_vcpuinfo;
+
+/*
+ * from V2 the pinning of a vcpu is read with a separate call
+ */
+#define XEN_V2_OP_GETVCPUMAP   25
+typedef struct xen_v2_setvcpumap xen_v2_getvcpumap;
+typedef struct xen_v2d5_setvcpumap xen_v2d5_getvcpumap;
+
+/*
+ * from V2 we get the scheduler information
+ */
+#define XEN_V2_OP_GETSCHEDULERID       4
+
+/*
+ * from V2 we get the available heap information
+ */
+#define XEN_V2_OP_GETAVAILHEAP         9
+
+/*
+ * from V2 we get the scheduler parameter
+ */
+#define XEN_V2_OP_SCHEDULER            16
+/* Scheduler types. */
+#define XEN_SCHEDULER_SEDF       4
+#define XEN_SCHEDULER_CREDIT     5
+/* get/set scheduler parameters */
+#define XEN_DOMCTL_SCHEDOP_putinfo 0
+#define XEN_DOMCTL_SCHEDOP_getinfo 1
+
+struct xen_v2_setschedinfo {
+    uint32_t sched_id;
+    uint32_t cmd;
+    union {
+        struct xen_domctl_sched_sedf {
+            uint64_t period ALIGN_64;
+            uint64_t slice  ALIGN_64;
+            uint64_t latency ALIGN_64;
+            uint32_t extratime;
+            uint32_t weight;
+        } sedf;
+        struct xen_domctl_sched_credit {
+            uint16_t weight;
+            uint16_t cap;
+        } credit;
+    } u;
+};
+typedef struct xen_v2_setschedinfo xen_v2_setschedinfo;
+typedef struct xen_v2_setschedinfo xen_v2_getschedinfo;
+
+
+/*
+ * The hypercall operation structures also have changed on
+ * changeset 86d26e6ec89b
+ */
+/* the old structure */
+struct xen_op_v0 {
+    uint32_t cmd;
+    uint32_t interface_version;
+    union {
+        xen_v0_getdomaininfolistop getdomaininfolist;
+        xen_v0_domainop          domain;
+        xen_v0_setmaxmem         setmaxmem;
+        xen_v0_setmaxvcpu        setmaxvcpu;
+        xen_v0_setvcpumap        setvcpumap;
+        xen_v0_vcpuinfo          getvcpuinfo;
+        uint8_t padding[128];
+    } u;
+};
+typedef struct xen_op_v0 xen_op_v0;
+typedef struct xen_op_v0 xen_op_v1;
+
+/* the new structure for systems operations */
+struct xen_op_v2_sys {
+    uint32_t cmd;
+    uint32_t interface_version;
+    union {
+        xen_v2_getdomaininfolistop   getdomaininfolist;
+        xen_v2s3_getdomaininfolistop getdomaininfolists3;
+        xen_v2_getschedulerid        getschedulerid;
+        xen_v2s4_availheap           availheap;
+        xen_v2s5_availheap           availheap5;
+        uint8_t padding[128];
+    } u;
+};
+typedef struct xen_op_v2_sys xen_op_v2_sys;
+
+/* the new structure for domains operation */
+struct xen_op_v2_dom {
+    uint32_t cmd;
+    uint32_t interface_version;
+    domid_t  domain;
+    union {
+        xen_v2_setmaxmem         setmaxmem;
+        xen_v2d5_setmaxmem       setmaxmemd5;
+        xen_v2_setmaxvcpu        setmaxvcpu;
+        xen_v2_setvcpumap        setvcpumap;
+        xen_v2d5_setvcpumap      setvcpumapd5;
+        xen_v2_vcpuinfo          getvcpuinfo;
+        xen_v2d5_vcpuinfo        getvcpuinfod5;
+        xen_v2_getvcpumap        getvcpumap;
+        xen_v2d5_getvcpumap      getvcpumapd5;
+        xen_v2_setschedinfo      setschedinfo;
+        xen_v2_getschedinfo      getschedinfo;
+        uint8_t padding[128];
+    } u;
+};
+typedef struct xen_op_v2_dom xen_op_v2_dom;
+
+
+#ifdef __linux__
+#define XEN_HYPERVISOR_SOCKET  "/proc/xen/privcmd"
+#define HYPERVISOR_CAPABILITIES        "/sys/hypervisor/properties/capabilities"
+#elif defined(__sun)
+#define XEN_HYPERVISOR_SOCKET  "/dev/xen/privcmd"
+#else
+#error "unsupported platform"
+#endif
+
+#ifndef PROXY
+static unsigned long xenHypervisorGetMaxMemory(virDomainPtr domain);
+#endif
+
+#ifndef PROXY
+struct xenUnifiedDriver xenHypervisorDriver = {
+    xenHypervisorOpen, /* open */
+    xenHypervisorClose, /* close */
+    xenHypervisorGetVersion, /* version */
+    NULL, /* hostname */
+    NULL, /* nodeGetInfo */
+    xenHypervisorGetCapabilities, /* getCapabilities */
+    xenHypervisorListDomains, /* listDomains */
+    xenHypervisorNumOfDomains, /* numOfDomains */
+    NULL, /* domainCreateXML */
+    xenHypervisorPauseDomain, /* domainSuspend */
+    xenHypervisorResumeDomain, /* domainResume */
+    NULL, /* domainShutdown */
+    NULL, /* domainReboot */
+    xenHypervisorDestroyDomain, /* domainDestroy */
+    xenHypervisorDomainGetOSType, /* domainGetOSType */
+    xenHypervisorGetMaxMemory, /* domainGetMaxMemory */
+    xenHypervisorSetMaxMemory, /* domainSetMaxMemory */
+    NULL, /* domainSetMemory */
+    xenHypervisorGetDomainInfo, /* domainGetInfo */
+    NULL, /* domainSave */
+    NULL, /* domainRestore */
+    NULL, /* domainCoreDump */
+    xenHypervisorSetVcpus, /* domainSetVcpus */
+    xenHypervisorPinVcpu, /* domainPinVcpu */
+    xenHypervisorGetVcpus, /* domainGetVcpus */
+    xenHypervisorGetVcpuMax, /* domainGetMaxVcpus */
+    NULL, /* listDefinedDomains */
+    NULL, /* numOfDefinedDomains */
+    NULL, /* domainCreate */
+    NULL, /* domainDefineXML */
+    NULL, /* domainUndefine */
+    NULL, /* domainAttachDevice */
+    NULL, /* domainDetachDevice */
+    NULL, /* domainGetAutostart */
+    NULL, /* domainSetAutostart */
+    xenHypervisorGetSchedulerType, /* domainGetSchedulerType */
+    xenHypervisorGetSchedulerParameters, /* domainGetSchedulerParameters */
+    xenHypervisorSetSchedulerParameters, /* domainSetSchedulerParameters */
+};
+#endif /* !PROXY */
+
+#define virXenError(conn, code, fmt...)                                      \
+        if (in_init == 0)                                                    \
+            virReportErrorHelper(conn, VIR_FROM_XEN, code, __FILE__,       \
+                                   __FUNCTION__, __LINE__, fmt)
+
+#ifndef PROXY
+
+/**
+ * virXenErrorFunc:
+ * @conn: connection, if known
+ * @error: the error number
+ * @func: the function failing
+ * @info: extra information string
+ * @value: extra information number
+ *
+ * Handle an error at the xend daemon interface
+ */
+static void
+virXenErrorFunc(virConnectPtr conn,
+                virErrorNumber error, const char *func, const char *info,
+                int value)
+{
+    char fullinfo[1000];
+    const char *errmsg;
+
+    if ((error == VIR_ERR_OK) || (in_init != 0))
+        return;
+
+
+    errmsg =virErrorMsg(error, info);
+    if (func != NULL) {
+        snprintf(fullinfo, 999, "%s: %s", func, info);
+        fullinfo[999] = 0;
+        virRaiseError(conn, NULL, NULL, VIR_FROM_XEN, error, VIR_ERR_ERROR,
+                        errmsg, fullinfo, NULL, value, 0, errmsg, fullinfo,
+                        value);
+    } else {
+        virRaiseError(conn, NULL, NULL, VIR_FROM_XEN, error, VIR_ERR_ERROR,
+                        errmsg, info, NULL, value, 0, errmsg, info,
+                        value);
+    }
+}
+
+#endif /* PROXY */
+
+/**
+ * xenHypervisorDoV0Op:
+ * @handle: the handle to the Xen hypervisor
+ * @op: pointer to the hypervisor operation structure
+ *
+ * Do an hypervisor operation though the old interface,
+ * this leads to an hypervisor call through ioctl.
+ *
+ * Returns 0 in case of success and -1 in case of error.
+ */
+static int
+xenHypervisorDoV0Op(int handle, xen_op_v0 * op)
+{
+    int ret;
+    v0_hypercall_t hc;
+
+    memset(&hc, 0, sizeof(hc));
+    op->interface_version = hv_version << 8;
+    hc.op = __HYPERVISOR_dom0_op;
+    hc.arg[0] = (unsigned long) op;
+
+    if (lock_pages(op, sizeof(dom0_op_t)) < 0) {
+        virXenError(NULL, VIR_ERR_XEN_CALL, " locking");
+        return (-1);
+    }
+
+    ret = ioctl(handle, xen_ioctl_hypercall_cmd, (unsigned long) &hc);
+    if (ret < 0) {
+        virXenError(NULL, VIR_ERR_XEN_CALL, " ioctl %d",
+                    xen_ioctl_hypercall_cmd);
+    }
+
+    if (unlock_pages(op, sizeof(dom0_op_t)) < 0) {
+        virXenError(NULL, VIR_ERR_XEN_CALL, " releasing");
+        ret = -1;
+    }
+
+    if (ret < 0)
+        return (-1);
+
+    return (0);
+}
+/**
+ * xenHypervisorDoV1Op:
+ * @handle: the handle to the Xen hypervisor
+ * @op: pointer to the hypervisor operation structure
+ *
+ * Do an hypervisor v1 operation, this leads to an hypervisor call through
+ * ioctl.
+ *
+ * Returns 0 in case of success and -1 in case of error.
+ */
+static int
+xenHypervisorDoV1Op(int handle, xen_op_v1* op)
+{
+    int ret;
+    hypercall_t hc;
+
+    memset(&hc, 0, sizeof(hc));
+    op->interface_version = DOM0_INTERFACE_VERSION;
+    hc.op = __HYPERVISOR_dom0_op;
+    hc.arg[0] = (unsigned long) op;
+
+    if (lock_pages(op, sizeof(dom0_op_t)) < 0) {
+        virXenError(NULL, VIR_ERR_XEN_CALL, " locking");
+        return (-1);
+    }
+
+    ret = ioctl(handle, xen_ioctl_hypercall_cmd, (unsigned long) &hc);
+    if (ret < 0) {
+        virXenError(NULL, VIR_ERR_XEN_CALL, " ioctl %d",
+                    xen_ioctl_hypercall_cmd);
+    }
+
+    if (unlock_pages(op, sizeof(dom0_op_t)) < 0) {
+        virXenError(NULL, VIR_ERR_XEN_CALL, " releasing");
+        ret = -1;
+    }
+
+    if (ret < 0)
+        return (-1);
+
+    return (0);
+}
+
+/**
+ * xenHypervisorDoV2Sys:
+ * @handle: the handle to the Xen hypervisor
+ * @op: pointer to the hypervisor operation structure
+ *
+ * Do an hypervisor v2 system operation, this leads to an hypervisor
+ * call through ioctl.
+ *
+ * Returns 0 in case of success and -1 in case of error.
+ */
+static int
+xenHypervisorDoV2Sys(int handle, xen_op_v2_sys* op)
+{
+    int ret;
+    hypercall_t hc;
+
+    memset(&hc, 0, sizeof(hc));
+    op->interface_version = sys_interface_version;
+    hc.op = __HYPERVISOR_sysctl;
+    hc.arg[0] = (unsigned long) op;
+
+    if (lock_pages(op, sizeof(dom0_op_t)) < 0) {
+        virXenError(NULL, VIR_ERR_XEN_CALL, " locking");
+        return (-1);
+    }
+
+    ret = ioctl(handle, xen_ioctl_hypercall_cmd, (unsigned long) &hc);
+    if (ret < 0) {
+        virXenError(NULL, VIR_ERR_XEN_CALL, " sys ioctl %d",
+                                            xen_ioctl_hypercall_cmd);
+    }
+
+    if (unlock_pages(op, sizeof(dom0_op_t)) < 0) {
+        virXenError(NULL, VIR_ERR_XEN_CALL, " releasing");
+        ret = -1;
+    }
+
+    if (ret < 0)
+        return (-1);
+
+    return (0);
+}
+
+/**
+ * xenHypervisorDoV2Dom:
+ * @handle: the handle to the Xen hypervisor
+ * @op: pointer to the hypervisor domain operation structure
+ *
+ * Do an hypervisor v2 domain operation, this leads to an hypervisor
+ * call through ioctl.
+ *
+ * Returns 0 in case of success and -1 in case of error.
+ */
+static int
+xenHypervisorDoV2Dom(int handle, xen_op_v2_dom* op)
+{
+    int ret;
+    hypercall_t hc;
+
+    memset(&hc, 0, sizeof(hc));
+    op->interface_version = dom_interface_version;
+    hc.op = __HYPERVISOR_domctl;
+    hc.arg[0] = (unsigned long) op;
+
+    if (lock_pages(op, sizeof(dom0_op_t)) < 0) {
+        virXenError(NULL, VIR_ERR_XEN_CALL, " locking");
+        return (-1);
+    }
+
+    ret = ioctl(handle, xen_ioctl_hypercall_cmd, (unsigned long) &hc);
+    if (ret < 0) {
+        virXenError(NULL, VIR_ERR_XEN_CALL, " ioctl %d",
+                    xen_ioctl_hypercall_cmd);
+    }
+
+    if (unlock_pages(op, sizeof(dom0_op_t)) < 0) {
+        virXenError(NULL, VIR_ERR_XEN_CALL, " releasing");
+        ret = -1;
+    }
+
+    if (ret < 0)
+        return (-1);
+
+    return (0);
+}
+
+/**
+ * virXen_getdomaininfolist:
+ * @handle: the hypervisor handle
+ * @first_domain: first domain in the range
+ * @maxids: maximum number of domains to list
+ * @dominfos: output structures
+ *
+ * Do a low level hypercall to list existing domains information
+ *
+ * Returns the number of domains or -1 in case of failure
+ */
+static int
+virXen_getdomaininfolist(int handle, int first_domain, int maxids,
+                         xen_getdomaininfolist *dominfos)
+{
+    int ret = -1;
+
+    if (lock_pages(XEN_GETDOMAININFOLIST_DATA(dominfos),
+              XEN_GETDOMAININFO_SIZE * maxids) < 0) {
+        virXenError(NULL, VIR_ERR_XEN_CALL, " locking");
+        return (-1);
+    }
+    if (hypervisor_version > 1) {
+        xen_op_v2_sys op;
+
+        memset(&op, 0, sizeof(op));
+        op.cmd = XEN_V2_OP_GETDOMAININFOLIST;
+
+        if (sys_interface_version < 3) {
+            op.u.getdomaininfolist.first_domain = (domid_t) first_domain;
+            op.u.getdomaininfolist.max_domains = maxids;
+            op.u.getdomaininfolist.buffer = dominfos->v2;
+            op.u.getdomaininfolist.num_domains = maxids;
+        } else {
+            op.u.getdomaininfolists3.first_domain = (domid_t) first_domain;
+            op.u.getdomaininfolists3.max_domains = maxids;
+            op.u.getdomaininfolists3.buffer.v = dominfos->v2d5;
+            op.u.getdomaininfolists3.num_domains = maxids;
+        }
+        ret = xenHypervisorDoV2Sys(handle, &op);
+
+        if (ret == 0) {
+            if (sys_interface_version < 3)
+                ret = op.u.getdomaininfolist.num_domains;
+            else
+                ret = op.u.getdomaininfolists3.num_domains;
+        }
+    } else if (hypervisor_version == 1) {
+        xen_op_v1 op;
+
+        memset(&op, 0, sizeof(op));
+        op.cmd = XEN_V1_OP_GETDOMAININFOLIST;
+        op.u.getdomaininfolist.first_domain = (domid_t) first_domain;
+        op.u.getdomaininfolist.max_domains = maxids;
+        op.u.getdomaininfolist.buffer = dominfos->v0;
+        op.u.getdomaininfolist.num_domains = maxids;
+        ret = xenHypervisorDoV1Op(handle, &op);
+        if (ret == 0)
+            ret = op.u.getdomaininfolist.num_domains;
+    } else if (hypervisor_version == 0) {
+        xen_op_v0 op;
+
+        memset(&op, 0, sizeof(op));
+        op.cmd = XEN_V0_OP_GETDOMAININFOLIST;
+        op.u.getdomaininfolist.first_domain = (domid_t) first_domain;
+        op.u.getdomaininfolist.max_domains = maxids;
+        op.u.getdomaininfolist.buffer = dominfos->v0;
+        op.u.getdomaininfolist.num_domains = maxids;
+        ret = xenHypervisorDoV0Op(handle, &op);
+        if (ret == 0)
+            ret = op.u.getdomaininfolist.num_domains;
+    }
+    if (unlock_pages(XEN_GETDOMAININFOLIST_DATA(dominfos),
+                XEN_GETDOMAININFO_SIZE * maxids) < 0) {
+        virXenError(NULL, VIR_ERR_XEN_CALL, " release");
+        ret = -1;
+    }
+    return(ret);
+}
+
+static int
+virXen_getdomaininfo(int handle, int first_domain,
+                     xen_getdomaininfo *dominfo) {
+    xen_getdomaininfolist dominfos;
+
+    if (hypervisor_version < 2) {
+        dominfos.v0 = &(dominfo->v0);
+    } else {
+        dominfos.v2 = &(dominfo->v2);
+    }
+
+    return virXen_getdomaininfolist(handle, first_domain, 1, &dominfos);
+}
+
+
+#ifndef PROXY
+/**
+ * xenHypervisorGetSchedulerType:
+ * @domain: pointer to the Xen Hypervisor block
+ * @nparams:give a number of scheduler parameters.
+ *
+ * Do a low level hypercall to get scheduler type
+ *
+ * Returns scheduler name or NULL in case of failure
+ */
+char *
+xenHypervisorGetSchedulerType(virDomainPtr domain, int *nparams)
+{
+    char *schedulertype = NULL;
+    xenUnifiedPrivatePtr priv;
+
+    if ((domain == NULL) || (domain->conn == NULL)) {
+        virXenErrorFunc(NULL, VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
+                        "domain or conn is NULL", 0);
+        return NULL;
+    }
+
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+    if (priv->handle < 0) {
+        virXenErrorFunc(domain->conn, VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
+                        "priv->handle invalid", 0);
+        return NULL;
+    }
+    if (domain->id < 0) {
+        virXenError(domain->conn, VIR_ERR_OPERATION_INVALID,
+                    "%s", _("domain is not running"));
+        return NULL;
+    }
+
+    /*
+     * Support only dom_interface_version >=5
+     * (Xen3.1.0 or later)
+     * TODO: check on Xen 3.0.3
+     */
+    if (dom_interface_version < 5) {
+        virXenErrorFunc(domain->conn, VIR_ERR_NO_XEN, __FUNCTION__,
+                        "unsupported in dom interface < 5", 0);
+        return NULL;
+    }
+
+    if (hypervisor_version > 1) {
+        xen_op_v2_sys op;
+        int ret;
+
+        memset(&op, 0, sizeof(op));
+        op.cmd = XEN_V2_OP_GETSCHEDULERID;
+        ret = xenHypervisorDoV2Sys(priv->handle, &op);
+        if (ret < 0)
+            return(NULL);
+
+        switch (op.u.getschedulerid.sched_id){
+            case XEN_SCHEDULER_SEDF:
+                schedulertype = strdup("sedf");
+                if (nparams)
+                    *nparams = 6;
+                break;
+            case XEN_SCHEDULER_CREDIT:
+                schedulertype = strdup("credit");
+                if (nparams)
+                    *nparams = 2;
+                break;
+            default:
+                break;
+        }
+    }
+
+    return schedulertype;
+}
+
+static const char *str_weight = "weight";
+static const char *str_cap = "cap";
+
+/**
+ * xenHypervisorGetSchedulerParameters:
+ * @domain: pointer to the Xen Hypervisor block
+ * @params: pointer to scheduler parameters.
+ *     This memory area should be allocated before calling.
+ * @nparams:this parameter should be same as
+ *     a given number of scheduler parameters.
+ *     from xenHypervisorGetSchedulerType().
+ *
+ * Do a low level hypercall to get scheduler parameters
+ *
+ * Returns 0 or -1 in case of failure
+ */
+int
+xenHypervisorGetSchedulerParameters(virDomainPtr domain,
+                                    virSchedParameterPtr params, int *nparams)
+{
+    xenUnifiedPrivatePtr priv;
+
+    if ((domain == NULL) || (domain->conn == NULL)) {
+        virXenErrorFunc(NULL, VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
+                        "domain or conn is NULL", 0);
+        return -1;
+    }
+
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+    if (priv->handle < 0) {
+        virXenErrorFunc(domain->conn, VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
+                        "priv->handle invalid", 0);
+        return -1;
+    }
+    if (domain->id < 0) {
+        virXenError(domain->conn, VIR_ERR_OPERATION_INVALID,
+                    "%s", _("domain is not running"));
+        return -1;
+    }
+
+    /*
+     * Support only dom_interface_version >=5
+     * (Xen3.1.0 or later)
+     * TODO: check on Xen 3.0.3
+     */
+    if (dom_interface_version < 5) {
+        virXenErrorFunc(domain->conn, VIR_ERR_NO_XEN, __FUNCTION__,
+                        "unsupported in dom interface < 5", 0);
+        return -1;
+    }
+
+    if (hypervisor_version > 1) {
+        xen_op_v2_sys op_sys;
+        xen_op_v2_dom op_dom;
+        int ret;
+
+        memset(&op_sys, 0, sizeof(op_sys));
+        op_sys.cmd = XEN_V2_OP_GETSCHEDULERID;
+        ret = xenHypervisorDoV2Sys(priv->handle, &op_sys);
+        if (ret < 0)
+            return -1;
+
+        switch (op_sys.u.getschedulerid.sched_id){
+            case XEN_SCHEDULER_SEDF:
+                /* TODO: Implement for Xen/SEDF */
+                TODO
+                return(-1);
+            case XEN_SCHEDULER_CREDIT:
+                if (*nparams < 2)
+                    return(-1);
+                memset(&op_dom, 0, sizeof(op_dom));
+                op_dom.cmd = XEN_V2_OP_SCHEDULER;
+                op_dom.domain = (domid_t) domain->id;
+                op_dom.u.getschedinfo.sched_id = XEN_SCHEDULER_CREDIT;
+                op_dom.u.getschedinfo.cmd = XEN_DOMCTL_SCHEDOP_getinfo;
+                ret = xenHypervisorDoV2Dom(priv->handle, &op_dom);
+                if (ret < 0)
+                    return(-1);
+
+                strncpy (params[0].field, str_weight, VIR_DOMAIN_SCHED_FIELD_LENGTH);
+                params[0].field[VIR_DOMAIN_SCHED_FIELD_LENGTH-1] = '\0';
+                params[0].type = VIR_DOMAIN_SCHED_FIELD_UINT;
+                params[0].value.ui = op_dom.u.getschedinfo.u.credit.weight;
+
+                strncpy (params[1].field, str_cap, VIR_DOMAIN_SCHED_FIELD_LENGTH);
+                params[1].field[VIR_DOMAIN_SCHED_FIELD_LENGTH-1] = '\0';
+                params[1].type = VIR_DOMAIN_SCHED_FIELD_UINT;
+                params[1].value.ui = op_dom.u.getschedinfo.u.credit.cap;
+
+                *nparams = 2;
+                break;
+            default:
+                virXenErrorFunc(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
+                        "Unknown scheduler", op_sys.u.getschedulerid.sched_id);
+                return -1;
+        }
+    }
+
+    return 0;
+}
+
+/**
+ * xenHypervisorSetSchedulerParameters:
+ * @domain: pointer to the Xen Hypervisor block
+ * @nparams:give a number of scheduler setting parameters .
+ *
+ * Do a low level hypercall to set scheduler parameters
+ *
+ * Returns 0 or -1 in case of failure
+ */
+int
+xenHypervisorSetSchedulerParameters(virDomainPtr domain,
+                                 virSchedParameterPtr params, int nparams)
+{
+    int i;
+    unsigned int val;
+    xenUnifiedPrivatePtr priv;
+    char buf[256];
+
+    if ((domain == NULL) || (domain->conn == NULL)) {
+        virXenErrorFunc (NULL, VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
+                         "domain or conn is NULL", 0);
+        return -1;
+    }
+
+    if ((nparams == 0) || (params == NULL)) {
+        virXenErrorFunc (domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
+                         "Noparameters given", 0);
+        return(-1);
+    }
+
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+    if (priv->handle < 0) {
+        virXenErrorFunc(domain->conn, VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
+                        "priv->handle invalid", 0);
+        return -1;
+    }
+    if (domain->id < 0) {
+        virXenError(domain->conn, VIR_ERR_OPERATION_INVALID,
+                    "%s", _("domain is not running"));
+        return -1;
+    }
+
+    /*
+     * Support only dom_interface_version >=5
+     * (Xen3.1.0 or later)
+     * TODO: check on Xen 3.0.3
+     */
+    if (dom_interface_version < 5) {
+        virXenErrorFunc(domain->conn, VIR_ERR_NO_XEN, __FUNCTION__,
+                        "unsupported in dom interface < 5", 0);
+        return -1;
+    }
+
+    if (hypervisor_version > 1) {
+        xen_op_v2_sys op_sys;
+        xen_op_v2_dom op_dom;
+        int ret;
+
+        memset(&op_sys, 0, sizeof(op_sys));
+        op_sys.cmd = XEN_V2_OP_GETSCHEDULERID;
+        ret = xenHypervisorDoV2Sys(priv->handle, &op_sys);
+        if (ret == -1) return -1;
+
+        switch (op_sys.u.getschedulerid.sched_id){
+        case XEN_SCHEDULER_SEDF:
+            /* TODO: Implement for Xen/SEDF */
+            TODO
+            return(-1);
+        case XEN_SCHEDULER_CREDIT: {
+            memset(&op_dom, 0, sizeof(op_dom));
+            op_dom.cmd = XEN_V2_OP_SCHEDULER;
+            op_dom.domain = (domid_t) domain->id;
+            op_dom.u.getschedinfo.sched_id = XEN_SCHEDULER_CREDIT;
+            op_dom.u.getschedinfo.cmd = XEN_DOMCTL_SCHEDOP_putinfo;
+
+            /*
+             * credit scheduler parameters
+             * following values do not change the parameters
+             */
+            op_dom.u.getschedinfo.u.credit.weight = 0;
+            op_dom.u.getschedinfo.u.credit.cap    = (uint16_t)~0U;
+
+            for (i = 0; i < nparams; i++) {
+                memset(&buf, 0, sizeof(buf));
+                if (STREQ (params[i].field, str_weight) &&
+                    params[i].type == VIR_DOMAIN_SCHED_FIELD_UINT) {
+                    val = params[i].value.ui;
+                    if ((val < 1) || (val > USHRT_MAX)) {
+                        snprintf(buf, sizeof(buf), _("Credit scheduler weight parameter (%d) is out of range (1-65535)"), val);
+                        virXenErrorFunc (domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__, buf, val);
+                        return(-1);
+                    }
+                    op_dom.u.getschedinfo.u.credit.weight = val;
+                } else if (STREQ (params[i].field, str_cap) &&
+                    params[i].type == VIR_DOMAIN_SCHED_FIELD_UINT) {
+                    val = params[i].value.ui;
+                    if (val > USHRT_MAX) {
+                        snprintf(buf, sizeof(buf), _("Credit scheduler cap parameter (%d) is out of range (0-65535)"), val);
+                        virXenErrorFunc (domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__, buf, val);
+                        return(-1);
+                    }
+                    op_dom.u.getschedinfo.u.credit.cap = val;
+                } else {
+                    virXenErrorFunc (domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
+                                     "Credit scheduler accepts 'cap' and 'weight' integer parameters",
+                                     0);
+                    return(-1);
+                }
+            }
+
+            ret = xenHypervisorDoV2Dom(priv->handle, &op_dom);
+            if (ret < 0)
+                return -1;
+            break;
+        }
+        default:
+            virXenErrorFunc(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
+                        "Unknown scheduler", op_sys.u.getschedulerid.sched_id);
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+
+int
+xenHypervisorDomainBlockStats (virDomainPtr dom,
+                               const char *path,
+                               struct _virDomainBlockStats *stats)
+{
+#ifdef __linux__
+    xenUnifiedPrivatePtr priv;
+    int ret;
+
+    priv = (xenUnifiedPrivatePtr) dom->conn->privateData;
+    xenUnifiedLock(priv);
+    /* Need to lock because it hits the xenstore handle :-( */
+    ret = xenLinuxDomainBlockStats (priv, dom, path, stats);
+    xenUnifiedUnlock(priv);
+    return ret;
+#else
+    virXenErrorFunc (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__,
+                     "block statistics not supported on this platform",
+                     dom->id);
+    return -1;
+#endif
+}
+
+/* Paths have the form vif<domid>.<n> (this interface checks that
+ * <domid> is the real domain ID and returns an error if not).
+ *
+ * In future we may allow you to query bridge stats (virbrX or
+ * xenbrX), but that will probably be through a separate
+ * virNetwork interface, as yet not decided.
+ */
+int
+xenHypervisorDomainInterfaceStats (virDomainPtr dom,
+                                   const char *path,
+                                   struct _virDomainInterfaceStats *stats)
+{
+#ifdef __linux__
+    int rqdomid, device;
+
+    /* Verify that the vif requested is one belonging to the current
+     * domain.
+     */
+    if (sscanf (path, "vif%d.%d", &rqdomid, &device) != 2) {
+        virXenErrorFunc (dom->conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
+                         "invalid path, should be vif<domid>.<n>.", 0);
+        return -1;
+    }
+    if (rqdomid != dom->id) {
+        virXenErrorFunc (dom->conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
+                         "invalid path, vif<domid> should match this domain ID", 0);
+        return -1;
+    }
+
+    return linuxDomainInterfaceStats (dom->conn, path, stats);
+#else
+    virXenErrorFunc (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__,
+                     "/proc/net/dev: Interface not found", 0);
+    return -1;
+#endif
+}
+
+/**
+ * virXen_pausedomain:
+ * @handle: the hypervisor handle
+ * @id: the domain id
+ *
+ * Do a low level hypercall to pause the domain
+ *
+ * Returns 0 or -1 in case of failure
+ */
+static int
+virXen_pausedomain(int handle, int id)
+{
+    int ret = -1;
+
+    if (hypervisor_version > 1) {
+        xen_op_v2_dom op;
+
+        memset(&op, 0, sizeof(op));
+        op.cmd = XEN_V2_OP_PAUSEDOMAIN;
+        op.domain = (domid_t) id;
+        ret = xenHypervisorDoV2Dom(handle, &op);
+    } else if (hypervisor_version == 1) {
+        xen_op_v1 op;
+
+        memset(&op, 0, sizeof(op));
+        op.cmd = XEN_V1_OP_PAUSEDOMAIN;
+        op.u.domain.domain = (domid_t) id;
+        ret = xenHypervisorDoV1Op(handle, &op);
+    } else if (hypervisor_version == 0) {
+        xen_op_v0 op;
+
+        memset(&op, 0, sizeof(op));
+        op.cmd = XEN_V0_OP_PAUSEDOMAIN;
+        op.u.domain.domain = (domid_t) id;
+        ret = xenHypervisorDoV0Op(handle, &op);
+    }
+    return(ret);
+}
+
+/**
+ * virXen_unpausedomain:
+ * @handle: the hypervisor handle
+ * @id: the domain id
+ *
+ * Do a low level hypercall to unpause the domain
+ *
+ * Returns 0 or -1 in case of failure
+ */
+static int
+virXen_unpausedomain(int handle, int id)
+{
+    int ret = -1;
+
+    if (hypervisor_version > 1) {
+        xen_op_v2_dom op;
+
+        memset(&op, 0, sizeof(op));
+        op.cmd = XEN_V2_OP_UNPAUSEDOMAIN;
+        op.domain = (domid_t) id;
+        ret = xenHypervisorDoV2Dom(handle, &op);
+    } else if (hypervisor_version == 1) {
+        xen_op_v1 op;
+
+        memset(&op, 0, sizeof(op));
+        op.cmd = XEN_V1_OP_UNPAUSEDOMAIN;
+        op.u.domain.domain = (domid_t) id;
+        ret = xenHypervisorDoV1Op(handle, &op);
+    } else if (hypervisor_version == 0) {
+        xen_op_v0 op;
+
+        memset(&op, 0, sizeof(op));
+        op.cmd = XEN_V0_OP_UNPAUSEDOMAIN;
+        op.u.domain.domain = (domid_t) id;
+        ret = xenHypervisorDoV0Op(handle, &op);
+    }
+    return(ret);
+}
+
+/**
+ * virXen_destroydomain:
+ * @handle: the hypervisor handle
+ * @id: the domain id
+ *
+ * Do a low level hypercall to destroy the domain
+ *
+ * Returns 0 or -1 in case of failure
+ */
+static int
+virXen_destroydomain(int handle, int id)
+{
+    int ret = -1;
+
+    if (hypervisor_version > 1) {
+        xen_op_v2_dom op;
+
+        memset(&op, 0, sizeof(op));
+        op.cmd = XEN_V2_OP_DESTROYDOMAIN;
+        op.domain = (domid_t) id;
+        ret = xenHypervisorDoV2Dom(handle, &op);
+    } else if (hypervisor_version == 1) {
+        xen_op_v1 op;
+
+        memset(&op, 0, sizeof(op));
+        op.cmd = XEN_V1_OP_DESTROYDOMAIN;
+        op.u.domain.domain = (domid_t) id;
+        ret = xenHypervisorDoV1Op(handle, &op);
+    } else if (hypervisor_version == 0) {
+        xen_op_v0 op;
+
+        memset(&op, 0, sizeof(op));
+        op.cmd = XEN_V0_OP_DESTROYDOMAIN;
+        op.u.domain.domain = (domid_t) id;
+        ret = xenHypervisorDoV0Op(handle, &op);
+    }
+    return(ret);
+}
+
+/**
+ * virXen_setmaxmem:
+ * @handle: the hypervisor handle
+ * @id: the domain id
+ * @memory: the amount of memory in kilobytes
+ *
+ * Do a low level hypercall to change the max memory amount
+ *
+ * Returns 0 or -1 in case of failure
+ */
+static int
+virXen_setmaxmem(int handle, int id, unsigned long memory)
+{
+    int ret = -1;
+
+    if (hypervisor_version > 1) {
+        xen_op_v2_dom op;
+
+        memset(&op, 0, sizeof(op));
+        op.cmd = XEN_V2_OP_SETMAXMEM;
+        op.domain = (domid_t) id;
+        if (dom_interface_version < 5)
+            op.u.setmaxmem.maxmem = memory;
+        else
+            op.u.setmaxmemd5.maxmem = memory;
+        ret = xenHypervisorDoV2Dom(handle, &op);
+    } else if (hypervisor_version == 1) {
+        xen_op_v1 op;
+
+        memset(&op, 0, sizeof(op));
+        op.cmd = XEN_V1_OP_SETMAXMEM;
+        op.u.setmaxmem.domain = (domid_t) id;
+        op.u.setmaxmem.maxmem = memory;
+        ret = xenHypervisorDoV1Op(handle, &op);
+    } else if (hypervisor_version == 0) {
+        xen_op_v0 op;
+
+        memset(&op, 0, sizeof(op));
+        op.cmd = XEN_V0_OP_SETMAXMEM;
+        op.u.setmaxmem.domain = (domid_t) id;
+        op.u.setmaxmem.maxmem = memory;
+        ret = xenHypervisorDoV0Op(handle, &op);
+    }
+    return(ret);
+}
+
+/**
+ * virXen_setmaxvcpus:
+ * @handle: the hypervisor handle
+ * @id: the domain id
+ * @vcpus: the numbers of vcpus
+ *
+ * Do a low level hypercall to change the max vcpus amount
+ *
+ * Returns 0 or -1 in case of failure
+ */
+static int
+virXen_setmaxvcpus(int handle, int id, unsigned int vcpus)
+{
+    int ret = -1;
+
+    if (hypervisor_version > 1) {
+        xen_op_v2_dom op;
+
+        memset(&op, 0, sizeof(op));
+        op.cmd = XEN_V2_OP_SETMAXVCPU;
+        op.domain = (domid_t) id;
+        op.u.setmaxvcpu.maxvcpu = vcpus;
+        ret = xenHypervisorDoV2Dom(handle, &op);
+    } else if (hypervisor_version == 1) {
+        xen_op_v1 op;
+
+        memset(&op, 0, sizeof(op));
+        op.cmd = XEN_V1_OP_SETMAXVCPU;
+        op.u.setmaxvcpu.domain = (domid_t) id;
+        op.u.setmaxvcpu.maxvcpu = vcpus;
+        ret = xenHypervisorDoV1Op(handle, &op);
+    } else if (hypervisor_version == 0) {
+        xen_op_v0 op;
+
+        memset(&op, 0, sizeof(op));
+        op.cmd = XEN_V0_OP_SETMAXVCPU;
+        op.u.setmaxvcpu.domain = (domid_t) id;
+        op.u.setmaxvcpu.maxvcpu = vcpus;
+        ret = xenHypervisorDoV0Op(handle, &op);
+    }
+    return(ret);
+}
+
+/**
+ * virXen_setvcpumap:
+ * @handle: the hypervisor handle
+ * @id: the domain id
+ * @vcpu: the vcpu to map
+ * @cpumap: the bitmap for this vcpu
+ * @maplen: the size of the bitmap in bytes
+ *
+ * Do a low level hypercall to change the pinning for vcpu
+ *
+ * Returns 0 or -1 in case of failure
+ */
+static int
+virXen_setvcpumap(int handle, int id, unsigned int vcpu,
+                  unsigned char * cpumap, int maplen)
+{
+    int ret = -1;
+    unsigned char *new = NULL;
+    unsigned char *bitmap = NULL;
+    uint32_t nr_cpus;
+
+    if (hypervisor_version > 1) {
+        xen_op_v2_dom op;
+
+        if (lock_pages(cpumap, maplen) < 0) {
+            virXenError(NULL, VIR_ERR_XEN_CALL, " locking");
+            return (-1);
+        }
+        memset(&op, 0, sizeof(op));
+        op.cmd = XEN_V2_OP_SETVCPUMAP;
+        op.domain = (domid_t) id;
+
+        /* The allocated memory to cpumap must be 'sizeof(uint64_t)' byte *
+         * for Xen, and also nr_cpus must be 'sizeof(uint64_t) * 8'       */
+        if (maplen < 8) {
+            if (VIR_ALLOC_N(new, sizeof(uint64_t)) < 0) {
+                virReportOOMError(NULL);
+                return (-1);
+            }
+            memcpy(new, cpumap, maplen);
+            bitmap = new;
+            nr_cpus = sizeof(uint64_t) * 8;
+        } else {
+            bitmap = cpumap;
+            nr_cpus = maplen * 8;
+        }
+
+        if (dom_interface_version < 5) {
+            op.u.setvcpumap.vcpu = vcpu;
+            op.u.setvcpumap.cpumap.bitmap = bitmap;
+            op.u.setvcpumap.cpumap.nr_cpus = nr_cpus;
+        } else {
+            op.u.setvcpumapd5.vcpu = vcpu;
+            op.u.setvcpumapd5.cpumap.bitmap.v = bitmap;
+            op.u.setvcpumapd5.cpumap.nr_cpus = nr_cpus;
+        }
+        ret = xenHypervisorDoV2Dom(handle, &op);
+        VIR_FREE(new);
+
+        if (unlock_pages(cpumap, maplen) < 0) {
+            virXenError(NULL, VIR_ERR_XEN_CALL, " release");
+            ret = -1;
+        }
+    } else {
+        cpumap_t xen_cpumap; /* limited to 64 CPUs in old hypervisors */
+        uint64_t *pm = &xen_cpumap;
+        int j;
+
+        if ((maplen > (int)sizeof(cpumap_t)) || (sizeof(cpumap_t) & 7))
+            return (-1);
+
+        memset(pm, 0, sizeof(cpumap_t));
+        for (j = 0; j < maplen; j++)
+            *(pm + (j / 8)) |= cpumap[j] << (8 * (j & 7));
+
+        if (hypervisor_version == 1) {
+            xen_op_v1 op;
+
+            memset(&op, 0, sizeof(op));
+            op.cmd = XEN_V1_OP_SETVCPUMAP;
+            op.u.setvcpumap.domain = (domid_t) id;
+            op.u.setvcpumap.vcpu = vcpu;
+            op.u.setvcpumap.cpumap = xen_cpumap;
+            ret = xenHypervisorDoV1Op(handle, &op);
+        } else if (hypervisor_version == 0) {
+            xen_op_v0 op;
+
+            memset(&op, 0, sizeof(op));
+            op.cmd = XEN_V0_OP_SETVCPUMAP;
+            op.u.setvcpumap.domain = (domid_t) id;
+            op.u.setvcpumap.vcpu = vcpu;
+            op.u.setvcpumap.cpumap = xen_cpumap;
+            ret = xenHypervisorDoV0Op(handle, &op);
+        }
+    }
+    return(ret);
+}
+#endif /* !PROXY*/
+
+/**
+ * virXen_getvcpusinfo:
+ * @handle: the hypervisor handle
+ * @id: the domain id
+ * @vcpu: the vcpu to map
+ * @cpumap: the bitmap for this vcpu
+ * @maplen: the size of the bitmap in bytes
+ *
+ * Do a low level hypercall to change the pinning for vcpu
+ *
+ * Returns 0 or -1 in case of failure
+ */
+static int
+virXen_getvcpusinfo(int handle, int id, unsigned int vcpu, virVcpuInfoPtr ipt,
+                    unsigned char *cpumap, int maplen)
+{
+    int ret = -1;
+
+    if (hypervisor_version > 1) {
+        xen_op_v2_dom op;
+
+        memset(&op, 0, sizeof(op));
+        op.cmd = XEN_V2_OP_GETVCPUINFO;
+        op.domain = (domid_t) id;
+        if (dom_interface_version < 5)
+            op.u.getvcpuinfo.vcpu = (uint16_t) vcpu;
+        else
+            op.u.getvcpuinfod5.vcpu = (uint16_t) vcpu;
+        ret = xenHypervisorDoV2Dom(handle, &op);
+
+        if (ret < 0)
+            return(-1);
+        ipt->number = vcpu;
+        if (dom_interface_version < 5) {
+            if (op.u.getvcpuinfo.online) {
+                if (op.u.getvcpuinfo.running)
+                    ipt->state = VIR_VCPU_RUNNING;
+                if (op.u.getvcpuinfo.blocked)
+                    ipt->state = VIR_VCPU_BLOCKED;
+            } else
+                ipt->state = VIR_VCPU_OFFLINE;
+
+            ipt->cpuTime = op.u.getvcpuinfo.cpu_time;
+            ipt->cpu = op.u.getvcpuinfo.online ? (int)op.u.getvcpuinfo.cpu : -1;
+        } else {
+            if (op.u.getvcpuinfod5.online) {
+                if (op.u.getvcpuinfod5.running)
+                    ipt->state = VIR_VCPU_RUNNING;
+                if (op.u.getvcpuinfod5.blocked)
+                    ipt->state = VIR_VCPU_BLOCKED;
+            } else
+                ipt->state = VIR_VCPU_OFFLINE;
+
+            ipt->cpuTime = op.u.getvcpuinfod5.cpu_time;
+            ipt->cpu = op.u.getvcpuinfod5.online ? (int)op.u.getvcpuinfod5.cpu : -1;
+        }
+        if ((cpumap != NULL) && (maplen > 0)) {
+            if (lock_pages(cpumap, maplen) < 0) {
+                virXenError(NULL, VIR_ERR_XEN_CALL, " locking");
+                return (-1);
+            }
+            memset(cpumap, 0, maplen);
+            memset(&op, 0, sizeof(op));
+            op.cmd = XEN_V2_OP_GETVCPUMAP;
+            op.domain = (domid_t) id;
+            if (dom_interface_version < 5) {
+                op.u.getvcpumap.vcpu = vcpu;
+                op.u.getvcpumap.cpumap.bitmap = cpumap;
+                op.u.getvcpumap.cpumap.nr_cpus = maplen * 8;
+            } else {
+                op.u.getvcpumapd5.vcpu = vcpu;
+                op.u.getvcpumapd5.cpumap.bitmap.v = cpumap;
+                op.u.getvcpumapd5.cpumap.nr_cpus = maplen * 8;
+            }
+            ret = xenHypervisorDoV2Dom(handle, &op);
+            if (unlock_pages(cpumap, maplen) < 0) {
+                virXenError(NULL, VIR_ERR_XEN_CALL, " release");
+                ret = -1;
+            }
+        }
+    } else {
+        int mapl = maplen;
+        int cpu;
+
+        if (maplen > (int)sizeof(cpumap_t))
+            mapl = (int)sizeof(cpumap_t);
+
+        if (hypervisor_version == 1) {
+            xen_op_v1 op;
+
+            memset(&op, 0, sizeof(op));
+            op.cmd = XEN_V1_OP_GETVCPUINFO;
+            op.u.getvcpuinfo.domain = (domid_t) id;
+            op.u.getvcpuinfo.vcpu = vcpu;
+            ret = xenHypervisorDoV1Op(handle, &op);
+            if (ret < 0)
+                return(-1);
+            ipt->number = vcpu;
+            if (op.u.getvcpuinfo.online) {
+                if (op.u.getvcpuinfo.running) ipt->state = VIR_VCPU_RUNNING;
+                if (op.u.getvcpuinfo.blocked) ipt->state = VIR_VCPU_BLOCKED;
+            }
+            else ipt->state = VIR_VCPU_OFFLINE;
+            ipt->cpuTime = op.u.getvcpuinfo.cpu_time;
+            ipt->cpu = op.u.getvcpuinfo.online ? (int)op.u.getvcpuinfo.cpu : -1;
+            if ((cpumap != NULL) && (maplen > 0)) {
+                for (cpu = 0; cpu < (mapl * 8); cpu++) {
+                    if (op.u.getvcpuinfo.cpumap & ((uint64_t)1<<cpu))
+                        VIR_USE_CPU(cpumap, cpu);
+                }
+            }
+        } else if (hypervisor_version == 0) {
+            xen_op_v1 op;
+
+            memset(&op, 0, sizeof(op));
+            op.cmd = XEN_V0_OP_GETVCPUINFO;
+            op.u.getvcpuinfo.domain = (domid_t) id;
+            op.u.getvcpuinfo.vcpu = vcpu;
+            ret = xenHypervisorDoV0Op(handle, &op);
+            if (ret < 0)
+                return(-1);
+            ipt->number = vcpu;
+            if (op.u.getvcpuinfo.online) {
+                if (op.u.getvcpuinfo.running) ipt->state = VIR_VCPU_RUNNING;
+                if (op.u.getvcpuinfo.blocked) ipt->state = VIR_VCPU_BLOCKED;
+            }
+            else ipt->state = VIR_VCPU_OFFLINE;
+            ipt->cpuTime = op.u.getvcpuinfo.cpu_time;
+            ipt->cpu = op.u.getvcpuinfo.online ? (int)op.u.getvcpuinfo.cpu : -1;
+            if ((cpumap != NULL) && (maplen > 0)) {
+                for (cpu = 0; cpu < (mapl * 8); cpu++) {
+                    if (op.u.getvcpuinfo.cpumap & ((uint64_t)1<<cpu))
+                        VIR_USE_CPU(cpumap, cpu);
+                }
+            }
+        }
+    }
+    return(ret);
+}
+
+/**
+ * xenHypervisorInit:
+ *
+ * Initialize the hypervisor layer. Try to detect the kind of interface
+ * used i.e. pre or post changeset 10277
+ */
+int
+xenHypervisorInit(void)
+{
+    int fd, ret, cmd, errcode;
+    hypercall_t hc;
+    v0_hypercall_t v0_hc;
+    xen_getdomaininfo info;
+    virVcpuInfoPtr ipt = NULL;
+
+    if (initialized) {
+        if (hypervisor_version == -1)
+            return (-1);
+        return(0);
+    }
+    initialized = 1;
+    in_init = 1;
+
+    /* Compile regular expressions used by xenHypervisorGetCapabilities.
+     * Note that errors here are really internal errors since these
+     * regexps should never fail to compile.
+     */
+    errcode = regcomp (&flags_hvm_rec, flags_hvm_re, REG_EXTENDED);
+    if (errcode != 0) {
+        char error[100];
+        regerror (errcode, &flags_hvm_rec, error, sizeof error);
+        regfree (&flags_hvm_rec);
+        virXenError (NULL, VIR_ERR_INTERNAL_ERROR, "%s", error);
+        in_init = 0;
+        return -1;
+    }
+    errcode = regcomp (&flags_pae_rec, flags_pae_re, REG_EXTENDED);
+    if (errcode != 0) {
+        char error[100];
+        regerror (errcode, &flags_pae_rec, error, sizeof error);
+        regfree (&flags_pae_rec);
+        regfree (&flags_hvm_rec);
+        virXenError (NULL, VIR_ERR_INTERNAL_ERROR, "%s", error);
+        in_init = 0;
+        return -1;
+    }
+    errcode = regcomp (&xen_cap_rec, xen_cap_re, REG_EXTENDED);
+    if (errcode != 0) {
+        char error[100];
+        regerror (errcode, &xen_cap_rec, error, sizeof error);
+        regfree (&xen_cap_rec);
+        regfree (&flags_pae_rec);
+        regfree (&flags_hvm_rec);
+        virXenError (NULL, VIR_ERR_INTERNAL_ERROR, "%s", error);
+        in_init = 0;
+        return -1;
+    }
+
+    /* Xen hypervisor version detection begins. */
+    ret = open(XEN_HYPERVISOR_SOCKET, O_RDWR);
+    if (ret < 0) {
+        hypervisor_version = -1;
+        return(-1);
+    }
+    fd = ret;
+
+    /*
+     * The size of the hypervisor call block changed July 2006
+     * this detect if we are using the new or old hypercall_t structure
+     */
+    hc.op = __HYPERVISOR_xen_version;
+    hc.arg[0] = (unsigned long) XENVER_version;
+    hc.arg[1] = 0;
+
+    cmd = IOCTL_PRIVCMD_HYPERCALL;
+    ret = ioctl(fd, cmd, (unsigned long) &hc);
+
+    if ((ret != -1) && (ret != 0)) {
+        DEBUG("Using new hypervisor call: %X\n", ret);
+        hv_version = ret;
+        xen_ioctl_hypercall_cmd = cmd;
+        goto detect_v2;
+    }
+
+#ifndef __sun
+    /*
+     * check if the old hypercall are actually working
+     */
+    v0_hc.op = __HYPERVISOR_xen_version;
+    v0_hc.arg[0] = (unsigned long) XENVER_version;
+    v0_hc.arg[1] = 0;
+    cmd = _IOC(_IOC_NONE, 'P', 0, sizeof(v0_hypercall_t));
+    ret = ioctl(fd, cmd, (unsigned long) &v0_hc);
+    if ((ret != -1) && (ret != 0)) {
+        DEBUG("Using old hypervisor call: %X\n", ret);
+        hv_version = ret;
+        xen_ioctl_hypercall_cmd = cmd;
+        hypervisor_version = 0;
+        goto done;
+    }
+#endif
+
+    /*
+     * we failed to make any hypercall
+     */
+
+    hypervisor_version = -1;
+    virXenError(NULL, VIR_ERR_XEN_CALL, " ioctl %lu",
+                (unsigned long) IOCTL_PRIVCMD_HYPERCALL);
+    close(fd);
+    in_init = 0;
+    return(-1);
+
+ detect_v2:
+    /*
+     * The hypercalls were refactored into 3 different section in August 2006
+     * Try to detect if we are running a version post 3.0.2 with the new ones
+     * or the old ones
+     */
+    hypervisor_version = 2;
+
+    if (VIR_ALLOC(ipt) < 0) {
+        virReportOOMError(NULL);
+        return(-1);
+    }
+    /* Currently consider RHEL5.0 Fedora7, xen-3.1, and xen-unstable */
+    sys_interface_version = 2; /* XEN_SYSCTL_INTERFACE_VERSION */
+    if (virXen_getdomaininfo(fd, 0, &info) == 1) {
+        /* RHEL 5.0 */
+        dom_interface_version = 3; /* XEN_DOMCTL_INTERFACE_VERSION */
+        if (virXen_getvcpusinfo(fd, 0, 0, ipt, NULL, 0) == 0){
+            DEBUG0("Using hypervisor call v2, sys ver2 dom ver3\n");
+            goto done;
+        }
+        /* Fedora 7 */
+        dom_interface_version = 4; /* XEN_DOMCTL_INTERFACE_VERSION */
+        if (virXen_getvcpusinfo(fd, 0, 0, ipt, NULL, 0) == 0){
+            DEBUG0("Using hypervisor call v2, sys ver2 dom ver4\n");
+            goto done;
+        }
+    }
+
+    sys_interface_version = 3; /* XEN_SYSCTL_INTERFACE_VERSION */
+    if (virXen_getdomaininfo(fd, 0, &info) == 1) {
+        /* xen-3.1 */
+        dom_interface_version = 5; /* XEN_DOMCTL_INTERFACE_VERSION */
+        if (virXen_getvcpusinfo(fd, 0, 0, ipt, NULL, 0) == 0){
+            DEBUG0("Using hypervisor call v2, sys ver3 dom ver5\n");
+            goto done;
+        }
+    }
+
+    sys_interface_version = 4; /* XEN_SYSCTL_INTERFACE_VERSION */
+    if (virXen_getdomaininfo(fd, 0, &info) == 1) {
+        /* Fedora 8 */
+        dom_interface_version = 5; /* XEN_DOMCTL_INTERFACE_VERSION */
+        if (virXen_getvcpusinfo(fd, 0, 0, ipt, NULL, 0) == 0){
+            DEBUG0("Using hypervisor call v2, sys ver4 dom ver5\n");
+            goto done;
+        }
+    }
+
+    sys_interface_version = 6; /* XEN_SYSCTL_INTERFACE_VERSION */
+    if (virXen_getdomaininfo(fd, 0, &info) == 1) {
+        /* Xen 3.2, Fedora 9 */
+        dom_interface_version = 5; /* XEN_DOMCTL_INTERFACE_VERSION */
+        if (virXen_getvcpusinfo(fd, 0, 0, ipt, NULL, 0) == 0){
+            DEBUG0("Using hypervisor call v2, sys ver6 dom ver5\n");
+            goto done;
+        }
+    }
+
+    hypervisor_version = 1;
+    sys_interface_version = -1;
+    if (virXen_getdomaininfo(fd, 0, &info) == 1) {
+        DEBUG0("Using hypervisor call v1\n");
+        goto done;
+    }
+
+    /*
+     * we failed to make the getdomaininfolist hypercall
+     */
+
+    DEBUG0("Failed to find any Xen hypervisor method\n");
+    hypervisor_version = -1;
+    virXenError(NULL, VIR_ERR_XEN_CALL, " ioctl %lu",
+                (unsigned long)IOCTL_PRIVCMD_HYPERCALL);
+    close(fd);
+    in_init = 0;
+    VIR_FREE(ipt);
+    return(-1);
+
+ done:
+    close(fd);
+    in_init = 0;
+    VIR_FREE(ipt);
+    return(0);
+}
+
+/**
+ * xenHypervisorOpen:
+ * @conn: pointer to the connection block
+ * @name: URL for the target, NULL for local
+ * @flags: combination of virDrvOpenFlag(s)
+ *
+ * Connects to the Xen hypervisor.
+ *
+ * Returns 0 or -1 in case of error.
+ */
+virDrvOpenStatus
+xenHypervisorOpen(virConnectPtr conn,
+                  virConnectAuthPtr auth ATTRIBUTE_UNUSED,
+                  int flags ATTRIBUTE_UNUSED)
+{
+    int ret;
+    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
+
+    if (initialized == 0)
+        if (xenHypervisorInit() == -1)
+            return -1;
+
+    priv->handle = -1;
+
+    ret = open(XEN_HYPERVISOR_SOCKET, O_RDWR);
+    if (ret < 0) {
+        virXenError(conn, VIR_ERR_NO_XEN, "%s", XEN_HYPERVISOR_SOCKET);
+        return (-1);
+    }
+
+    priv->handle = ret;
+
+    return(0);
+}
+
+/**
+ * xenHypervisorClose:
+ * @conn: pointer to the connection block
+ *
+ * Close the connection to the Xen hypervisor.
+ *
+ * Returns 0 in case of success or -1 in case of error.
+ */
+int
+xenHypervisorClose(virConnectPtr conn)
+{
+    int ret;
+    xenUnifiedPrivatePtr priv;
+
+    if (conn == NULL)
+        return (-1);
+
+    priv = (xenUnifiedPrivatePtr) conn->privateData;
+
+    if (priv->handle < 0)
+        return -1;
+
+    ret = close(priv->handle);
+    if (ret < 0)
+        return (-1);
+
+    return (0);
+}
+
+
+/**
+ * xenHypervisorGetVersion:
+ * @conn: pointer to the connection block
+ * @hvVer: where to store the version
+ *
+ * Call the hypervisor to extracts his own internal API version
+ *
+ * Returns 0 in case of success, -1 in case of error
+ */
+int
+xenHypervisorGetVersion(virConnectPtr conn, unsigned long *hvVer)
+{
+    xenUnifiedPrivatePtr priv;
+
+    if (conn == NULL)
+        return -1;
+    priv = (xenUnifiedPrivatePtr) conn->privateData;
+    if (priv->handle < 0 || hvVer == NULL)
+        return (-1);
+    *hvVer = (hv_version >> 16) * 1000000 + (hv_version & 0xFFFF) * 1000;
+    return(0);
+}
+
+struct guest_arch {
+    const char *model;
+    int bits;
+    int hvm;
+    int pae;
+    int nonpae;
+    int ia64_be;
+};
+
+
+static virCapsPtr
+xenHypervisorBuildCapabilities(virConnectPtr conn,
+                               const char *hostmachine,
+                               int host_pae,
+                               const char *hvm_type,
+                               struct guest_arch *guest_archs,
+                               int nr_guest_archs) {
+    virCapsPtr caps;
+    int i;
+    int hv_major = hv_version >> 16;
+    int hv_minor = hv_version & 0xFFFF;
+
+    if ((caps = virCapabilitiesNew(hostmachine, 1, 1)) == NULL)
+        goto no_memory;
+
+    virCapabilitiesSetMacPrefix(caps, (unsigned char[]){ 0x00, 0x16, 0x3e });
+
+    if (hvm_type && STRNEQ(hvm_type, "") &&
+        virCapabilitiesAddHostFeature(caps, hvm_type) < 0)
+        goto no_memory;
+    if (host_pae &&
+        virCapabilitiesAddHostFeature(caps, "pae") < 0)
+        goto no_memory;
+
+
+    if (virCapabilitiesAddHostMigrateTransport(caps,
+                                               "xenmigr") < 0)
+        goto no_memory;
+
+
+    if (sys_interface_version >= SYS_IFACE_MIN_VERS_NUMA) {
+        if (xenDaemonNodeGetTopology(conn, caps) != 0) {
+            virCapabilitiesFree(caps);
+            return NULL;
+        }
+    }
+
+    for (i = 0; i < nr_guest_archs; ++i) {
+        virCapsGuestPtr guest;
+        char const *const xen_machines[] = {guest_archs[i].hvm ? "xenfv" : "xenpv"};
+        virCapsGuestMachinePtr *machines;
+
+        if ((machines = virCapabilitiesAllocMachines(xen_machines, 1)) == NULL)
+            goto no_memory;
+
+        if ((guest = virCapabilitiesAddGuest(caps,
+                                             guest_archs[i].hvm ? "hvm" : "xen",
+                                             guest_archs[i].model,
+                                             guest_archs[i].bits,
+                                             (STREQ(hostmachine, "x86_64") ?
+                                              "/usr/lib64/xen/bin/qemu-dm" :
+                                              "/usr/lib/xen/bin/qemu-dm"),
+                                             (guest_archs[i].hvm ?
+                                              "/usr/lib/xen/boot/hvmloader" :
+                                              NULL),
+                                             1,
+                                             machines)) == NULL) {
+            virCapabilitiesFreeMachines(machines, 1);
+            goto no_memory;
+        }
+        machines = NULL;
+
+        if (virCapabilitiesAddGuestDomain(guest,
+                                          "xen",
+                                          NULL,
+                                          NULL,
+                                          0,
+                                          NULL) == NULL)
+            goto no_memory;
+
+        if (guest_archs[i].pae &&
+            virCapabilitiesAddGuestFeature(guest,
+                                           "pae",
+                                           1,
+                                           0) == NULL)
+            goto no_memory;
+
+        if (guest_archs[i].nonpae &&
+            virCapabilitiesAddGuestFeature(guest,
+                                           "nonpae",
+                                           1,
+                                           0) == NULL)
+            goto no_memory;
+
+        if (guest_archs[i].ia64_be &&
+            virCapabilitiesAddGuestFeature(guest,
+                                           "ia64_be",
+                                           1,
+                                           0) == NULL)
+            goto no_memory;
+
+        if (guest_archs[i].hvm) {
+            if (virCapabilitiesAddGuestFeature(guest,
+                                               "acpi",
+                                               1, 1) == NULL)
+                goto no_memory;
+
+            // In Xen 3.1.0, APIC is always on and can't be toggled
+            if (virCapabilitiesAddGuestFeature(guest,
+                                               "apic",
+                                               1,
+                                               (hv_major > 3 &&
+                                                hv_minor > 0 ?
+                                                0 : 1)) == NULL)
+                goto no_memory;
+        }
+    }
+
+    return caps;
+
+ no_memory:
+    virCapabilitiesFree(caps);
+    return NULL;
+}
+
+#ifdef __sun
+
+static int
+get_cpu_flags(virConnectPtr conn, const char **hvm, int *pae, int *longmode)
+{
+    struct {
+        uint32_t r_eax, r_ebx, r_ecx, r_edx;
+    } regs;
+
+    char tmpbuf[20];
+    int ret = 0;
+    int fd;
+
+    /* returns -1, errno 22 if in 32-bit mode */
+    *longmode = (sysinfo(SI_ARCHITECTURE_64, tmpbuf, sizeof(tmpbuf)) != -1);
+
+    if ((fd = open("/dev/cpu/self/cpuid", O_RDONLY)) == -1 ||
+        pread(fd, &regs, sizeof(regs), 0) != sizeof(regs)) {
+        char ebuf[1024];
+        virXenError(conn, VIR_ERR_SYSTEM_ERROR,
+            "couldn't read CPU flags: %s", virStrerror(errno, ebuf, sizeof ebuf));
+        goto out;
+    }
+
+    *pae = 0;
+    *hvm = "";
+
+    if (STREQLEN((const char *)&regs.r_ebx, "AuthcAMDenti", 12)) {
+        if (pread(fd, &regs, sizeof (regs), 0x80000001) == sizeof (regs)) {
+            /* Read secure virtual machine bit (bit 2 of ECX feature ID) */
+            if ((regs.r_ecx >> 2) & 1) {
+                *hvm = "svm";
+            }
+            if ((regs.r_edx >> 6) & 1)
+                *pae = 1;
+        }
+    } else if (STREQLEN((const char *)&regs.r_ebx, "GenuntelineI", 12)) {
+        if (pread(fd, &regs, sizeof (regs), 0x00000001) == sizeof (regs)) {
+            /* Read VMXE feature bit (bit 5 of ECX feature ID) */
+            if ((regs.r_ecx >> 5) & 1)
+                *hvm = "vmx";
+            if ((regs.r_edx >> 6) & 1)
+                *pae = 1;
+        }
+    }
+
+    ret = 1;
+
+out:
+    if (fd != -1)
+        close(fd);
+    return ret;
+}
+
+static virCapsPtr
+xenHypervisorMakeCapabilitiesSunOS(virConnectPtr conn)
+{
+    struct guest_arch guest_arches[32];
+    int i = 0;
+    virCapsPtr caps = NULL;
+    struct utsname utsname;
+    int pae, longmode;
+    const char *hvm;
+
+    if (!get_cpu_flags(conn, &hvm, &pae, &longmode))
+        return NULL;
+
+    /* Really, this never fails - look at the man-page. */
+    uname (&utsname);
+
+    guest_arches[i].model = "i686";
+    guest_arches[i].bits = 32;
+    guest_arches[i].hvm = 0;
+    guest_arches[i].pae = pae;
+    guest_arches[i].nonpae = !pae;
+    guest_arches[i].ia64_be = 0;
+    i++;
+
+    if (longmode) {
+        guest_arches[i].model = "x86_64";
+        guest_arches[i].bits = 64;
+        guest_arches[i].hvm = 0;
+        guest_arches[i].pae = 0;
+        guest_arches[i].nonpae = 0;
+        guest_arches[i].ia64_be = 0;
+        i++;
+    }
+
+    if (hvm[0] != '\0') {
+        guest_arches[i].model = "i686";
+        guest_arches[i].bits = 32;
+        guest_arches[i].hvm = 1;
+        guest_arches[i].pae = pae;
+        guest_arches[i].nonpae = 1;
+        guest_arches[i].ia64_be = 0;
+        i++;
+
+        if (longmode) {
+            guest_arches[i].model = "x86_64";
+            guest_arches[i].bits = 64;
+            guest_arches[i].hvm = 1;
+            guest_arches[i].pae = 0;
+            guest_arches[i].nonpae = 0;
+            guest_arches[i].ia64_be = 0;
+            i++;
+        }
+    }
+
+    if ((caps = xenHypervisorBuildCapabilities(conn,
+                                               utsname.machine,
+                                               pae, hvm,
+                                               guest_arches, i)) == NULL)
+        virReportOOMError(NULL);
+
+    return caps;
+}
+
+#endif /* __sun */
+
+/**
+ * xenHypervisorMakeCapabilitiesInternal:
+ * @conn: pointer to the connection block
+ * @cpuinfo: file handle containing /proc/cpuinfo data, or NULL
+ * @capabilities: file handle containing /sys/hypervisor/properties/capabilities data, or NULL
+ *
+ * Return the capabilities of this hypervisor.
+ */
+virCapsPtr
+xenHypervisorMakeCapabilitiesInternal(virConnectPtr conn,
+                                      const char *hostmachine,
+                                      FILE *cpuinfo, FILE *capabilities)
+{
+    char line[1024], *str, *token;
+    regmatch_t subs[4];
+    char *saveptr = NULL;
+    int i;
+
+    char hvm_type[4] = ""; /* "vmx" or "svm" (or "" if not in CPU). */
+    int host_pae = 0;
+    struct guest_arch guest_archs[32];
+    int nr_guest_archs = 0;
+    virCapsPtr caps = NULL;
+
+    memset(guest_archs, 0, sizeof(guest_archs));
+
+    /* /proc/cpuinfo: flags: Intel calls HVM "vmx", AMD calls it "svm".
+     * It's not clear if this will work on IA64, let alone other
+     * architectures and non-Linux. (XXX)
+     */
+    if (cpuinfo) {
+        while (fgets (line, sizeof line, cpuinfo)) {
+            if (regexec (&flags_hvm_rec, line, sizeof(subs)/sizeof(regmatch_t), subs, 0) == 0
+                && subs[0].rm_so != -1) {
+                strncpy (hvm_type,
+                         &line[subs[1].rm_so], subs[1].rm_eo-subs[1].rm_so+1);
+                hvm_type[subs[1].rm_eo-subs[1].rm_so] = '\0';
+            } else if (regexec (&flags_pae_rec, line, 0, NULL, 0) == 0)
+                host_pae = 1;
+        }
+    }
+
+    /* Most of the useful info is in /sys/hypervisor/properties/capabilities
+     * which is documented in the code in xen-unstable.hg/xen/arch/.../setup.c.
+     *
+     * It is a space-separated list of supported guest architectures.
+     *
+     * For x86:
+     *    TYP-VER-ARCH[p]
+     *    ^   ^   ^    ^
+     *    |   |   |    +-- PAE supported
+     *    |   |   +------- x86_32 or x86_64
+     *    |   +----------- the version of Xen, eg. "3.0"
+     *    +--------------- "xen" or "hvm" for para or full virt respectively
+     *
+     * For PPC this file appears to be always empty (?)
+     *
+     * For IA64:
+     *    TYP-VER-ARCH[be]
+     *    ^   ^   ^    ^
+     *    |   |   |    +-- Big-endian supported
+     *    |   |   +------- always "ia64"
+     *    |   +----------- the version of Xen, eg. "3.0"
+     *    +--------------- "xen" or "hvm" for para or full virt respectively
+     */
+
+    /* Expecting one line in this file - ignore any more. */
+    if ((capabilities) && (fgets (line, sizeof line, capabilities))) {
+        /* Split the line into tokens.  strtok_r is OK here because we "own"
+         * this buffer.  Parse out the features from each token.
+         */
+        for (str = line, nr_guest_archs = 0;
+             nr_guest_archs < sizeof guest_archs / sizeof guest_archs[0]
+                 && (token = strtok_r (str, " ", &saveptr)) != NULL;
+             str = NULL) {
+
+            if (regexec (&xen_cap_rec, token, sizeof subs / sizeof subs[0],
+                         subs, 0) == 0) {
+                int hvm = STRPREFIX(&token[subs[1].rm_so], "hvm");
+                const char *model;
+                int bits, pae = 0, nonpae = 0, ia64_be = 0;
+
+                if (STRPREFIX(&token[subs[2].rm_so], "x86_32")) {
+                    model = "i686";
+                    bits = 32;
+                    if (subs[3].rm_so != -1 &&
+                        STRPREFIX(&token[subs[3].rm_so], "p"))
+                        pae = 1;
+                    else
+                        nonpae = 1;
+                }
+                else if (STRPREFIX(&token[subs[2].rm_so], "x86_64")) {
+                    model = "x86_64";
+                    bits = 64;
+                }
+                else if (STRPREFIX(&token[subs[2].rm_so], "ia64")) {
+                    model = "ia64";
+                    bits = 64;
+                    if (subs[3].rm_so != -1 &&
+                        STRPREFIX(&token[subs[3].rm_so], "be"))
+                        ia64_be = 1;
+                }
+                else if (STRPREFIX(&token[subs[2].rm_so], "powerpc64")) {
+                    model = "ppc64";
+                    bits = 64;
+                } else {
+                    /* XXX surely no other Xen archs exist  */
+                    continue;
+                }
+
+                /* Search for existing matching (model,hvm) tuple */
+                for (i = 0 ; i < nr_guest_archs ; i++) {
+                    if (STREQ(guest_archs[i].model, model) &&
+                        guest_archs[i].hvm == hvm) {
+                        break;
+                    }
+                }
+
+                /* Too many arch flavours - highly unlikely ! */
+                if (i >= ARRAY_CARDINALITY(guest_archs))
+                    continue;
+                /* Didn't find a match, so create a new one */
+                if (i == nr_guest_archs)
+                    nr_guest_archs++;
+
+                guest_archs[i].model = model;
+                guest_archs[i].bits = bits;
+                guest_archs[i].hvm = hvm;
+
+                /* Careful not to overwrite a previous positive
+                   setting with a negative one here - some archs
+                   can do both pae & non-pae, but Xen reports
+                   separately capabilities so we're merging archs */
+                if (pae)
+                    guest_archs[i].pae = pae;
+                if (nonpae)
+                    guest_archs[i].nonpae = nonpae;
+                if (ia64_be)
+                    guest_archs[i].ia64_be = ia64_be;
+            }
+        }
+    }
+
+    if ((caps = xenHypervisorBuildCapabilities(conn,
+                                               hostmachine,
+                                               host_pae,
+                                               hvm_type,
+                                               guest_archs,
+                                               nr_guest_archs)) == NULL)
+        goto no_memory;
+
+    return caps;
+
+ no_memory:
+    virReportOOMError(NULL);
+    virCapabilitiesFree(caps);
+    return NULL;
+}
+
+/**
+ * xenHypervisorMakeCapabilities:
+ *
+ * Return the capabilities of this hypervisor.
+ */
+virCapsPtr
+xenHypervisorMakeCapabilities(virConnectPtr conn)
+{
+#ifdef __sun
+    return xenHypervisorMakeCapabilitiesSunOS(conn);
+#else
+    virCapsPtr caps;
+    FILE *cpuinfo, *capabilities;
+    struct utsname utsname;
+
+    /* Really, this never fails - look at the man-page. */
+    uname (&utsname);
+
+    cpuinfo = fopen ("/proc/cpuinfo", "r");
+    if (cpuinfo == NULL) {
+        if (errno != ENOENT) {
+            virReportSystemError(conn, errno,
+                                 _("cannot read file %s"),
+                                 "/proc/cpuinfo");
+            return NULL;
+        }
+    }
+
+    capabilities = fopen ("/sys/hypervisor/properties/capabilities", "r");
+    if (capabilities == NULL) {
+        if (errno != ENOENT) {
+            fclose(cpuinfo);
+            virReportSystemError(conn, errno,
+                                 _("cannot read file %s"),
+                                 "/sys/hypervisor/properties/capabilities");
+            return NULL;
+        }
+    }
+
+    caps = xenHypervisorMakeCapabilitiesInternal(conn,
+                                                 utsname.machine,
+                                                 cpuinfo,
+                                                 capabilities);
+
+    if (cpuinfo)
+        fclose(cpuinfo);
+    if (capabilities)
+        fclose(capabilities);
+
+    return caps;
+#endif /* __sun */
+}
+
+
+
+/**
+ * xenHypervisorGetCapabilities:
+ * @conn: pointer to the connection block
+ *
+ * Return the capabilities of this hypervisor.
+ */
+char *
+xenHypervisorGetCapabilities (virConnectPtr conn)
+{
+    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
+    char *xml;
+
+    if (!(xml = virCapabilitiesFormatXML(priv->caps))) {
+        virReportOOMError(conn);
+        return NULL;
+    }
+
+    return xml;
+}
+
+
+/**
+ * xenHypervisorNumOfDomains:
+ * @conn: pointer to the connection block
+ *
+ * Provides the number of active domains.
+ *
+ * Returns the number of domain found or -1 in case of error
+ */
+int
+xenHypervisorNumOfDomains(virConnectPtr conn)
+{
+    xen_getdomaininfolist dominfos;
+    int ret, nbids;
+    static int last_maxids = 2;
+    int maxids = last_maxids;
+    xenUnifiedPrivatePtr priv;
+
+    if (conn == NULL)
+        return -1;
+    priv = (xenUnifiedPrivatePtr) conn->privateData;
+    if (priv->handle < 0)
+        return (-1);
+
+ retry:
+    if (!(XEN_GETDOMAININFOLIST_ALLOC(dominfos, maxids))) {
+        virReportOOMError(conn);
+        return(-1);
+    }
+
+    XEN_GETDOMAININFOLIST_CLEAR(dominfos, maxids);
+
+    ret = virXen_getdomaininfolist(priv->handle, 0, maxids, &dominfos);
+
+    XEN_GETDOMAININFOLIST_FREE(dominfos);
+
+    if (ret < 0)
+        return (-1);
+
+    nbids = ret;
+    /* Can't possibly have more than 65,000 concurrent guests
+     * so limit how many times we try, to avoid increasing
+     * without bound & thus allocating all of system memory !
+     * XXX I'll regret this comment in a few years time ;-)
+     */
+    if (nbids == maxids) {
+        if (maxids < 65000) {
+            last_maxids *= 2;
+            maxids *= 2;
+            goto retry;
+        }
+        nbids = -1;
+    }
+    if ((nbids < 0) || (nbids > maxids))
+        return(-1);
+    return(nbids);
+}
+
+/**
+ * xenHypervisorListDomains:
+ * @conn: pointer to the connection block
+ * @ids: array to collect the list of IDs of active domains
+ * @maxids: size of @ids
+ *
+ * Collect the list of active domains, and store their ID in @maxids
+ *
+ * Returns the number of domain found or -1 in case of error
+ */
+int
+xenHypervisorListDomains(virConnectPtr conn, int *ids, int maxids)
+{
+    xen_getdomaininfolist dominfos;
+    int ret, nbids, i;
+    xenUnifiedPrivatePtr priv;
+
+    if (conn == NULL)
+        return -1;
+
+    priv = (xenUnifiedPrivatePtr) conn->privateData;
+    if (priv->handle < 0 ||
+        (ids == NULL) || (maxids < 0))
+        return (-1);
+
+    if (maxids == 0)
+        return(0);
+
+    if (!(XEN_GETDOMAININFOLIST_ALLOC(dominfos, maxids))) {
+        virReportOOMError(conn);
+        return(-1);
+    }
+
+    XEN_GETDOMAININFOLIST_CLEAR(dominfos, maxids);
+    memset(ids, 0, maxids * sizeof(int));
+
+    ret = virXen_getdomaininfolist(priv->handle, 0, maxids, &dominfos);
+
+    if (ret < 0) {
+        XEN_GETDOMAININFOLIST_FREE(dominfos);
+        return (-1);
+    }
+
+    nbids = ret;
+    if ((nbids < 0) || (nbids > maxids)) {
+        XEN_GETDOMAININFOLIST_FREE(dominfos);
+        return(-1);
+    }
+
+    for (i = 0;i < nbids;i++) {
+        ids[i] = XEN_GETDOMAININFOLIST_DOMAIN(dominfos, i);
+    }
+
+    XEN_GETDOMAININFOLIST_FREE(dominfos);
+    return (nbids);
+}
+
+
+#ifndef PROXY
+char *
+xenHypervisorDomainGetOSType (virDomainPtr dom)
+{
+    xenUnifiedPrivatePtr priv;
+    xen_getdomaininfo dominfo;
+
+    priv = (xenUnifiedPrivatePtr) dom->conn->privateData;
+    if (priv->handle < 0)
+        return (NULL);
+
+    /* HV's earlier than 3.1.0 don't include the HVM flags in guests status*/
+    if (hypervisor_version < 2 ||
+        dom_interface_version < 4)
+        return (NULL);
+
+    XEN_GETDOMAININFO_CLEAR(dominfo);
+
+    if (virXen_getdomaininfo(priv->handle, dom->id, &dominfo) < 0)
+        return (NULL);
+
+    if (XEN_GETDOMAININFO_DOMAIN(dominfo) != dom->id)
+        return (NULL);
+
+    if (XEN_GETDOMAININFO_FLAGS(dominfo) & DOMFLAGS_HVM)
+        return strdup("hvm");
+    return strdup("linux");
+}
+
+virDomainPtr
+xenHypervisorLookupDomainByID(virConnectPtr conn,
+                              int id)
+{
+    xenUnifiedPrivatePtr priv;
+    xen_getdomaininfo dominfo;
+    virDomainPtr ret;
+    char *name;
+
+    priv = (xenUnifiedPrivatePtr) conn->privateData;
+    if (priv->handle < 0)
+        return (NULL);
+
+    XEN_GETDOMAININFO_CLEAR(dominfo);
+
+    if (virXen_getdomaininfo(priv->handle, id, &dominfo) < 0)
+        return (NULL);
+
+    if (XEN_GETDOMAININFO_DOMAIN(dominfo) != id)
+        return (NULL);
+
+    xenUnifiedLock(priv);
+    name = xenStoreDomainGetName(conn, id);
+    xenUnifiedUnlock(priv);
+    if (!name)
+        return (NULL);
+
+    ret = virGetDomain(conn, name, XEN_GETDOMAININFO_UUID(dominfo));
+    if (ret)
+        ret->id = id;
+    VIR_FREE(name);
+    return ret;
+}
+
+
+virDomainPtr
+xenHypervisorLookupDomainByUUID(virConnectPtr conn,
+                                const unsigned char *uuid)
+{
+    xen_getdomaininfolist dominfos;
+    xenUnifiedPrivatePtr priv;
+    virDomainPtr ret;
+    char *name;
+    int maxids = 100, nids, i, id;
+
+    priv = (xenUnifiedPrivatePtr) conn->privateData;
+    if (priv->handle < 0)
+        return (NULL);
+
+ retry:
+    if (!(XEN_GETDOMAININFOLIST_ALLOC(dominfos, maxids))) {
+        virReportOOMError(conn);
+        return(NULL);
+    }
+
+    XEN_GETDOMAININFOLIST_CLEAR(dominfos, maxids);
+
+    nids = virXen_getdomaininfolist(priv->handle, 0, maxids, &dominfos);
+
+    if (nids < 0) {
+        XEN_GETDOMAININFOLIST_FREE(dominfos);
+        return (NULL);
+    }
+
+    /* Can't possibly have more than 65,000 concurrent guests
+     * so limit how many times we try, to avoid increasing
+     * without bound & thus allocating all of system memory !
+     * XXX I'll regret this comment in a few years time ;-)
+     */
+    if (nids == maxids) {
+        XEN_GETDOMAININFOLIST_FREE(dominfos);
+        if (maxids < 65000) {
+            maxids *= 2;
+            goto retry;
+        }
+        return (NULL);
+    }
+
+    id = -1;
+    for (i = 0 ; i < nids ; i++) {
+        if (memcmp(XEN_GETDOMAININFOLIST_UUID(dominfos, i), uuid, VIR_UUID_BUFLEN) == 0) {
+            id = XEN_GETDOMAININFOLIST_DOMAIN(dominfos, i);
+            break;
+        }
+    }
+    XEN_GETDOMAININFOLIST_FREE(dominfos);
+
+    if (id == -1)
+        return (NULL);
+
+    xenUnifiedLock(priv);
+    name = xenStoreDomainGetName(conn, id);
+    xenUnifiedUnlock(priv);
+    if (!name)
+        return (NULL);
+
+    ret = virGetDomain(conn, name, uuid);
+    if (ret)
+        ret->id = id;
+    VIR_FREE(name);
+    return ret;
+}
+#endif
+
+/**
+ * xenHypervisorGetMaxVcpus:
+ *
+ * Returns the maximum of CPU defined by Xen.
+ */
+int
+xenHypervisorGetMaxVcpus(virConnectPtr conn,
+                         const char *type ATTRIBUTE_UNUSED)
+{
+    xenUnifiedPrivatePtr priv;
+
+    if (conn == NULL)
+        return -1;
+    priv = (xenUnifiedPrivatePtr) conn->privateData;
+    if (priv->handle < 0)
+        return (-1);
+
+    return MAX_VIRT_CPUS;
+}
+
+/**
+ * xenHypervisorGetDomMaxMemory:
+ * @conn: connection data
+ * @id: domain id
+ *
+ * Retrieve the maximum amount of physical memory allocated to a
+ * domain.
+ *
+ * Returns the memory size in kilobytes or 0 in case of error.
+ */
+unsigned long
+xenHypervisorGetDomMaxMemory(virConnectPtr conn, int id)
+{
+    xenUnifiedPrivatePtr priv;
+    xen_getdomaininfo dominfo;
+    int ret;
+
+    if (conn == NULL)
+        return 0;
+
+    priv = (xenUnifiedPrivatePtr) conn->privateData;
+    if (priv->handle < 0)
+        return 0;
+
+    if (kb_per_pages == 0) {
+        kb_per_pages = sysconf(_SC_PAGESIZE) / 1024;
+        if (kb_per_pages <= 0)
+            kb_per_pages = 4;
+    }
+
+    XEN_GETDOMAININFO_CLEAR(dominfo);
+
+    ret = virXen_getdomaininfo(priv->handle, id, &dominfo);
+
+    if ((ret < 0) || (XEN_GETDOMAININFO_DOMAIN(dominfo) != id))
+        return (0);
+
+    return((unsigned long) XEN_GETDOMAININFO_MAX_PAGES(dominfo) * kb_per_pages);
+}
+
+#ifndef PROXY
+/**
+ * xenHypervisorGetMaxMemory:
+ * @domain: a domain object or NULL
+ *
+ * Retrieve the maximum amount of physical memory allocated to a
+ * domain. If domain is NULL, then this get the amount of memory reserved
+ * to Domain0 i.e. the domain where the application runs.
+ *
+ * Returns the memory size in kilobytes or 0 in case of error.
+ */
+static unsigned long
+xenHypervisorGetMaxMemory(virDomainPtr domain)
+{
+    xenUnifiedPrivatePtr priv;
+
+    if ((domain == NULL) || (domain->conn == NULL))
+        return 0;
+
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+    if (priv->handle < 0 || domain->id < 0)
+        return (0);
+
+    return(xenHypervisorGetDomMaxMemory(domain->conn, domain->id));
+}
+#endif
+
+/**
+ * xenHypervisorGetDomInfo:
+ * @conn: connection data
+ * @id: the domain ID
+ * @info: the place where information should be stored
+ *
+ * Do an hypervisor call to get the related set of domain information.
+ *
+ * Returns 0 in case of success, -1 in case of error.
+ */
+int
+xenHypervisorGetDomInfo(virConnectPtr conn, int id, virDomainInfoPtr info)
+{
+    xenUnifiedPrivatePtr priv;
+    xen_getdomaininfo dominfo;
+    int ret;
+    uint32_t domain_flags, domain_state, domain_shutdown_cause;
+
+    if (kb_per_pages == 0) {
+        kb_per_pages = sysconf(_SC_PAGESIZE) / 1024;
+        if (kb_per_pages <= 0)
+            kb_per_pages = 4;
+    }
+
+    if (conn == NULL)
+        return -1;
+
+    priv = (xenUnifiedPrivatePtr) conn->privateData;
+    if (priv->handle < 0 || info == NULL)
+        return (-1);
+
+    memset(info, 0, sizeof(virDomainInfo));
+    XEN_GETDOMAININFO_CLEAR(dominfo);
+
+    ret = virXen_getdomaininfo(priv->handle, id, &dominfo);
+
+    if ((ret < 0) || (XEN_GETDOMAININFO_DOMAIN(dominfo) != id))
+        return (-1);
+
+    domain_flags = XEN_GETDOMAININFO_FLAGS(dominfo);
+    domain_flags &= ~DOMFLAGS_HVM; /* Mask out HVM flags */
+    domain_state = domain_flags & 0xFF; /* Mask out high bits */
+    switch (domain_state) {
+        case DOMFLAGS_DYING:
+            info->state = VIR_DOMAIN_SHUTDOWN;
+            break;
+        case DOMFLAGS_SHUTDOWN:
+            /* The domain is shutdown.  Determine the cause. */
+            domain_shutdown_cause = domain_flags >> DOMFLAGS_SHUTDOWNSHIFT;
+            switch (domain_shutdown_cause) {
+                case SHUTDOWN_crash:
+                    info->state = VIR_DOMAIN_CRASHED;
+                    break;
+                default:
+                    info->state = VIR_DOMAIN_SHUTOFF;
+            }
+            break;
+        case DOMFLAGS_PAUSED:
+            info->state = VIR_DOMAIN_PAUSED;
+            break;
+        case DOMFLAGS_BLOCKED:
+            info->state = VIR_DOMAIN_BLOCKED;
+            break;
+        case DOMFLAGS_RUNNING:
+            info->state = VIR_DOMAIN_RUNNING;
+            break;
+        default:
+            info->state = VIR_DOMAIN_NOSTATE;
+    }
+
+    /*
+     * the API brings back the cpu time in nanoseconds,
+     * convert to microseconds, same thing convert to
+     * kilobytes from page counts
+     */
+    info->cpuTime = XEN_GETDOMAININFO_CPUTIME(dominfo);
+    info->memory = XEN_GETDOMAININFO_TOT_PAGES(dominfo) * kb_per_pages;
+    info->maxMem = XEN_GETDOMAININFO_MAX_PAGES(dominfo);
+    if(info->maxMem != UINT_MAX)
+        info->maxMem *= kb_per_pages;
+    info->nrVirtCpu = XEN_GETDOMAININFO_CPUCOUNT(dominfo);
+    return (0);
+}
+
+/**
+ * xenHypervisorGetDomainInfo:
+ * @domain: pointer to the domain block
+ * @info: the place where information should be stored
+ *
+ * Do an hypervisor call to get the related set of domain information.
+ *
+ * Returns 0 in case of success, -1 in case of error.
+ */
+int
+xenHypervisorGetDomainInfo(virDomainPtr domain, virDomainInfoPtr info)
+{
+    xenUnifiedPrivatePtr priv;
+
+    if ((domain == NULL) || (domain->conn == NULL))
+        return -1;
+
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+    if (priv->handle < 0 || info == NULL ||
+        (domain->id < 0))
+        return (-1);
+
+    return(xenHypervisorGetDomInfo(domain->conn, domain->id, info));
+
+}
+
+#ifndef PROXY
+/**
+ * xenHypervisorNodeGetCellsFreeMemory:
+ * @conn: pointer to the hypervisor connection
+ * @freeMems: pointer to the array of unsigned long long
+ * @startCell: index of first cell to return freeMems info on.
+ * @maxCells: Maximum number of cells for which freeMems information can
+ *            be returned.
+ *
+ * This call returns the amount of free memory in one or more NUMA cells.
+ * The @freeMems array must be allocated by the caller and will be filled
+ * with the amount of free memory in kilobytes for each cell requested,
+ * starting with startCell (in freeMems[0]), up to either
+ * (startCell + maxCells), or the number of additional cells in the node,
+ * whichever is smaller.
+ *
+ * Returns the number of entries filled in freeMems, or -1 in case of error.
+ */
+int
+xenHypervisorNodeGetCellsFreeMemory(virConnectPtr conn, unsigned long long *freeMems,
+                                    int startCell, int maxCells)
+{
+    xen_op_v2_sys op_sys;
+    int i, j, ret;
+    xenUnifiedPrivatePtr priv;
+
+    if (conn == NULL) {
+        virXenErrorFunc (conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
+                        "invalid argument", 0);
+        return -1;
+    }
+
+    priv = conn->privateData;
+
+    if (priv->nbNodeCells < 0) {
+        virXenErrorFunc (conn, VIR_ERR_XEN_CALL, __FUNCTION__,
+                         "cannot determine actual number of cells",0);
+        return(-1);
+    }
+
+    if ((maxCells < 1) || (startCell >= priv->nbNodeCells)) {
+        virXenErrorFunc (conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
+                        "invalid argument", 0);
+        return -1;
+    }
+
+    /*
+     * Support only sys_interface_version >=4
+     */
+    if (sys_interface_version < SYS_IFACE_MIN_VERS_NUMA) {
+        virXenErrorFunc (conn, VIR_ERR_XEN_CALL, __FUNCTION__,
+                        "unsupported in sys interface < 4", 0);
+        return -1;
+    }
+
+    if (priv->handle < 0) {
+        virXenErrorFunc (conn, VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
+                        "priv->handle invalid", 0);
+        return -1;
+    }
+
+    memset(&op_sys, 0, sizeof(op_sys));
+    op_sys.cmd = XEN_V2_OP_GETAVAILHEAP;
+
+    for (i = startCell, j = 0;(i < priv->nbNodeCells) && (j < maxCells);i++,j++) {
+        if (sys_interface_version >= 5)
+            op_sys.u.availheap5.node = i;
+        else
+            op_sys.u.availheap.node = i;
+        ret = xenHypervisorDoV2Sys(priv->handle, &op_sys);
+        if (ret < 0) {
+            return(-1);
+        }
+        if (sys_interface_version >= 5)
+            freeMems[j] = op_sys.u.availheap5.avail_bytes;
+        else
+            freeMems[j] = op_sys.u.availheap.avail_bytes;
+    }
+    return (j);
+}
+
+
+/**
+ * xenHypervisorPauseDomain:
+ * @domain: pointer to the domain block
+ *
+ * Do an hypervisor call to pause the given domain
+ *
+ * Returns 0 in case of success, -1 in case of error.
+ */
+int
+xenHypervisorPauseDomain(virDomainPtr domain)
+{
+    int ret;
+    xenUnifiedPrivatePtr priv;
+
+    if ((domain == NULL) || (domain->conn == NULL))
+        return -1;
+
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+    if (priv->handle < 0 || domain->id < 0)
+        return (-1);
+
+    ret = virXen_pausedomain(priv->handle, domain->id);
+    if (ret < 0)
+        return (-1);
+    return (0);
+}
+
+/**
+ * xenHypervisorResumeDomain:
+ * @domain: pointer to the domain block
+ *
+ * Do an hypervisor call to resume the given domain
+ *
+ * Returns 0 in case of success, -1 in case of error.
+ */
+int
+xenHypervisorResumeDomain(virDomainPtr domain)
+{
+    int ret;
+    xenUnifiedPrivatePtr priv;
+
+    if ((domain == NULL) || (domain->conn == NULL))
+        return -1;
+
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+    if (priv->handle < 0 || domain->id < 0)
+        return (-1);
+
+    ret = virXen_unpausedomain(priv->handle, domain->id);
+    if (ret < 0)
+        return (-1);
+    return (0);
+}
+
+/**
+ * xenHypervisorDestroyDomain:
+ * @domain: pointer to the domain block
+ *
+ * Do an hypervisor call to destroy the given domain
+ *
+ * Returns 0 in case of success, -1 in case of error.
+ */
+int
+xenHypervisorDestroyDomain(virDomainPtr domain)
+{
+    int ret;
+    xenUnifiedPrivatePtr priv;
+
+    if (domain == NULL || domain->conn == NULL)
+        return -1;
+
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+    if (priv->handle < 0 || domain->id < 0)
+        return (-1);
+
+    ret = virXen_destroydomain(priv->handle, domain->id);
+    if (ret < 0)
+        return (-1);
+    return (0);
+}
+
+/**
+ * xenHypervisorSetMaxMemory:
+ * @domain: pointer to the domain block
+ * @memory: the max memory size in kilobytes.
+ *
+ * Do an hypervisor call to change the maximum amount of memory used
+ *
+ * Returns 0 in case of success, -1 in case of error.
+ */
+int
+xenHypervisorSetMaxMemory(virDomainPtr domain, unsigned long memory)
+{
+    int ret;
+    xenUnifiedPrivatePtr priv;
+
+    if (domain == NULL || domain->conn == NULL)
+        return -1;
+
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+    if (priv->handle < 0 || domain->id < 0)
+        return (-1);
+
+    ret = virXen_setmaxmem(priv->handle, domain->id, memory);
+    if (ret < 0)
+        return (-1);
+    return (0);
+}
+#endif /* PROXY */
+
+#ifndef PROXY
+/**
+ * xenHypervisorSetVcpus:
+ * @domain: pointer to domain object
+ * @nvcpus: the new number of virtual CPUs for this domain
+ *
+ * Dynamically change the number of virtual CPUs used by the domain.
+ *
+ * Returns 0 in case of success, -1 in case of failure.
+ */
+
+int
+xenHypervisorSetVcpus(virDomainPtr domain, unsigned int nvcpus)
+{
+    int ret;
+    xenUnifiedPrivatePtr priv;
+
+    if (domain == NULL || domain->conn == NULL)
+        return -1;
+
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+    if (priv->handle < 0 || domain->id < 0 || nvcpus < 1)
+        return (-1);
+
+    ret = virXen_setmaxvcpus(priv->handle, domain->id, nvcpus);
+    if (ret < 0)
+        return (-1);
+    return (0);
+}
+
+/**
+ * xenHypervisorPinVcpu:
+ * @domain: pointer to domain object
+ * @vcpu: virtual CPU number
+ * @cpumap: pointer to a bit map of real CPUs (in 8-bit bytes)
+ * @maplen: length of cpumap in bytes
+ *
+ * Dynamically change the real CPUs which can be allocated to a virtual CPU.
+ *
+ * Returns 0 in case of success, -1 in case of failure.
+ */
+
+int
+xenHypervisorPinVcpu(virDomainPtr domain, unsigned int vcpu,
+                     unsigned char *cpumap, int maplen)
+{
+    int ret;
+    xenUnifiedPrivatePtr priv;
+
+    if (domain == NULL || domain->conn == NULL)
+        return -1;
+
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+    if (priv->handle < 0 || (domain->id < 0) ||
+        (cpumap == NULL) || (maplen < 1))
+        return (-1);
+
+    ret = virXen_setvcpumap(priv->handle, domain->id, vcpu,
+                            cpumap, maplen);
+    if (ret < 0)
+        return (-1);
+    return (0);
+}
+#endif
+
+/**
+ * virDomainGetVcpus:
+ * @domain: pointer to domain object, or NULL for Domain0
+ * @info: pointer to an array of virVcpuInfo structures (OUT)
+ * @maxinfo: number of structures in info array
+ * @cpumaps: pointer to an bit map of real CPUs for all vcpus of this domain (in 8-bit bytes) (OUT)
+ *     If cpumaps is NULL, then no cpumap information is returned by the API.
+ *     It's assumed there is <maxinfo> cpumap in cpumaps array.
+ *     The memory allocated to cpumaps must be (maxinfo * maplen) bytes
+ *     (ie: calloc(maxinfo, maplen)).
+ *     One cpumap inside cpumaps has the format described in virDomainPinVcpu() API.
+ * @maplen: number of bytes in one cpumap, from 1 up to size of CPU map in
+ *     underlying virtualization system (Xen...).
+ *
+ * Extract information about virtual CPUs of domain, store it in info array
+ * and also in cpumaps if this pointer isn't NULL.
+ *
+ * Returns the number of info filled in case of success, -1 in case of failure.
+ */
+#ifndef PROXY
+int
+xenHypervisorGetVcpus(virDomainPtr domain, virVcpuInfoPtr info, int maxinfo,
+                      unsigned char *cpumaps, int maplen)
+{
+    xen_getdomaininfo dominfo;
+    int ret;
+    xenUnifiedPrivatePtr priv;
+    virVcpuInfoPtr ipt;
+    int nbinfo, i;
+
+    if (domain == NULL || domain->conn == NULL)
+        return -1;
+
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+    if (priv->handle < 0 || (domain->id < 0) ||
+        (info == NULL) || (maxinfo < 1) ||
+        (sizeof(cpumap_t) & 7))
+        return (-1);
+    if ((cpumaps != NULL) && (maplen < 1))
+        return -1;
+
+    /* first get the number of virtual CPUs in this domain */
+    XEN_GETDOMAININFO_CLEAR(dominfo);
+    ret = virXen_getdomaininfo(priv->handle, domain->id,
+                               &dominfo);
+
+    if ((ret < 0) || (XEN_GETDOMAININFO_DOMAIN(dominfo) != domain->id))
+        return (-1);
+    nbinfo = XEN_GETDOMAININFO_CPUCOUNT(dominfo) + 1;
+    if (nbinfo > maxinfo) nbinfo = maxinfo;
+
+    if (cpumaps != NULL)
+        memset(cpumaps, 0, maxinfo * maplen);
+
+    for (i = 0, ipt = info; i < nbinfo; i++, ipt++) {
+        if ((cpumaps != NULL) && (i < maxinfo)) {
+            ret = virXen_getvcpusinfo(priv->handle, domain->id, i,
+                                      ipt,
+                                      (unsigned char *)VIR_GET_CPUMAP(cpumaps, maplen, i),
+                                      maplen);
+            if (ret < 0)
+                return(-1);
+        } else {
+            ret = virXen_getvcpusinfo(priv->handle, domain->id, i,
+                                      ipt, NULL, 0);
+            if (ret < 0)
+                return(-1);
+        }
+    }
+    return nbinfo;
+}
+#endif /* PROXY */
+
+/**
+ * xenHypervisorGetVcpuMax:
+ *
+ *  Returns the maximum number of virtual CPUs supported for
+ *  the guest VM. If the guest is inactive, this is the maximum
+ *  of CPU defined by Xen. If the guest is running this reflect
+ *  the maximum number of virtual CPUs the guest was booted with.
+ */
+int
+xenHypervisorGetVcpuMax(virDomainPtr domain)
+{
+    xen_getdomaininfo dominfo;
+    int ret;
+    int maxcpu;
+    xenUnifiedPrivatePtr priv;
+
+    if (domain == NULL || domain->conn == NULL)
+        return -1;
+
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+    if (priv->handle < 0)
+        return (-1);
+
+    /* inactive domain */
+    if (domain->id < 0) {
+        maxcpu = MAX_VIRT_CPUS;
+    } else {
+        XEN_GETDOMAININFO_CLEAR(dominfo);
+        ret = virXen_getdomaininfo(priv->handle, domain->id,
+                                   &dominfo);
+
+        if ((ret < 0) || (XEN_GETDOMAININFO_DOMAIN(dominfo) != domain->id))
+            return (-1);
+        maxcpu = XEN_GETDOMAININFO_MAXCPUID(dominfo) + 1;
+    }
+
+    return maxcpu;
+}
+
+/**
+ * xenHavePrivilege()
+ *
+ * Return true if the current process should be able to connect to Xen.
+ */
+int
+xenHavePrivilege()
+{
+#ifdef __sun
+    return priv_ineffect (PRIV_XVM_CONTROL);
+#else
+    return access(XEN_HYPERVISOR_SOCKET, R_OK) == 0;
+#endif
+}
diff --git a/src/xen/xen_hypervisor.h b/src/xen/xen_hypervisor.h
new file mode 100644 (file)
index 0000000..766f676
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * xen_internal.h: internal API for direct access to Xen hypervisor level
+ *
+ * Copyright (C) 2005 Red Hat, Inc.
+ *
+ * See COPYING.LIB for the License of this software
+ *
+ * Daniel Veillard <veillard@redhat.com>
+ */
+
+#ifndef __VIR_XEN_INTERNAL_H__
+#define __VIR_XEN_INTERNAL_H__
+
+#include <libxml/uri.h>
+
+#include "internal.h"
+#include "capabilities.h"
+#include "driver.h"
+
+extern struct xenUnifiedDriver xenHypervisorDriver;
+int    xenHypervisorInit                 (void);
+
+virCapsPtr xenHypervisorMakeCapabilities (virConnectPtr conn);
+
+/* The following calls are made directly by the Xen proxy: */
+
+virDomainPtr
+        xenHypervisorLookupDomainByID   (virConnectPtr conn,
+                                         int id);
+virDomainPtr
+        xenHypervisorLookupDomainByUUID (virConnectPtr conn,
+                                         const unsigned char *uuid);
+char *
+        xenHypervisorDomainGetOSType    (virDomainPtr dom);
+
+virDrvOpenStatus
+        xenHypervisorOpen               (virConnectPtr conn,
+                                         virConnectAuthPtr auth,
+                                         int flags);
+int     xenHypervisorClose              (virConnectPtr conn);
+int     xenHypervisorGetVersion         (virConnectPtr conn,
+                                         unsigned long *hvVer);
+virCapsPtr
+        xenHypervisorMakeCapabilitiesInternal(virConnectPtr conn,
+                                              const char *hostmachine,
+                                              FILE *cpuinfo,
+                                              FILE *capabilities);
+char *
+        xenHypervisorGetCapabilities    (virConnectPtr conn);
+unsigned long
+        xenHypervisorGetDomMaxMemory    (virConnectPtr conn,
+                                         int id);
+int     xenHypervisorNumOfDomains       (virConnectPtr conn);
+int     xenHypervisorListDomains        (virConnectPtr conn,
+                                         int *ids,
+                                         int maxids);
+int     xenHypervisorGetMaxVcpus        (virConnectPtr conn,
+                                         const char *type);
+int     xenHypervisorDestroyDomain      (virDomainPtr domain);
+int     xenHypervisorResumeDomain       (virDomainPtr domain);
+int     xenHypervisorPauseDomain        (virDomainPtr domain);
+int     xenHypervisorGetDomainInfo        (virDomainPtr domain,
+                                         virDomainInfoPtr info);
+int     xenHypervisorGetDomInfo         (virConnectPtr conn,
+                                         int id,
+                                         virDomainInfoPtr info);
+int     xenHypervisorSetMaxMemory       (virDomainPtr domain,
+                                         unsigned long memory);
+int     xenHypervisorCheckID            (virConnectPtr conn,
+                                         int id);
+int     xenHypervisorSetVcpus           (virDomainPtr domain,
+                                         unsigned int nvcpus);
+int     xenHypervisorPinVcpu            (virDomainPtr domain,
+                                         unsigned int vcpu,
+                                         unsigned char *cpumap,
+                                         int maplen);
+int     xenHypervisorGetVcpus           (virDomainPtr domain,
+                                         virVcpuInfoPtr info,
+                                         int maxinfo,
+                                         unsigned char *cpumaps,
+                                         int maplen);
+int     xenHypervisorGetVcpuMax         (virDomainPtr domain);
+
+char *  xenHypervisorGetSchedulerType   (virDomainPtr domain,
+                                         int *nparams);
+
+int     xenHypervisorGetSchedulerParameters(virDomainPtr domain,
+                                         virSchedParameterPtr params,
+                                         int *nparams);
+
+int     xenHypervisorSetSchedulerParameters(virDomainPtr domain,
+                                         virSchedParameterPtr params,
+                                         int nparams);
+
+int     xenHypervisorDomainBlockStats   (virDomainPtr domain,
+                                         const char *path,
+                                         struct _virDomainBlockStats *stats);
+int     xenHypervisorDomainInterfaceStats (virDomainPtr domain,
+                                         const char *path,
+                                         struct _virDomainInterfaceStats *stats);
+
+int     xenHypervisorNodeGetCellsFreeMemory(virConnectPtr conn,
+                                          unsigned long long *freeMems,
+                                          int startCell,
+                                          int maxCells);
+
+int    xenHavePrivilege(void);
+
+#endif                          /* __VIR_XEN_INTERNAL_H__ */
diff --git a/src/xen/xen_inotify.c b/src/xen/xen_inotify.c
new file mode 100644 (file)
index 0000000..7deb1db
--- /dev/null
@@ -0,0 +1,492 @@
+/*
+ * xen_inofify.c: Xen notification of xml file activity in the
+ *                following dirs:
+ *                /etc/xen
+ *                /var/lib/xend/domains
+ *
+ * Copyright (C) 2008 VirtualIron
+ *
+ * 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: Ben Guthro
+ */
+#include <config.h>
+#include <dirent.h>
+#include <sys/inotify.h>
+
+#include "virterror_internal.h"
+#include "datatypes.h"
+#include "driver.h"
+#include "memory.h"
+#include "event.h"
+#include "xen_driver.h"
+#include "conf.h"
+#include "domain_conf.h"
+#include "xen_inotify.h"
+#include "xend_internal.h"
+#include "logging.h"
+#include "uuid.h"
+
+#include "xm_internal.h" /* for xenXMDomainConfigParse */
+
+#define VIR_FROM_THIS VIR_FROM_XEN_INOTIFY
+
+#define virXenInotifyError(conn, code, fmt...)                                 \
+        virReportErrorHelper(NULL, VIR_FROM_XEN_INOTIFY, code, __FILE__,      \
+                               __FUNCTION__, __LINE__, fmt)
+
+#define LIBVIRTD_DOMAINS_DIR "/var/lib/xend/domains"
+
+struct xenUnifiedDriver xenInotifyDriver = {
+    xenInotifyOpen, /* open */
+    xenInotifyClose, /* close */
+    NULL, /* version */
+    NULL, /* hostname */
+    NULL, /* nodeGetInfo */
+    NULL, /* getCapabilities */
+    NULL, /* listDomains */
+    NULL, /* numOfDomains */
+    NULL, /* domainCreateLinux */
+    NULL, /* domainSuspend */
+    NULL, /* domainResume */
+    NULL, /* domainShutdown */
+    NULL, /* domainReboot */
+    NULL, /* domainDestroy */
+    NULL, /* domainGetOSType */
+    NULL, /* domainGetMaxMemory */
+    NULL, /* domainSetMaxMemory */
+    NULL, /* domainSetMemory */
+    NULL, /* domainGetInfo */
+    NULL, /* domainSave */
+    NULL, /* domainRestore */
+    NULL, /* domainCoreDump */
+    NULL, /* domainSetVcpus */
+    NULL, /* domainPinVcpu */
+    NULL, /* domainGetVcpus */
+    NULL, /* domainGetMaxVcpus */
+    NULL, /* listDefinedDomains */
+    NULL, /* numOfDefinedDomains */
+    NULL, /* domainCreate */
+    NULL, /* domainDefineXML */
+    NULL, /* domainUndefine */
+    NULL, /* domainAttachDevice */
+    NULL, /* domainDetachDevice */
+    NULL, /* domainGetAutostart */
+    NULL, /* domainSetAutostart */
+    NULL, /* domainGetSchedulerType */
+    NULL, /* domainGetSchedulerParameters */
+    NULL, /* domainSetSchedulerParameters */
+};
+
+static int
+xenInotifyXenCacheLookup(virConnectPtr conn,
+                         const char *filename,
+                         char **name, unsigned char *uuid) {
+    xenUnifiedPrivatePtr priv = conn->privateData;
+    xenXMConfCachePtr entry;
+
+    if (!(entry = virHashLookup(priv->configCache, filename))) {
+        DEBUG("No config found for %s", filename);
+        return -1;
+    }
+
+    *name = strdup(entry->def->name);
+    memcpy(uuid, entry->def->uuid, VIR_UUID_BUFLEN);
+
+    if (!*name) {
+        DEBUG0("Error getting dom from def");
+        return -1;
+    }
+    return 0;
+}
+
+static int
+xenInotifyXendDomainsDirLookup(virConnectPtr conn, const char *filename,
+                               char **name, unsigned char *uuid) {
+    int i;
+    virDomainPtr dom;
+    const char *uuid_str;
+    unsigned char rawuuid[VIR_UUID_BUFLEN];
+    xenUnifiedPrivatePtr priv = conn->privateData;
+
+    /* xend is managing domains. we will get
+    * a filename in the manner:
+    * /var/lib/xend/domains/<uuid>/
+    */
+    uuid_str = filename + strlen(LIBVIRTD_DOMAINS_DIR) + 1;
+
+    if (virUUIDParse(uuid_str, rawuuid) < 0) {
+        virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
+                           _("parsing uuid %s"), uuid_str);
+        return -1;
+    }
+    /* call directly into xend here, as driver may not yet
+       be set during open while we are building our
+       initial list of domains */
+    DEBUG("Looking for dom with uuid: %s", uuid_str);
+    /* XXX Should not have to go via a virDomainPtr obj instance */
+    if(!(dom = xenDaemonLookupByUUID(conn, rawuuid))) {
+        /* If we are here, the domain has gone away.
+           search for, and create a domain from the stored
+           list info */
+        for (i = 0 ; i < priv->configInfoList->count ; i++) {
+            if (!memcmp(uuid, priv->configInfoList->doms[i]->uuid, VIR_UUID_BUFLEN)) {
+                *name = strdup(priv->configInfoList->doms[i]->name);
+                if (!*name) {
+                    virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
+                                       _("finding dom for %s"), uuid_str);
+                    return -1;
+                }
+                memcpy(uuid, priv->configInfoList->doms[i]->uuid, VIR_UUID_BUFLEN);
+                DEBUG0("Found dom on list");
+                return 0;
+            }
+        }
+        virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
+                           "%s", _("finding dom on config list"));
+        return -1;
+    }
+
+    if (!(*name = strdup(dom->name)))
+        return -1;
+    memcpy(uuid, dom->uuid, VIR_UUID_BUFLEN);
+    virDomainFree(dom);
+    /* succeeded too find domain by uuid */
+    return 0;
+}
+
+static int
+xenInotifyDomainLookup(virConnectPtr conn,
+                       const char *filename,
+                       char **name, unsigned char *uuid) {
+    xenUnifiedPrivatePtr priv = conn->privateData;
+    if (priv->useXenConfigCache)
+        return xenInotifyXenCacheLookup(conn, filename, name, uuid);
+    else
+        return xenInotifyXendDomainsDirLookup(conn, filename, name, uuid);
+}
+
+static virDomainEventPtr
+xenInotifyDomainEventFromFile(virConnectPtr conn,
+                              const char *filename,
+                              int type, int detail) {
+    virDomainEventPtr event;
+    char *name = NULL;
+    unsigned char uuid[VIR_UUID_BUFLEN];
+
+    if (xenInotifyDomainLookup(conn, filename, &name, uuid) < 0)
+        return NULL;
+
+    event = virDomainEventNew(-1, name, uuid, type, detail);
+    VIR_FREE(name);
+    return event;
+}
+
+static int
+xenInotifyXendDomainsDirRemoveEntry(virConnectPtr conn,
+                                    const char *fname) {
+    xenUnifiedPrivatePtr priv = conn->privateData;
+    const char *uuidstr = fname + strlen(LIBVIRTD_DOMAINS_DIR) + 1;
+    unsigned char uuid[VIR_UUID_BUFLEN];
+    int i;
+
+    if (virUUIDParse(uuidstr, uuid) < 0) {
+        virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
+                           _("parsing uuid %s"), uuidstr);
+        return -1;
+    }
+
+    /* match and remove on uuid */
+    for (i = 0 ; i < priv->configInfoList->count ; i++) {
+        if (!memcmp(uuid, priv->configInfoList->doms[i]->uuid, VIR_UUID_BUFLEN)) {
+            VIR_FREE(priv->configInfoList->doms[i]->name);
+            VIR_FREE(priv->configInfoList->doms[i]);
+
+            if (i < (priv->configInfoList->count - 1))
+                memmove(priv->configInfoList->doms + i,
+                        priv->configInfoList->doms + i + 1,
+                        sizeof(*(priv->configInfoList->doms)) *
+                                (priv->configInfoList->count - (i + 1)));
+
+            if (VIR_REALLOC_N(priv->configInfoList->doms,
+                              priv->configInfoList->count - 1) < 0) {
+                ; /* Failure to reduce memory allocation isn't fatal */
+            }
+            priv->configInfoList->count--;
+            return 0;
+        }
+    }
+    return -1;
+}
+
+static int
+xenInotifyXendDomainsDirAddEntry(virConnectPtr conn,
+                                 const char *fname) {
+    char *name = NULL;
+    unsigned char uuid[VIR_UUID_BUFLEN];
+    xenUnifiedPrivatePtr priv = conn->privateData;
+
+    if (xenInotifyDomainLookup(conn, fname, &name, uuid) < 0) {
+        virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
+                           "%s", _("Error looking up domain"));
+        return -1;
+    }
+
+    if (xenUnifiedAddDomainInfo(priv->configInfoList,
+                                -1, name, uuid) < 0) {
+        virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
+                        "%s", _("Error adding file to config cache"));
+        VIR_FREE(name);
+        return -1;
+    }
+    VIR_FREE(name);
+    return 0;
+}
+
+static int
+xenInotifyRemoveDomainConfigInfo(virConnectPtr conn,
+                                 const char *fname) {
+    xenUnifiedPrivatePtr priv = conn->privateData;
+    return priv->useXenConfigCache ?
+        xenXMConfigCacheRemoveFile(conn, fname) :
+        xenInotifyXendDomainsDirRemoveEntry(conn, fname);
+}
+
+static int
+xenInotifyAddDomainConfigInfo(virConnectPtr conn,
+                              const char *fname) {
+    xenUnifiedPrivatePtr priv = conn->privateData;
+    return priv->useXenConfigCache ?
+        xenXMConfigCacheAddFile(conn, fname) :
+        xenInotifyXendDomainsDirAddEntry(conn, fname);
+}
+
+static void
+xenInotifyEvent(int watch ATTRIBUTE_UNUSED,
+                int fd,
+                int events ATTRIBUTE_UNUSED,
+                void *data)
+{
+    char buf[1024];
+    char fname[1024];
+    struct inotify_event *e;
+    int got;
+    char *tmp, *name;
+    virConnectPtr conn = data;
+    xenUnifiedPrivatePtr priv = NULL;
+
+    DEBUG0("got inotify event");
+
+    if( conn && conn->privateData ) {
+        priv = conn->privateData;
+    } else {
+        virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
+                           "%s", _("conn, or private data is NULL"));
+        return;
+    }
+
+    xenUnifiedLock(priv);
+
+reread:
+    got = read(fd, buf, sizeof(buf));
+    if (got == -1) {
+        if (errno == EINTR)
+            goto reread;
+        goto cleanup;
+    }
+
+    tmp = buf;
+    while (got) {
+        if (got < sizeof(struct inotify_event))
+            goto cleanup; /* bad */
+
+        e = (struct inotify_event *)tmp;
+        tmp += sizeof(struct inotify_event);
+        got -= sizeof(struct inotify_event);
+
+        if (got < e->len)
+            goto cleanup;
+
+        tmp += e->len;
+        got -= e->len;
+
+        name = (char *)&(e->name);
+
+        snprintf(fname, 1024, "%s/%s",
+                 priv->configDir, name);
+
+        if (e->mask & (IN_DELETE | IN_MOVED_FROM)) {
+            virDomainEventPtr event =
+                xenInotifyDomainEventFromFile(conn, fname,
+                                              VIR_DOMAIN_EVENT_UNDEFINED,
+                                              VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
+            if (!event)
+                xenUnifiedDomainEventDispatch(conn->privateData, event);
+            else
+                virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
+                                   "%s", _("looking up dom"));
+
+            if (xenInotifyRemoveDomainConfigInfo(conn, fname) < 0 ) {
+                virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
+                                   "%s", _("Error adding file to config cache"));
+                goto cleanup;
+            }
+        } else if (e->mask & ( IN_CREATE | IN_CLOSE_WRITE | IN_MOVED_TO) ) {
+            virDomainEventPtr event;
+            if (xenInotifyAddDomainConfigInfo(conn, fname) < 0 ) {
+                virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
+                                   "%s", _("Error adding file to config cache"));
+                goto cleanup;
+            }
+
+            event = xenInotifyDomainEventFromFile(conn, fname,
+                                                  VIR_DOMAIN_EVENT_DEFINED,
+                                                  VIR_DOMAIN_EVENT_DEFINED_ADDED);
+
+            if (event)
+                xenUnifiedDomainEventDispatch(conn->privateData, event);
+            else
+                virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
+                                   "%s", _("looking up dom"));
+
+        }
+
+    }
+
+cleanup:
+    xenUnifiedUnlock(priv);
+}
+
+/**
+ * xenInotifyOpen:
+ * @conn: pointer to the connection block
+ * @name: URL for the target, NULL for local
+ * @flags: combination of virDrvOpenFlag(s)
+ *
+ * Connects and starts listening for inotify events
+ *
+ * Returns 0 or -1 in case of error.
+ */
+virDrvOpenStatus
+xenInotifyOpen(virConnectPtr conn ATTRIBUTE_UNUSED,
+             virConnectAuthPtr auth ATTRIBUTE_UNUSED,
+             int flags ATTRIBUTE_UNUSED)
+{
+    DIR *dh;
+    struct dirent *ent;
+    char path[PATH_MAX];
+    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
+
+    if (priv->configDir) {
+        priv->useXenConfigCache = 1;
+    } else {
+        /* /var/lib/xend/domains/<uuid>/config.sxp */
+        priv->configDir = LIBVIRTD_DOMAINS_DIR;
+        priv->useXenConfigCache = 0;
+
+        if (VIR_ALLOC(priv->configInfoList) < 0) {
+            virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
+                               "%s", _("failed to allocate configInfoList"));
+            return -1;
+        }
+
+        /* populate initial list */
+        if (!(dh = opendir(priv->configDir))) {
+            virReportSystemError(NULL, errno,
+                                 _("cannot open directory: %s"),
+                                 priv->configDir);
+            return -1;
+        }
+        while ((ent = readdir(dh))) {
+            if (STRPREFIX(ent->d_name, "."))
+                continue;
+
+            /* Build the full file path */
+            if ((strlen(priv->configDir) + 1 +
+                 strlen(ent->d_name) + 1) > PATH_MAX)
+                continue;
+            strcpy(path, priv->configDir);
+            strcat(path, "/");
+            strcat(path, ent->d_name);
+
+            if (xenInotifyAddDomainConfigInfo(conn, path) < 0 ) {
+                virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
+                                   "%s", _("Error adding file to config list"));
+                closedir(dh);
+                return -1;
+            }
+        }
+        closedir(dh);
+    }
+
+    if ((priv->inotifyFD = inotify_init()) < 0) {
+        virReportSystemError(NULL, errno,
+                             "%s", _("initializing inotify"));
+        return -1;
+    }
+
+    DEBUG("Adding a watch on %s", priv->configDir);
+    if (inotify_add_watch(priv->inotifyFD,
+                          priv->configDir,
+                          IN_CREATE |
+                          IN_CLOSE_WRITE | IN_DELETE |
+                          IN_MOVED_TO | IN_MOVED_FROM) < 0) {
+        virReportSystemError(NULL, errno,
+                             _("adding watch on %s"),
+                             priv->configDir);
+        return -1;
+    }
+
+    DEBUG0("Building initial config cache");
+    if (priv->useXenConfigCache &&
+        xenXMConfigCacheRefresh (conn) < 0) {
+        DEBUG("Failed to enable XM config cache %s", conn->err.message);
+        return -1;
+    }
+
+    DEBUG0("Registering with event loop");
+    /* Add the handle for monitoring */
+    if ((priv->inotifyWatch = virEventAddHandle(priv->inotifyFD, VIR_EVENT_HANDLE_READABLE,
+                                                xenInotifyEvent, conn, NULL)) < 0) {
+        DEBUG0("Failed to add inotify handle, disabling events");
+    }
+
+    virConnectRef(conn);
+    return 0;
+}
+
+/**
+ * xenInotifyClose:
+ * @conn: pointer to the connection block
+ *
+ * Close and stop listening for inotify events
+ *
+ * Returns 0 in case of success or -1 in case of error.
+ */
+int
+xenInotifyClose(virConnectPtr conn)
+{
+    xenUnifiedPrivatePtr priv = conn->privateData;
+
+    if (priv->configInfoList)
+        xenUnifiedDomainInfoListFree(priv->configInfoList);
+
+    if (priv->inotifyWatch != -1)
+        virEventRemoveHandle(priv->inotifyWatch);
+    close(priv->inotifyFD);
+    virUnrefConnect(conn);
+
+    return 0;
+}
diff --git a/src/xen/xen_inotify.h b/src/xen/xen_inotify.h
new file mode 100644 (file)
index 0000000..70bc63c
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * xen_inofify.h: Xen notification of xml files
+ *
+ * Copyright (C) 2008 VirtualIron
+ *
+ * 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: Ben Guthro
+ */
+#ifndef __VIR_XEN_INOTIFY_H__
+#define __VIR_XEN_INOTIFY_H__
+
+#include "internal.h"
+#include "driver.h"
+
+extern struct xenUnifiedDriver xenInotifyDriver;
+
+virDrvOpenStatus       xenInotifyOpen  (virConnectPtr conn,
+                                         virConnectAuthPtr auth,
+                                         int flags);
+int            xenInotifyClose         (virConnectPtr conn);
+#endif
diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c
new file mode 100644 (file)
index 0000000..350ef8c
--- /dev/null
@@ -0,0 +1,5914 @@
+/*
+ * xend_internal.c: access to Xen though the Xen Daemon interface
+ *
+ * Copyright (C) 2005
+ *
+ *      Anthony Liguori <aliguori@us.ibm.com>
+ *
+ *  This file is subject to the terms and conditions of the GNU Lesser General
+ *  Public License. See the file COPYING.LIB in the main directory of this
+ *  archive for more details.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/errno.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <math.h>
+#include <stdarg.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <libxml/uri.h>
+#include <errno.h>
+
+#include "virterror_internal.h"
+#include "logging.h"
+#include "datatypes.h"
+#include "xend_internal.h"
+#include "driver.h"
+#include "util.h"
+#include "sexpr.h"
+#include "buf.h"
+#include "uuid.h"
+#include "xen_driver.h"
+#include "xen_hypervisor.h"
+#include "xs_internal.h" /* To extract VNC port & Serial console TTY */
+#include "memory.h"
+
+/* required for cpumap_t */
+#include <xen/dom0_ops.h>
+
+#define VIR_FROM_THIS VIR_FROM_XEND
+
+#ifndef PROXY
+
+/*
+ * The number of Xen scheduler parameters
+ */
+#define XEN_SCHED_SEDF_NPARAM   6
+#define XEN_SCHED_CRED_NPARAM   2
+
+#endif /* PROXY */
+
+#ifdef WITH_RHEL5_API
+#define XEND_CONFIG_MAX_VERS_NET_TYPE_IOEMU 0
+#define XEND_CONFIG_MIN_VERS_PVFB_NEWCONF 2
+#else
+#define XEND_CONFIG_MAX_VERS_NET_TYPE_IOEMU 3
+#define XEND_CONFIG_MIN_VERS_PVFB_NEWCONF 3
+#endif
+
+
+#ifndef PROXY
+static int
+xenDaemonFormatSxprDisk(virConnectPtr conn ATTRIBUTE_UNUSED,
+                        virDomainDiskDefPtr def,
+                        virBufferPtr buf,
+                        int hvm,
+                        int xendConfigVersion,
+                        int isAttach);
+static int
+xenDaemonFormatSxprNet(virConnectPtr conn ATTRIBUTE_UNUSED,
+                       virDomainNetDefPtr def,
+                       virBufferPtr buf,
+                       int hvm,
+                       int xendConfigVersion,
+                       int isAttach);
+static int
+xenDaemonFormatSxprOnePCI(virConnectPtr conn,
+                          virDomainHostdevDefPtr def,
+                          virBufferPtr buf);
+
+static int
+virDomainXMLDevID(virDomainPtr domain,
+                  virDomainDeviceDefPtr dev,
+                  char *class,
+                  char *ref,
+                  int ref_len);
+#endif
+
+#define virXendError(conn, code, fmt...)                                     \
+        virReportErrorHelper(conn, VIR_FROM_XEND, code, __FILE__,          \
+                               __FUNCTION__, __LINE__, fmt)
+
+#define virXendErrorInt(conn, code, ival)                                    \
+        virXendError(conn, code, "%d", ival)
+
+/**
+ * do_connect:
+ * @xend: pointer to the Xen Daemon structure
+ *
+ * Internal routine to (re)connect to the daemon
+ *
+ * Returns the socket file descriptor or -1 in case of error
+ */
+static int
+do_connect(virConnectPtr xend)
+{
+    int s;
+    int serrno;
+    int no_slow_start = 1;
+    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) xend->privateData;
+
+    s = socket(priv->addrfamily, SOCK_STREAM, priv->addrprotocol);
+    if (s == -1) {
+        virXendError(xend, VIR_ERR_INTERNAL_ERROR,
+                     "%s", _("failed to create a socket"));
+        return -1;
+    }
+
+    /*
+     * try to desactivate slow-start
+     */
+    setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (void *)&no_slow_start,
+               sizeof(no_slow_start));
+
+
+    if (connect(s, (struct sockaddr *)&priv->addr, priv->addrlen) == -1) {
+        serrno = errno;
+        close(s);
+        errno = serrno;
+        s = -1;
+
+        /*
+         * Connecting to XenD when privileged is mandatory, so log this
+         * error
+         */
+        if (xenHavePrivilege()) {
+            virXendError(xend, VIR_ERR_INTERNAL_ERROR,
+                         "%s", _("failed to connect to xend"));
+        }
+    }
+
+    return s;
+}
+
+/**
+ * wr_sync:
+ * @xend: the xend connection object
+ * @fd:  the file descriptor
+ * @buffer: the I/O buffer
+ * @size: the size of the I/O
+ * @do_read: write operation if 0, read operation otherwise
+ *
+ * Do a synchronous read or write on the file descriptor
+ *
+ * Returns the number of bytes exchanged, or -1 in case of error
+ */
+static size_t
+wr_sync(virConnectPtr xend, int fd, void *buffer, size_t size, int do_read)
+{
+    size_t offset = 0;
+
+    while (offset < size) {
+        ssize_t len;
+
+        if (do_read) {
+            len = read(fd, ((char *) buffer) + offset, size - offset);
+        } else {
+            len = write(fd, ((char *) buffer) + offset, size - offset);
+        }
+
+        /* recoverable error, retry  */
+        if ((len == -1) && ((errno == EAGAIN) || (errno == EINTR))) {
+            continue;
+        }
+
+        /* eof */
+        if (len == 0) {
+            break;
+        }
+
+        /* unrecoverable error */
+        if (len == -1) {
+            if (do_read)
+                virXendError(xend, VIR_ERR_INTERNAL_ERROR,
+                             "%s", _("failed to read from Xen Daemon"));
+            else
+                virXendError(xend, VIR_ERR_INTERNAL_ERROR,
+                             "%s", _("failed to read from Xen Daemon"));
+
+            return (-1);
+        }
+
+        offset += len;
+    }
+
+    return offset;
+}
+
+/**
+ * sread:
+ * @xend: the xend connection object
+ * @fd:  the file descriptor
+ * @buffer: the I/O buffer
+ * @size: the size of the I/O
+ *
+ * Internal routine to do a synchronous read
+ *
+ * Returns the number of bytes read, or -1 in case of error
+ */
+static ssize_t
+sread(virConnectPtr xend, int fd, void *buffer, size_t size)
+{
+    return wr_sync(xend, fd, buffer, size, 1);
+}
+
+/**
+ * swrite:
+ * @xend: the xend connection object
+ * @fd:  the file descriptor
+ * @buffer: the I/O buffer
+ * @size: the size of the I/O
+ *
+ * Internal routine to do a synchronous write
+ *
+ * Returns the number of bytes written, or -1 in case of error
+ */
+static ssize_t
+swrite(virConnectPtr xend, int fd, const void *buffer, size_t size)
+{
+    return wr_sync(xend, fd, (void *) buffer, size, 0);
+}
+
+/**
+ * swrites:
+ * @xend: the xend connection object
+ * @fd:  the file descriptor
+ * @string: the string to write
+ *
+ * Internal routine to do a synchronous write of a string
+ *
+ * Returns the number of bytes written, or -1 in case of error
+ */
+static ssize_t
+swrites(virConnectPtr xend, int fd, const char *string)
+{
+    return swrite(xend, fd, string, strlen(string));
+}
+
+/**
+ * sreads:
+ * @xend: the xend connection object
+ * @fd:  the file descriptor
+ * @buffer: the I/O buffer
+ * @n_buffer: the size of the I/O buffer
+ *
+ * Internal routine to do a synchronous read of a line
+ *
+ * Returns the number of bytes read, or -1 in case of error
+ */
+static ssize_t
+sreads(virConnectPtr xend, int fd, char *buffer, size_t n_buffer)
+{
+    size_t offset;
+
+    if (n_buffer < 1)
+        return (-1);
+
+    for (offset = 0; offset < (n_buffer - 1); offset++) {
+        ssize_t ret;
+
+        ret = sread(xend, fd, buffer + offset, 1);
+        if (ret == 0)
+            break;
+        else if (ret == -1)
+            return ret;
+
+        if (buffer[offset] == '\n') {
+            offset++;
+            break;
+        }
+    }
+    buffer[offset] = 0;
+
+    return offset;
+}
+
+static int
+istartswith(const char *haystack, const char *needle)
+{
+    return STRCASEEQLEN(haystack, needle, strlen(needle));
+}
+
+
+/**
+ * xend_req:
+ * @xend: the xend connection object
+ * @fd: the file descriptor
+ * @content: the buffer to store the content
+ * @n_content: the size of the buffer
+ *
+ * Read the HTTP response from a Xen Daemon request.
+ *
+ * Returns the HTTP return code.
+ */
+static int
+xend_req(virConnectPtr xend, int fd, char *content, size_t n_content)
+{
+    char buffer[4096];
+    int content_length = -1;
+    int retcode = 0;
+
+    while (sreads(xend, fd, buffer, sizeof(buffer)) > 0) {
+        if (STREQ(buffer, "\r\n"))
+            break;
+
+        if (istartswith(buffer, "Content-Length: "))
+            content_length = atoi(buffer + 16);
+        else if (istartswith(buffer, "HTTP/1.1 "))
+            retcode = atoi(buffer + 9);
+    }
+
+    if (content_length > -1) {
+        ssize_t ret;
+
+        if ((unsigned int) content_length > (n_content + 1))
+            content_length = n_content - 1;
+
+        ret = sread(xend, fd, content, content_length);
+        if (ret < 0)
+            return -1;
+
+        content[ret] = 0;
+    } else {
+        content[0] = 0;
+    }
+
+    return retcode;
+}
+
+/**
+ * xend_get:
+ * @xend: pointer to the Xen Daemon structure
+ * @path: the path used for the HTTP request
+ * @content: the buffer to store the content
+ * @n_content: the size of the buffer
+ *
+ * Do an HTTP GET RPC with the Xen Daemon
+ *
+ * Returns the HTTP return code or -1 in case or error.
+ */
+static int
+xend_get(virConnectPtr xend, const char *path,
+         char *content, size_t n_content)
+{
+    int ret;
+    int s = do_connect(xend);
+
+    if (s == -1)
+        return s;
+
+    swrites(xend, s, "GET ");
+    swrites(xend, s, path);
+    swrites(xend, s, " HTTP/1.1\r\n");
+
+    swrites(xend, s,
+            "Host: localhost:8000\r\n"
+            "Accept-Encoding: identity\r\n"
+            "Content-Type: application/x-www-form-urlencoded\r\n" "\r\n");
+
+    ret = xend_req(xend, s, content, n_content);
+    close(s);
+
+    if (((ret < 0) || (ret >= 300)) &&
+        ((ret != 404) || (!STRPREFIX(path, "/xend/domain/")))) {
+        virXendError(xend, VIR_ERR_GET_FAILED,
+                     _("%d status from xen daemon: %s:%s"),
+                     ret, path, content);
+    }
+
+    return ret;
+}
+
+#ifndef PROXY
+/**
+ * xend_post:
+ * @xend: pointer to the Xen Daemon structure
+ * @path: the path used for the HTTP request
+ * @ops: the information sent for the POST
+ * @content: the buffer to store the content
+ * @n_content: the size of the buffer
+ *
+ * Do an HTTP POST RPC with the Xen Daemon, this usually makes changes at the
+ * Xen level.
+ *
+ * Returns the HTTP return code or -1 in case or error.
+ */
+static int
+xend_post(virConnectPtr xend, const char *path, const char *ops,
+          char *content, size_t n_content)
+{
+    char buffer[100];
+    int ret;
+    int s = do_connect(xend);
+
+    if (s == -1)
+        return s;
+
+    swrites(xend, s, "POST ");
+    swrites(xend, s, path);
+    swrites(xend, s, " HTTP/1.1\r\n");
+
+    swrites(xend, s,
+            "Host: localhost:8000\r\n"
+            "Accept-Encoding: identity\r\n"
+            "Content-Type: application/x-www-form-urlencoded\r\n"
+            "Content-Length: ");
+    snprintf(buffer, sizeof(buffer), "%d", (int) strlen(ops));
+    swrites(xend ,s, buffer);
+    swrites(xend, s, "\r\n\r\n");
+    swrites(xend, s, ops);
+
+    ret = xend_req(xend, s, content, n_content);
+    close(s);
+
+    if ((ret < 0) || (ret >= 300)) {
+        virXendError(xend, VIR_ERR_POST_FAILED,
+                     _("xend_post: error from xen daemon: %s"), content);
+    } else if ((ret == 202) && (strstr(content, "failed") != NULL)) {
+        virXendError(xend, VIR_ERR_POST_FAILED,
+                     _("xend_post: error from xen daemon: %s"), content);
+        ret = -1;
+    } else if (((ret >= 200) && (ret <= 202)) && (strstr(content, "xend.err") != NULL)) {
+        /* This is to catch case of things like 'virsh dump Domain-0 foo'
+         * which returns a success code, but the word 'xend.err'
+         * in body to indicate error :-(
+         */
+        virXendError(xend, VIR_ERR_POST_FAILED,
+                     _("xend_post: error from xen daemon: %s"), content);
+        ret = -1;
+    }
+
+    return ret;
+}
+#endif /* ! PROXY */
+
+
+/**
+ * http2unix:
+ * @xend: the xend connection object
+ * @ret: the http return code
+ *
+ * Convert the HTTP return code to 0/-1 and set errno if needed
+ *
+ * Return -1 in case of error code 0 otherwise
+ */
+static int
+http2unix(virConnectPtr xend, int ret)
+{
+    switch (ret) {
+        case -1:
+            break;
+        case 200:
+        case 201:
+        case 202:
+            return 0;
+        case 404:
+            errno = ESRCH;
+            break;
+        case 500:
+            errno = EIO;
+            break;
+        default:
+            virXendErrorInt(xend, VIR_ERR_HTTP_ERROR, ret);
+            errno = EINVAL;
+            break;
+    }
+    return -1;
+}
+
+#ifndef PROXY
+/**
+ * xend_op_ext:
+ * @xend: pointer to the Xen Daemon structure
+ * @path: path for the object
+ * @error: buffer for the error output
+ * @n_error: size of @error
+ * @key: the key for the operation
+ * @ap: input values to pass to the operation
+ *
+ * internal routine to run a POST RPC operation to the Xen Daemon
+ *
+ * Returns 0 in case of success, -1 in case of failure.
+ */
+static int
+xend_op_ext(virConnectPtr xend, const char *path, char *error,
+            size_t n_error, const char *key, va_list ap)
+{
+    const char *k = key, *v;
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    int ret;
+    char *content;
+
+    while (k) {
+        v = va_arg(ap, const char *);
+
+        virBufferVSprintf(&buf, "%s", k);
+        virBufferVSprintf(&buf, "%s", "=");
+        virBufferVSprintf(&buf, "%s", v);
+        k = va_arg(ap, const char *);
+
+        if (k)
+            virBufferVSprintf(&buf, "%s", "&");
+    }
+
+    if (virBufferError(&buf)) {
+        virReportOOMError(NULL);
+        return -1;
+    }
+
+    content = virBufferContentAndReset(&buf);
+    ret = http2unix(xend, xend_post(xend, path, content, error, n_error));
+    VIR_FREE(content);
+
+    return ret;
+}
+
+
+/**
+ * xend_op:
+ * @xend: pointer to the Xen Daemon structure
+ * @name: the domain name target of this operation
+ * @error: buffer for the error output
+ * @n_error: size of @error
+ * @key: the key for the operation
+ * @ap: input values to pass to the operation
+ * @...: input values to pass to the operation
+ *
+ * internal routine to run a POST RPC operation to the Xen Daemon targetting
+ * a given domain.
+ *
+ * Returns 0 in case of success, -1 in case of failure.
+ */
+static int
+xend_op(virConnectPtr xend, const char *name, const char *key, ...)
+{
+    char buffer[1024];
+    char error[1024];
+    va_list ap;
+    int ret;
+
+    snprintf(buffer, sizeof(buffer), "/xend/domain/%s", name);
+
+    va_start(ap, key);
+    ret = xend_op_ext(xend, buffer, error, sizeof(error), key, ap);
+    va_end(ap);
+
+    return ret;
+}
+
+#endif /* ! PROXY */
+
+/**
+ * sexpr_get:
+ * @xend: pointer to the Xen Daemon structure
+ * @fmt: format string for the path of the operation
+ * @...: extra data to build the path of the operation
+ *
+ * Internal routine to run a simple GET RPC operation to the Xen Daemon
+ *
+ * Returns a parsed S-Expression in case of success, NULL in case of failure
+ */
+static struct sexpr *sexpr_get(virConnectPtr xend, const char *fmt, ...)
+  ATTRIBUTE_FMT_PRINTF(2,3);
+
+static struct sexpr *
+sexpr_get(virConnectPtr xend, const char *fmt, ...)
+{
+    char buffer[4096];
+    char path[1024];
+    va_list ap;
+    int ret;
+
+    va_start(ap, fmt);
+    vsnprintf(path, sizeof(path), fmt, ap);
+    va_end(ap);
+
+    ret = xend_get(xend, path, buffer, sizeof(buffer));
+    ret = http2unix(xend ,ret);
+    if (ret == -1)
+        return NULL;
+
+    return string2sexpr(buffer);
+}
+
+/**
+ * sexpr_int:
+ * @sexpr: an S-Expression
+ * @name: the name for the value
+ *
+ * convenience function to lookup an int value in the S-Expression
+ *
+ * Returns the value found or 0 if not found (but may not be an error).
+ * This function suffers from the flaw that zero is both a correct
+ * return value and an error indicator: careful!
+ */
+static int
+sexpr_int(const struct sexpr *sexpr, const char *name)
+{
+    const char *value = sexpr_node(sexpr, name);
+
+    if (value) {
+        return strtol(value, NULL, 0);
+    }
+    return 0;
+}
+
+
+/**
+ * sexpr_float:
+ * @sexpr: an S-Expression
+ * @name: the name for the value
+ *
+ * convenience function to lookup a float value in the S-Expression
+ *
+ * Returns the value found or 0 if not found (but may not be an error)
+ */
+static double
+sexpr_float(const struct sexpr *sexpr, const char *name)
+{
+    const char *value = sexpr_node(sexpr, name);
+
+    if (value) {
+        return strtod(value, NULL);
+    }
+    return 0;
+}
+
+/**
+ * sexpr_u64:
+ * @sexpr: an S-Expression
+ * @name: the name for the value
+ *
+ * convenience function to lookup a 64bits unsigned int value in the
+ * S-Expression
+ *
+ * Returns the value found or 0 if not found (but may not be an error)
+ */
+static uint64_t
+sexpr_u64(const struct sexpr *sexpr, const char *name)
+{
+    const char *value = sexpr_node(sexpr, name);
+
+    if (value) {
+        return strtoll(value, NULL, 0);
+    }
+    return 0;
+}
+
+
+/**
+ * sexpr_uuid:
+ * @ptr: where to store the UUID, incremented
+ * @sexpr: an S-Expression
+ * @name: the name for the value
+ *
+ * convenience function to lookup an UUID value from the S-Expression
+ *
+ * Returns a -1 on error, 0 on success
+ */
+static int
+sexpr_uuid(unsigned char *ptr, const struct sexpr *node, const char *path)
+{
+    const char *r = sexpr_node(node, path);
+    if (!r)
+        return -1;
+    return virUUIDParse(r, ptr);
+}
+
+
+#ifndef PROXY
+/**
+ * urlencode:
+ * @string: the input URL
+ *
+ * Encode an URL see RFC 2396 and following
+ *
+ * Returns the new string or NULL in case of error.
+ */
+static char *
+urlencode(const char *string)
+{
+    size_t len = strlen(string);
+    char *buffer;
+    char *ptr;
+    size_t i;
+
+    if (VIR_ALLOC_N(buffer, len * 3 + 1) < 0) {
+        virReportOOMError(NULL);
+        return (NULL);
+    }
+    ptr = buffer;
+    for (i = 0; i < len; i++) {
+        switch (string[i]) {
+            case ' ':
+            case '\n':
+                snprintf(ptr, 4, "%%%02x", string[i]);
+                ptr += 3;
+                break;
+            default:
+                *ptr = string[i];
+                ptr++;
+        }
+    }
+
+    *ptr = 0;
+
+    return buffer;
+}
+#endif /* ! PROXY */
+
+/* PUBLIC FUNCTIONS */
+
+/**
+ * xenDaemonOpen_unix:
+ * @conn: an existing virtual connection block
+ * @path: the path for the Xen Daemon socket
+ *
+ * Creates a localhost Xen Daemon connection
+ * Note: this doesn't try to check if the connection actually works
+ *
+ * Returns 0 in case of success, -1 in case of error.
+ */
+int
+xenDaemonOpen_unix(virConnectPtr conn, const char *path)
+{
+    struct sockaddr_un *addr;
+    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
+
+    if ((conn == NULL) || (path == NULL))
+        return (-1);
+
+    memset(&priv->addr, 0, sizeof(priv->addr));
+    priv->addrfamily = AF_UNIX;
+    /*
+     * This must be zero on Solaris at least for AF_UNIX (which should
+     * really be PF_UNIX, but doesn't matter).
+     */
+    priv->addrprotocol = 0;
+    priv->addrlen = sizeof(struct sockaddr_un);
+
+    addr = (struct sockaddr_un *)&priv->addr;
+    addr->sun_family = AF_UNIX;
+    memset(addr->sun_path, 0, sizeof(addr->sun_path));
+    strncpy(addr->sun_path, path, sizeof(addr->sun_path));
+
+    return (0);
+}
+
+#ifndef PROXY
+/**
+ * xenDaemonOpen_tcp:
+ * @conn: an existing virtual connection block
+ * @host: the host name for the Xen Daemon
+ * @port: the port
+ *
+ * Creates a possibly remote Xen Daemon connection
+ * Note: this doesn't try to check if the connection actually works
+ *
+ * Returns 0 in case of success, -1 in case of error.
+ */
+static int
+xenDaemonOpen_tcp(virConnectPtr conn, const char *host, const char *port)
+{
+    xenUnifiedPrivatePtr priv;
+    struct addrinfo *res, *r;
+    struct addrinfo hints;
+    int saved_errno = EINVAL;
+    int ret;
+
+    if ((conn == NULL) || (host == NULL) || (port == NULL))
+        return (-1);
+
+    priv = (xenUnifiedPrivatePtr) conn->privateData;
+
+    priv->addrlen = 0;
+    memset(&priv->addr, 0, sizeof(priv->addr));
+
+    // http://people.redhat.com/drepper/userapi-ipv6.html
+    memset (&hints, 0, sizeof hints);
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_flags = AI_ADDRCONFIG;
+
+    ret = getaddrinfo (host, port, &hints, &res);
+    if (ret != 0) {
+        virXendError(NULL, VIR_ERR_UNKNOWN_HOST,
+                     _("unable to resolve hostname '%s': %s"),
+                     host, gai_strerror (ret));
+        return -1;
+    }
+
+    /* Try to connect to each returned address in turn. */
+    for (r = res; r; r = r->ai_next) {
+        int sock;
+
+        sock = socket (r->ai_family, SOCK_STREAM, r->ai_protocol);
+        if (sock == -1) {
+            saved_errno = errno;
+            continue;
+        }
+
+        if (connect (sock, r->ai_addr, r->ai_addrlen) == -1) {
+            saved_errno = errno;
+            close (sock);
+            continue;
+        }
+
+        priv->addrlen = r->ai_addrlen;
+        priv->addrfamily = r->ai_family;
+        priv->addrprotocol = r->ai_protocol;
+        memcpy(&priv->addr,
+               r->ai_addr,
+               r->ai_addrlen);
+        close(sock);
+        break;
+    }
+
+    freeaddrinfo (res);
+
+    if (!priv->addrlen) {
+        /* Don't raise error when unprivileged, since proxy takes over */
+        if (xenHavePrivilege())
+            virReportSystemError(conn, saved_errno,
+                                 _("unable to connect to '%s:%s'"),
+                                 host, port);
+        return -1;
+    }
+
+    return 0;
+}
+
+
+/**
+ * xend_wait_for_devices:
+ * @xend: pointer to the Xem Daemon block
+ * @name: name for the domain
+ *
+ * Block the domain until all the virtual devices are ready. This operation
+ * is needed when creating a domain before resuming it.
+ *
+ * Returns 0 in case of success, -1 (with errno) in case of error.
+ */
+int
+xend_wait_for_devices(virConnectPtr xend, const char *name)
+{
+    return xend_op(xend, name, "op", "wait_for_devices", NULL);
+}
+
+
+#endif /* PROXY */
+
+
+/**
+ * xenDaemonListDomainsOld:
+ * @xend: pointer to the Xem Daemon block
+ *
+ * This method will return an array of names of currently running
+ * domains.  The memory should be released will a call to free().
+ *
+ * Returns a list of names or NULL in case of error.
+ */
+char **
+xenDaemonListDomainsOld(virConnectPtr xend)
+{
+    size_t extra = 0;
+    struct sexpr *root = NULL;
+    char **ret = NULL;
+    int count = 0;
+    int i;
+    char *ptr;
+    struct sexpr *_for_i, *node;
+
+    root = sexpr_get(xend, "/xend/domain");
+    if (root == NULL)
+        goto error;
+
+    for (_for_i = root, node = root->u.s.car; _for_i->kind == SEXPR_CONS;
+         _for_i = _for_i->u.s.cdr, node = _for_i->u.s.car) {
+        if (node->kind != SEXPR_VALUE)
+            continue;
+        extra += strlen(node->u.value) + 1;
+        count++;
+    }
+
+    /*
+     * We can'tuse the normal allocation routines as we are mixing
+     * an array of char * at the beginning followed by an array of char
+     * ret points to the NULL terminated array of char *
+     * ptr points to the current string after that array but in the same
+     * allocated block
+     */
+    if (virAlloc((void *)&ptr,
+                 (count + 1) * sizeof(char *) + extra * sizeof(char)) < 0)
+        goto error;
+
+    ret = (char **) ptr;
+    ptr += sizeof(char *) * (count + 1);
+
+    i = 0;
+    for (_for_i = root, node = root->u.s.car; _for_i->kind == SEXPR_CONS;
+         _for_i = _for_i->u.s.cdr, node = _for_i->u.s.car) {
+        if (node->kind != SEXPR_VALUE)
+            continue;
+        ret[i] = ptr;
+        strcpy(ptr, node->u.value);
+        ptr += strlen(node->u.value) + 1;
+        i++;
+    }
+
+    ret[i] = NULL;
+
+  error:
+    sexpr_free(root);
+    return ret;
+}
+
+#ifndef PROXY
+/**
+ * xenDaemonDomainCreateXML:
+ * @xend: A xend instance
+ * @sexpr: An S-Expr description of the domain.
+ *
+ * This method will create a domain based the passed in description.  The
+ * domain will be paused after creation and must be unpaused with
+ * xenDaemonResumeDomain() to begin execution.
+ * This method may be deprecated once switching to XML-RPC based communcations
+ * with xend.
+ *
+ * Returns 0 for success, -1 (with errno) on error
+ */
+
+int
+xenDaemonDomainCreateXML(virConnectPtr xend, const char *sexpr)
+{
+    int ret, serrno;
+    char *ptr;
+
+    ptr = urlencode(sexpr);
+    if (ptr == NULL) {
+        /* this should be caught at the interface but ... */
+        virXendError(xend, VIR_ERR_INTERNAL_ERROR,
+                     "%s", _("failed to urlencode the create S-Expr"));
+        return (-1);
+    }
+
+    ret = xend_op(xend, "", "op", "create", "config", ptr, NULL);
+
+    serrno = errno;
+    VIR_FREE(ptr);
+    errno = serrno;
+
+    return ret;
+}
+#endif /* ! PROXY */
+
+/**
+ * xenDaemonDomainLookupByName_ids:
+ * @xend: A xend instance
+ * @domname: The name of the domain
+ * @uuid: return value for the UUID if not NULL
+ *
+ * This method looks up the id of a domain
+ *
+ * Returns the id on success; -1 (with errno) on error
+ */
+int
+xenDaemonDomainLookupByName_ids(virConnectPtr xend, const char *domname,
+                                unsigned char *uuid)
+{
+    struct sexpr *root;
+    const char *value;
+    int ret = -1;
+
+    if (uuid != NULL)
+        memset(uuid, 0, VIR_UUID_BUFLEN);
+    root = sexpr_get(xend, "/xend/domain/%s?detail=1", domname);
+    if (root == NULL)
+        goto error;
+
+    value = sexpr_node(root, "domain/domid");
+    if (value == NULL) {
+        virXendError(xend, VIR_ERR_INTERNAL_ERROR,
+                     "%s", _("domain information incomplete, missing domid"));
+        goto error;
+    }
+    ret = strtol(value, NULL, 0);
+    if ((ret == 0) && (value[0] != '0')) {
+        virXendError(xend, VIR_ERR_INTERNAL_ERROR,
+                     "%s", _("domain information incorrect domid not numeric"));
+        ret = -1;
+    } else if (uuid != NULL) {
+        if (sexpr_uuid(uuid, root, "domain/uuid") < 0) {
+            virXendError(xend, VIR_ERR_INTERNAL_ERROR,
+                         "%s", _("domain information incomplete, missing uuid"));
+        }
+    }
+
+  error:
+    sexpr_free(root);
+    return (ret);
+}
+
+
+/**
+ * xenDaemonDomainLookupByID:
+ * @xend: A xend instance
+ * @id: The id of the domain
+ * @name: return value for the name if not NULL
+ * @uuid: return value for the UUID if not NULL
+ *
+ * This method looks up the name of a domain based on its id
+ *
+ * Returns the 0 on success; -1 (with errno) on error
+ */
+int
+xenDaemonDomainLookupByID(virConnectPtr xend,
+                          int id,
+                          char **domname,
+                          unsigned char *uuid)
+{
+    const char *name = NULL;
+    struct sexpr *root;
+
+    memset(uuid, 0, VIR_UUID_BUFLEN);
+
+    root = sexpr_get(xend, "/xend/domain/%d?detail=1", id);
+    if (root == NULL)
+      goto error;
+
+    name = sexpr_node(root, "domain/name");
+    if (name == NULL) {
+      virXendError(xend, VIR_ERR_INTERNAL_ERROR,
+                   "%s", _("domain information incomplete, missing name"));
+      goto error;
+    }
+    if (domname)
+      *domname = strdup(name);
+
+    if (sexpr_uuid(uuid, root, "domain/uuid") < 0) {
+      virXendError(xend, VIR_ERR_INTERNAL_ERROR,
+                   "%s", _("domain information incomplete, missing uuid"));
+      goto error;
+    }
+
+    sexpr_free(root);
+    return (0);
+
+error:
+    sexpr_free(root);
+    if (domname)
+        VIR_FREE(*domname);
+    return (-1);
+}
+
+
+#ifndef PROXY
+static int
+xend_detect_config_version(virConnectPtr conn) {
+    struct sexpr *root;
+    const char *value;
+    xenUnifiedPrivatePtr priv;
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virXendError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (-1);
+    }
+
+    priv = (xenUnifiedPrivatePtr) conn->privateData;
+
+    root = sexpr_get(conn, "/xend/node/");
+    if (root == NULL)
+        return (-1);
+
+    value = sexpr_node(root, "node/xend_config_format");
+
+    if (value) {
+        priv->xendConfigVersion = strtol(value, NULL, 10);
+    }  else {
+        /* Xen prior to 3.0.3 did not have the xend_config_format
+           field, and is implicitly version 1. */
+        priv->xendConfigVersion = 1;
+    }
+    sexpr_free(root);
+    return (0);
+}
+
+#endif /* PROXY */
+
+/*****************************************************************
+ ******
+ ****** Parsing of SEXPR into virDomainDef objects
+ ******
+ *****************************************************************/
+
+/**
+ * xenDaemonParseSxprOS
+ * @xend: the xend connection object
+ * @node: the root of the parsed S-Expression
+ * @def: the domain config
+ * @hvm: true or 1 if no contains HVM S-Expression
+ * @bootloader: true or 1 if a bootloader is defined
+ *
+ * Parse the xend sexp for description of os and append it to buf.
+ *
+ * Returns 0 in case of success and -1 in case of error
+ */
+static int
+xenDaemonParseSxprOS(virConnectPtr xend,
+                     const struct sexpr *node,
+                     virDomainDefPtr def,
+                     int hvm)
+{
+    if (hvm) {
+        if (sexpr_node_copy(node, "domain/image/hvm/loader", &def->os.loader) < 0)
+            goto no_memory;
+        if (def->os.loader == NULL) {
+            if (sexpr_node_copy(node, "domain/image/hvm/kernel", &def->os.loader) < 0)
+                goto no_memory;
+
+            if (def->os.loader == NULL) {
+                virXendError(xend, VIR_ERR_INTERNAL_ERROR,
+                             "%s", _("domain information incomplete, missing HVM loader"));
+                return(-1);
+            }
+        } else {
+            if (sexpr_node_copy(node, "domain/image/hvm/kernel", &def->os.kernel) < 0)
+                goto no_memory;
+            if (sexpr_node_copy(node, "domain/image/hvm/ramdisk", &def->os.initrd) < 0)
+                goto no_memory;
+            if (sexpr_node_copy(node, "domain/image/hvm/args", &def->os.cmdline) < 0)
+                goto no_memory;
+            if (sexpr_node_copy(node, "domain/image/hvm/root", &def->os.root) < 0)
+                goto no_memory;
+        }
+    } else {
+        if (sexpr_node_copy(node, "domain/image/linux/kernel", &def->os.kernel) < 0)
+            goto no_memory;
+        if (sexpr_node_copy(node, "domain/image/linux/ramdisk", &def->os.initrd) < 0)
+            goto no_memory;
+        if (sexpr_node_copy(node, "domain/image/linux/args", &def->os.cmdline) < 0)
+            goto no_memory;
+        if (sexpr_node_copy(node, "domain/image/linux/root", &def->os.root) < 0)
+            goto no_memory;
+    }
+
+    /* If HVM kenrel == loader, then old xend, so kill off kernel */
+    if (hvm &&
+        def->os.kernel &&
+        STREQ(def->os.kernel, def->os.loader)) {
+        VIR_FREE(def->os.kernel);
+    }
+
+    if (!def->os.kernel &&
+        hvm) {
+        const char *boot = sexpr_node(node, "domain/image/hvm/boot");
+        if ((boot != NULL) && (boot[0] != 0)) {
+            while (*boot &&
+                   def->os.nBootDevs < VIR_DOMAIN_BOOT_LAST) {
+                if (*boot == 'a')
+                    def->os.bootDevs[def->os.nBootDevs++] = VIR_DOMAIN_BOOT_FLOPPY;
+                else if (*boot == 'c')
+                    def->os.bootDevs[def->os.nBootDevs++] = VIR_DOMAIN_BOOT_DISK;
+                else if (*boot == 'd')
+                    def->os.bootDevs[def->os.nBootDevs++] = VIR_DOMAIN_BOOT_CDROM;
+                else if (*boot == 'n')
+                    def->os.bootDevs[def->os.nBootDevs++] = VIR_DOMAIN_BOOT_NET;
+                boot++;
+            }
+        }
+    }
+
+    if (!hvm &&
+        !def->os.kernel &&
+        !def->os.bootloader) {
+        virXendError(xend, VIR_ERR_INTERNAL_ERROR,
+                     "%s", _("domain information incomplete, missing kernel & bootloader"));
+        return -1;
+    }
+
+    return 0;
+
+no_memory:
+    virReportOOMError(xend);
+    return -1;
+}
+
+
+int
+xend_parse_sexp_desc_char(virConnectPtr conn,
+                          virBufferPtr buf,
+                          const char *devtype,
+                          int portNum,
+                          const char *value,
+                          const char *tty)
+{
+    const char *type;
+    int telnet = 0;
+    char *bindPort = NULL;
+    char *bindHost = NULL;
+    char *connectPort = NULL;
+    char *connectHost = NULL;
+    char *path = NULL;
+    int ret = -1;
+
+    if (value[0] == '/') {
+        type = "dev";
+    } else if (STRPREFIX(value, "null")) {
+        type = "null";
+        value = NULL;
+    } else if (STRPREFIX(value, "vc")) {
+        type = "vc";
+        value = NULL;
+    } else if (STRPREFIX(value, "pty")) {
+        type = "pty";
+        value = NULL;
+    } else if (STRPREFIX(value, "stdio")) {
+        type = "stdio";
+        value = NULL;
+    } else if (STRPREFIX(value, "file:")) {
+        type = "file";
+        value += sizeof("file:")-1;
+    } else if (STRPREFIX(value, "pipe:")) {
+        type = "pipe";
+        value += sizeof("pipe:")-1;
+    } else if (STRPREFIX(value, "tcp:")) {
+        type = "tcp";
+        value += sizeof("tcp:")-1;
+    } else if (STRPREFIX(value, "telnet:")) {
+        type = "tcp";
+        value += sizeof("telnet:")-1;
+        telnet = 1;
+    } else if (STRPREFIX(value, "udp:")) {
+        type = "udp";
+        value += sizeof("udp:")-1;
+    } else if (STRPREFIX(value, "unix:")) {
+        type = "unix";
+        value += sizeof("unix:")-1;
+    } else {
+        virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                     "%s", _("Unknown char device type"));
+        return -1;
+    }
+
+    /* Compat with legacy  <console tty='/dev/pts/5'/> syntax */
+    if (STREQ(devtype, "console") &&
+        STREQ(type, "pty") &&
+        tty != NULL) {
+        virBufferVSprintf(buf, "    <%s type='%s' tty='%s'>\n",
+                          devtype, type, tty);
+    } else {
+        virBufferVSprintf(buf, "    <%s type='%s'>\n",
+                          devtype, type);
+    }
+
+    if (STREQ(type, "null") ||
+        STREQ(type, "vc") ||
+        STREQ(type, "stdio")) {
+        /* no source needed */
+    } else if (STREQ(type, "pty")) {
+        if (tty)
+            virBufferVSprintf(buf, "      <source path='%s'/>\n",
+                              tty);
+    } else if (STREQ(type, "file") ||
+               STREQ(type, "pipe")) {
+        virBufferVSprintf(buf, "      <source path='%s'/>\n",
+                          value);
+    } else if (STREQ(type, "tcp")) {
+        const char *offset = strchr(value, ':');
+        const char *offset2;
+        const char *mode, *protocol;
+
+        if (offset == NULL) {
+            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                         "%s", _("malformed char device string"));
+            goto error;
+        }
+
+        if (offset != value &&
+            (bindHost = strndup(value, offset - value)) == NULL)
+            goto no_memory;
+
+        offset2 = strchr(offset, ',');
+        if (offset2 == NULL)
+            bindPort = strdup(offset+1);
+        else
+            bindPort = strndup(offset+1, offset2-(offset+1));
+        if (bindPort == NULL)
+            goto no_memory;
+
+        if (offset2 && strstr(offset2, ",listen"))
+            mode = "bind";
+        else
+            mode = "connect";
+        protocol = telnet ? "telnet":"raw";
+
+        if (bindHost) {
+            virBufferVSprintf(buf,
+                              "      <source mode='%s' host='%s' service='%s'/>\n",
+                              mode, bindHost, bindPort);
+        } else {
+            virBufferVSprintf(buf,
+                              "      <source mode='%s' service='%s'/>\n",
+                              mode, bindPort);
+        }
+        virBufferVSprintf(buf,
+                          "      <protocol type='%s'/>\n",
+                          protocol);
+    } else if (STREQ(type, "udp")) {
+        const char *offset = strchr(value, ':');
+        const char *offset2, *offset3;
+
+        if (offset == NULL) {
+            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                         "%s", _("malformed char device string"));
+            goto error;
+        }
+
+        if (offset != value &&
+            (connectHost = strndup(value, offset - value)) == NULL)
+            goto no_memory;
+
+        offset2 = strchr(offset, '@');
+        if (offset2 != NULL) {
+            if ((connectPort = strndup(offset + 1, offset2-(offset+1))) == NULL)
+                goto no_memory;
+
+            offset3 = strchr(offset2, ':');
+            if (offset3 == NULL) {
+                virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                             "%s", _("malformed char device string"));
+                goto error;
+            }
+
+            if (offset3 > (offset2 + 1) &&
+                (bindHost = strndup(offset2 + 1, offset3 - (offset2+1))) == NULL)
+                goto no_memory;
+
+            if ((bindPort = strdup(offset3 + 1)) == NULL)
+                goto no_memory;
+        } else {
+            if ((connectPort = strdup(offset + 1)) == NULL)
+                goto no_memory;
+        }
+
+        if (connectPort) {
+            if (connectHost) {
+                virBufferVSprintf(buf,
+                                  "      <source mode='connect' host='%s' service='%s'/>\n",
+                                  connectHost, connectPort);
+            } else {
+                virBufferVSprintf(buf,
+                                  "      <source mode='connect' service='%s'/>\n",
+                                  connectPort);
+            }
+        }
+        if (bindPort) {
+            if (bindHost) {
+                virBufferVSprintf(buf,
+                                  "      <source mode='bind' host='%s' service='%s'/>\n",
+                                  bindHost, bindPort);
+            } else {
+                virBufferVSprintf(buf,
+                                  "      <source mode='bind' service='%s'/>\n",
+                                  bindPort);
+            }
+        }
+
+    } else if (STREQ(type, "unix")) {
+        const char *offset = strchr(value, ',');
+        int dolisten = 0;
+        if (offset)
+            path = strndup(value, (offset - value));
+        else
+            path = strdup(value);
+        if (path == NULL)
+            goto no_memory;
+
+        if (offset != NULL &&
+            strstr(offset, ",listen") != NULL)
+            dolisten = 1;
+
+        virBufferVSprintf(buf, "      <source mode='%s' path='%s'/>\n",
+                          dolisten ? "bind" : "connect", path);
+    }
+
+    virBufferVSprintf(buf, "      <target port='%d'/>\n",
+                      portNum);
+
+    virBufferVSprintf(buf, "    </%s>\n",
+                      devtype);
+
+    ret = 0;
+
+    if (ret == -1) {
+no_memory:
+        virReportOOMError(conn);
+    }
+
+error:
+
+    VIR_FREE(path);
+    VIR_FREE(bindHost);
+    VIR_FREE(bindPort);
+    VIR_FREE(connectHost);
+    VIR_FREE(connectPort);
+
+    return ret;
+}
+
+virDomainChrDefPtr
+xenDaemonParseSxprChar(virConnectPtr conn,
+                       const char *value,
+                       const char *tty)
+{
+    char prefix[10];
+    char *tmp;
+    virDomainChrDefPtr def;
+
+    if (VIR_ALLOC(def) < 0) {
+        virReportOOMError(conn);
+        return NULL;
+    }
+
+    strncpy(prefix, value, sizeof(prefix)-1);
+    NUL_TERMINATE(prefix);
+
+    if (value[0] == '/') {
+        def->type = VIR_DOMAIN_CHR_TYPE_DEV;
+    } else {
+        if ((tmp = strchr(prefix, ':')) != NULL) {
+            *tmp = '\0';
+            value += (tmp - prefix) + 1;
+        }
+
+        if (STREQ(prefix, "telnet")) {
+            def->type = VIR_DOMAIN_CHR_TYPE_TCP;
+            def->data.tcp.protocol = VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET;
+        } else {
+            if ((def->type = virDomainChrTypeFromString(prefix)) < 0) {
+                virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                             _("unknown chr device type '%s'"), prefix);
+                goto error;
+            }
+        }
+    }
+
+    /* Compat with legacy  <console tty='/dev/pts/5'/> syntax */
+    switch (def->type) {
+    case VIR_DOMAIN_CHR_TYPE_PTY:
+        if (tty != NULL &&
+            !(def->data.file.path = strdup(tty)))
+            goto no_memory;
+        break;
+
+    case VIR_DOMAIN_CHR_TYPE_FILE:
+    case VIR_DOMAIN_CHR_TYPE_PIPE:
+        if (!(def->data.file.path = strdup(value)))
+            goto no_memory;
+        break;
+
+    case VIR_DOMAIN_CHR_TYPE_TCP:
+    {
+        const char *offset = strchr(value, ':');
+        const char *offset2;
+
+        if (offset == NULL) {
+            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                         "%s", _("malformed char device string"));
+            goto error;
+        }
+
+        if (offset != value &&
+            (def->data.tcp.host = strndup(value, offset - value)) == NULL)
+            goto no_memory;
+
+        offset2 = strchr(offset, ',');
+        if (offset2 == NULL)
+            def->data.tcp.service = strdup(offset+1);
+        else
+            def->data.tcp.service = strndup(offset+1, offset2-(offset+1));
+        if (def->data.tcp.service == NULL)
+            goto no_memory;
+
+        if (offset2 && strstr(offset2, ",listen"))
+            def->data.tcp.listen = 1;
+    }
+    break;
+
+    case VIR_DOMAIN_CHR_TYPE_UDP:
+    {
+        const char *offset = strchr(value, ':');
+        const char *offset2, *offset3;
+
+        if (offset == NULL) {
+            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                         "%s", _("malformed char device string"));
+            goto error;
+        }
+
+        if (offset != value &&
+            (def->data.udp.connectHost = strndup(value, offset - value)) == NULL)
+            goto no_memory;
+
+        offset2 = strchr(offset, '@');
+        if (offset2 != NULL) {
+            if ((def->data.udp.connectService = strndup(offset + 1, offset2-(offset+1))) == NULL)
+                goto no_memory;
+
+            offset3 = strchr(offset2, ':');
+            if (offset3 == NULL) {
+                virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                             "%s", _("malformed char device string"));
+                goto error;
+            }
+
+            if (offset3 > (offset2 + 1) &&
+                (def->data.udp.bindHost = strndup(offset2 + 1, offset3 - (offset2+1))) == NULL)
+                goto no_memory;
+
+            if ((def->data.udp.bindService = strdup(offset3 + 1)) == NULL)
+                goto no_memory;
+        } else {
+            if ((def->data.udp.connectService = strdup(offset + 1)) == NULL)
+                goto no_memory;
+        }
+    }
+    break;
+
+    case VIR_DOMAIN_CHR_TYPE_UNIX:
+    {
+        const char *offset = strchr(value, ',');
+        if (offset)
+            def->data.nix.path = strndup(value, (offset - value));
+        else
+            def->data.nix.path = strdup(value);
+        if (def->data.nix.path == NULL)
+            goto no_memory;
+
+        if (offset != NULL &&
+            strstr(offset, ",listen") != NULL)
+            def->data.nix.listen = 1;
+    }
+    break;
+    }
+
+    return def;
+
+no_memory:
+    virReportOOMError(conn);
+error:
+    virDomainChrDefFree(def);
+    return NULL;
+}
+
+/**
+ * xend_parse_sexp_desc_disks
+ * @conn: connection
+ * @root: root sexpr
+ * @xendConfigVersion: version of xend
+ *
+ * This parses out block devices from the domain sexpr
+ *
+ * Returns 0 if successful or -1 if failed.
+ */
+static int
+xenDaemonParseSxprDisks(virConnectPtr conn,
+                        virDomainDefPtr def,
+                        const struct sexpr *root,
+                        int hvm,
+                        int xendConfigVersion)
+{
+    const struct sexpr *cur, *node;
+    virDomainDiskDefPtr disk = NULL;
+
+    for (cur = root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
+        node = cur->u.s.car;
+        /* Normally disks are in a (device (vbd ...)) block
+           but blktap disks ended up in a differently named
+           (device (tap ....)) block.... */
+        if (sexpr_lookup(node, "device/vbd") ||
+            sexpr_lookup(node, "device/tap")) {
+            char *offset;
+            const char *src = NULL;
+            const char *dst = NULL;
+            const char *mode = NULL;
+
+            /* Again dealing with (vbd...) vs (tap ...) differences */
+            if (sexpr_lookup(node, "device/vbd")) {
+                src = sexpr_node(node, "device/vbd/uname");
+                dst = sexpr_node(node, "device/vbd/dev");
+                mode = sexpr_node(node, "device/vbd/mode");
+            } else {
+                src = sexpr_node(node, "device/tap/uname");
+                dst = sexpr_node(node, "device/tap/dev");
+                mode = sexpr_node(node, "device/tap/mode");
+            }
+
+            if (VIR_ALLOC(disk) < 0)
+                goto no_memory;
+
+            if (dst == NULL) {
+                virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                             "%s", _("domain information incomplete, vbd has no dev"));
+                goto error;
+            }
+
+            if (src == NULL) {
+                /* There is a case without the uname to the CD-ROM device */
+                offset = strchr(dst, ':');
+                if (!offset ||
+                    !hvm ||
+                    STRNEQ(offset, ":cdrom")) {
+                    virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                                 "%s", _("domain information incomplete, vbd has no src"));
+                    goto error;
+                }
+            }
+
+            if (src != NULL) {
+                offset = strchr(src, ':');
+                if (!offset) {
+                    virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                                 "%s", _("cannot parse vbd filename, missing driver name"));
+                    goto error;
+                }
+
+                if (VIR_ALLOC_N(disk->driverName, (offset-src)+1) < 0)
+                    goto no_memory;
+                strncpy(disk->driverName, src, (offset-src));
+                disk->driverName[offset-src] = '\0';
+
+                src = offset + 1;
+
+                if (STREQ (disk->driverName, "tap")) {
+                    offset = strchr(src, ':');
+                    if (!offset) {
+                        virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                                     "%s", _("cannot parse vbd filename, missing driver type"));
+                        goto error;
+                    }
+
+                    if (VIR_ALLOC_N(disk->driverType, (offset-src)+1)< 0)
+                        goto no_memory;
+                    strncpy(disk->driverType, src, (offset-src));
+                    disk->driverType[offset-src] = '\0';
+
+                    src = offset + 1;
+                    /* Its possible to use blktap driver for block devs
+                       too, but kinda pointless because blkback is better,
+                       so we assume common case here. If blktap becomes
+                       omnipotent, we can revisit this, perhaps stat()'ing
+                       the src file in question */
+                    disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
+                } else if (STREQ(disk->driverName, "phy")) {
+                    disk->type = VIR_DOMAIN_DISK_TYPE_BLOCK;
+                } else if (STREQ(disk->driverName, "file")) {
+                    disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
+                }
+            } else {
+                /* No CDROM media so can't really tell. We'll just
+                   call if a FILE for now and update when media
+                   is inserted later */
+                disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
+            }
+
+            if (STREQLEN (dst, "ioemu:", 6))
+                dst += 6;
+
+            disk->device = VIR_DOMAIN_DISK_DEVICE_DISK;
+            /* New style disk config from Xen >= 3.0.3 */
+            if (xendConfigVersion > 1) {
+                offset = strrchr(dst, ':');
+                if (offset) {
+                    if (STREQ (offset, ":cdrom")) {
+                        disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
+                    } else if (STREQ (offset, ":disk")) {
+                        /* The default anyway */
+                    } else {
+                        /* Unknown, lets pretend its a disk too */
+                    }
+                    offset[0] = '\0';
+                }
+            }
+
+            if (!(disk->dst = strdup(dst)))
+                goto no_memory;
+            if (src &&
+                !(disk->src = strdup(src)))
+                goto no_memory;
+
+            if (STRPREFIX(disk->dst, "xvd"))
+                disk->bus = VIR_DOMAIN_DISK_BUS_XEN;
+            else if (STRPREFIX(disk->dst, "hd"))
+                disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
+            else if (STRPREFIX(disk->dst, "sd"))
+                disk->bus = VIR_DOMAIN_DISK_BUS_SCSI;
+            else
+                disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
+
+            if (mode &&
+                strchr(mode, 'r'))
+                disk->readonly = 1;
+            if (mode &&
+                strchr(mode, '!'))
+                disk->shared = 1;
+
+            if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0)
+                goto no_memory;
+
+            def->disks[def->ndisks++] = disk;
+            disk = NULL;
+        }
+    }
+
+    return 0;
+
+no_memory:
+    virReportOOMError(conn);
+
+error:
+    virDomainDiskDefFree(disk);
+    return -1;
+}
+
+
+static int
+xenDaemonParseSxprNets(virConnectPtr conn,
+                       virDomainDefPtr def,
+                       const struct sexpr *root)
+{
+    virDomainNetDefPtr net = NULL;
+    const struct sexpr *cur, *node;
+    const char *tmp;
+    int vif_index = 0;
+
+    for (cur = root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
+        node = cur->u.s.car;
+        if (sexpr_lookup(node, "device/vif")) {
+            const char *tmp2, *model;
+            char buf[50];
+            tmp2 = sexpr_node(node, "device/vif/script");
+            tmp = sexpr_node(node, "device/vif/bridge");
+            model = sexpr_node(node, "device/vif/model");
+
+            if (VIR_ALLOC(net) < 0)
+                goto no_memory;
+
+            if (tmp != NULL ||
+                (tmp2 != NULL && STREQ(tmp2, DEFAULT_VIF_SCRIPT))) {
+                net->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
+                /* XXX virtual network reverse resolve */
+
+                if (tmp &&
+                    !(net->data.bridge.brname = strdup(tmp)))
+                    goto no_memory;
+                if (tmp2 &&
+                    net->type == VIR_DOMAIN_NET_TYPE_BRIDGE &&
+                    !(net->data.bridge.script = strdup(tmp2)))
+                    goto no_memory;
+                tmp = sexpr_node(node, "device/vif/ip");
+                if (tmp &&
+                    !(net->data.bridge.ipaddr = strdup(tmp)))
+                    goto no_memory;
+            } else {
+                net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
+                if (tmp2 &&
+                    !(net->data.ethernet.script = strdup(tmp2)))
+                    goto no_memory;
+                tmp = sexpr_node(node, "device/vif/ip");
+                if (tmp &&
+                    !(net->data.ethernet.ipaddr = strdup(tmp)))
+                    goto no_memory;
+            }
+
+            tmp = sexpr_node(node, "device/vif/vifname");
+            if (!tmp) {
+                snprintf(buf, sizeof(buf), "vif%d.%d", def->id, vif_index);
+                tmp = buf;
+            }
+            if (!(net->ifname = strdup(tmp)))
+                goto no_memory;
+
+            tmp = sexpr_node(node, "device/vif/mac");
+            if (tmp) {
+                unsigned int mac[6];
+                if (sscanf(tmp, "%02x:%02x:%02x:%02x:%02x:%02x",
+                           (unsigned int*)&mac[0],
+                           (unsigned int*)&mac[1],
+                           (unsigned int*)&mac[2],
+                           (unsigned int*)&mac[3],
+                           (unsigned int*)&mac[4],
+                           (unsigned int*)&mac[5]) != 6) {
+                    virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                                 _("malformed mac address '%s'"),
+                                 tmp);
+                    goto cleanup;
+                }
+                net->mac[0] = mac[0];
+                net->mac[1] = mac[1];
+                net->mac[2] = mac[2];
+                net->mac[3] = mac[3];
+                net->mac[4] = mac[4];
+                net->mac[5] = mac[5];
+            }
+
+            if (model &&
+                !(net->model = strdup(model)))
+                goto no_memory;
+
+            if (VIR_REALLOC_N(def->nets, def->nnets + 1) < 0)
+                goto no_memory;
+
+            def->nets[def->nnets++] = net;
+            vif_index++;
+        }
+    }
+
+    return 0;
+
+no_memory:
+    virReportOOMError(conn);
+cleanup:
+    virDomainNetDefFree(net);
+    return -1;
+}
+
+
+int
+xenDaemonParseSxprSound(virConnectPtr conn,
+                        virDomainDefPtr def,
+                        const char *str)
+{
+    if (STREQ(str, "all")) {
+        int i;
+
+        /*
+         * Special compatability code for Xen with a bogus
+         * sound=all in config.
+         *
+         * NB delibrately, don't include all possible
+         * sound models anymore, just the 2 that were
+         * historically present in Xen's QEMU.
+         *
+         * ie just es1370 + sb16.
+         *
+         * Hence use of MODEL_ES1370 + 1, instead of MODEL_LAST
+         */
+
+        if (VIR_ALLOC_N(def->sounds,
+                        VIR_DOMAIN_SOUND_MODEL_ES1370 + 1) < 0)
+            goto no_memory;
+
+
+        for (i = 0 ; i < (VIR_DOMAIN_SOUND_MODEL_ES1370 + 1) ; i++) {
+            virDomainSoundDefPtr sound;
+            if (VIR_ALLOC(sound) < 0)
+                goto no_memory;
+            sound->model = i;
+            def->sounds[def->nsounds++] = sound;
+        }
+    } else {
+        char model[10];
+        const char *offset = str, *offset2;
+
+        do {
+            int len;
+            virDomainSoundDefPtr sound;
+            offset2 = strchr(offset, ',');
+            if (offset2)
+                len = (offset2 - offset);
+            else
+                len = strlen(offset);
+            if (len > (sizeof(model)-1)) {
+                virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                                 _("unexpected sound model %s"), offset);
+                goto error;
+            }
+            strncpy(model, offset, len);
+            model[len] = '\0';
+
+            if (VIR_ALLOC(sound) < 0)
+                goto no_memory;
+
+            if ((sound->model = virDomainSoundModelTypeFromString(model)) < 0) {
+                VIR_FREE(sound);
+                goto error;
+            }
+
+            if (VIR_REALLOC_N(def->sounds, def->nsounds+1) < 0) {
+                virDomainSoundDefFree(sound);
+                goto no_memory;
+            }
+
+            def->sounds[def->nsounds++] = sound;
+            offset = offset2 ? offset2 + 1 : NULL;
+        } while (offset);
+    }
+
+    return 0;
+
+no_memory:
+    virReportOOMError(conn);
+error:
+    return -1;
+}
+
+
+static int
+xenDaemonParseSxprUSB(virConnectPtr conn,
+                      virDomainDefPtr def,
+                      const struct sexpr *root)
+{
+    struct sexpr *cur, *node;
+    const char *tmp;
+
+    for (cur = sexpr_lookup(root, "domain/image/hvm"); cur && cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
+        node = cur->u.s.car;
+        if (sexpr_lookup(node, "usbdevice")) {
+            tmp = sexpr_node(node, "usbdevice");
+            if (tmp && *tmp) {
+                if (STREQ(tmp, "tablet") ||
+                    STREQ(tmp, "mouse")) {
+                    virDomainInputDefPtr input;
+                    if (VIR_ALLOC(input) < 0)
+                        goto no_memory;
+                    input->bus = VIR_DOMAIN_INPUT_BUS_USB;
+                    if (STREQ(tmp, "tablet"))
+                        input->type = VIR_DOMAIN_INPUT_TYPE_TABLET;
+                    else
+                        input->type = VIR_DOMAIN_INPUT_TYPE_MOUSE;
+
+                    if (VIR_REALLOC_N(def->inputs, def->ninputs+1) < 0) {
+                        VIR_FREE(input);
+                        goto no_memory;
+                    }
+                    def->inputs[def->ninputs++] = input;
+                } else {
+                    /* XXX Handle other non-input USB devices later */
+                }
+            }
+        }
+    }
+    return 0;
+
+no_memory:
+    virReportOOMError(conn);
+    return -1;
+}
+
+static int
+xenDaemonParseSxprGraphicsOld(virConnectPtr conn,
+                              virDomainDefPtr def,
+                              const struct sexpr *root,
+                              int hvm,
+                              int xendConfigVersion)
+{
+#ifndef PROXY
+    xenUnifiedPrivatePtr priv = conn->privateData;
+#endif
+    const char *tmp;
+    virDomainGraphicsDefPtr graphics = NULL;
+
+    if ((tmp = sexpr_fmt_node(root, "domain/image/%s/vnc", hvm ? "hvm" : "linux")) &&
+        tmp[0] == '1') {
+        /* Graphics device (HVM, or old (pre-3.0.4) style PV VNC config) */
+        int port;
+        const char *listenAddr = sexpr_fmt_node(root, "domain/image/%s/vnclisten", hvm ? "hvm" : "linux");
+        const char *vncPasswd = sexpr_fmt_node(root, "domain/image/%s/vncpasswd", hvm ? "hvm" : "linux");
+        const char *keymap = sexpr_fmt_node(root, "domain/image/%s/keymap", hvm ? "hvm" : "linux");
+        const char *unused = sexpr_fmt_node(root, "domain/image/%s/vncunused", hvm ? "hvm" : "linux");
+
+        xenUnifiedLock(priv);
+        port = xenStoreDomainGetVNCPort(conn, def->id);
+        xenUnifiedUnlock(priv);
+
+        if (VIR_ALLOC(graphics) < 0)
+            goto no_memory;
+
+        graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_VNC;
+        /* For Xen >= 3.0.3, don't generate a fixed port mapping
+         * because it will almost certainly be wrong ! Just leave
+         * it as -1 which lets caller see that the VNC server isn't
+         * present yet. Subsquent dumps of the XML will eventually
+         * find the port in XenStore once VNC server has started
+         */
+        if (port == -1 && xendConfigVersion < 2)
+            port = 5900 + def->id;
+
+        if ((unused && STREQ(unused, "1")) || port == -1)
+            graphics->data.vnc.autoport = 1;
+        graphics->data.vnc.port = port;
+
+        if (listenAddr &&
+            !(graphics->data.vnc.listenAddr = strdup(listenAddr)))
+            goto no_memory;
+
+        if (vncPasswd &&
+            !(graphics->data.vnc.passwd = strdup(vncPasswd)))
+            goto no_memory;
+
+        if (keymap &&
+            !(graphics->data.vnc.keymap = strdup(keymap)))
+            goto no_memory;
+
+        if (VIR_ALLOC_N(def->graphics, 1) < 0)
+            goto no_memory;
+        def->graphics[0] = graphics;
+        def->ngraphics = 1;
+        graphics = NULL;
+    } else if ((tmp = sexpr_fmt_node(root, "domain/image/%s/sdl", hvm ? "hvm" : "linux")) &&
+               tmp[0] == '1') {
+        /* Graphics device (HVM, or old (pre-3.0.4) style PV sdl config) */
+        const char *display = sexpr_fmt_node(root, "domain/image/%s/display", hvm ? "hvm" : "linux");
+        const char *xauth = sexpr_fmt_node(root, "domain/image/%s/xauthority", hvm ? "hvm" : "linux");
+
+        if (VIR_ALLOC(graphics) < 0)
+            goto no_memory;
+
+        graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_SDL;
+        if (display &&
+            !(graphics->data.sdl.display = strdup(display)))
+            goto no_memory;
+        if (xauth &&
+            !(graphics->data.sdl.xauth = strdup(xauth)))
+            goto no_memory;
+
+        if (VIR_ALLOC_N(def->graphics, 1) < 0)
+            goto no_memory;
+        def->graphics[0] = graphics;
+        def->ngraphics = 1;
+        graphics = NULL;
+    }
+
+    return 0;
+
+no_memory:
+    virReportOOMError(conn);
+    virDomainGraphicsDefFree(graphics);
+    return -1;
+}
+
+
+static int
+xenDaemonParseSxprGraphicsNew(virConnectPtr conn,
+                              virDomainDefPtr def,
+                              const struct sexpr *root)
+{
+#ifndef PROXY
+    xenUnifiedPrivatePtr priv = conn->privateData;
+#endif
+    virDomainGraphicsDefPtr graphics = NULL;
+    const struct sexpr *cur, *node;
+    const char *tmp;
+
+    /* append network devices and framebuffer */
+    for (cur = root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
+        node = cur->u.s.car;
+        if (sexpr_lookup(node, "device/vfb")) {
+            /* New style graphics config for PV guests in >= 3.0.4,
+             * or for HVM guests in >= 3.0.5 */
+            if (sexpr_node(node, "device/vfb/type")) {
+                tmp = sexpr_node(node, "device/vfb/type");
+            } else if (sexpr_node(node, "device/vfb/vnc")) {
+                tmp = "vnc";
+            } else if (sexpr_node(node, "device/vfb/sdl")) {
+                tmp = "sdl";
+            } else {
+                tmp = "unknown";
+            }
+
+            if (VIR_ALLOC(graphics) < 0)
+                goto no_memory;
+
+            if ((graphics->type = virDomainGraphicsTypeFromString(tmp)) < 0) {
+                virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                             _("unknown graphics type '%s'"), tmp);
+                goto error;
+            }
+
+            if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
+                const char *display = sexpr_node(node, "device/vfb/display");
+                const char *xauth = sexpr_node(node, "device/vfb/xauthority");
+                if (display &&
+                    !(graphics->data.sdl.display = strdup(display)))
+                    goto no_memory;
+                if (xauth &&
+                    !(graphics->data.sdl.xauth = strdup(xauth)))
+                    goto no_memory;
+            } else {
+                int port;
+                const char *listenAddr = sexpr_node(node, "device/vfb/vnclisten");
+                const char *vncPasswd = sexpr_node(node, "device/vfb/vncpasswd");
+                const char *keymap = sexpr_node(node, "device/vfb/keymap");
+                const char *unused = sexpr_node(node, "device/vfb/vncunused");
+
+                xenUnifiedLock(priv);
+                port = xenStoreDomainGetVNCPort(conn, def->id);
+                xenUnifiedUnlock(priv);
+
+                // Didn't find port entry in xenstore
+                if (port == -1) {
+                    const char *str = sexpr_node(node, "device/vfb/vncdisplay");
+                    int val;
+                    if (str != NULL && virStrToLong_i(str, NULL, 0, &val) == 0)
+                        port = val;
+                }
+
+                if ((unused && STREQ(unused, "1")) || port == -1)
+                    graphics->data.vnc.autoport = 1;
+
+                if (port >= 0 && port < 5900)
+                    port += 5900;
+                graphics->data.vnc.port = port;
+
+                if (listenAddr &&
+                    !(graphics->data.vnc.listenAddr = strdup(listenAddr)))
+                    goto no_memory;
+
+                if (vncPasswd &&
+                    !(graphics->data.vnc.passwd = strdup(vncPasswd)))
+                    goto no_memory;
+
+                if (keymap &&
+                    !(graphics->data.vnc.keymap = strdup(keymap)))
+                    goto no_memory;
+            }
+
+            if (VIR_ALLOC_N(def->graphics, 1) < 0)
+                goto no_memory;
+            def->graphics[0] = graphics;
+            def->ngraphics = 1;
+            graphics = NULL;
+            break;
+        }
+    }
+
+    return 0;
+
+no_memory:
+    virReportOOMError(conn);
+error:
+    virDomainGraphicsDefFree(graphics);
+    return -1;
+}
+
+/**
+ * xenDaemonParseSxprPCI
+ * @conn: connection
+ * @root: root sexpr
+ *
+ * This parses out block devices from the domain sexpr
+ *
+ * Returns 0 if successful or -1 if failed.
+ */
+static int
+xenDaemonParseSxprPCI(virConnectPtr conn,
+                      virDomainDefPtr def,
+                      const struct sexpr *root)
+{
+    const struct sexpr *cur, *tmp = NULL, *node;
+    virDomainHostdevDefPtr dev = NULL;
+
+    /*
+     * With the (domain ...) block we have the following odd setup
+     *
+     * (device
+     *    (pci
+     *       (dev (domain 0x0000) (bus 0x00) (slot 0x1b) (func 0x0))
+     *       (dev (domain 0x0000) (bus 0x00) (slot 0x13) (func 0x0))
+     *    )
+     * )
+     *
+     * Normally there is one (device ...) block per device, but in
+     * wierd world of Xen PCI, once (device ...) covers multiple
+     * devices.
+     */
+
+    for (cur = root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
+        node = cur->u.s.car;
+        if ((tmp = sexpr_lookup(node, "device/pci")) != NULL)
+            break;
+    }
+
+    if (!tmp)
+        return 0;
+
+    for (cur = tmp; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
+        const char *domain = NULL;
+        const char *bus = NULL;
+        const char *slot = NULL;
+        const char *func = NULL;
+        int domainID;
+        int busID;
+        int slotID;
+        int funcID;
+
+        node = cur->u.s.car;
+        if (!sexpr_lookup(node, "dev"))
+            continue;
+
+        if (!(domain = sexpr_node(node, "dev/domain"))) {
+            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                         "%s", _("missing PCI domain"));
+            goto error;
+        }
+        if (!(bus = sexpr_node(node, "dev/bus"))) {
+            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                         "%s", _("missing PCI bus"));
+            goto error;
+        }
+        if (!(slot = sexpr_node(node, "dev/slot"))) {
+            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                         "%s", _("missing PCI slot"));
+            goto error;
+        }
+        if (!(func = sexpr_node(node, "dev/func"))) {
+            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                         "%s", _("missing PCI func"));
+            goto error;
+        }
+
+        if (virStrToLong_i(domain, NULL, 0, &domainID) < 0) {
+            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                         _("cannot parse PCI domain '%s'"), domain);
+            goto error;
+        }
+        if (virStrToLong_i(bus, NULL, 0, &busID) < 0) {
+            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                         _("cannot parse PCI bus '%s'"), bus);
+            goto error;
+        }
+        if (virStrToLong_i(slot, NULL, 0, &slotID) < 0) {
+            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                         _("cannot parse PCI slot '%s'"), slot);
+            goto error;
+        }
+        if (virStrToLong_i(func, NULL, 0, &funcID) < 0) {
+            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                         _("cannot parse PCI func '%s'"), func);
+            goto error;
+        }
+
+        if (VIR_ALLOC(dev) < 0)
+            goto no_memory;
+
+        dev->mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS;
+        dev->managed = 0;
+        dev->source.subsys.type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI;
+        dev->source.subsys.u.pci.domain = domainID;
+        dev->source.subsys.u.pci.bus = busID;
+        dev->source.subsys.u.pci.slot = slotID;
+        dev->source.subsys.u.pci.function = funcID;
+
+        if (VIR_REALLOC_N(def->hostdevs, def->nhostdevs+1) < 0) {
+            goto no_memory;
+        }
+
+        def->hostdevs[def->nhostdevs++] = dev;
+    }
+
+    return 0;
+
+no_memory:
+    virReportOOMError(conn);
+
+error:
+    virDomainHostdevDefFree(dev);
+    return -1;
+}
+
+
+/**
+ * xenDaemonParseSxpr:
+ * @conn: the connection associated with the XML
+ * @root: the root of the parsed S-Expression
+ * @xendConfigVersion: version of xend
+ * @cpus: set of cpus the domain may be pinned to
+ *
+ * Parse the xend sexp description and turn it into the XML format similar
+ * to the one unsed for creation.
+ *
+ * Returns the 0 terminated XML string or NULL in case of error.
+ *         the caller must free() the returned value.
+ */
+static virDomainDefPtr
+xenDaemonParseSxpr(virConnectPtr conn,
+                   const struct sexpr *root,
+                   int xendConfigVersion,
+                   const char *cpus)
+{
+#ifndef PROXY
+    xenUnifiedPrivatePtr priv = conn->privateData;
+#endif
+    const char *tmp;
+    virDomainDefPtr def;
+    int hvm = 0;
+    char *tty = NULL;
+
+    if (VIR_ALLOC(def) < 0)
+        goto no_memory;
+
+    tmp = sexpr_node(root, "domain/domid");
+    if (tmp == NULL && xendConfigVersion < 3) { /* Old XenD, domid was mandatory */
+        virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                     "%s", _("domain information incomplete, missing id"));
+        goto error;
+    }
+    def->virtType = VIR_DOMAIN_VIRT_XEN;
+    if (tmp)
+        def->id = sexpr_int(root, "domain/domid");
+    else
+        def->id = -1;
+
+    if (sexpr_node_copy(root, "domain/name", &def->name) < 0)
+        goto no_memory;
+    if (def->name == NULL) {
+        virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                     "%s", _("domain information incomplete, missing name"));
+        goto error;
+    }
+
+    tmp = sexpr_node(root, "domain/uuid");
+    if (tmp == NULL) {
+        virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                     "%s", _("domain information incomplete, missing name"));
+        goto error;
+    }
+    virUUIDParse(tmp, def->uuid);
+
+    hvm = sexpr_lookup(root, "domain/image/hvm") ? 1 : 0;
+    if (!hvm) {
+        if (sexpr_node_copy(root, "domain/bootloader",
+                            &def->os.bootloader) < 0)
+            goto no_memory;
+
+        if (!def->os.bootloader &&
+            sexpr_has(root, "domain/bootloader") &&
+            (def->os.bootloader = strdup("")) == NULL)
+            goto no_memory;
+
+        if (def->os.bootloader &&
+            sexpr_node_copy(root, "domain/bootloader_args",
+                            &def->os.bootloaderArgs) < 0)
+            goto no_memory;
+    }
+
+    if (!(def->os.type = strdup(hvm ? "hvm" : "linux")))
+        goto no_memory;
+
+    if (def->id != 0) {
+        if (sexpr_lookup(root, "domain/image")) {
+            if (xenDaemonParseSxprOS(conn, root, def, hvm) < 0)
+                goto error;
+        }
+    }
+
+    def->maxmem = (unsigned long) (sexpr_u64(root, "domain/maxmem") << 10);
+    def->memory = (unsigned long) (sexpr_u64(root, "domain/memory") << 10);
+    if (def->memory > def->maxmem)
+        def->maxmem = def->memory;
+
+    if (cpus != NULL) {
+        def->cpumasklen = VIR_DOMAIN_CPUMASK_LEN;
+        if (VIR_ALLOC_N(def->cpumask, def->cpumasklen) < 0) {
+            virReportOOMError(conn);
+            goto error;
+        }
+
+        if (virDomainCpuSetParse(conn, &cpus,
+                                 0, def->cpumask,
+                                 def->cpumasklen) < 0) {
+            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                         _("invalid CPU mask %s"), cpus);
+            goto error;
+        }
+    }
+
+    def->vcpus = sexpr_int(root, "domain/vcpus");
+
+    tmp = sexpr_node(root, "domain/on_poweroff");
+    if (tmp != NULL) {
+        if ((def->onPoweroff = virDomainLifecycleTypeFromString(tmp)) < 0) {
+            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                         _("unknown lifecycle type %s"), tmp);
+            goto error;
+        }
+    } else
+        def->onPoweroff = VIR_DOMAIN_LIFECYCLE_DESTROY;
+
+    tmp = sexpr_node(root, "domain/on_reboot");
+    if (tmp != NULL) {
+        if ((def->onReboot = virDomainLifecycleTypeFromString(tmp)) < 0) {
+            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                         _("unknown lifecycle type %s"), tmp);
+            goto error;
+        }
+    } else
+        def->onReboot = VIR_DOMAIN_LIFECYCLE_RESTART;
+
+    tmp = sexpr_node(root, "domain/on_crash");
+    if (tmp != NULL) {
+        if ((def->onCrash = virDomainLifecycleTypeFromString(tmp)) < 0) {
+            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                         _("unknown lifecycle type %s"), tmp);
+            goto error;
+        }
+    } else
+        def->onCrash = VIR_DOMAIN_LIFECYCLE_DESTROY;
+
+
+    if (hvm) {
+        if (sexpr_int(root, "domain/image/hvm/acpi"))
+            def->features |= (1 << VIR_DOMAIN_FEATURE_ACPI);
+        if (sexpr_int(root, "domain/image/hvm/apic"))
+            def->features |= (1 << VIR_DOMAIN_FEATURE_APIC);
+        if (sexpr_int(root, "domain/image/hvm/pae"))
+            def->features |= (1 << VIR_DOMAIN_FEATURE_PAE);
+
+        /* Old XenD only allows localtime here for HVM */
+        if (sexpr_int(root, "domain/image/hvm/localtime"))
+            def->localtime = 1;
+    }
+
+    /* Current XenD allows localtime here, for PV and HVM */
+    if (sexpr_int(root, "domain/localtime"))
+        def->localtime = 1;
+
+    if (sexpr_node_copy(root, hvm ?
+                        "domain/image/hvm/device_model" :
+                        "domain/image/linux/device_model",
+                        &def->emulator) < 0)
+        goto no_memory;
+
+    /* append block devices */
+    if (xenDaemonParseSxprDisks(conn, def, root, hvm, xendConfigVersion) < 0)
+        goto error;
+
+    if (xenDaemonParseSxprNets(conn, def, root) < 0)
+        goto error;
+
+    if (xenDaemonParseSxprPCI(conn, def, root) < 0)
+        goto error;
+
+    /* New style graphics device config */
+    if (xenDaemonParseSxprGraphicsNew(conn, def, root) < 0)
+        goto error;
+
+    /* Graphics device (HVM <= 3.0.4, or PV <= 3.0.3) vnc config */
+    if ((def->ngraphics == 0) &&
+        xenDaemonParseSxprGraphicsOld(conn, def, root, hvm, xendConfigVersion) < 0)
+        goto error;
+
+
+    /* Old style cdrom config from Xen <= 3.0.2 */
+    if (hvm &&
+        xendConfigVersion == 1) {
+        tmp = sexpr_node(root, "domain/image/hvm/cdrom");
+        if ((tmp != NULL) && (tmp[0] != 0)) {
+            virDomainDiskDefPtr disk;
+            if (VIR_ALLOC(disk) < 0)
+                goto no_memory;
+            if (!(disk->src = strdup(tmp))) {
+                virDomainDiskDefFree(disk);
+                goto no_memory;
+            }
+            disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
+            disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
+            if (!(disk->dst = strdup("hdc"))) {
+                virDomainDiskDefFree(disk);
+                goto no_memory;
+            }
+            if (!(disk->driverName = strdup("file"))) {
+                virDomainDiskDefFree(disk);
+                goto no_memory;
+            }
+            disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
+            disk->readonly = 1;
+
+            if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0) {
+                virDomainDiskDefFree(disk);
+                goto no_memory;
+            }
+            def->disks[def->ndisks++] = disk;
+        }
+    }
+
+
+    /* Floppy disk config */
+    if (hvm) {
+        const char *const fds[] = { "fda", "fdb" };
+        int i;
+        for (i = 0 ; i < ARRAY_CARDINALITY(fds) ; i++) {
+            tmp = sexpr_fmt_node(root, "domain/image/hvm/%s", fds[i]);
+            if ((tmp != NULL) && (tmp[0] != 0)) {
+                virDomainDiskDefPtr disk;
+                if (VIR_ALLOC(disk) < 0)
+                    goto no_memory;
+                if (!(disk->src = strdup(tmp))) {
+                    VIR_FREE(disk);
+                    goto no_memory;
+                }
+                disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
+                disk->device = VIR_DOMAIN_DISK_DEVICE_FLOPPY;
+                if (!(disk->dst = strdup(fds[i]))) {
+                    virDomainDiskDefFree(disk);
+                    goto no_memory;
+                }
+                if (!(disk->driverName = strdup("file"))) {
+                    virDomainDiskDefFree(disk);
+                    goto no_memory;
+                }
+                disk->bus = VIR_DOMAIN_DISK_BUS_FDC;
+
+                if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0) {
+                    virDomainDiskDefFree(disk);
+                    goto no_memory;
+                }
+                def->disks[def->ndisks++] = disk;
+            }
+        }
+    }
+
+    /* in case of HVM we have USB device emulation */
+    if (hvm &&
+        xenDaemonParseSxprUSB(conn, def, root) < 0)
+        goto error;
+
+    /* Character device config */
+    xenUnifiedLock(priv);
+    tty = xenStoreDomainGetConsolePath(conn, def->id);
+    xenUnifiedUnlock(priv);
+    if (hvm) {
+        tmp = sexpr_node(root, "domain/image/hvm/serial");
+        if (tmp && STRNEQ(tmp, "none")) {
+            virDomainChrDefPtr chr;
+            if ((chr = xenDaemonParseSxprChar(conn, tmp, tty)) == NULL)
+                goto error;
+            if (VIR_REALLOC_N(def->serials, def->nserials+1) < 0) {
+                virDomainChrDefFree(chr);
+                goto no_memory;
+            }
+            def->serials[def->nserials++] = chr;
+        }
+        tmp = sexpr_node(root, "domain/image/hvm/parallel");
+        if (tmp && STRNEQ(tmp, "none")) {
+            virDomainChrDefPtr chr;
+            /* XXX does XenD stuff parallel port tty info into xenstore somewhere ? */
+            if ((chr = xenDaemonParseSxprChar(conn, tmp, NULL)) == NULL)
+                goto error;
+            if (VIR_REALLOC_N(def->parallels, def->nparallels+1) < 0) {
+                virDomainChrDefFree(chr);
+                goto no_memory;
+            }
+            def->parallels[def->nparallels++] = chr;
+        }
+    } else {
+        /* Fake a paravirt console, since that's not in the sexpr */
+        if (!(def->console = xenDaemonParseSxprChar(conn, "pty", tty)))
+            goto error;
+    }
+    VIR_FREE(tty);
+
+
+    /* Sound device config */
+    if (hvm &&
+        (tmp = sexpr_node(root, "domain/image/hvm/soundhw")) != NULL &&
+        *tmp) {
+        if (xenDaemonParseSxprSound(conn, def, tmp) < 0)
+            goto error;
+    }
+
+    return def;
+
+no_memory:
+    virReportOOMError(conn);
+error:
+    VIR_FREE(tty);
+    virDomainDefFree(def);
+    return NULL;
+}
+
+virDomainDefPtr
+xenDaemonParseSxprString(virConnectPtr conn,
+                         const char *sexpr,
+                         int xendConfigVersion)
+{
+    struct sexpr *root = string2sexpr(sexpr);
+    virDomainDefPtr def;
+
+    if (!root)
+        return NULL;
+
+    def = xenDaemonParseSxpr(conn, root, xendConfigVersion, NULL);
+
+    sexpr_free(root);
+
+    return def;
+}
+
+
+/**
+ * sexpr_to_xend_domain_info:
+ * @root: an S-Expression describing a domain
+ * @info: a info data structure to fill=up
+ *
+ * Internal routine filling up the info structure with the values from
+ * the domain root provided.
+ *
+ * Returns 0 in case of success, -1 in case of error
+ */
+static int
+sexpr_to_xend_domain_info(virDomainPtr domain, const struct sexpr *root,
+                          virDomainInfoPtr info)
+{
+    const char *flags;
+
+
+    if ((root == NULL) || (info == NULL))
+        return (-1);
+
+    info->memory = sexpr_u64(root, "domain/memory") << 10;
+    info->maxMem = sexpr_u64(root, "domain/maxmem") << 10;
+    flags = sexpr_node(root, "domain/state");
+
+    if (flags) {
+        if (strchr(flags, 'c'))
+            info->state = VIR_DOMAIN_CRASHED;
+        else if (strchr(flags, 's'))
+            info->state = VIR_DOMAIN_SHUTOFF;
+        else if (strchr(flags, 'd'))
+            info->state = VIR_DOMAIN_SHUTDOWN;
+        else if (strchr(flags, 'p'))
+            info->state = VIR_DOMAIN_PAUSED;
+        else if (strchr(flags, 'b'))
+            info->state = VIR_DOMAIN_BLOCKED;
+        else if (strchr(flags, 'r'))
+            info->state = VIR_DOMAIN_RUNNING;
+    } else {
+        /* Inactive domains don't have a state reported, so
+           mark them SHUTOFF, rather than NOSTATE */
+        if (domain->id < 0)
+            info->state = VIR_DOMAIN_SHUTOFF;
+        else
+            info->state = VIR_DOMAIN_NOSTATE;
+    }
+    info->cpuTime = sexpr_float(root, "domain/cpu_time") * 1000000000;
+    info->nrVirtCpu = sexpr_int(root, "domain/vcpus");
+    return (0);
+}
+
+/**
+ * sexpr_to_xend_node_info:
+ * @root: an S-Expression describing a domain
+ * @info: a info data structure to fill up
+ *
+ * Internal routine filling up the info structure with the values from
+ * the node root provided.
+ *
+ * Returns 0 in case of success, -1 in case of error
+ */
+static int
+sexpr_to_xend_node_info(const struct sexpr *root, virNodeInfoPtr info)
+{
+    const char *machine;
+
+
+    if ((root == NULL) || (info == NULL))
+        return (-1);
+
+    machine = sexpr_node(root, "node/machine");
+    if (machine == NULL) {
+        info->model[0] = 0;
+    } else {
+        snprintf(&info->model[0], sizeof(info->model) - 1, "%s", machine);
+        info->model[sizeof(info->model) - 1] = 0;
+    }
+    info->memory = (unsigned long) sexpr_u64(root, "node/total_memory") << 10;
+
+    info->cpus = sexpr_int(root, "node/nr_cpus");
+    info->mhz = sexpr_int(root, "node/cpu_mhz");
+    info->nodes = sexpr_int(root, "node/nr_nodes");
+    info->sockets = sexpr_int(root, "node/sockets_per_node");
+    info->cores = sexpr_int(root, "node/cores_per_socket");
+    info->threads = sexpr_int(root, "node/threads_per_core");
+
+    /* Xen 3.2.0 replaces sockets_per_node with 'nr_cpus'.
+     * Old Xen calculated sockets_per_node using its internal
+     * nr_cpus / (nodes*cores*threads), so fake it ourselves
+     * in the same way
+     */
+    if (info->sockets == 0) {
+        int nr_cpus = sexpr_int(root, "node/nr_cpus");
+        int procs = info->nodes * info->cores * info->threads;
+        if (procs == 0) /* Sanity check in case of Xen bugs in futures..*/
+            return (-1);
+        info->sockets = nr_cpus / procs;
+        /* Should already be fine, but for further sanity make
+         * sure we have at least one socket
+         */
+        if (info->sockets == 0)
+            info->sockets = 1;
+    }
+    return (0);
+}
+
+
+/**
+ * sexpr_to_xend_topology
+ * @root: an S-Expression describing a node
+ * @caps: capability info
+ *
+ * Internal routine populating capability info with
+ * NUMA node mapping details
+ *
+ * Does nothing when the system doesn't support NUMA (not an error).
+ *
+ * Returns 0 in case of success, -1 in case of error
+ */
+static int
+sexpr_to_xend_topology(virConnectPtr conn,
+                       const struct sexpr *root,
+                       virCapsPtr caps)
+{
+    const char *nodeToCpu;
+    const char *cur;
+    char *cpuset = NULL;
+    int *cpuNums = NULL;
+    int cell, cpu, nb_cpus;
+    int n = 0;
+    int numCpus;
+
+    nodeToCpu = sexpr_node(root, "node/node_to_cpu");
+    if (nodeToCpu == NULL)
+        return 0;               /* no NUMA support */
+
+    numCpus = sexpr_int(root, "node/nr_cpus");
+
+
+    if (VIR_ALLOC_N(cpuset, numCpus) < 0)
+        goto memory_error;
+    if (VIR_ALLOC_N(cpuNums, numCpus) < 0)
+        goto memory_error;
+
+    cur = nodeToCpu;
+    while (*cur != 0) {
+        /*
+         * Find the next NUMA cell described in the xend output
+         */
+        cur = strstr(cur, "node");
+        if (cur == NULL)
+            break;
+        cur += 4;
+        cell = virParseNumber(&cur);
+        if (cell < 0)
+            goto parse_error;
+        virSkipSpaces(&cur);
+        if (*cur != ':')
+            goto parse_error;
+        cur++;
+        virSkipSpaces(&cur);
+        if (STRPREFIX(cur, "no cpus")) {
+            nb_cpus = 0;
+            for (cpu = 0; cpu < numCpus; cpu++)
+                cpuset[cpu] = 0;
+        } else {
+            nb_cpus = virDomainCpuSetParse(conn, &cur, 'n', cpuset, numCpus);
+            if (nb_cpus < 0)
+                goto error;
+        }
+
+        for (n = 0, cpu = 0; cpu < numCpus; cpu++)
+            if (cpuset[cpu] == 1)
+                cpuNums[n++] = cpu;
+
+        if (virCapabilitiesAddHostNUMACell(caps,
+                                           cell,
+                                           nb_cpus,
+                                           cpuNums) < 0)
+            goto memory_error;
+    }
+    VIR_FREE(cpuNums);
+    VIR_FREE(cpuset);
+    return (0);
+
+  parse_error:
+    virXendError(conn, VIR_ERR_XEN_CALL, "%s", _("topology syntax error"));
+  error:
+    VIR_FREE(cpuNums);
+    VIR_FREE(cpuset);
+
+    return (-1);
+
+  memory_error:
+    VIR_FREE(cpuNums);
+    VIR_FREE(cpuset);
+    virReportOOMError(conn);
+    return (-1);
+}
+
+
+#ifndef PROXY
+/**
+ * sexpr_to_domain:
+ * @conn: an existing virtual connection block
+ * @root: an S-Expression describing a domain
+ *
+ * Internal routine returning the associated virDomainPtr for this domain
+ *
+ * Returns the domain pointer or NULL in case of error.
+ */
+static virDomainPtr
+sexpr_to_domain(virConnectPtr conn, const struct sexpr *root)
+{
+    virDomainPtr ret = NULL;
+    unsigned char uuid[VIR_UUID_BUFLEN];
+    const char *name;
+    const char *tmp;
+    xenUnifiedPrivatePtr priv;
+
+    if ((conn == NULL) || (root == NULL))
+        return(NULL);
+
+    priv = (xenUnifiedPrivatePtr) conn->privateData;
+
+    if (sexpr_uuid(uuid, root, "domain/uuid") < 0)
+        goto error;
+    name = sexpr_node(root, "domain/name");
+    if (name == NULL)
+        goto error;
+
+    ret = virGetDomain(conn, name, uuid);
+    if (ret == NULL) return NULL;
+
+    tmp = sexpr_node(root, "domain/domid");
+    /* New 3.0.4 XenD will not report a domid for inactive domains,
+     * so only error out for old XenD
+     */
+    if (!tmp && priv->xendConfigVersion < 3)
+        goto error;
+
+    if (tmp)
+        ret->id = sexpr_int(root, "domain/domid");
+    else
+        ret->id = -1; /* An inactive domain */
+
+    return (ret);
+
+error:
+    virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                 "%s", _("failed to parse Xend domain information"));
+    if (ret != NULL)
+        virUnrefDomain(ret);
+    return(NULL);
+}
+#endif /* !PROXY */
+
+/*****************************************************************
+ ******
+ ******
+ ******
+ ******
+             Refactored
+ ******
+ ******
+ ******
+ ******
+ *****************************************************************/
+#ifndef PROXY
+/**
+ * xenDaemonOpen:
+ * @conn: an existing virtual connection block
+ * @name: optional argument to select a connection type
+ * @flags: combination of virDrvOpenFlag(s)
+ *
+ * Creates a localhost Xen Daemon connection
+ *
+ * Returns 0 in case of success, -1 in case of error.
+ */
+virDrvOpenStatus
+xenDaemonOpen(virConnectPtr conn,
+              virConnectAuthPtr auth ATTRIBUTE_UNUSED,
+              int flags ATTRIBUTE_UNUSED)
+{
+    char *port = NULL;
+    int ret = VIR_DRV_OPEN_ERROR;
+
+    /* Switch on the scheme, which we expect to be NULL (file),
+     * "http" or "xen".
+     */
+    if (conn->uri->scheme == NULL) {
+        /* It should be a file access */
+        if (conn->uri->path == NULL) {
+            virXendError(NULL, VIR_ERR_NO_CONNECT, __FUNCTION__);
+            goto failed;
+        }
+        if (xenDaemonOpen_unix(conn, conn->uri->path) < 0 ||
+            xend_detect_config_version(conn) == -1)
+            goto failed;
+    }
+    else if (STRCASEEQ (conn->uri->scheme, "xen")) {
+        /*
+         * try first to open the unix socket
+         */
+        if (xenDaemonOpen_unix(conn, "/var/lib/xend/xend-socket") == 0 &&
+            xend_detect_config_version(conn) != -1)
+            goto done;
+
+        /*
+         * try though http on port 8000
+         */
+        if (xenDaemonOpen_tcp(conn, "localhost", "8000") < 0 ||
+            xend_detect_config_version(conn) == -1)
+            goto failed;
+    } else if (STRCASEEQ (conn->uri->scheme, "http")) {
+        if (conn->uri->port &&
+            virAsprintf(&port, "%d", conn->uri->port) == -1)
+            goto failed;
+
+        if (xenDaemonOpen_tcp(conn,
+                              conn->uri->server ? conn->uri->server : "localhost",
+                              port ? port : "8000") < 0 ||
+            xend_detect_config_version(conn) == -1)
+            goto failed;
+    } else {
+        virXendError(NULL, VIR_ERR_NO_CONNECT, __FUNCTION__);
+        goto failed;
+    }
+
+ done:
+    ret = VIR_DRV_OPEN_SUCCESS;
+
+failed:
+    VIR_FREE(port);
+    return ret;
+}
+
+
+/**
+ * xenDaemonClose:
+ * @conn: an existing virtual connection block
+ *
+ * This method should be called when a connection to xend instance
+ * initialized with xenDaemonOpen is no longer needed
+ * to free the associated resources.
+ *
+ * Returns 0 in case of success, -1 in case of error
+ */
+int
+xenDaemonClose(virConnectPtr conn ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+/**
+ * xenDaemonDomainSuspend:
+ * @domain: pointer to the Domain block
+ *
+ * Pause the domain, the domain is not scheduled anymore though its resources
+ * are preserved. Use xenDaemonDomainResume() to resume execution.
+ *
+ * Returns 0 in case of success, -1 (with errno) in case of error.
+ */
+int
+xenDaemonDomainSuspend(virDomainPtr domain)
+{
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
+        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                     __FUNCTION__);
+        return(-1);
+    }
+
+    if (domain->id < 0) {
+        virXendError(domain->conn, VIR_ERR_OPERATION_INVALID,
+                     _("Domain %s isn't running."), domain->name);
+        return(-1);
+    }
+
+    return xend_op(domain->conn, domain->name, "op", "pause", NULL);
+}
+
+/**
+ * xenDaemonDomainResume:
+ * @xend: pointer to the Xem Daemon block
+ * @name: name for the domain
+ *
+ * Resume the domain after xenDaemonDomainSuspend() has been called
+ *
+ * Returns 0 in case of success, -1 (with errno) in case of error.
+ */
+int
+xenDaemonDomainResume(virDomainPtr domain)
+{
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
+        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                     __FUNCTION__);
+        return(-1);
+    }
+
+    if (domain->id < 0) {
+        virXendError(domain->conn, VIR_ERR_OPERATION_INVALID,
+                     _("Domain %s isn't running."), domain->name);
+        return(-1);
+    }
+
+    return xend_op(domain->conn, domain->name, "op", "unpause", NULL);
+}
+
+/**
+ * xenDaemonDomainShutdown:
+ * @domain: pointer to the Domain block
+ *
+ * Shutdown the domain, the OS is requested to properly shutdown
+ * and the domain may ignore it.  It will return immediately
+ * after queuing the request.
+ *
+ * Returns 0 in case of success, -1 (with errno) in case of error.
+ */
+int
+xenDaemonDomainShutdown(virDomainPtr domain)
+{
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
+        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                     __FUNCTION__);
+        return(-1);
+    }
+
+    if (domain->id < 0) {
+        virXendError(domain->conn, VIR_ERR_OPERATION_INVALID,
+                     _("Domain %s isn't running."), domain->name);
+        return(-1);
+    }
+
+    return xend_op(domain->conn, domain->name, "op", "shutdown", "reason", "poweroff", NULL);
+}
+
+/**
+ * xenDaemonDomainReboot:
+ * @domain: pointer to the Domain block
+ * @flags: extra flags for the reboot operation, not used yet
+ *
+ * Reboot the domain, the OS is requested to properly shutdown
+ * and restart but the domain may ignore it.  It will return immediately
+ * after queuing the request.
+ *
+ * Returns 0 in case of success, -1 (with errno) in case of error.
+ */
+int
+xenDaemonDomainReboot(virDomainPtr domain, unsigned int flags ATTRIBUTE_UNUSED)
+{
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
+        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                     __FUNCTION__);
+        return(-1);
+    }
+
+    if (domain->id < 0) {
+        virXendError(domain->conn, VIR_ERR_OPERATION_INVALID,
+                     _("Domain %s isn't running."), domain->name);
+        return(-1);
+    }
+
+    return xend_op(domain->conn, domain->name, "op", "shutdown", "reason", "reboot", NULL);
+}
+
+/**
+ * xenDaemonDomainDestroy:
+ * @domain: pointer to the Domain block
+ *
+ * Abruptly halt the domain, the OS is not properly shutdown and the
+ * resources allocated for the domain are immediately freed, mounted
+ * filesystems will be marked as uncleanly shutdown.
+ * After calling this function, the domain's status will change to
+ * dying and will go away completely once all of the resources have been
+ * unmapped (usually from the backend devices).
+ *
+ * Returns 0 in case of success, -1 (with errno) in case of error.
+ */
+int
+xenDaemonDomainDestroy(virDomainPtr domain)
+{
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
+        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                     __FUNCTION__);
+        return(-1);
+    }
+
+    if (domain->id < 0) {
+        virXendError(domain->conn, VIR_ERR_OPERATION_INVALID,
+                     _("Domain %s isn't running."), domain->name);
+        return(-1);
+    }
+
+    return xend_op(domain->conn, domain->name, "op", "destroy", NULL);
+}
+
+/**
+ * xenDaemonDomainGetOSType:
+ * @domain: a domain object
+ *
+ * Get the type of domain operation system.
+ *
+ * Returns the new string or NULL in case of error, the string must be
+ *         freed by the caller.
+ */
+static char *
+xenDaemonDomainGetOSType(virDomainPtr domain)
+{
+    char *type;
+    struct sexpr *root;
+    xenUnifiedPrivatePtr priv;
+
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
+        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                     __FUNCTION__);
+        return(NULL);
+    }
+
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+
+    if (domain->id < 0 && priv->xendConfigVersion < 3)
+        return(NULL);
+
+    /* can we ask for a subset ? worth it ? */
+    root = sexpr_get(domain->conn, "/xend/domain/%s?detail=1", domain->name);
+    if (root == NULL)
+        return(NULL);
+
+    if (sexpr_lookup(root, "domain/image/hvm")) {
+        type = strdup("hvm");
+    } else {
+        type = strdup("linux");
+    }
+
+    sexpr_free(root);
+
+    return(type);
+}
+
+/**
+ * xenDaemonDomainSave:
+ * @domain: pointer to the Domain block
+ * @filename: path for the output file
+ *
+ * This method will suspend a domain and save its memory contents to
+ * a file on disk.  Use xenDaemonDomainRestore() to restore a domain after
+ * saving.
+ * Note that for remote Xen Daemon the file path will be interpreted in
+ * the remote host.
+ *
+ * Returns 0 in case of success, -1 (with errno) in case of error.
+ */
+int
+xenDaemonDomainSave(virDomainPtr domain, const char *filename)
+{
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL) ||
+        (filename == NULL)) {
+        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                     __FUNCTION__);
+        return(-1);
+    }
+
+    if (domain->id < 0) {
+        virXendError(domain->conn, VIR_ERR_OPERATION_INVALID,
+                     _("Domain %s isn't running."), domain->name);
+        return(-1);
+    }
+
+    /* We can't save the state of Domain-0, that would mean stopping it too */
+    if (domain->id == 0) {
+        return(-1);
+    }
+
+    return xend_op(domain->conn, domain->name, "op", "save", "file", filename, NULL);
+}
+
+/**
+ * xenDaemonDomainCoreDump:
+ * @domain: pointer to the Domain block
+ * @filename: path for the output file
+ * @flags: extra flags, currently unused
+ *
+ * This method will dump the core of a domain on a given file for analysis.
+ * Note that for remote Xen Daemon the file path will be interpreted in
+ * the remote host.
+ *
+ * Returns 0 in case of success, -1 in case of error.
+ */
+static int
+xenDaemonDomainCoreDump(virDomainPtr domain, const char *filename,
+                        int flags ATTRIBUTE_UNUSED)
+{
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL) ||
+        (filename == NULL)) {
+        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                     __FUNCTION__);
+        return(-1);
+    }
+
+    if (domain->id < 0) {
+        virXendError(domain->conn, VIR_ERR_OPERATION_INVALID,
+                     _("Domain %s isn't running."), domain->name);
+        return(-1);
+    }
+
+    return xend_op(domain->conn, domain->name, "op", "dump", "file", filename,
+                   "live", "0", "crash", "0", NULL);
+}
+
+/**
+ * xenDaemonDomainRestore:
+ * @conn: pointer to the Xem Daemon block
+ * @filename: path for the output file
+ *
+ * This method will restore a domain saved to disk by xenDaemonDomainSave().
+ * Note that for remote Xen Daemon the file path will be interpreted in
+ * the remote host.
+ *
+ * Returns 0 in case of success, -1 (with errno) in case of error.
+ */
+int
+xenDaemonDomainRestore(virConnectPtr conn, const char *filename)
+{
+    if ((conn == NULL) || (filename == NULL)) {
+        /* this should be caught at the interface but ... */
+        virXendError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (-1);
+    }
+    return xend_op(conn, "", "op", "restore", "file", filename, NULL);
+}
+#endif /* !PROXY */
+
+/**
+ * xenDaemonDomainGetMaxMemory:
+ * @domain: pointer to the domain block
+ *
+ * Ask the Xen Daemon for the maximum memory allowed for a domain
+ *
+ * Returns the memory size in kilobytes or 0 in case of error.
+ */
+unsigned long
+xenDaemonDomainGetMaxMemory(virDomainPtr domain)
+{
+    unsigned long ret = 0;
+    struct sexpr *root;
+    xenUnifiedPrivatePtr priv;
+
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
+        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                     __FUNCTION__);
+        return(-1);
+    }
+
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+
+    if (domain->id < 0 && priv->xendConfigVersion < 3)
+        return(-1);
+
+    /* can we ask for a subset ? worth it ? */
+    root = sexpr_get(domain->conn, "/xend/domain/%s?detail=1", domain->name);
+    if (root == NULL)
+        return(0);
+
+    ret = (unsigned long) sexpr_u64(root, "domain/memory") << 10;
+    sexpr_free(root);
+
+    return(ret);
+}
+
+#ifndef PROXY
+/**
+ * xenDaemonDomainSetMaxMemory:
+ * @domain: pointer to the Domain block
+ * @memory: The maximum memory in kilobytes
+ *
+ * This method will set the maximum amount of memory that can be allocated to
+ * a domain.  Please note that a domain is able to allocate up to this amount
+ * on its own.
+ *
+ * Returns 0 for success; -1 (with errno) on error
+ */
+int
+xenDaemonDomainSetMaxMemory(virDomainPtr domain, unsigned long memory)
+{
+    char buf[1024];
+    xenUnifiedPrivatePtr priv;
+
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
+        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                     __FUNCTION__);
+        return(-1);
+    }
+
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+
+    if (domain->id < 0 && priv->xendConfigVersion < 3)
+        return(-1);
+
+    snprintf(buf, sizeof(buf), "%lu", memory >> 10);
+    return xend_op(domain->conn, domain->name, "op", "maxmem_set", "memory",
+                   buf, NULL);
+}
+
+/**
+ * xenDaemonDomainSetMemory:
+ * @domain: pointer to the Domain block
+ * @memory: The target memory in kilobytes
+ *
+ * This method will set a target memory allocation for a given domain and
+ * request that the guest meet this target.  The guest may or may not actually
+ * achieve this target.  When this function returns, it does not signify that
+ * the domain has actually reached that target.
+ *
+ * Memory for a domain can only be allocated up to the maximum memory setting.
+ * There is no safe guard for allocations that are too small so be careful
+ * when using this function to reduce a domain's memory usage.
+ *
+ * Returns 0 for success; -1 (with errno) on error
+ */
+int
+xenDaemonDomainSetMemory(virDomainPtr domain, unsigned long memory)
+{
+    char buf[1024];
+    xenUnifiedPrivatePtr priv;
+
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
+        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                     __FUNCTION__);
+        return(-1);
+    }
+
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+
+    if (domain->id < 0 && priv->xendConfigVersion < 3)
+        return(-1);
+
+    snprintf(buf, sizeof(buf), "%lu", memory >> 10);
+    return xend_op(domain->conn, domain->name, "op", "mem_target_set",
+                   "target", buf, NULL);
+}
+
+#endif /* ! PROXY */
+
+virDomainDefPtr
+xenDaemonDomainFetch(virConnectPtr conn,
+                     int domid,
+                     const char *name,
+                     const char *cpus)
+{
+    struct sexpr *root;
+    xenUnifiedPrivatePtr priv;
+    virDomainDefPtr def;
+
+    if (name)
+        root = sexpr_get(conn, "/xend/domain/%s?detail=1", name);
+    else
+        root = sexpr_get(conn, "/xend/domain/%d?detail=1", domid);
+    if (root == NULL) {
+        virXendError (conn, VIR_ERR_XEN_CALL,
+                      "%s", _("xenDaemonDomainFetch failed to"
+                        " find this domain"));
+        return (NULL);
+    }
+
+    priv = (xenUnifiedPrivatePtr) conn->privateData;
+
+    if (!(def = xenDaemonParseSxpr(conn,
+                                   root,
+                                   priv->xendConfigVersion,
+                                   cpus)))
+        goto cleanup;
+
+cleanup:
+    sexpr_free(root);
+
+    return (def);
+}
+
+
+#ifndef PROXY
+/**
+ * xenDaemonDomainDumpXML:
+ * @domain: a domain object
+ * @flags: potential dump flags
+ * @cpus: list of cpu the domain is pinned to.
+ *
+ * Provide an XML description of the domain.
+ *
+ * Returns a 0 terminated UTF-8 encoded XML instance, or NULL in case of error.
+ *         the caller must free() the returned value.
+ */
+char *
+xenDaemonDomainDumpXML(virDomainPtr domain, int flags, const char *cpus)
+{
+    xenUnifiedPrivatePtr priv;
+    virDomainDefPtr def;
+    char *xml;
+
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
+        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                     __FUNCTION__);
+        return(NULL);
+    }
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+
+    if (domain->id < 0 && priv->xendConfigVersion < 3) {
+        // fall-through to the next driver to handle
+        return(NULL);
+    }
+
+    if (!(def = xenDaemonDomainFetch(domain->conn,
+                                     domain->id,
+                                     domain->name,
+                                     cpus)))
+        return(NULL);
+
+    xml = virDomainDefFormat(domain->conn, def, flags);
+
+    virDomainDefFree(def);
+
+    return xml;
+}
+#endif /* !PROXY */
+
+/**
+ * xenDaemonDomainGetInfo:
+ * @domain: a domain object
+ * @info: pointer to a virDomainInfo structure allocated by the user
+ *
+ * This method looks up information about a domain and update the
+ * information block provided.
+ *
+ * Returns 0 in case of success, -1 in case of error
+ */
+int
+xenDaemonDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
+{
+    struct sexpr *root;
+    int ret;
+    xenUnifiedPrivatePtr priv;
+
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL) ||
+        (info == NULL)) {
+        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                     __FUNCTION__);
+        return(-1);
+    }
+
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+
+    if (domain->id < 0 && priv->xendConfigVersion < 3)
+        return(-1);
+
+    root = sexpr_get(domain->conn, "/xend/domain/%s?detail=1", domain->name);
+    if (root == NULL)
+        return (-1);
+
+    ret = sexpr_to_xend_domain_info(domain, root, info);
+    sexpr_free(root);
+    return (ret);
+}
+
+#ifndef PROXY
+/**
+ * xenDaemonLookupByName:
+ * @conn: A xend instance
+ * @name: The name of the domain
+ *
+ * This method looks up information about a domain and returns
+ * it in the form of a struct xend_domain.  This should be
+ * free()'d when no longer needed.
+ *
+ * Returns domain info on success; NULL (with errno) on error
+ */
+virDomainPtr
+xenDaemonLookupByName(virConnectPtr conn, const char *domname)
+{
+    struct sexpr *root;
+    virDomainPtr ret = NULL;
+
+    if ((conn == NULL) || (domname == NULL)) {
+        virXendError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return(NULL);
+    }
+
+    root = sexpr_get(conn, "/xend/domain/%s?detail=1", domname);
+    if (root == NULL)
+        goto error;
+
+    ret = sexpr_to_domain(conn, root);
+
+error:
+    sexpr_free(root);
+    return(ret);
+}
+#endif /* ! PROXY */
+
+/**
+ * xenDaemonNodeGetInfo:
+ * @conn: pointer to the Xen Daemon block
+ * @info: pointer to a virNodeInfo structure allocated by the user
+ *
+ * Extract hardware information about the node.
+ *
+ * Returns 0 in case of success and -1 in case of failure.
+ */
+int
+xenDaemonNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info) {
+    int ret = -1;
+    struct sexpr *root;
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virXendError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (-1);
+    }
+    if (info == NULL) {
+        virXendError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (-1);
+    }
+
+    root = sexpr_get(conn, "/xend/node/");
+    if (root == NULL)
+        return (-1);
+
+    ret = sexpr_to_xend_node_info(root, info);
+    sexpr_free(root);
+    return (ret);
+}
+
+/**
+ * xenDaemonNodeGetTopology:
+ * @conn: pointer to the Xen Daemon block
+ * @caps: capabilities info
+ *
+ * This method retrieves a node's topology information.
+ *
+ * Returns -1 in case of error, 0 otherwise.
+ */
+int
+xenDaemonNodeGetTopology(virConnectPtr conn,
+                         virCapsPtr caps) {
+    int ret = -1;
+    struct sexpr *root;
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virXendError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (-1);
+    }
+
+    if (caps == NULL) {
+        virXendError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (-1);
+    }
+
+    root = sexpr_get(conn, "/xend/node/");
+    if (root == NULL) {
+        return (-1);
+    }
+
+    ret = sexpr_to_xend_topology(conn, root, caps);
+    sexpr_free(root);
+    return (ret);
+}
+
+/**
+ * xenDaemonGetVersion:
+ * @conn: pointer to the Xen Daemon block
+ * @hvVer: return value for the version of the running hypervisor (OUT)
+ *
+ * Get the version level of the Hypervisor running.
+ *
+ * Returns -1 in case of error, 0 otherwise. if the version can't be
+ *    extracted by lack of capacities returns 0 and @hvVer is 0, otherwise
+ *    @hvVer value is major * 1,000,000 + minor * 1,000 + release
+ */
+int
+xenDaemonGetVersion(virConnectPtr conn, unsigned long *hvVer)
+{
+    struct sexpr *root;
+    int major, minor;
+    unsigned long version;
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virXendError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (-1);
+    }
+    if (hvVer == NULL) {
+        virXendError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (-1);
+    }
+    root = sexpr_get(conn, "/xend/node/");
+    if (root == NULL)
+        return(-1);
+
+    major = sexpr_int(root, "node/xen_major");
+    minor = sexpr_int(root, "node/xen_minor");
+    sexpr_free(root);
+    version = major * 1000000 + minor * 1000;
+    *hvVer = version;
+    return(0);
+}
+
+#ifndef PROXY
+/**
+ * xenDaemonListDomains:
+ * @conn: pointer to the hypervisor connection
+ * @ids: array to collect the list of IDs of active domains
+ * @maxids: size of @ids
+ *
+ * Collect the list of active domains, and store their ID in @maxids
+ * TODO: this is quite expensive at the moment since there isn't one
+ *       xend RPC providing both name and id for all domains.
+ *
+ * Returns the number of domain found or -1 in case of error
+ */
+int
+xenDaemonListDomains(virConnectPtr conn, int *ids, int maxids)
+{
+    struct sexpr *root = NULL;
+    int ret = -1;
+    struct sexpr *_for_i, *node;
+    long id;
+
+    if (maxids == 0)
+        return(0);
+
+    if ((ids == NULL) || (maxids < 0))
+        goto error;
+    root = sexpr_get(conn, "/xend/domain");
+    if (root == NULL)
+        goto error;
+
+    ret = 0;
+
+    for (_for_i = root, node = root->u.s.car; _for_i->kind == SEXPR_CONS;
+         _for_i = _for_i->u.s.cdr, node = _for_i->u.s.car) {
+        if (node->kind != SEXPR_VALUE)
+            continue;
+        id = xenDaemonDomainLookupByName_ids(conn, node->u.value, NULL);
+        if (id >= 0)
+            ids[ret++] = (int) id;
+        if (ret >= maxids)
+            break;
+    }
+
+error:
+    sexpr_free(root);
+    return(ret);
+}
+
+/**
+ * xenDaemonNumOfDomains:
+ * @conn: pointer to the hypervisor connection
+ *
+ * Provides the number of active domains.
+ *
+ * Returns the number of domain found or -1 in case of error
+ */
+static int
+xenDaemonNumOfDomains(virConnectPtr conn)
+{
+    struct sexpr *root = NULL;
+    int ret = -1;
+    struct sexpr *_for_i, *node;
+
+    root = sexpr_get(conn, "/xend/domain");
+    if (root == NULL)
+        goto error;
+
+    ret = 0;
+
+    for (_for_i = root, node = root->u.s.car; _for_i->kind == SEXPR_CONS;
+         _for_i = _for_i->u.s.cdr, node = _for_i->u.s.car) {
+        if (node->kind != SEXPR_VALUE)
+            continue;
+        ret++;
+    }
+
+error:
+    sexpr_free(root);
+    return(ret);
+}
+#endif /* ! PROXY */
+
+#ifndef PROXY
+/**
+ * xenDaemonLookupByID:
+ * @conn: pointer to the hypervisor connection
+ * @id: the domain ID number
+ *
+ * Try to find a domain based on the hypervisor ID number
+ *
+ * Returns a new domain object or NULL in case of failure
+ */
+virDomainPtr
+xenDaemonLookupByID(virConnectPtr conn, int id) {
+    char *name = NULL;
+    unsigned char uuid[VIR_UUID_BUFLEN];
+    virDomainPtr ret;
+
+    if (xenDaemonDomainLookupByID(conn, id, &name, uuid) < 0) {
+        goto error;
+    }
+
+    ret = virGetDomain(conn, name, uuid);
+    if (ret == NULL) goto error;
+
+    ret->id = id;
+    VIR_FREE(name);
+    return (ret);
+
+ error:
+    VIR_FREE(name);
+    return (NULL);
+}
+
+/**
+ * xenDaemonDomainSetVcpus:
+ * @domain: pointer to domain object
+ * @nvcpus: the new number of virtual CPUs for this domain
+ *
+ * Dynamically change the number of virtual CPUs used by the domain.
+ *
+ * Returns 0 for success; -1 (with errno) on error
+ */
+int
+xenDaemonDomainSetVcpus(virDomainPtr domain, unsigned int vcpus)
+{
+    char buf[VIR_UUID_BUFLEN];
+    xenUnifiedPrivatePtr priv;
+
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)
+     || (vcpus < 1)) {
+        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                     __FUNCTION__);
+        return (-1);
+    }
+
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+
+    if (domain->id < 0 && priv->xendConfigVersion < 3)
+        return(-1);
+
+    snprintf(buf, sizeof(buf), "%d", vcpus);
+    return(xend_op(domain->conn, domain->name, "op", "set_vcpus", "vcpus",
+                   buf, NULL));
+}
+
+/**
+ * xenDaemonDomainPinCpu:
+ * @domain: pointer to domain object
+ * @vcpu: virtual CPU number
+ * @cpumap: pointer to a bit map of real CPUs (in 8-bit bytes)
+ * @maplen: length of cpumap in bytes
+ *
+ * Dynamically change the real CPUs which can be allocated to a virtual CPU.
+ * NOTE: The XenD cpu affinity map format changed from "[0,1,2]" to
+ *       "0,1,2"
+ *       the XenD cpu affinity works only after cset 19579.
+ *       there is no fine grained xend version detection possible, so we
+ *       use the old format for anything before version 3
+ *
+ * Returns 0 for success; -1 (with errno) on error
+ */
+int
+xenDaemonDomainPinVcpu(virDomainPtr domain, unsigned int vcpu,
+                     unsigned char *cpumap, int maplen)
+{
+    char buf[VIR_UUID_BUFLEN], mapstr[sizeof(cpumap_t) * 64];
+    int i, j;
+    xenUnifiedPrivatePtr priv;
+
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)
+     || (cpumap == NULL) || (maplen < 1) || (maplen > (int)sizeof(cpumap_t))) {
+        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                     __FUNCTION__);
+        return (-1);
+    }
+
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+    if (priv->xendConfigVersion < 3) {
+        mapstr[0] = '[';
+        mapstr[1] = 0;
+    } else {
+        mapstr[0] = 0;
+    }
+
+    /* from bit map, build character string of mapped CPU numbers */
+    for (i = 0; i < maplen; i++) for (j = 0; j < 8; j++)
+     if (cpumap[i] & (1 << j)) {
+        snprintf(buf, sizeof(buf), "%d,", (8 * i) + j);
+        strcat(mapstr, buf);
+    }
+    if (priv->xendConfigVersion < 3)
+        mapstr[strlen(mapstr) - 1] = ']';
+    else
+        mapstr[strlen(mapstr) - 1] = 0;
+
+    snprintf(buf, sizeof(buf), "%d", vcpu);
+    return(xend_op(domain->conn, domain->name, "op", "pincpu", "vcpu", buf,
+                  "cpumap", mapstr, NULL));
+}
+
+/**
+ * virDomainGetVcpus:
+ * @domain: pointer to domain object, or NULL for Domain0
+ * @info: pointer to an array of virVcpuInfo structures (OUT)
+ * @maxinfo: number of structures in info array
+ * @cpumaps: pointer to an bit map of real CPUs for all vcpus of this domain (in 8-bit bytes) (OUT)
+ *     If cpumaps is NULL, then no cpumap information is returned by the API.
+ *     It's assumed there is <maxinfo> cpumap in cpumaps array.
+ *     The memory allocated to cpumaps must be (maxinfo * maplen) bytes
+ *     (ie: calloc(maxinfo, maplen)).
+ *     One cpumap inside cpumaps has the format described in virDomainPinVcpu() API.
+ * @maplen: number of bytes in one cpumap, from 1 up to size of CPU map in
+ *     underlying virtualization system (Xen...).
+ *
+ * Extract information about virtual CPUs of domain, store it in info array
+ * and also in cpumaps if this pointer isn't NULL.
+ *
+ * Returns the number of info filled in case of success, -1 in case of failure.
+ */
+int
+xenDaemonDomainGetVcpus(virDomainPtr domain, virVcpuInfoPtr info, int maxinfo,
+                        unsigned char *cpumaps, int maplen)
+{
+    struct sexpr *root, *s, *t;
+    virVcpuInfoPtr ipt = info;
+    int nbinfo = 0, oln;
+    unsigned char *cpumap;
+    int vcpu, cpu;
+
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)
+        || (info == NULL) || (maxinfo < 1)) {
+        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                     __FUNCTION__);
+        return (-1);
+    }
+    if (cpumaps != NULL && maplen < 1) {
+        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                     __FUNCTION__);
+        return (-1);
+    }
+
+    root = sexpr_get(domain->conn, "/xend/domain/%s?op=vcpuinfo", domain->name);
+    if (root == NULL)
+        return (-1);
+
+    if (cpumaps != NULL)
+        memset(cpumaps, 0, maxinfo * maplen);
+
+    /* scan the sexprs from "(vcpu (number x)...)" and get parameter values */
+    for (s = root; s->kind == SEXPR_CONS; s = s->u.s.cdr) {
+        if ((s->u.s.car->kind == SEXPR_CONS) &&
+            (s->u.s.car->u.s.car->kind == SEXPR_VALUE) &&
+            STREQ(s->u.s.car->u.s.car->u.value, "vcpu")) {
+            t = s->u.s.car;
+            vcpu = ipt->number = sexpr_int(t, "vcpu/number");
+            if ((oln = sexpr_int(t, "vcpu/online")) != 0) {
+                if (sexpr_int(t, "vcpu/running")) ipt->state = VIR_VCPU_RUNNING;
+                if (sexpr_int(t, "vcpu/blocked")) ipt->state = VIR_VCPU_BLOCKED;
+            }
+            else
+                ipt->state = VIR_VCPU_OFFLINE;
+            ipt->cpuTime = sexpr_float(t, "vcpu/cpu_time") * 1000000000;
+            ipt->cpu = oln ? sexpr_int(t, "vcpu/cpu") : -1;
+
+            if (cpumaps != NULL && vcpu >= 0 && vcpu < maxinfo) {
+                cpumap = (unsigned char *) VIR_GET_CPUMAP(cpumaps, maplen, vcpu);
+                /*
+                 * get sexpr from "(cpumap (x y z...))" and convert values
+                 * to bitmap
+                 */
+                for (t = t->u.s.cdr; t->kind == SEXPR_CONS; t = t->u.s.cdr)
+                    if ((t->u.s.car->kind == SEXPR_CONS) &&
+                        (t->u.s.car->u.s.car->kind == SEXPR_VALUE) &&
+                        STREQ(t->u.s.car->u.s.car->u.value, "cpumap") &&
+                        (t->u.s.car->u.s.cdr->kind == SEXPR_CONS)) {
+                        for (t = t->u.s.car->u.s.cdr->u.s.car; t->kind == SEXPR_CONS; t = t->u.s.cdr)
+                            if (t->u.s.car->kind == SEXPR_VALUE
+                                && virStrToLong_i(t->u.s.car->u.value, NULL, 10, &cpu) == 0
+                                && cpu >= 0
+                                && (VIR_CPU_MAPLEN(cpu+1) <= maplen)) {
+                                VIR_USE_CPU(cpumap, cpu);
+                            }
+                        break;
+                    }
+            }
+
+            if (++nbinfo == maxinfo) break;
+            ipt++;
+        }
+    }
+    sexpr_free(root);
+    return(nbinfo);
+}
+
+/**
+ * xenDaemonLookupByUUID:
+ * @conn: pointer to the hypervisor connection
+ * @uuid: the raw UUID for the domain
+ *
+ * Try to lookup a domain on xend based on its UUID.
+ *
+ * Returns a new domain object or NULL in case of failure
+ */
+virDomainPtr
+xenDaemonLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
+{
+    virDomainPtr ret;
+    char *name = NULL;
+    int id = -1;
+    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
+
+    /* Old approach for xen <= 3.0.3 */
+    if (priv->xendConfigVersion < 3) {
+        char **names, **tmp;
+        unsigned char ident[VIR_UUID_BUFLEN];
+        names = xenDaemonListDomainsOld(conn);
+        tmp = names;
+
+        if (names == NULL) {
+            return (NULL);
+        }
+        while (*tmp != NULL) {
+            id = xenDaemonDomainLookupByName_ids(conn, *tmp, &ident[0]);
+            if (id >= 0) {
+                if (!memcmp(uuid, ident, VIR_UUID_BUFLEN)) {
+                    name = strdup(*tmp);
+                    break;
+                }
+            }
+            tmp++;
+        }
+        VIR_FREE(names);
+    } else { /* New approach for xen >= 3.0.4 */
+        char *domname = NULL;
+        char uuidstr[VIR_UUID_STRING_BUFLEN];
+        struct sexpr *root = NULL;
+
+        virUUIDFormat(uuid, uuidstr);
+        root = sexpr_get(conn, "/xend/domain/%s?detail=1", uuidstr);
+        if (root == NULL)
+            return (NULL);
+        domname = (char*)sexpr_node(root, "domain/name");
+        if (sexpr_node(root, "domain/domid")) /* only active domains have domid */
+            id = sexpr_int(root, "domain/domid");
+        else
+            id = -1;
+        name = domname ? strdup(domname) : NULL;
+        sexpr_free(root);
+    }
+
+    if (name == NULL)
+        return (NULL);
+
+    ret = virGetDomain(conn, name, uuid);
+    if (ret == NULL) goto cleanup;
+
+    ret->id = id;
+
+  cleanup:
+    VIR_FREE(name);
+    return (ret);
+}
+
+/**
+ * xenDaemonCreateXML:
+ * @conn: pointer to the hypervisor connection
+ * @xmlDesc: an XML description of the domain
+ * @flags: an optional set of virDomainFlags
+ *
+ * Launch a new Linux guest domain, based on an XML description similar
+ * to the one returned by virDomainGetXMLDesc()
+ * This function may requires privileged access to the hypervisor.
+ *
+ * Returns a new domain object or NULL in case of failure
+ */
+static virDomainPtr
+xenDaemonCreateXML(virConnectPtr conn, const char *xmlDesc,
+                     unsigned int flags ATTRIBUTE_UNUSED)
+{
+    int ret;
+    char *sexpr;
+    virDomainPtr dom = NULL;
+    xenUnifiedPrivatePtr priv;
+    virDomainDefPtr def;
+
+    priv = (xenUnifiedPrivatePtr) conn->privateData;
+
+    if (!(def = virDomainDefParseString(conn,
+                                        priv->caps,
+                                        xmlDesc,
+                                        VIR_DOMAIN_XML_INACTIVE)))
+        return (NULL);
+
+    if (!(sexpr = xenDaemonFormatSxpr(conn, def, priv->xendConfigVersion))) {
+        virDomainDefFree(def);
+        return (NULL);
+    }
+
+    ret = xenDaemonDomainCreateXML(conn, sexpr);
+    VIR_FREE(sexpr);
+    if (ret != 0) {
+        goto error;
+    }
+
+    /* This comes before wait_for_devices, to ensure that latter
+       cleanup will destroy the domain upon failure */
+    if (!(dom = virDomainLookupByName(conn, def->name)))
+        goto error;
+
+    if (xend_wait_for_devices(conn, def->name) < 0)
+        goto error;
+
+    if (xenDaemonDomainResume(dom) < 0)
+        goto error;
+
+    virDomainDefFree(def);
+    return (dom);
+
+  error:
+    /* Make sure we don't leave a still-born domain around */
+    if (dom != NULL) {
+        xenDaemonDomainDestroy(dom);
+        virUnrefDomain(dom);
+    }
+    virDomainDefFree(def);
+    return (NULL);
+}
+
+/**
+ * xenDaemonAttachDevice:
+ * @domain: pointer to domain object
+ * @xml: pointer to XML description of device
+ *
+ * Create a virtual device attachment to backend.
+ * XML description is translated into S-expression.
+ *
+ * Returns 0 in case of success, -1 in case of failure.
+ */
+static int
+xenDaemonAttachDevice(virDomainPtr domain, const char *xml)
+{
+    xenUnifiedPrivatePtr priv;
+    char *sexpr = NULL;
+    int ret = -1;
+    virDomainDeviceDefPtr dev = NULL;
+    virDomainDefPtr def = NULL;
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    char class[8], ref[80];
+
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
+        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                     __FUNCTION__);
+        return -1;
+    }
+
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+
+    /*
+     * on older Xen without the inactive guests management
+     * avoid doing this on inactive guests
+     */
+    if ((domain->id < 0) && (priv->xendConfigVersion < 3))
+        return -1;
+
+    if (!(def = xenDaemonDomainFetch(domain->conn,
+                                     domain->id,
+                                     domain->name,
+                                     NULL)))
+        goto cleanup;
+
+    if (!(dev = virDomainDeviceDefParse(domain->conn,
+                                        priv->caps,
+                                        def, xml, VIR_DOMAIN_XML_INACTIVE)))
+        goto cleanup;
+
+
+    switch (dev->type) {
+    case VIR_DOMAIN_DEVICE_DISK:
+        if (xenDaemonFormatSxprDisk(domain->conn,
+                                    dev->data.disk,
+                                    &buf,
+                                    STREQ(def->os.type, "hvm") ? 1 : 0,
+                                    priv->xendConfigVersion, 1) < 0)
+            goto cleanup;
+        break;
+
+    case VIR_DOMAIN_DEVICE_NET:
+        if (xenDaemonFormatSxprNet(domain->conn,
+                                   dev->data.net,
+                                   &buf,
+                                   STREQ(def->os.type, "hvm") ? 1 : 0,
+                                   priv->xendConfigVersion, 1) < 0)
+            goto cleanup;
+        break;
+
+    case VIR_DOMAIN_DEVICE_HOSTDEV:
+        if (dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+            dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
+            if (xenDaemonFormatSxprOnePCI(domain->conn,
+                                          dev->data.hostdev,
+                                          &buf) < 0)
+                goto cleanup;
+        } else {
+            virXendError(domain->conn, VIR_ERR_NO_SUPPORT, "%s",
+                         _("unsupported device type"));
+            goto cleanup;
+        }
+        break;
+
+    default:
+        virXendError(domain->conn, VIR_ERR_NO_SUPPORT, "%s",
+                     _("unsupported device type"));
+        goto cleanup;
+    }
+
+    sexpr = virBufferContentAndReset(&buf);
+
+    if (virDomainXMLDevID(domain, dev, class, ref, sizeof(ref))) {
+        /* device doesn't exist, define it */
+        ret = xend_op(domain->conn, domain->name, "op", "device_create",
+                      "config", sexpr, NULL);
+    }
+    else {
+        /* device exists, attempt to modify it */
+        ret = xend_op(domain->conn, domain->name, "op", "device_configure",
+                      "config", sexpr, "dev", ref, NULL);
+    }
+
+cleanup:
+    VIR_FREE(sexpr);
+    virDomainDefFree(def);
+    virDomainDeviceDefFree(dev);
+    return ret;
+}
+
+/**
+ * xenDaemonDetachDevice:
+ * @domain: pointer to domain object
+ * @xml: pointer to XML description of device
+ *
+ * Destroy a virtual device attachment to backend.
+ *
+ * Returns 0 in case of success, -1 in case of failure.
+ */
+static int
+xenDaemonDetachDevice(virDomainPtr domain, const char *xml)
+{
+    xenUnifiedPrivatePtr priv;
+    char class[8], ref[80];
+    virDomainDeviceDefPtr dev = NULL;
+    virDomainDefPtr def = NULL;
+    int ret = -1;
+
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
+        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                     __FUNCTION__);
+        return (-1);
+    }
+
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+
+    /*
+     * on older Xen without the inactive guests management
+     * avoid doing this on inactive guests
+     */
+    if ((domain->id < 0) && (priv->xendConfigVersion < 3))
+        return -1;
+
+    if (!(def = xenDaemonDomainFetch(domain->conn,
+                                     domain->id,
+                                     domain->name,
+                                     NULL)))
+        goto cleanup;
+
+    if (!(dev = virDomainDeviceDefParse(domain->conn,
+                                        priv->caps,
+                                        def, xml, VIR_DOMAIN_XML_INACTIVE)))
+        goto cleanup;
+
+    if (virDomainXMLDevID(domain, dev, class, ref, sizeof(ref)))
+        goto cleanup;
+
+    ret = xend_op(domain->conn, domain->name, "op", "device_destroy",
+                  "type", class, "dev", ref, "force", "0", "rm_cfg", "1", NULL);
+
+cleanup:
+    virDomainDefFree(def);
+    virDomainDeviceDefFree(dev);
+
+    return ret;
+}
+
+int
+xenDaemonDomainGetAutostart(virDomainPtr domain,
+                            int *autostart)
+{
+    struct sexpr *root;
+    const char *tmp;
+    xenUnifiedPrivatePtr priv;
+
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
+        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                     __FUNCTION__);
+        return (-1);
+    }
+
+    /* xm_internal.c (the support for defined domains from /etc/xen
+     * config files used by old Xen) will handle this.
+     */
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+    if (priv->xendConfigVersion < 3)
+        return(-1);
+
+    root = sexpr_get(domain->conn, "/xend/domain/%s?detail=1", domain->name);
+    if (root == NULL) {
+        virXendError (domain->conn, VIR_ERR_XEN_CALL,
+                      "%s", _("xenDaemonGetAutostart failed to find this domain"));
+        return (-1);
+    }
+
+    *autostart = 0;
+
+    tmp = sexpr_node(root, "domain/on_xend_start");
+    if (tmp && STREQ(tmp, "start")) {
+        *autostart = 1;
+    }
+
+    sexpr_free(root);
+    return 0;
+}
+
+int
+xenDaemonDomainSetAutostart(virDomainPtr domain,
+                            int autostart)
+{
+    struct sexpr *root, *autonode;
+    const char *autostr;
+    char buf[4096];
+    int ret = -1;
+    xenUnifiedPrivatePtr priv;
+
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
+        virXendError((domain ? domain->conn : NULL), VIR_ERR_INTERNAL_ERROR,
+                     __FUNCTION__);
+        return (-1);
+    }
+
+    /* xm_internal.c (the support for defined domains from /etc/xen
+     * config files used by old Xen) will handle this.
+     */
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+    if (priv->xendConfigVersion < 3)
+        return(-1);
+
+    root = sexpr_get(domain->conn, "/xend/domain/%s?detail=1", domain->name);
+    if (root == NULL) {
+        virXendError (domain->conn, VIR_ERR_XEN_CALL,
+                      "%s", _("xenDaemonSetAutostart failed to find this domain"));
+        return (-1);
+    }
+
+    autostr = sexpr_node(root, "domain/on_xend_start");
+    if (autostr) {
+        if (!STREQ(autostr, "ignore") && !STREQ(autostr, "start")) {
+            virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR,
+                         "%s", _("unexpected value from on_xend_start"));
+            goto error;
+        }
+
+        // Change the autostart value in place, then define the new sexpr
+        autonode = sexpr_lookup(root, "domain/on_xend_start");
+        VIR_FREE(autonode->u.s.car->u.value);
+        autonode->u.s.car->u.value = (autostart ? strdup("start")
+                                                : strdup("ignore"));
+        if (!(autonode->u.s.car->u.value)) {
+            virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR,
+                         "%s", _("no memory"));
+            goto error;
+        }
+
+        if (sexpr2string(root, buf, sizeof(buf)) == 0) {
+            virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR,
+                         "%s", _("sexpr2string failed"));
+            goto error;
+        }
+        if (xend_op(domain->conn, "", "op", "new", "config", buf, NULL) != 0) {
+            virXendError(domain->conn, VIR_ERR_XEN_CALL,
+                         "%s", _("Failed to redefine sexpr"));
+            goto error;
+        }
+    } else {
+        virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR,
+                     "%s", _("on_xend_start not present in sexpr"));
+        goto error;
+    }
+
+    ret = 0;
+  error:
+    sexpr_free(root);
+    return ret;
+}
+
+int
+xenDaemonDomainMigratePrepare (virConnectPtr dconn,
+                               char **cookie ATTRIBUTE_UNUSED,
+                               int *cookielen ATTRIBUTE_UNUSED,
+                               const char *uri_in,
+                               char **uri_out,
+                               unsigned long flags ATTRIBUTE_UNUSED,
+                               const char *dname ATTRIBUTE_UNUSED,
+                               unsigned long resource ATTRIBUTE_UNUSED)
+{
+    int r;
+    char hostname [HOST_NAME_MAX+1];
+
+    /* If uri_in is NULL, get the current hostname as a best guess
+     * of how the source host should connect to us.  Note that caller
+     * deallocates this string.
+     */
+    if (uri_in == NULL) {
+        r = gethostname (hostname, HOST_NAME_MAX+1);
+        if (r == -1) {
+            virReportSystemError(dconn, errno,
+                                 _("unable to resolve name %s"), hostname);
+            return -1;
+        }
+        *uri_out = strdup (hostname);
+        if (*uri_out == NULL) {
+            virReportOOMError(dconn);
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+int
+xenDaemonDomainMigratePerform (virDomainPtr domain,
+                               const char *cookie ATTRIBUTE_UNUSED,
+                               int cookielen ATTRIBUTE_UNUSED,
+                               const char *uri,
+                               unsigned long flags,
+                               const char *dname,
+                               unsigned long bandwidth)
+{
+    /* Upper layers have already checked domain. */
+    virConnectPtr conn = domain->conn;
+    /* NB: Passing port=0 to xend means it ignores
+     * the port.  However this is somewhat specific to
+     * the internals of the xend Python code. (XXX).
+     */
+    char port[16] = "0";
+    char live[2] = "0";
+    int ret;
+    char *p, *hostname = NULL;
+
+    /* Xen doesn't support renaming domains during migration. */
+    if (dname) {
+        virXendError (conn, VIR_ERR_NO_SUPPORT,
+                      "%s", _("xenDaemonDomainMigrate: Xen does not support"
+                        " renaming domains during migration"));
+        return -1;
+    }
+
+    /* Xen (at least up to 3.1.0) takes a resource parameter but
+     * ignores it.
+     */
+    if (bandwidth) {
+        virXendError (conn, VIR_ERR_NO_SUPPORT,
+                      "%s", _("xenDaemonDomainMigrate: Xen does not support"
+                        " bandwidth limits during migration"));
+        return -1;
+    }
+
+    /* Check the flags. */
+    if ((flags & VIR_MIGRATE_LIVE)) {
+        strcpy (live, "1");
+        flags &= ~VIR_MIGRATE_LIVE;
+    }
+    if (flags != 0) {
+        virXendError (conn, VIR_ERR_NO_SUPPORT,
+                      "%s", _("xenDaemonDomainMigrate: unsupported flag"));
+        return -1;
+    }
+
+    /* Set hostname and port.
+     *
+     * URI is non-NULL (guaranteed by caller).  We expect either
+     * "hostname", "hostname:port" or "xenmigr://hostname[:port]/".
+     */
+    if (strstr (uri, "//")) {   /* Full URI. */
+        xmlURIPtr uriptr = xmlParseURI (uri);
+        if (!uriptr) {
+            virXendError (conn, VIR_ERR_INVALID_ARG,
+                          "%s", _("xenDaemonDomainMigrate: invalid URI"));
+            return -1;
+        }
+        if (uriptr->scheme && STRCASENEQ (uriptr->scheme, "xenmigr")) {
+            virXendError (conn, VIR_ERR_INVALID_ARG,
+                          "%s", _("xenDaemonDomainMigrate: only xenmigr://"
+                            " migrations are supported by Xen"));
+            xmlFreeURI (uriptr);
+            return -1;
+        }
+        if (!uriptr->server) {
+            virXendError (conn, VIR_ERR_INVALID_ARG,
+                          "%s", _("xenDaemonDomainMigrate: a hostname must be"
+                            " specified in the URI"));
+            xmlFreeURI (uriptr);
+            return -1;
+        }
+        hostname = strdup (uriptr->server);
+        if (!hostname) {
+            virReportOOMError (conn);
+            xmlFreeURI (uriptr);
+            return -1;
+        }
+        if (uriptr->port)
+            snprintf (port, sizeof port, "%d", uriptr->port);
+        xmlFreeURI (uriptr);
+    }
+    else if ((p = strrchr (uri, ':')) != NULL) { /* "hostname:port" */
+        int port_nr, n;
+
+        if (sscanf (p+1, "%d", &port_nr) != 1) {
+            virXendError (conn, VIR_ERR_INVALID_ARG,
+                          "%s", _("xenDaemonDomainMigrate: invalid port number"));
+            return -1;
+        }
+        snprintf (port, sizeof port, "%d", port_nr);
+
+        /* Get the hostname. */
+        n = p - uri; /* n = Length of hostname in bytes. */
+        hostname = strdup (uri);
+        if (!hostname) {
+            virReportOOMError (conn);
+            return -1;
+        }
+        hostname[n] = '\0';
+    }
+    else {                      /* "hostname" (or IP address) */
+        hostname = strdup (uri);
+        if (!hostname) {
+            virReportOOMError (conn);
+            return -1;
+        }
+    }
+
+    DEBUG("hostname = %s, port = %s", hostname, port);
+
+    /* Make the call. */
+    ret = xend_op (domain->conn, domain->name,
+                   "op", "migrate",
+                   "destination", hostname,
+                   "live", live,
+                   "port", port,
+                   "node", "-1",
+                   "ssl", "0",
+                   "resource", "0", /* required, xend ignores it */
+                   NULL);
+    VIR_FREE (hostname);
+
+    DEBUG0("migration done");
+
+    return ret;
+}
+
+virDomainPtr xenDaemonDomainDefineXML(virConnectPtr conn, const char *xmlDesc) {
+    int ret;
+    char *sexpr;
+    virDomainPtr dom;
+    xenUnifiedPrivatePtr priv;
+    virDomainDefPtr def;
+
+    priv = (xenUnifiedPrivatePtr) conn->privateData;
+
+    if (priv->xendConfigVersion < 3)
+        return(NULL);
+
+    if (!(def = virDomainDefParseString(conn, priv->caps, xmlDesc,
+                                        VIR_DOMAIN_XML_INACTIVE))) {
+        virXendError(conn, VIR_ERR_XML_ERROR,
+                     "%s", _("failed to parse domain description"));
+        return (NULL);
+    }
+
+    if (!(sexpr = xenDaemonFormatSxpr(conn, def, priv->xendConfigVersion))) {
+        virXendError(conn, VIR_ERR_XML_ERROR,
+                     "%s", _("failed to build sexpr"));
+        goto error;
+    }
+
+    DEBUG("Defining w/ sexpr: \n%s", sexpr);
+
+    ret = xend_op(conn, "", "op", "new", "config", sexpr, NULL);
+    VIR_FREE(sexpr);
+    if (ret != 0) {
+        virXendError(conn, VIR_ERR_XEN_CALL,
+                     _("Failed to create inactive domain %s\n"), def->name);
+        goto error;
+    }
+
+    dom = virDomainLookupByName(conn, def->name);
+    if (dom == NULL) {
+        goto error;
+    }
+    virDomainDefFree(def);
+    return (dom);
+
+  error:
+    virDomainDefFree(def);
+    return (NULL);
+}
+int xenDaemonDomainCreate(virDomainPtr domain)
+{
+    xenUnifiedPrivatePtr priv;
+    int ret;
+    virDomainPtr tmp;
+
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
+        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                     __FUNCTION__);
+        return(-1);
+    }
+
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+
+    if (priv->xendConfigVersion < 3)
+        return(-1);
+
+    ret = xend_op(domain->conn, domain->name, "op", "start", NULL);
+
+    if (ret != -1) {
+        /* Need to force a refresh of this object's ID */
+        tmp = virDomainLookupByName(domain->conn, domain->name);
+        if (tmp) {
+            domain->id = tmp->id;
+            virDomainFree(tmp);
+        }
+    }
+    return ret;
+}
+
+int xenDaemonDomainUndefine(virDomainPtr domain)
+{
+    xenUnifiedPrivatePtr priv;
+
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
+        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                     __FUNCTION__);
+        return(-1);
+    }
+
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+
+    if (priv->xendConfigVersion < 3)
+        return(-1);
+
+    return xend_op(domain->conn, domain->name, "op", "delete", NULL);
+}
+
+/**
+ * xenDaemonNumOfDomains:
+ * @conn: pointer to the hypervisor connection
+ *
+ * Provides the number of active domains.
+ *
+ * Returns the number of domain found or -1 in case of error
+ */
+static int
+xenDaemonNumOfDefinedDomains(virConnectPtr conn)
+{
+    struct sexpr *root = NULL;
+    int ret = -1;
+    struct sexpr *_for_i, *node;
+    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
+
+    /* xm_internal.c (the support for defined domains from /etc/xen
+     * config files used by old Xen) will handle this.
+     */
+    if (priv->xendConfigVersion < 3)
+        return(-1);
+
+    root = sexpr_get(conn, "/xend/domain?state=halted");
+    if (root == NULL)
+        goto error;
+
+    ret = 0;
+
+    for (_for_i = root, node = root->u.s.car; _for_i->kind == SEXPR_CONS;
+         _for_i = _for_i->u.s.cdr, node = _for_i->u.s.car) {
+        if (node->kind != SEXPR_VALUE)
+            continue;
+        ret++;
+    }
+
+error:
+    sexpr_free(root);
+    return(ret);
+}
+
+static int
+xenDaemonListDefinedDomains(virConnectPtr conn, char **const names, int maxnames) {
+    struct sexpr *root = NULL;
+    int ret = -1;
+    struct sexpr *_for_i, *node;
+    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
+
+    if (priv->xendConfigVersion < 3)
+        return(-1);
+
+    if ((names == NULL) || (maxnames < 0))
+        goto error;
+    if (maxnames == 0)
+        return(0);
+
+    root = sexpr_get(conn, "/xend/domain?state=halted");
+    if (root == NULL)
+        goto error;
+
+    ret = 0;
+
+    for (_for_i = root, node = root->u.s.car; _for_i->kind == SEXPR_CONS;
+         _for_i = _for_i->u.s.cdr, node = _for_i->u.s.car) {
+        if (node->kind != SEXPR_VALUE)
+            continue;
+
+        names[ret++] = strdup(node->u.value);
+        if (ret >= maxnames)
+            break;
+    }
+
+error:
+    sexpr_free(root);
+    return(ret);
+}
+
+/**
+ * xenDaemonGetSchedulerType:
+ * @domain: pointer to the Domain block
+ * @nparams: give a number of scheduler parameters
+ *
+ * Get the scheduler type of Xen
+ *
+ * Returns a scheduler name (credit or sedf) which must be freed by the
+ * caller or NULL in case of failure
+ */
+static char *
+xenDaemonGetSchedulerType(virDomainPtr domain, int *nparams)
+{
+    xenUnifiedPrivatePtr priv;
+    struct sexpr *root;
+    const char *ret = NULL;
+    char *schedulertype = NULL;
+
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)
+        || (nparams == NULL)) {
+        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                     __FUNCTION__);
+        return NULL;
+    }
+
+    /* Support only xendConfigVersion >=4 */
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+    if (priv->xendConfigVersion < 4) {
+        virXendError (domain->conn, VIR_ERR_NO_SUPPORT,
+                      "%s", _("unsupported in xendConfigVersion < 4"));
+        return NULL;
+    }
+
+    root = sexpr_get(domain->conn, "/xend/node/");
+    if (root == NULL)
+        return NULL;
+
+    /* get xen_scheduler from xend/node */
+    ret = sexpr_node(root, "node/xen_scheduler");
+    if (ret == NULL){
+        virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR,
+                     "%s", _("node information incomplete, missing scheduler name"));
+        goto error;
+    }
+    if (STREQ (ret, "credit")) {
+        schedulertype = strdup("credit");
+        if (schedulertype == NULL){
+            virXendError(domain->conn, VIR_ERR_SYSTEM_ERROR, "%s", _("strdup failed"));
+            goto error;
+        }
+        *nparams = XEN_SCHED_CRED_NPARAM;
+    } else if (STREQ (ret, "sedf")) {
+        schedulertype = strdup("sedf");
+        if (schedulertype == NULL){
+            virXendError(domain->conn, VIR_ERR_SYSTEM_ERROR, "%s", _("strdup failed"));
+            goto error;
+        }
+        *nparams = XEN_SCHED_SEDF_NPARAM;
+    } else {
+        virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR, "%s", _("Unknown scheduler"));
+        goto error;
+    }
+
+error:
+    sexpr_free(root);
+    return schedulertype;
+
+}
+
+static const char *str_weight = "weight";
+static const char *str_cap = "cap";
+
+/**
+ * xenDaemonGetSchedulerParameters:
+ * @domain: pointer to the Domain block
+ * @params: pointer to scheduler parameters
+ *          This memory area must be allocated by the caller
+ * @nparams: a number of scheduler parameters which should be same as a
+ *           given number from xenDaemonGetSchedulerType()
+ *
+ * Get the scheduler parameters
+ *
+ * Returns 0 or -1 in case of failure
+ */
+static int
+xenDaemonGetSchedulerParameters(virDomainPtr domain,
+                                virSchedParameterPtr params, int *nparams)
+{
+    xenUnifiedPrivatePtr priv;
+    struct sexpr *root;
+    char *sched_type = NULL;
+    int sched_nparam = 0;
+    int ret = -1;
+
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)
+        || (params == NULL) || (nparams == NULL)) {
+        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                     __FUNCTION__);
+        return (-1);
+    }
+
+    /* Support only xendConfigVersion >=4 */
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+    if (priv->xendConfigVersion < 4) {
+        virXendError (domain->conn, VIR_ERR_NO_SUPPORT,
+                      "%s", _("unsupported in xendConfigVersion < 4"));
+        return (-1);
+    }
+
+    /* look up the information by domain name */
+    root = sexpr_get(domain->conn, "/xend/domain/%s?detail=1", domain->name);
+    if (root == NULL)
+        return (-1);
+
+    /* get the scheduler type */
+    sched_type = xenDaemonGetSchedulerType(domain, &sched_nparam);
+    if (sched_type == NULL) {
+        virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR,
+                     "%s", _("Failed to get a scheduler name"));
+        goto error;
+    }
+
+    switch (sched_nparam){
+        case XEN_SCHED_SEDF_NPARAM:
+            /* TODO: Implement for Xen/SEDF */
+            TODO
+            goto error;
+        case XEN_SCHED_CRED_NPARAM:
+            /* get cpu_weight/cpu_cap from xend/domain */
+            if (sexpr_node(root, "domain/cpu_weight") == NULL) {
+                virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR,
+                        "%s", _("domain information incomplete, missing cpu_weight"));
+                goto error;
+            }
+            if (sexpr_node(root, "domain/cpu_cap") == NULL) {
+                virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR,
+                        "%s", _("domain information incomplete, missing cpu_cap"));
+                goto error;
+            }
+
+            strncpy (params[0].field, str_weight, VIR_DOMAIN_SCHED_FIELD_LENGTH);
+            params[0].field[VIR_DOMAIN_SCHED_FIELD_LENGTH-1] = '\0';
+            params[0].type = VIR_DOMAIN_SCHED_FIELD_UINT;
+            params[0].value.ui = sexpr_int(root, "domain/cpu_weight");
+
+            strncpy (params[1].field, str_cap, VIR_DOMAIN_SCHED_FIELD_LENGTH);
+            params[1].field[VIR_DOMAIN_SCHED_FIELD_LENGTH-1] = '\0';
+            params[1].type = VIR_DOMAIN_SCHED_FIELD_UINT;
+            params[1].value.ui = sexpr_int(root, "domain/cpu_cap");
+            *nparams = XEN_SCHED_CRED_NPARAM;
+            ret = 0;
+            break;
+        default:
+            virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR, "%s", _("Unknown scheduler"));
+            goto error;
+    }
+
+error:
+    sexpr_free(root);
+    VIR_FREE(sched_type);
+    return (ret);
+}
+
+/**
+ * xenDaemonSetSchedulerParameters:
+ * @domain: pointer to the Domain block
+ * @params: pointer to scheduler parameters
+ * @nparams: a number of scheduler setting parameters
+ *
+ * Set the scheduler parameters
+ *
+ * Returns 0 or -1 in case of failure
+ */
+static int
+xenDaemonSetSchedulerParameters(virDomainPtr domain,
+                                virSchedParameterPtr params, int nparams)
+{
+    xenUnifiedPrivatePtr priv;
+    struct sexpr *root;
+    char *sched_type = NULL;
+    int i;
+    int sched_nparam = 0;
+    int ret = -1;
+
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)
+        || (params == NULL)) {
+        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                     __FUNCTION__);
+        return (-1);
+    }
+
+    /* Support only xendConfigVersion >=4 and active domains */
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+    if (priv->xendConfigVersion < 4) {
+        virXendError (domain->conn, VIR_ERR_NO_SUPPORT,
+                      "%s", _("unsupported in xendConfigVersion < 4"));
+        return (-1);
+    }
+
+    /* look up the information by domain name */
+    root = sexpr_get(domain->conn, "/xend/domain/%s?detail=1", domain->name);
+    if (root == NULL)
+        return (-1);
+
+    /* get the scheduler type */
+    sched_type = xenDaemonGetSchedulerType(domain, &sched_nparam);
+    if (sched_type == NULL) {
+        virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR,
+                     "%s", _("Failed to get a scheduler name"));
+        goto error;
+    }
+
+    switch (sched_nparam){
+        case XEN_SCHED_SEDF_NPARAM:
+            /* TODO: Implement for Xen/SEDF */
+            TODO
+            goto error;
+        case XEN_SCHED_CRED_NPARAM: {
+            char buf_weight[VIR_UUID_BUFLEN];
+            char buf_cap[VIR_UUID_BUFLEN];
+            const char *weight = NULL;
+            const char *cap = NULL;
+
+            /* get the scheduler parameters */
+            memset(&buf_weight, 0, VIR_UUID_BUFLEN);
+            memset(&buf_cap, 0, VIR_UUID_BUFLEN);
+            for (i = 0; i < nparams; i++) {
+                if (STREQ (params[i].field, str_weight) &&
+                    params[i].type == VIR_DOMAIN_SCHED_FIELD_UINT) {
+                    snprintf(buf_weight, sizeof(buf_weight), "%u", params[i].value.ui);
+                } else if (STREQ (params[i].field, str_cap) &&
+                    params[i].type == VIR_DOMAIN_SCHED_FIELD_UINT) {
+                    snprintf(buf_cap, sizeof(buf_cap), "%u", params[i].value.ui);
+                } else {
+                    virXendError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+                    goto error;
+                }
+            }
+
+            /* if not get the scheduler parameter, set the current setting */
+            if (strlen(buf_weight) == 0) {
+                weight = sexpr_node(root, "domain/cpu_weight");
+                if (weight == NULL) {
+                    virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR,
+                                "%s", _("domain information incomplete, missing cpu_weight"));
+                    goto error;
+                }
+                snprintf(buf_weight, sizeof(buf_weight), "%s", weight);
+            }
+            if (strlen(buf_cap) == 0) {
+                cap = sexpr_node(root, "domain/cpu_cap");
+                if (cap == NULL) {
+                    virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR,
+                                "%s", _("domain information incomplete, missing cpu_cap"));
+                    goto error;
+                }
+                snprintf(buf_cap, sizeof(buf_cap), "%s", cap);
+            }
+
+            ret = xend_op(domain->conn, domain->name, "op",
+                          "domain_sched_credit_set", "weight", buf_weight,
+                          "cap", buf_cap, NULL);
+            break;
+        }
+        default:
+            virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR, "%s", _("Unknown scheduler"));
+            goto error;
+    }
+
+error:
+    sexpr_free(root);
+    VIR_FREE(sched_type);
+    return (ret);
+}
+
+/**
+ * xenDaemonDomainBlockPeek:
+ * @dom: domain object
+ * @path: path to the file or device
+ * @offset: offset
+ * @size: size
+ * @buffer: return buffer
+ *
+ * Returns 0 if successful, -1 if error, -2 if declined.
+ */
+int
+xenDaemonDomainBlockPeek (virDomainPtr domain, const char *path,
+                          unsigned long long offset, size_t size,
+                          void *buffer)
+{
+    xenUnifiedPrivatePtr priv;
+    struct sexpr *root = NULL;
+    int fd = -1, ret = -1;
+    int found = 0, i;
+    virDomainDefPtr def;
+
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+
+    if (domain->id < 0 && priv->xendConfigVersion < 3)
+        return -2;              /* Decline, allow XM to handle it. */
+
+    /* Security check: The path must correspond to a block device. */
+    if (domain->id > 0)
+        root = sexpr_get (domain->conn, "/xend/domain/%d?detail=1",
+                          domain->id);
+    else if (domain->id < 0)
+        root = sexpr_get (domain->conn, "/xend/domain/%s?detail=1",
+                          domain->name);
+    else {
+        /* This call always fails for dom0. */
+        virXendError (domain->conn, VIR_ERR_NO_SUPPORT,
+                      "%s", _("domainBlockPeek is not supported for dom0"));
+        return -1;
+    }
+
+    if (!root) {
+        virXendError (domain->conn, VIR_ERR_XEN_CALL, __FUNCTION__);
+        return -1;
+    }
+
+    if (!(def = xenDaemonParseSxpr(domain->conn, root, priv->xendConfigVersion, NULL)))
+        goto cleanup;
+
+    for (i = 0 ; i < def->ndisks ; i++) {
+        if (def->disks[i]->src &&
+            STREQ(def->disks[i]->src, path)) {
+            found = 1;
+            break;
+        }
+    }
+    if (!found) {
+        virXendError (domain->conn, VIR_ERR_INVALID_ARG,
+                      _("%s: invalid path"), path);
+        goto cleanup;
+    }
+
+    /* The path is correct, now try to open it and get its size. */
+    fd = open (path, O_RDONLY);
+    if (fd == -1) {
+        virReportSystemError(domain->conn, errno,
+                             _("failed to open for reading: %s"),
+                             path);
+        goto cleanup;
+    }
+
+    /* Seek and read. */
+    /* NB. Because we configure with AC_SYS_LARGEFILE, off_t should
+     * be 64 bits on all platforms.
+     */
+    if (lseek (fd, offset, SEEK_SET) == (off_t) -1 ||
+        saferead (fd, buffer, size) == (ssize_t) -1) {
+        virReportSystemError(domain->conn, errno,
+                             _("failed to lseek or read from file: %s"),
+                             path);
+        goto cleanup;
+    }
+
+    ret = 0;
+ cleanup:
+    if (fd >= 0) close (fd);
+    sexpr_free(root);
+    virDomainDefFree(def);
+    return ret;
+}
+
+struct xenUnifiedDriver xenDaemonDriver = {
+    xenDaemonOpen,               /* open */
+    xenDaemonClose,              /* close */
+    xenDaemonGetVersion,         /* version */
+    NULL,                        /* hostname */
+    xenDaemonNodeGetInfo,        /* nodeGetInfo */
+    NULL,                        /* getCapabilities */
+    xenDaemonListDomains,        /* listDomains */
+    xenDaemonNumOfDomains,       /* numOfDomains */
+    xenDaemonCreateXML,          /* domainCreateXML */
+    xenDaemonDomainSuspend,      /* domainSuspend */
+    xenDaemonDomainResume,       /* domainResume */
+    xenDaemonDomainShutdown,     /* domainShutdown */
+    xenDaemonDomainReboot,       /* domainReboot */
+    xenDaemonDomainDestroy,      /* domainDestroy */
+    xenDaemonDomainGetOSType,    /* domainGetOSType */
+    xenDaemonDomainGetMaxMemory, /* domainGetMaxMemory */
+    xenDaemonDomainSetMaxMemory, /* domainSetMaxMemory */
+    xenDaemonDomainSetMemory,    /* domainMaxMemory */
+    xenDaemonDomainGetInfo,      /* domainGetInfo */
+    xenDaemonDomainSave,         /* domainSave */
+    xenDaemonDomainRestore,      /* domainRestore */
+    xenDaemonDomainCoreDump,     /* domainCoreDump */
+    xenDaemonDomainSetVcpus,     /* domainSetVcpus */
+    xenDaemonDomainPinVcpu,      /* domainPinVcpu */
+    xenDaemonDomainGetVcpus,     /* domainGetVcpus */
+    NULL,                        /* domainGetMaxVcpus */
+    xenDaemonListDefinedDomains, /* listDefinedDomains */
+    xenDaemonNumOfDefinedDomains,/* numOfDefinedDomains */
+    xenDaemonDomainCreate,       /* domainCreate */
+    xenDaemonDomainDefineXML,    /* domainDefineXML */
+    xenDaemonDomainUndefine,     /* domainUndefine */
+    xenDaemonAttachDevice,       /* domainAttachDevice */
+    xenDaemonDetachDevice,       /* domainDetachDevice */
+    xenDaemonDomainGetAutostart, /* domainGetAutostart */
+    xenDaemonDomainSetAutostart, /* domainSetAutostart */
+    xenDaemonGetSchedulerType,   /* domainGetSchedulerType */
+    xenDaemonGetSchedulerParameters, /* domainGetSchedulerParameters */
+    xenDaemonSetSchedulerParameters, /* domainSetSchedulerParameters */
+};
+
+/************************************************************************
+ *                                                                     *
+ * Converter functions to go from the XML tree to an S-Expr for Xen    *
+ *                                                                     *
+ ************************************************************************/
+
+
+/**
+ * virtDomainParseXMLGraphicsDescVFB:
+ * @conn: pointer to the hypervisor connection
+ * @node: node containing graphics description
+ * @buf: a buffer for the result S-Expr
+ *
+ * Parse the graphics part of the XML description and add it to the S-Expr
+ * in buf.  This is a temporary interface as the S-Expr interface will be
+ * replaced by XML-RPC in the future. However the XML format should stay
+ * valid over time.
+ *
+ * Returns 0 in case of success, -1 in case of error
+ */
+static int
+xenDaemonFormatSxprGraphicsNew(virConnectPtr conn,
+                               virDomainGraphicsDefPtr def,
+                               virBufferPtr buf)
+{
+    if (def->type != VIR_DOMAIN_GRAPHICS_TYPE_SDL &&
+        def->type != VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
+        virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                     _("unexpected graphics type %d"),
+                     def->type);
+        return -1;
+    }
+
+    virBufferAddLit(buf, "(device (vkbd))");
+    virBufferAddLit(buf, "(device (vfb ");
+
+    if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
+        virBufferAddLit(buf, "(type sdl)");
+        if (def->data.sdl.display)
+            virBufferVSprintf(buf, "(display '%s')", def->data.sdl.display);
+        if (def->data.sdl.xauth)
+            virBufferVSprintf(buf, "(xauthority '%s')", def->data.sdl.xauth);
+    } else if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
+        virBufferAddLit(buf, "(type vnc)");
+        if (def->data.vnc.autoport) {
+            virBufferAddLit(buf, "(vncunused 1)");
+        } else {
+            virBufferAddLit(buf, "(vncunused 0)");
+            virBufferVSprintf(buf, "(vncdisplay %d)", def->data.vnc.port-5900);
+        }
+
+        if (def->data.vnc.listenAddr)
+            virBufferVSprintf(buf, "(vnclisten '%s')", def->data.vnc.listenAddr);
+        if (def->data.vnc.passwd)
+            virBufferVSprintf(buf, "(vncpasswd '%s')", def->data.vnc.passwd);
+        if (def->data.vnc.keymap)
+            virBufferVSprintf(buf, "(keymap '%s')", def->data.vnc.keymap);
+    }
+
+    virBufferAddLit(buf, "))");
+
+    return 0;
+}
+
+
+static int
+xenDaemonFormatSxprGraphicsOld(virConnectPtr conn,
+                               virDomainGraphicsDefPtr def,
+                               virBufferPtr buf,
+                               int xendConfigVersion)
+{
+    if (def->type != VIR_DOMAIN_GRAPHICS_TYPE_SDL &&
+        def->type != VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
+        virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                     _("unexpected graphics type %d"),
+                     def->type);
+        return -1;
+    }
+
+    if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
+        virBufferAddLit(buf, "(sdl 1)");
+        if (def->data.sdl.display)
+            virBufferVSprintf(buf, "(display '%s')", def->data.sdl.display);
+        if (def->data.sdl.xauth)
+            virBufferVSprintf(buf, "(xauthority '%s')", def->data.sdl.xauth);
+    } else if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
+        virBufferAddLit(buf, "(vnc 1)");
+        if (xendConfigVersion >= 2) {
+            if (def->data.vnc.autoport) {
+                virBufferAddLit(buf, "(vncunused 1)");
+            } else {
+                virBufferAddLit(buf, "(vncunused 0)");
+                virBufferVSprintf(buf, "(vncdisplay %d)", def->data.vnc.port-5900);
+            }
+
+            if (def->data.vnc.listenAddr)
+                virBufferVSprintf(buf, "(vnclisten '%s')", def->data.vnc.listenAddr);
+            if (def->data.vnc.passwd)
+                virBufferVSprintf(buf, "(vncpasswd '%s')", def->data.vnc.passwd);
+            if (def->data.vnc.keymap)
+                virBufferVSprintf(buf, "(keymap '%s')", def->data.vnc.keymap);
+
+        }
+    }
+
+    return 0;
+}
+
+int
+xenDaemonFormatSxprChr(virConnectPtr conn,
+                       virDomainChrDefPtr def,
+                       virBufferPtr buf)
+{
+    const char *type = virDomainChrTypeToString(def->type);
+
+    if (!type) {
+        virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                     "%s", _("unexpected chr device type"));
+        return -1;
+    }
+
+    switch (def->type) {
+    case VIR_DOMAIN_CHR_TYPE_NULL:
+    case VIR_DOMAIN_CHR_TYPE_STDIO:
+    case VIR_DOMAIN_CHR_TYPE_VC:
+    case VIR_DOMAIN_CHR_TYPE_PTY:
+        virBufferVSprintf(buf, "%s", type);
+        break;
+
+    case VIR_DOMAIN_CHR_TYPE_FILE:
+    case VIR_DOMAIN_CHR_TYPE_PIPE:
+        virBufferVSprintf(buf, "%s:%s", type, def->data.file.path);
+        break;
+
+    case VIR_DOMAIN_CHR_TYPE_DEV:
+        virBufferVSprintf(buf, "%s", def->data.file.path);
+        break;
+
+    case VIR_DOMAIN_CHR_TYPE_TCP:
+        virBufferVSprintf(buf, "%s:%s:%s%s",
+                          (def->data.tcp.protocol == VIR_DOMAIN_CHR_TCP_PROTOCOL_RAW ?
+                           "tcp" : "telnet"),
+                          (def->data.tcp.host ? def->data.tcp.host : ""),
+                          (def->data.tcp.service ? def->data.tcp.service : ""),
+                          (def->data.tcp.listen ? ",listen" : ""));
+        break;
+
+    case VIR_DOMAIN_CHR_TYPE_UDP:
+        virBufferVSprintf(buf, "%s:%s:%s@%s:%s", type,
+                          (def->data.udp.connectHost ? def->data.udp.connectHost : ""),
+                          (def->data.udp.connectService ? def->data.udp.connectService : ""),
+                          (def->data.udp.bindHost ? def->data.udp.bindHost : ""),
+                          (def->data.udp.bindService ? def->data.udp.bindService : ""));
+        break;
+
+    case VIR_DOMAIN_CHR_TYPE_UNIX:
+        virBufferVSprintf(buf, "%s:%s%s", type,
+                          def->data.nix.path,
+                          def->data.nix.listen ? ",listen" : "");
+        break;
+    }
+
+    if (virBufferError(buf))
+        return -1;
+
+    return 0;
+}
+
+
+/**
+ * virDomainParseXMLDiskDesc:
+ * @node: node containing disk description
+ * @conn: pointer to the hypervisor connection
+ * @buf: a buffer for the result S-Expr
+ * @xendConfigVersion: xend configuration file format
+ *
+ * Parse the one disk in the XML description and add it to the S-Expr in buf
+ * This is a temporary interface as the S-Expr interface
+ * will be replaced by XML-RPC in the future. However the XML format should
+ * stay valid over time.
+ *
+ * Returns 0 in case of success, -1 in case of error.
+ */
+static int
+xenDaemonFormatSxprDisk(virConnectPtr conn ATTRIBUTE_UNUSED,
+                        virDomainDiskDefPtr def,
+                        virBufferPtr buf,
+                        int hvm,
+                        int xendConfigVersion,
+                        int isAttach)
+{
+    /* Xend (all versions) put the floppy device config
+     * under the hvm (image (os)) block
+     */
+    if (hvm &&
+        def->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
+        if (isAttach) {
+            virXendError(conn, VIR_ERR_INVALID_ARG,
+                     _("Cannot directly attach floppy %s"), def->src);
+            return -1;
+        }
+        return 0;
+    }
+
+    /* Xend <= 3.0.2 doesn't include cdrom config here */
+    if (hvm &&
+        def->device == VIR_DOMAIN_DISK_DEVICE_CDROM &&
+        xendConfigVersion == 1) {
+        if (isAttach) {
+            virXendError(conn, VIR_ERR_INVALID_ARG,
+                     _("Cannot directly attach CDROM %s"), def->src);
+            return -1;
+        }
+        return 0;
+    }
+
+    if (!isAttach)
+        virBufferAddLit(buf, "(device ");
+
+    /* Normally disks are in a (device (vbd ...)) block
+     * but blktap disks ended up in a differently named
+     * (device (tap ....)) block.... */
+    if (def->driverName &&
+        STREQ(def->driverName, "tap")) {
+        virBufferAddLit(buf, "(tap ");
+    } else {
+        virBufferAddLit(buf, "(vbd ");
+    }
+
+    if (hvm) {
+        /* Xend <= 3.0.2 wants a ioemu: prefix on devices for HVM */
+        if (xendConfigVersion == 1)
+            virBufferVSprintf(buf, "(dev 'ioemu:%s')", def->dst);
+        else                    /* But newer does not */
+            virBufferVSprintf(buf, "(dev '%s:%s')", def->dst,
+                              def->device == VIR_DOMAIN_DISK_DEVICE_CDROM ?
+                              "cdrom" : "disk");
+    } else if (def->device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
+        virBufferVSprintf(buf, "(dev '%s:cdrom')", def->dst);
+    } else {
+        virBufferVSprintf(buf, "(dev '%s')", def->dst);
+    }
+
+    if (def->src) {
+        if (def->driverName) {
+            if (STREQ(def->driverName, "tap")) {
+                virBufferVSprintf(buf, "(uname '%s:%s:%s')",
+                                  def->driverName,
+                                  def->driverType ? def->driverType : "aio",
+                                  def->src);
+            } else {
+                virBufferVSprintf(buf, "(uname '%s:%s')",
+                                  def->driverName,
+                                  def->src);
+            }
+        } else {
+            if (def->type == VIR_DOMAIN_DISK_TYPE_FILE) {
+                virBufferVSprintf(buf, "(uname 'file:%s')", def->src);
+            } else {
+                if (def->src[0] == '/')
+                    virBufferVSprintf(buf, "(uname 'phy:%s')", def->src);
+                else
+                    virBufferVSprintf(buf, "(uname 'phy:/dev/%s')", def->src);
+            }
+        }
+    }
+
+    if (def->readonly)
+        virBufferAddLit(buf, "(mode 'r')");
+    else if (def->shared)
+        virBufferAddLit(buf, "(mode 'w!')");
+    else
+        virBufferAddLit(buf, "(mode 'w')");
+
+    if (!isAttach)
+        virBufferAddLit(buf, ")");
+
+    virBufferAddLit(buf, ")");
+
+    return 0;
+}
+
+/**
+ * xenDaemonFormatSxprNet
+ * @conn: pointer to the hypervisor connection
+ * @node: node containing the interface description
+ * @buf: a buffer for the result S-Expr
+ * @xendConfigVersion: xend configuration file format
+ *
+ * Parse the one interface the XML description and add it to the S-Expr in buf
+ * This is a temporary interface as the S-Expr interface
+ * will be replaced by XML-RPC in the future. However the XML format should
+ * stay valid over time.
+ *
+ * Returns 0 in case of success, -1 in case of error.
+ */
+static int
+xenDaemonFormatSxprNet(virConnectPtr conn,
+                       virDomainNetDefPtr def,
+                       virBufferPtr buf,
+                       int hvm,
+                       int xendConfigVersion,
+                       int isAttach)
+{
+    const char *script = DEFAULT_VIF_SCRIPT;
+
+    if (def->type != VIR_DOMAIN_NET_TYPE_BRIDGE &&
+        def->type != VIR_DOMAIN_NET_TYPE_NETWORK &&
+        def->type != VIR_DOMAIN_NET_TYPE_ETHERNET) {
+        virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                     _("unsupported network type %d"), def->type);
+        return -1;
+    }
+
+    if (!isAttach)
+        virBufferAddLit(buf, "(device ");
+
+    virBufferAddLit(buf, "(vif ");
+
+    virBufferVSprintf(buf,
+                      "(mac '%02x:%02x:%02x:%02x:%02x:%02x')",
+                      def->mac[0], def->mac[1], def->mac[2],
+                      def->mac[3], def->mac[4], def->mac[5]);
+
+    switch (def->type) {
+    case VIR_DOMAIN_NET_TYPE_BRIDGE:
+        virBufferVSprintf(buf, "(bridge '%s')", def->data.bridge.brname);
+        if (def->data.bridge.script)
+            script = def->data.bridge.script;
+
+        virBufferVSprintf(buf, "(script '%s')", script);
+        if (def->data.bridge.ipaddr != NULL)
+            virBufferVSprintf(buf, "(ip '%s')", def->data.bridge.ipaddr);
+        break;
+
+    case VIR_DOMAIN_NET_TYPE_NETWORK:
+    {
+        virNetworkPtr network =
+            virNetworkLookupByName(conn, def->data.network.name);
+        char *bridge;
+
+        if (!network) {
+            virXendError(conn, VIR_ERR_NO_NETWORK, "%s",
+                         def->data.network.name);
+            return -1;
+        }
+
+        bridge = virNetworkGetBridgeName(network);
+        virNetworkFree(network);
+        if (!bridge) {
+            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                         _("network %s is not active"),
+                         def->data.network.name);
+            return -1;
+        }
+        virBufferVSprintf(buf, "(bridge '%s')", bridge);
+        virBufferVSprintf(buf, "(script '%s')", script);
+        VIR_FREE(bridge);
+    }
+    break;
+
+    case VIR_DOMAIN_NET_TYPE_ETHERNET:
+        if (def->data.ethernet.script)
+            virBufferVSprintf(buf, "(script '%s')", def->data.ethernet.script);
+        if (def->data.ethernet.ipaddr != NULL)
+            virBufferVSprintf(buf, "(ip '%s')", def->data.ethernet.ipaddr);
+        break;
+    }
+
+    if (def->ifname != NULL &&
+        !STRPREFIX(def->ifname, "vif"))
+        virBufferVSprintf(buf, "(vifname '%s')", def->ifname);
+
+    if (def->model != NULL)
+        virBufferVSprintf(buf, "(model '%s')", def->model);
+
+    /*
+     * apparently (type ioemu) breaks paravirt drivers on HVM so skip this
+     * from Xen 3.1.0
+     */
+    if (hvm && xendConfigVersion <= XEND_CONFIG_MAX_VERS_NET_TYPE_IOEMU)
+        virBufferAddLit(buf, "(type ioemu)");
+
+    if (!isAttach)
+        virBufferAddLit(buf, ")");
+
+    virBufferAddLit(buf, ")");
+
+    return 0;
+}
+
+
+static void
+xenDaemonFormatSxprPCI(virDomainHostdevDefPtr def,
+                       virBufferPtr buf)
+{
+    virBufferVSprintf(buf, "(dev (domain 0x%04x)(bus 0x%02x)(slot 0x%02x)(func 0x%x))",
+                      def->source.subsys.u.pci.domain,
+                      def->source.subsys.u.pci.bus,
+                      def->source.subsys.u.pci.slot,
+                      def->source.subsys.u.pci.function);
+}
+
+static int
+xenDaemonFormatSxprOnePCI(virConnectPtr conn,
+                          virDomainHostdevDefPtr def,
+                          virBufferPtr buf)
+{
+    if (def->managed) {
+        virXendError(conn, VIR_ERR_NO_SUPPORT, "%s",
+                     _("managed PCI devices not supported with XenD"));
+        return -1;
+    }
+
+    virBufferAddLit(buf, "(pci ");
+    xenDaemonFormatSxprPCI(def, buf);
+    virBufferAddLit(buf, ")");
+
+    return 0;
+}
+
+static int
+xenDaemonFormatSxprAllPCI(virConnectPtr conn,
+                          virDomainDefPtr def,
+                          virBufferPtr buf)
+{
+    int hasPCI = 0;
+    int i;
+
+    for (i = 0 ; i < def->nhostdevs ; i++)
+        if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+            def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
+            hasPCI = 1;
+
+    if (!hasPCI)
+        return 0;
+
+    /*
+     * With the (domain ...) block we have the following odd setup
+     *
+     * (device
+     *    (pci
+     *       (dev (domain 0x0000) (bus 0x00) (slot 0x1b) (func 0x0))
+     *       (dev (domain 0x0000) (bus 0x00) (slot 0x13) (func 0x0))
+     *    )
+     * )
+     *
+     * Normally there is one (device ...) block per device, but in
+     * wierd world of Xen PCI, once (device ...) covers multiple
+     * devices.
+     */
+
+    virBufferAddLit(buf, "(device (pci ");
+    for (i = 0 ; i < def->nhostdevs ; i++) {
+        if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+            def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
+            if (def->hostdevs[i]->managed) {
+                virXendError(conn, VIR_ERR_NO_SUPPORT, "%s",
+                             _("managed PCI devices not supported with XenD"));
+                return -1;
+            }
+
+            xenDaemonFormatSxprPCI(def->hostdevs[i], buf);
+        }
+    }
+    virBufferAddLit(buf, "))");
+
+    return 0;
+}
+
+int
+xenDaemonFormatSxprSound(virConnectPtr conn,
+                         virDomainDefPtr def,
+                         virBufferPtr buf)
+{
+    const char *str;
+    int i;
+
+    for (i = 0 ; i < def->nsounds ; i++) {
+        if (!(str = virDomainSoundModelTypeToString(def->sounds[i]->model))) {
+            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                         _("unexpected sound model %d"),
+                         def->sounds[i]->model);
+            return -1;
+        }
+        virBufferVSprintf(buf, "%s%s", i ? "," : "", str);
+    }
+
+    if (virBufferError(buf))
+        return -1;
+
+    return 0;
+}
+
+
+static int
+xenDaemonFormatSxprInput(virConnectPtr conn,
+                         virDomainInputDefPtr input,
+                         virBufferPtr buf)
+{
+    if (input->bus != VIR_DOMAIN_INPUT_BUS_USB)
+        return 0;
+
+    if (input->type != VIR_DOMAIN_INPUT_TYPE_MOUSE &&
+        input->type != VIR_DOMAIN_INPUT_TYPE_TABLET) {
+        virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                     _("unexpected input type %d"), input->type);
+        return -1;
+    }
+
+    virBufferVSprintf(buf, "(usbdevice %s)",
+                      input->type == VIR_DOMAIN_INPUT_TYPE_MOUSE ?
+                      "mouse" : "tablet");
+
+    return 0;
+}
+
+
+/**
+ * xenDaemonFormatSxpr:
+ * @conn: pointer to the hypervisor connection
+ * @def: domain config definition
+ * @xendConfigVersion: xend configuration file format
+ *
+ * Generate an SEXPR representing the domain configuration.
+ *
+ * Returns the 0 terminatedi S-Expr string or NULL in case of error.
+ *         the caller must free() the returned value.
+ */
+char *
+xenDaemonFormatSxpr(virConnectPtr conn,
+                    virDomainDefPtr def,
+                    int xendConfigVersion)
+{
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    char uuidstr[VIR_UUID_STRING_BUFLEN];
+    const char *tmp;
+    int hvm = 0, i;
+
+    virBufferAddLit(&buf, "(vm ");
+    virBufferVSprintf(&buf, "(name '%s')", def->name);
+    virBufferVSprintf(&buf, "(memory %lu)(maxmem %lu)",
+                      def->memory/1024, def->maxmem/1024);
+    virBufferVSprintf(&buf, "(vcpus %lu)", def->vcpus);
+
+    if (def->cpumask) {
+        char *ranges = virDomainCpuSetFormat(conn, def->cpumask, def->cpumasklen);
+        if (ranges == NULL)
+            goto error;
+        virBufferVSprintf(&buf, "(cpus '%s')", ranges);
+        VIR_FREE(ranges);
+    }
+
+    virUUIDFormat(def->uuid, uuidstr);
+    virBufferVSprintf(&buf, "(uuid '%s')", uuidstr);
+
+    if (def->os.bootloader) {
+        if (def->os.bootloader[0])
+            virBufferVSprintf(&buf, "(bootloader '%s')", def->os.bootloader);
+        else
+            virBufferAddLit(&buf, "(bootloader)");
+
+        if (def->os.bootloaderArgs)
+            virBufferVSprintf(&buf, "(bootloader_args '%s')", def->os.bootloaderArgs);
+    }
+
+    if (!(tmp = virDomainLifecycleTypeToString(def->onPoweroff))) {
+        virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                     _("unexpected lifecycle value %d"), def->onPoweroff);
+        goto error;
+    }
+    virBufferVSprintf(&buf, "(on_poweroff '%s')", tmp);
+
+    if (!(tmp = virDomainLifecycleTypeToString(def->onReboot))) {
+        virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                     _("unexpected lifecycle value %d"), def->onReboot);
+        goto error;
+    }
+    virBufferVSprintf(&buf, "(on_reboot '%s')", tmp);
+
+    if (!(tmp = virDomainLifecycleTypeToString(def->onCrash))) {
+        virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                     _("unexpected lifecycle value %d"), def->onCrash);
+        goto error;
+    }
+    virBufferVSprintf(&buf, "(on_crash '%s')", tmp);
+
+    /* Set localtime here for current XenD (both PV & HVM) */
+    if (def->localtime)
+        virBufferAddLit(&buf, "(localtime 1)");
+
+    if (!def->os.bootloader) {
+        if (STREQ(def->os.type, "hvm"))
+            hvm = 1;
+
+        if (hvm)
+            virBufferAddLit(&buf, "(image (hvm ");
+        else
+            virBufferAddLit(&buf, "(image (linux ");
+
+        if (hvm &&
+            def->os.loader == NULL) {
+            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                         "%s",_("no HVM domain loader"));
+            goto error;
+        }
+
+        if (def->os.kernel)
+            virBufferVSprintf(&buf, "(kernel '%s')", def->os.kernel);
+        if (def->os.initrd)
+            virBufferVSprintf(&buf, "(ramdisk '%s')", def->os.initrd);
+        if (def->os.root)
+            virBufferVSprintf(&buf, "(root '%s')", def->os.root);
+        if (def->os.cmdline)
+            virBufferVSprintf(&buf, "(args '%s')", def->os.cmdline);
+
+        if (hvm) {
+            char bootorder[VIR_DOMAIN_BOOT_LAST+1];
+            if (def->os.kernel)
+                virBufferVSprintf(&buf, "(loader '%s')", def->os.loader);
+            else
+                virBufferVSprintf(&buf, "(kernel '%s')", def->os.loader);
+
+            virBufferVSprintf(&buf, "(vcpus %lu)", def->vcpus);
+
+            for (i = 0 ; i < def->os.nBootDevs ; i++) {
+                switch (def->os.bootDevs[i]) {
+                case VIR_DOMAIN_BOOT_FLOPPY:
+                    bootorder[i] = 'a';
+                    break;
+                default:
+                case VIR_DOMAIN_BOOT_DISK:
+                    bootorder[i] = 'c';
+                    break;
+                case VIR_DOMAIN_BOOT_CDROM:
+                    bootorder[i] = 'd';
+                    break;
+                case VIR_DOMAIN_BOOT_NET:
+                    bootorder[i] = 'n';
+                    break;
+                }
+            }
+            if (def->os.nBootDevs == 0) {
+                bootorder[0] = 'c';
+                bootorder[1] = '\0';
+            } else {
+                bootorder[def->os.nBootDevs] = '\0';
+            }
+            virBufferVSprintf(&buf, "(boot %s)", bootorder);
+
+            /* some disk devices are defined here */
+            for (i = 0 ; i < def->ndisks ; i++) {
+                switch (def->disks[i]->device) {
+                case VIR_DOMAIN_DISK_DEVICE_CDROM:
+                    /* Only xend <= 3.0.2 wants cdrom config here */
+                    if (xendConfigVersion != 1)
+                        break;
+                    if (!STREQ(def->disks[i]->dst, "hdc") ||
+                        def->disks[i]->src == NULL)
+                        break;
+
+                    virBufferVSprintf(&buf, "(cdrom '%s')",
+                                      def->disks[i]->src);
+                    break;
+
+                case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
+                    /* all xend versions define floppies here */
+                    virBufferVSprintf(&buf, "(%s '%s')", def->disks[i]->dst,
+                        def->disks[i]->src);
+                    break;
+
+                default:
+                    break;
+                }
+            }
+
+            if (def->features & (1 << VIR_DOMAIN_FEATURE_ACPI))
+                virBufferAddLit(&buf, "(acpi 1)");
+            if (def->features & (1 << VIR_DOMAIN_FEATURE_APIC))
+                virBufferAddLit(&buf, "(apic 1)");
+            if (def->features & (1 << VIR_DOMAIN_FEATURE_PAE))
+                virBufferAddLit(&buf, "(pae 1)");
+
+            virBufferAddLit(&buf, "(usb 1)");
+
+            for (i = 0 ; i < def->ninputs ; i++)
+                if (xenDaemonFormatSxprInput(conn, def->inputs[i], &buf) < 0)
+                    goto error;
+
+            if (def->parallels) {
+                virBufferAddLit(&buf, "(parallel ");
+                if (xenDaemonFormatSxprChr(conn, def->parallels[0], &buf) < 0)
+                    goto error;
+                virBufferAddLit(&buf, ")");
+            } else {
+                virBufferAddLit(&buf, "(parallel none)");
+            }
+            if (def->serials) {
+                virBufferAddLit(&buf, "(serial ");
+                if (xenDaemonFormatSxprChr(conn, def->serials[0], &buf) < 0)
+                    goto error;
+                virBufferAddLit(&buf, ")");
+            } else {
+                virBufferAddLit(&buf, "(serial none)");
+            }
+
+            /* Set localtime here to keep old XenD happy for HVM */
+            if (def->localtime)
+                virBufferAddLit(&buf, "(localtime 1)");
+
+            if (def->sounds) {
+                virBufferAddLit(&buf, "(soundhw '");
+                if (xenDaemonFormatSxprSound(conn, def, &buf) < 0)
+                    goto error;
+                virBufferAddLit(&buf, "')");
+            }
+        }
+
+        /* get the device emulation model */
+        if (def->emulator && (hvm || xendConfigVersion >= 3))
+            virBufferVSprintf(&buf, "(device_model '%s')", def->emulator);
+
+
+        /* PV graphics for xen <= 3.0.4, or HVM graphics for xen <= 3.1.0 */
+        if ((!hvm && xendConfigVersion < XEND_CONFIG_MIN_VERS_PVFB_NEWCONF) ||
+            (hvm && xendConfigVersion < 4)) {
+            if ((def->ngraphics == 1) &&
+                xenDaemonFormatSxprGraphicsOld(conn, def->graphics[0],
+                                               &buf, xendConfigVersion) < 0)
+                goto error;
+        }
+
+        virBufferAddLit(&buf, "))");
+    }
+
+    for (i = 0 ; i < def->ndisks ; i++)
+        if (xenDaemonFormatSxprDisk(conn, def->disks[i],
+                                    &buf, hvm, xendConfigVersion, 0) < 0)
+            goto error;
+
+    for (i = 0 ; i < def->nnets ; i++)
+        if (xenDaemonFormatSxprNet(conn, def->nets[i],
+                                   &buf, hvm, xendConfigVersion, 0) < 0)
+            goto error;
+
+    if (xenDaemonFormatSxprAllPCI(conn, def, &buf) < 0)
+        goto error;
+
+    /* New style PV graphics config xen >= 3.0.4,
+     * or HVM graphics config xen >= 3.0.5 */
+    if ((xendConfigVersion >= XEND_CONFIG_MIN_VERS_PVFB_NEWCONF && !hvm) ||
+        (xendConfigVersion >= 4 && hvm)) {
+        if ((def->ngraphics == 1) &&
+            xenDaemonFormatSxprGraphicsNew(conn, def->graphics[0], &buf) < 0)
+            goto error;
+    }
+
+    virBufferAddLit(&buf, ")"); /* closes (vm */
+
+    if (virBufferError(&buf)) {
+        virReportOOMError(conn);
+        return NULL;
+    }
+
+    return virBufferContentAndReset(&buf);
+
+error:
+    tmp = virBufferContentAndReset(&buf);
+    VIR_FREE(tmp);
+    return NULL;
+}
+
+
+/**
+ * virDomainXMLDevID:
+ * @domain: pointer to domain object
+ * @dev: pointer to device config object
+ * @class: Xen device class "vbd" or "vif" (OUT)
+ * @ref: Xen device reference (OUT)
+ *
+ * Set class according to XML root, and:
+ *  - if disk, copy in ref the target name from description
+ *  - if network, get MAC address from description, scan XenStore and
+ *    copy in ref the corresponding vif number.
+ *
+ * Returns 0 in case of success, -1 in case of failure.
+ */
+static int
+virDomainXMLDevID(virDomainPtr domain,
+                  virDomainDeviceDefPtr dev,
+                  char *class,
+                  char *ref,
+                  int ref_len)
+{
+    xenUnifiedPrivatePtr priv = domain->conn->privateData;
+    char *xref;
+
+    if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
+        if (dev->data.disk->driverName &&
+            STREQ(dev->data.disk->driverName, "tap"))
+            strcpy(class, "tap");
+        else
+            strcpy(class, "vbd");
+
+        if (dev->data.disk->dst == NULL)
+            return -1;
+        xenUnifiedLock(priv);
+        xref = xenStoreDomainGetDiskID(domain->conn, domain->id,
+                                       dev->data.disk->dst);
+        xenUnifiedUnlock(priv);
+        if (xref == NULL)
+            return -1;
+
+        strncpy(ref, xref, ref_len);
+        free(xref);
+        ref[ref_len - 1] = '\0';
+    } else if (dev->type == VIR_DOMAIN_DEVICE_NET) {
+        char mac[30];
+        virDomainNetDefPtr def = dev->data.net;
+        snprintf(mac, sizeof(mac), "%02x:%02x:%02x:%02x:%02x:%02x",
+                 def->mac[0], def->mac[1], def->mac[2],
+                 def->mac[3], def->mac[4], def->mac[5]);
+
+        strcpy(class, "vif");
+
+        xenUnifiedLock(priv);
+        xref = xenStoreDomainGetNetworkID(domain->conn, domain->id,
+                                          mac);
+        xenUnifiedUnlock(priv);
+        if (xref == NULL)
+            return -1;
+
+        strncpy(ref, xref, ref_len);
+        free(xref);
+        ref[ref_len - 1] = '\0';
+    } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV &&
+               dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+               dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
+    } else {
+        virXendError(NULL, VIR_ERR_NO_SUPPORT,
+                     "%s", _("hotplug of device type not supported"));
+        return -1;
+    }
+
+    return 0;
+}
+
+#endif /* ! PROXY */
diff --git a/src/xen/xend_internal.h b/src/xen/xend_internal.h
new file mode 100644 (file)
index 0000000..9d2571b
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * xend_internal.h
+ *
+ * Copyright (C) 2005,2006
+ *
+ *      Anthony Liguori <aliguori@us.ibm.com>
+ *     Daniel Veillard <veillard@redhat.com>
+ *
+ * Copyright 2006-2008 Red Hat
+ *
+ *  This file is subject to the terms and conditions of the GNU Lesser General
+ *  Public License. See the file COPYING in the main directory of this archive
+ *  for more details.
+ */
+
+#ifndef __XEND_INTERNAL_H_
+#define __XEND_INTERNAL_H_
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <libxml/uri.h>
+
+#include "internal.h"
+#include "capabilities.h"
+#include "domain_conf.h"
+#include "driver.h"
+#include "buf.h"
+
+#ifdef __sun
+#define DEFAULT_VIF_SCRIPT "vif-vnic"
+#else
+#define DEFAULT_VIF_SCRIPT "vif-bridge"
+#endif
+
+int
+xenDaemonOpen_unix(virConnectPtr conn, const char *path);
+
+/**
+ * \brief Blocks until a domain's devices are initialized
+ * \param xend A xend instance
+ * \param name The domain's name
+ * \return 0 for success; -1 (with errno) on error
+ *
+ * xen_create() returns after a domain has been allocated including
+ * its memory.  This does not guarentee, though, that the devices
+ * have come up properly.  For instance, if you create a VBD with an
+ * invalid filename, the error won't occur until after this function
+ * returns.
+ */
+    int xend_wait_for_devices(virConnectPtr xend, const char *name);
+
+
+/**
+ * \brief Create a new domain
+ * \param xend A xend instance
+ * \param sexpr An S-Expr defining the domain
+ * \return 0 for success; -1 (with errno) on error
+ *
+ * This method will create a domain based the passed in description.  The
+ * domain will be paused after creation and must be unpaused with
+ * xenDaemonResumeDomain() to begin execution.
+ */
+int xenDaemonDomainCreateXML(virConnectPtr xend, const char *sexpr);
+
+/**
+ * \brief Lookup the id of a domain
+ * \param xend A xend instance
+ * \param name The name of the domain
+ * \param uuid pointer to store a copy of the uuid
+ * \return the id number on success; -1 (with errno) on error
+ *
+ * This method looks up the ids of a domain
+ */
+int xenDaemonDomainLookupByName_ids(virConnectPtr xend,
+                            const char *name, unsigned char *uuid);
+
+
+/**
+ * \brief Lookup the name of a domain
+ * \param xend A xend instance
+ * \param id The id of the domain
+ * \param name pointer to store a copy of the name
+ * \param uuid pointer to store a copy of the uuid
+ *
+ * This method looks up the name/uuid of a domain
+ */
+int xenDaemonDomainLookupByID(virConnectPtr xend,
+                              int id,
+                              char **name, unsigned char *uuid);
+
+
+virDomainDefPtr
+xenDaemonDomainFetch(virConnectPtr xend,
+                     int domid,
+                     const char *name,
+                     const char *cpus);
+
+    int xend_parse_sexp_desc_char(virConnectPtr conn,
+                                  virBufferPtr buf,
+                                  const char *devtype,
+                                  int portNum,
+                                  const char *value,
+                                  const char *tty);
+
+virDomainDefPtr
+xenDaemonParseSxprString(virConnectPtr conn,
+                         const char *sexpr,
+                         int xendConfigVersion);
+
+int
+xenDaemonParseSxprSound(virConnectPtr conn,
+                        virDomainDefPtr def,
+                        const char *str);
+virDomainChrDefPtr
+xenDaemonParseSxprChar(virConnectPtr conn,
+                       const char *value,
+                       const char *tty);
+
+int
+xenDaemonFormatSxprChr(virConnectPtr conn,
+                       virDomainChrDefPtr def,
+                       virBufferPtr buf);
+int
+xenDaemonFormatSxprSound(virConnectPtr conn,
+                         virDomainDefPtr def,
+                         virBufferPtr buf);
+
+char *
+xenDaemonFormatSxpr(virConnectPtr conn,
+                    virDomainDefPtr def,
+                    int xendConfigVersion);
+
+  int is_sound_model_valid(const char *model);
+  int is_sound_model_conflict(const char *model, const char *soundstr);
+
+
+/* refactored ones */
+virDrvOpenStatus xenDaemonOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags);
+int xenDaemonClose(virConnectPtr conn);
+int xenDaemonGetVersion(virConnectPtr conn, unsigned long *hvVer);
+int xenDaemonNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info);
+int xenDaemonNodeGetTopology(virConnectPtr conn, virCapsPtr caps);
+int xenDaemonDomainSuspend(virDomainPtr domain);
+int xenDaemonDomainResume(virDomainPtr domain);
+int xenDaemonDomainShutdown(virDomainPtr domain);
+int xenDaemonDomainReboot(virDomainPtr domain, unsigned int flags);
+int xenDaemonDomainDestroy(virDomainPtr domain);
+int xenDaemonDomainSave(virDomainPtr domain, const char *filename);
+int xenDaemonDomainRestore(virConnectPtr conn, const char *filename);
+int xenDaemonDomainSetMemory(virDomainPtr domain, unsigned long memory);
+int xenDaemonDomainSetMaxMemory(virDomainPtr domain, unsigned long memory);
+int xenDaemonDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info);
+char *xenDaemonDomainDumpXML(virDomainPtr domain, int flags, const char *cpus);
+unsigned long xenDaemonDomainGetMaxMemory(virDomainPtr domain);
+char **xenDaemonListDomainsOld(virConnectPtr xend);
+
+virDomainPtr xenDaemonDomainDefineXML(virConnectPtr xend, const char *sexpr);
+int xenDaemonDomainCreate(virDomainPtr domain);
+int xenDaemonDomainUndefine(virDomainPtr domain);
+
+int    xenDaemonDomainSetVcpus         (virDomainPtr domain,
+                                         unsigned int vcpus);
+int    xenDaemonDomainPinVcpu          (virDomainPtr domain,
+                                         unsigned int vcpu,
+                                         unsigned char *cpumap,
+                                         int maplen);
+int    xenDaemonDomainGetVcpus         (virDomainPtr domain,
+                                         virVcpuInfoPtr info,
+                                         int maxinfo,
+                                         unsigned char *cpumaps,
+                                         int maplen);
+int xenDaemonDomainGetAutostart          (virDomainPtr dom,
+                                          int *autostart);
+int xenDaemonDomainSetAutostart          (virDomainPtr domain,
+                                          int autostart);
+
+/* xen_unified calls through here. */
+extern struct xenUnifiedDriver xenDaemonDriver;
+int xenDaemonInit (void);
+
+virDomainPtr xenDaemonLookupByID(virConnectPtr conn, int id);
+virDomainPtr xenDaemonLookupByUUID(virConnectPtr conn, const unsigned char *uuid);
+virDomainPtr xenDaemonLookupByName(virConnectPtr conn, const char *domname);
+int xenDaemonDomainMigratePrepare (virConnectPtr dconn, char **cookie, int *cookielen, const char *uri_in, char **uri_out, unsigned long flags, const char *dname, unsigned long resource);
+int xenDaemonDomainMigratePerform (virDomainPtr domain, const char *cookie, int cookielen, const char *uri, unsigned long flags, const char *dname, unsigned long resource);
+
+int xenDaemonDomainBlockPeek (virDomainPtr domain, const char *path, unsigned long long offset, size_t size, void *buffer);
+int xenDaemonListDomains(virConnectPtr conn, int *ids, int maxids);
+
+#endif /* __XEND_INTERNAL_H_ */
diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c
new file mode 100644 (file)
index 0000000..960b17a
--- /dev/null
@@ -0,0 +1,3066 @@
+/*
+ * xm_internal.h: helper routines for dealing with inactive domains
+ *
+ * Copyright (C) 2006-2007, 2009 Red Hat
+ * Copyright (C) 2006 Daniel P. Berrange
+ *
+ * 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: Daniel P. Berrange <berrange@redhat.com>
+ *
+ */
+
+#include <config.h>
+
+#include <dirent.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include <string.h>
+#include <errno.h>
+
+#include <unistd.h>
+#include <stdint.h>
+#include <xen/dom0_ops.h>
+
+#include "virterror_internal.h"
+#include "datatypes.h"
+#include "xm_internal.h"
+#include "xen_driver.h"
+#include "xend_internal.h"
+#include "hash.h"
+#include "buf.h"
+#include "uuid.h"
+#include "util.h"
+#include "memory.h"
+#include "logging.h"
+
+#define VIR_FROM_THIS VIR_FROM_XENXM
+
+#ifdef WITH_RHEL5_API
+#define XEND_CONFIG_MAX_VERS_NET_TYPE_IOEMU 0
+#define XEND_CONFIG_MIN_VERS_PVFB_NEWCONF 2
+#else
+#define XEND_CONFIG_MAX_VERS_NET_TYPE_IOEMU 3
+#define XEND_CONFIG_MIN_VERS_PVFB_NEWCONF 3
+#endif
+
+/* The true Xen limit varies but so far is always way
+   less than 1024, which is the Linux kernel limit according
+   to sched.h, so we'll match that for now */
+#define XEN_MAX_PHYSICAL_CPU 1024
+
+static int xenXMConfigSetString(virConfPtr conf, const char *setting,
+                                const char *str);
+char * xenXMAutoAssignMac(void);
+static int xenXMDomainAttachDevice(virDomainPtr domain, const char *xml);
+static int xenXMDomainDetachDevice(virDomainPtr domain, const char *xml);
+
+#define XM_REFRESH_INTERVAL 10
+
+#define XM_CONFIG_DIR "/etc/xen"
+#define XM_EXAMPLE_PREFIX "xmexample"
+#define XEND_CONFIG_FILE "xend-config.sxp"
+#define XEND_PCI_CONFIG_PREFIX "xend-pci-"
+#define QEMU_IF_SCRIPT "qemu-ifup"
+#define XM_XML_ERROR "Invalid xml"
+
+struct xenUnifiedDriver xenXMDriver = {
+    xenXMOpen, /* open */
+    xenXMClose, /* close */
+    NULL, /* version */
+    NULL, /* hostname */
+    NULL, /* nodeGetInfo */
+    NULL, /* getCapabilities */
+    NULL, /* listDomains */
+    NULL, /* numOfDomains */
+    NULL, /* domainCreateXML */
+    NULL, /* domainSuspend */
+    NULL, /* domainResume */
+    NULL, /* domainShutdown */
+    NULL, /* domainReboot */
+    NULL, /* domainDestroy */
+    NULL, /* domainGetOSType */
+    xenXMDomainGetMaxMemory, /* domainGetMaxMemory */
+    xenXMDomainSetMaxMemory, /* domainSetMaxMemory */
+    xenXMDomainSetMemory, /* domainMaxMemory */
+    xenXMDomainGetInfo, /* domainGetInfo */
+    NULL, /* domainSave */
+    NULL, /* domainRestore */
+    NULL, /* domainCoreDump */
+    xenXMDomainSetVcpus, /* domainSetVcpus */
+    xenXMDomainPinVcpu, /* domainPinVcpu */
+    NULL, /* domainGetVcpus */
+    NULL, /* domainGetMaxVcpus */
+    xenXMListDefinedDomains, /* listDefinedDomains */
+    xenXMNumOfDefinedDomains, /* numOfDefinedDomains */
+    xenXMDomainCreate, /* domainCreate */
+    xenXMDomainDefineXML, /* domainDefineXML */
+    xenXMDomainUndefine, /* domainUndefine */
+    xenXMDomainAttachDevice, /* domainAttachDevice */
+    xenXMDomainDetachDevice, /* domainDetachDevice */
+    NULL, /* domainGetAutostart */
+    NULL, /* domainSetAutostart */
+    NULL, /* domainGetSchedulerType */
+    NULL, /* domainGetSchedulerParameters */
+    NULL, /* domainSetSchedulerParameters */
+};
+
+#define xenXMError(conn, code, fmt...)                                       \
+        virReportErrorHelper(conn, VIR_FROM_XENXM, code, __FILE__,         \
+                               __FUNCTION__, __LINE__, fmt)
+
+#ifndef WITH_XEN_INOTIFY
+static int xenInotifyActive(virConnectPtr conn ATTRIBUTE_UNUSED)
+{
+   return 0;
+}
+#else
+static int xenInotifyActive(virConnectPtr conn)
+{
+   xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
+   return priv->inotifyWatch > 0;
+}
+#endif
+
+/* Convenience method to grab a int from the config file object */
+static int xenXMConfigGetBool(virConnectPtr conn,
+                              virConfPtr conf,
+                              const char *name,
+                              int *value,
+                              int def) {
+    virConfValuePtr val;
+
+    *value = 0;
+    if (!(val = virConfGetValue(conf, name))) {
+        *value = def;
+        return 0;
+    }
+
+    if (val->type == VIR_CONF_LONG) {
+        *value = val->l ? 1 : 0;
+    } else if (val->type == VIR_CONF_STRING) {
+        if (!val->str) {
+            *value = def;
+        }
+        *value = STREQ(val->str, "1") ? 1 : 0;
+    } else {
+        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                   _("config value %s was malformed"), name);
+        return -1;
+    }
+    return 0;
+}
+
+
+/* Convenience method to grab a int from the config file object */
+static int xenXMConfigGetULong(virConnectPtr conn,
+                               virConfPtr conf,
+                               const char *name,
+                               unsigned long *value,
+                               int def) {
+    virConfValuePtr val;
+
+    *value = 0;
+    if (!(val = virConfGetValue(conf, name))) {
+        *value = def;
+        return 0;
+    }
+
+    if (val->type == VIR_CONF_LONG) {
+        *value = val->l;
+    } else if (val->type == VIR_CONF_STRING) {
+        char *ret;
+        if (!val->str) {
+            *value = def;
+        }
+        *value = strtol(val->str, &ret, 10);
+        if (ret == val->str) {
+            xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                       _("config value %s was malformed"), name);
+            return -1;
+        }
+    } else {
+        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                   _("config value %s was malformed"), name);
+        return -1;
+    }
+    return 0;
+}
+
+
+/* Convenience method to grab a string from the config file object */
+static int xenXMConfigGetString(virConnectPtr conn,
+                                virConfPtr conf,
+                                const char *name,
+                                const char **value,
+                                const char *def) {
+    virConfValuePtr val;
+
+    *value = NULL;
+    if (!(val = virConfGetValue(conf, name))) {
+        *value = def;
+        return 0;
+    }
+
+    if (val->type != VIR_CONF_STRING) {
+        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                   _("config value %s was malformed"), name);
+        return -1;
+    }
+    if (!val->str)
+        *value = def;
+    else
+        *value = val->str;
+    return 0;
+}
+
+static int xenXMConfigCopyStringInternal(virConnectPtr conn,
+                                         virConfPtr conf,
+                                         const char *name,
+                                         char **value,
+                                         int allowMissing) {
+    virConfValuePtr val;
+
+    *value = NULL;
+    if (!(val = virConfGetValue(conf, name))) {
+        if (allowMissing)
+            return 0;
+        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                   _("config value %s was missing"), name);
+        return -1;
+    }
+
+    if (val->type != VIR_CONF_STRING) {
+        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                   _("config value %s was not a string"), name);
+        return -1;
+    }
+    if (!val->str) {
+        if (allowMissing)
+            return 0;
+        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                   _("config value %s was missing"), name);
+        return -1;
+    }
+
+    if (!(*value = strdup(val->str))) {
+        virReportOOMError(conn);
+        return -1;
+    }
+
+    return 0;
+}
+
+
+static int xenXMConfigCopyString(virConnectPtr conn,
+                                 virConfPtr conf,
+                                 const char *name,
+                                 char **value) {
+    return xenXMConfigCopyStringInternal(conn, conf, name, value, 0);
+}
+
+static int xenXMConfigCopyStringOpt(virConnectPtr conn,
+                                    virConfPtr conf,
+                                    const char *name,
+                                    char **value) {
+    return xenXMConfigCopyStringInternal(conn, conf, name, value, 1);
+}
+
+
+/* Convenience method to grab a string UUID from the config file object */
+static int xenXMConfigGetUUID(virConfPtr conf, const char *name, unsigned char *uuid) {
+    virConfValuePtr val;
+    if (!uuid || !name || !conf)
+        return (-1);
+    if (!(val = virConfGetValue(conf, name))) {
+        return (-1);
+    }
+
+    if (val->type != VIR_CONF_STRING)
+        return (-1);
+    if (!val->str)
+        return (-1);
+
+    if (virUUIDParse(val->str, uuid) < 0)
+        return (-1);
+
+    return (0);
+}
+
+
+/* Release memory associated with a cached config object */
+static void xenXMConfigFree(void *payload, const char *key ATTRIBUTE_UNUSED) {
+    xenXMConfCachePtr entry = (xenXMConfCachePtr)payload;
+    virDomainDefFree(entry->def);
+    VIR_FREE(entry);
+}
+
+struct xenXMConfigReaperData {
+    xenUnifiedPrivatePtr priv;
+    time_t now;
+};
+
+/* Remove any configs which were not refreshed recently */
+static int xenXMConfigReaper(const void *payload, const char *key ATTRIBUTE_UNUSED, const void *data) {
+    const struct xenXMConfigReaperData *args = data;
+    xenXMConfCachePtr entry = (xenXMConfCachePtr)payload;
+
+    /* We're going to purge this config file, so check if it
+       is currently mapped as owner of a named domain. */
+    if (entry->refreshedAt != args->now) {
+        const char *olddomname = entry->def->name;
+        char *nameowner = (char *)virHashLookup(args->priv->nameConfigMap, olddomname);
+        if (nameowner && STREQ(nameowner, key)) {
+            virHashRemoveEntry(args->priv->nameConfigMap, olddomname, NULL);
+        }
+        return (1);
+    }
+    return (0);
+}
+
+
+static virDomainDefPtr
+xenXMConfigReadFile(virConnectPtr conn, const char *filename) {
+    virConfPtr conf;
+    virDomainDefPtr def;
+
+    if (!(conf = virConfReadFile(filename, 0)))
+        return NULL;
+
+    def = xenXMDomainConfigParse(conn, conf);
+    virConfFree(conf);
+
+    return def;
+}
+
+static int
+xenXMConfigSaveFile(virConnectPtr conn, const char *filename, virDomainDefPtr def) {
+    virConfPtr conf;
+    int ret;
+
+    if (!(conf = xenXMDomainConfigFormat(conn, def)))
+        return -1;
+
+    ret = virConfWriteFile(filename, conf);
+    virConfFree(conf);
+    return ret;
+}
+
+
+/*
+ * Caller must hold the lock on 'conn->privateData' before
+ * calling this funtion
+ */
+int
+xenXMConfigCacheRemoveFile(virConnectPtr conn,
+                           const char *filename)
+{
+    xenUnifiedPrivatePtr priv = conn->privateData;
+    xenXMConfCachePtr entry;
+
+    entry = virHashLookup(priv->configCache, filename);
+    if (!entry) {
+        DEBUG("No config entry for %s", filename);
+        return 0;
+    }
+
+    virHashRemoveEntry(priv->nameConfigMap, entry->def->name, NULL);
+    virHashRemoveEntry(priv->configCache, filename, xenXMConfigFree);
+    DEBUG("Removed %s %s", entry->def->name, filename);
+    return 0;
+}
+
+
+/*
+ * Caller must hold the lock on 'conn->privateData' before
+ * calling this funtion
+ */
+int
+xenXMConfigCacheAddFile(virConnectPtr conn, const char *filename)
+{
+    xenUnifiedPrivatePtr priv = conn->privateData;
+    xenXMConfCachePtr entry;
+    struct stat st;
+    int newborn = 0;
+    time_t now = time(NULL);
+
+    DEBUG("Adding file %s", filename);
+
+    /* Get modified time */
+    if ((stat(filename, &st) < 0)) {
+        virReportSystemError(conn, errno,
+                             _("cannot stat: %s"),
+                             filename);
+        return -1;
+    }
+
+    /* Ignore zero length files, because inotify fires before
+       any content has actually been created */
+    if (st.st_size == 0) {
+        DEBUG("Ignoring zero length file %s", filename);
+        return -1;
+    }
+
+    /* If we already have a matching entry and it is not
+    modified, then carry on to next one*/
+    if ((entry = virHashLookup(priv->configCache, filename))) {
+        char *nameowner;
+
+        if (entry->refreshedAt >= st.st_mtime) {
+            entry->refreshedAt = now;
+            /* return success if up-to-date */
+            return 0;
+        }
+
+        /* If we currently own the name, then release it and
+            re-acquire it later - just in case it was renamed */
+        nameowner = (char *)virHashLookup(priv->nameConfigMap, entry->def->name);
+        if (nameowner && STREQ(nameowner, filename)) {
+            virHashRemoveEntry(priv->nameConfigMap, entry->def->name, NULL);
+        }
+
+        /* Clear existing config entry which needs refresh */
+        virDomainDefFree(entry->def);
+        entry->def = NULL;
+    } else { /* Completely new entry */
+        newborn = 1;
+        if (VIR_ALLOC(entry) < 0) {
+            virReportOOMError(conn);
+            return -1;
+        }
+        memcpy(entry->filename, filename, PATH_MAX);
+    }
+    entry->refreshedAt = now;
+
+    if (!(entry->def = xenXMConfigReadFile(conn, entry->filename))) {
+        DEBUG("Failed to read %s", entry->filename);
+        if (!newborn)
+            virHashRemoveEntry(priv->configCache, filename, NULL);
+        VIR_FREE(entry);
+        return -1;
+    }
+
+    /* If its a completely new entry, it must be stuck into
+        the cache (refresh'd entries are already registered) */
+    if (newborn) {
+        if (virHashAddEntry(priv->configCache, entry->filename, entry) < 0) {
+            virDomainDefFree(entry->def);
+            VIR_FREE(entry);
+            xenXMError (conn, VIR_ERR_INTERNAL_ERROR,
+                        "%s", _("xenXMConfigCacheRefresh: virHashAddEntry"));
+            return -1;
+        }
+    }
+
+    /* See if we need to map this config file in as the primary owner
+        * of the domain in question
+        */
+    if (!virHashLookup(priv->nameConfigMap, entry->def->name)) {
+        if (virHashAddEntry(priv->nameConfigMap, entry->def->name, entry->filename) < 0) {
+            virHashRemoveEntry(priv->configCache, filename, NULL);
+            virDomainDefFree(entry->def);
+            VIR_FREE(entry);
+        }
+    }
+    DEBUG("Added config %s %s", entry->def->name, filename);
+
+    return 0;
+}
+
+/* This method is called by various methods to scan /etc/xen
+ * (or whatever directory was set by  LIBVIRT_XM_CONFIG_DIR
+ * environment variable) and process any domain configs. It
+ * has rate-limited so never rescans more frequently than
+ * once every X seconds
+ *
+ * Caller must hold the lock on 'conn->privateData' before
+ * calling this funtion
+ */
+int xenXMConfigCacheRefresh (virConnectPtr conn) {
+    xenUnifiedPrivatePtr priv = conn->privateData;
+    DIR *dh;
+    struct dirent *ent;
+    time_t now = time(NULL);
+    int ret = -1;
+    struct xenXMConfigReaperData args;
+
+    if (now == ((time_t)-1)) {
+        virReportSystemError(conn, errno,
+                             "%s", _("cannot get time of day"));
+        return (-1);
+    }
+
+    /* Rate limit re-scans */
+    if ((now - priv->lastRefresh) < XM_REFRESH_INTERVAL)
+        return (0);
+
+    priv->lastRefresh = now;
+
+    /* Process the files in the config dir */
+    if (!(dh = opendir(priv->configDir))) {
+        virReportSystemError(conn, errno,
+                             _("cannot read directory %s"),
+                             priv->configDir);
+        return (-1);
+    }
+
+    while ((ent = readdir(dh))) {
+        struct stat st;
+        char path[PATH_MAX];
+
+        /*
+         * Skip a bunch of crufty files that clearly aren't config files
+         */
+
+        /* Like 'dot' files... */
+        if (STRPREFIX(ent->d_name, "."))
+            continue;
+        /* ...and the XenD server config file */
+        if (STRPREFIX(ent->d_name, XEND_CONFIG_FILE))
+            continue;
+        /* ...and random PCI config cruft */
+        if (STRPREFIX(ent->d_name, XEND_PCI_CONFIG_PREFIX))
+            continue;
+        /* ...and the example domain configs */
+        if (STRPREFIX(ent->d_name, XM_EXAMPLE_PREFIX))
+            continue;
+        /* ...and the QEMU networking script */
+        if (STRPREFIX(ent->d_name, QEMU_IF_SCRIPT))
+            continue;
+
+        /* ...and editor backups */
+        if (ent->d_name[0] == '#')
+            continue;
+        if (ent->d_name[strlen(ent->d_name)-1] == '~')
+            continue;
+
+        /* Build the full file path */
+        if ((strlen(priv->configDir) + 1 + strlen(ent->d_name) + 1) > PATH_MAX)
+            continue;
+        strcpy(path, priv->configDir);
+        strcat(path, "/");
+        strcat(path, ent->d_name);
+
+        /* Skip anything which isn't a file (takes care of scripts/ subdir */
+        if ((stat(path, &st) < 0) ||
+            (!S_ISREG(st.st_mode))) {
+            continue;
+        }
+
+        /* If we already have a matching entry and it is not
+           modified, then carry on to next one*/
+        if (xenXMConfigCacheAddFile(conn, path) < 0) {
+            /* Ignoring errors, since alot of stuff goes wrong in /etc/xen */
+        }
+    }
+
+    /* Reap all entries which were not changed, by comparing
+       their refresh timestamp - the timestamp should match
+       'now' if they were refreshed. If timestamp doesn't match
+       then the config is no longer on disk */
+    args.now = now;
+    args.priv = priv;
+    virHashRemoveSet(priv->configCache, xenXMConfigReaper, xenXMConfigFree, &args);
+    ret = 0;
+
+    if (dh)
+        closedir(dh);
+
+    return (ret);
+}
+
+
+/*
+ * The XM driver keeps a cache of config files as virDomainDefPtr
+ * objects in the xenUnifiedPrivatePtr. Optionally inotify lets
+ * us watch for changes (see separate driver), otherwise we poll
+ * every few seconds
+ */
+virDrvOpenStatus
+xenXMOpen (virConnectPtr conn,
+           virConnectAuthPtr auth ATTRIBUTE_UNUSED,
+           int flags ATTRIBUTE_UNUSED)
+{
+    xenUnifiedPrivatePtr priv = conn->privateData;
+
+    priv->configDir = XM_CONFIG_DIR;
+
+    priv->configCache = virHashCreate(50);
+    if (!priv->configCache)
+        return (-1);
+    priv->nameConfigMap = virHashCreate(50);
+    if (!priv->nameConfigMap) {
+        virHashFree(priv->configCache, NULL);
+        priv->configCache = NULL;
+        return (-1);
+    }
+    /* Force the cache to be reloaded next time that
+     * xenXMConfigCacheRefresh is called.
+     */
+    priv->lastRefresh = 0;
+
+    return (0);
+}
+
+/*
+ * Free the cached config files associated with this
+ * connection
+ */
+int xenXMClose(virConnectPtr conn) {
+    xenUnifiedPrivatePtr priv = conn->privateData;
+
+    virHashFree(priv->nameConfigMap, NULL);
+    virHashFree(priv->configCache, xenXMConfigFree);
+
+    return (0);
+}
+
+/*
+ * Since these are all offline domains, we only return info about
+ * VCPUs and memory.
+ */
+int xenXMDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info) {
+    xenUnifiedPrivatePtr priv;
+    const char *filename;
+    xenXMConfCachePtr entry;
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
+        xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                   __FUNCTION__);
+        return(-1);
+    }
+
+    if (domain->id != -1)
+        return (-1);
+
+    priv = domain->conn->privateData;
+    xenUnifiedLock(priv);
+
+    if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
+        goto error;
+
+    if (!(entry = virHashLookup(priv->configCache, filename)))
+        goto error;
+
+    memset(info, 0, sizeof(virDomainInfo));
+    info->maxMem = entry->def->maxmem;
+    info->memory = entry->def->memory;
+    info->nrVirtCpu = entry->def->vcpus;
+    info->state = VIR_DOMAIN_SHUTOFF;
+    info->cpuTime = 0;
+
+    xenUnifiedUnlock(priv);
+    return (0);
+
+error:
+    xenUnifiedUnlock(priv);
+    return -1;
+}
+
+#define MAX_VFB 1024
+/*
+ * Turn a config record into a lump of XML describing the
+ * domain, suitable for later feeding for virDomainCreateXML
+ */
+virDomainDefPtr
+xenXMDomainConfigParse(virConnectPtr conn, virConfPtr conf) {
+    const char *str;
+    int hvm = 0;
+    int val;
+    virConfValuePtr list;
+    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
+    virDomainDefPtr def = NULL;
+    virDomainDiskDefPtr disk = NULL;
+    virDomainNetDefPtr net = NULL;
+    virDomainGraphicsDefPtr graphics = NULL;
+    virDomainHostdevDefPtr hostdev = NULL;
+    int i;
+    const char *defaultArch, *defaultMachine;
+
+    if (VIR_ALLOC(def) < 0)
+        return NULL;
+
+    def->virtType = VIR_DOMAIN_VIRT_XEN;
+    def->id = -1;
+
+    if (xenXMConfigCopyString(conn, conf, "name", &def->name) < 0)
+        goto cleanup;
+    if (xenXMConfigGetUUID(conf, "uuid", def->uuid) < 0)
+        goto cleanup;
+
+
+    if ((xenXMConfigGetString(conn, conf, "builder", &str, "linux") == 0) &&
+        STREQ(str, "hvm"))
+        hvm = 1;
+
+    if (!(def->os.type = strdup(hvm ? "hvm" : "xen")))
+        goto no_memory;
+
+    defaultArch = virCapabilitiesDefaultGuestArch(priv->caps, def->os.type, virDomainVirtTypeToString(def->virtType));
+    if (defaultArch == NULL) {
+        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                   _("no supported architecture for os type '%s'"),
+                   def->os.type);
+        goto cleanup;
+    }
+    if (!(def->os.arch = strdup(defaultArch)))
+        goto no_memory;
+
+    defaultMachine = virCapabilitiesDefaultGuestMachine(priv->caps,
+                                                        def->os.type,
+                                                        def->os.arch);
+    if (defaultMachine != NULL) {
+        if (!(def->os.machine = strdup(defaultMachine)))
+            goto no_memory;
+    }
+
+    if (hvm) {
+        const char *boot;
+        if (xenXMConfigCopyString(conn, conf, "kernel", &def->os.loader) < 0)
+            goto cleanup;
+
+        if (xenXMConfigGetString(conn, conf, "boot", &boot, "c") < 0)
+            goto cleanup;
+
+        for (i = 0 ; i < VIR_DOMAIN_BOOT_LAST && boot[i] ; i++) {
+            switch (*boot) {
+            case 'a':
+                def->os.bootDevs[i] = VIR_DOMAIN_BOOT_FLOPPY;
+                break;
+            case 'd':
+                def->os.bootDevs[i] = VIR_DOMAIN_BOOT_CDROM;
+                break;
+            case 'n':
+                def->os.bootDevs[i] = VIR_DOMAIN_BOOT_NET;
+                break;
+            case 'c':
+            default:
+                def->os.bootDevs[i] = VIR_DOMAIN_BOOT_DISK;
+                break;
+            }
+            def->os.nBootDevs++;
+        }
+    } else {
+        if (xenXMConfigCopyStringOpt(conn, conf, "bootloader", &def->os.bootloader) < 0)
+            goto cleanup;
+        if (xenXMConfigCopyStringOpt(conn, conf, "bootargs", &def->os.bootloaderArgs) < 0)
+            goto cleanup;
+
+        if (xenXMConfigCopyStringOpt(conn, conf, "kernel", &def->os.kernel) < 0)
+            goto cleanup;
+        if (xenXMConfigCopyStringOpt(conn, conf, "ramdisk", &def->os.initrd) < 0)
+            goto cleanup;
+        if (xenXMConfigCopyStringOpt(conn, conf, "extra", &def->os.cmdline) < 0)
+            goto cleanup;
+    }
+
+    if (xenXMConfigGetULong(conn, conf, "memory", &def->memory, MIN_XEN_GUEST_SIZE * 2) < 0)
+        goto cleanup;
+
+    if (xenXMConfigGetULong(conn, conf, "maxmem", &def->maxmem, def->memory) < 0)
+        goto cleanup;
+
+    def->memory *= 1024;
+    def->maxmem *= 1024;
+
+
+    if (xenXMConfigGetULong(conn, conf, "vcpus", &def->vcpus, 1) < 0)
+        goto cleanup;
+
+    if (xenXMConfigGetString(conn, conf, "cpus", &str, NULL) < 0)
+        goto cleanup;
+    if (str) {
+        def->cpumasklen = 4096;
+        if (VIR_ALLOC_N(def->cpumask, def->cpumasklen) < 0)
+            goto no_memory;
+
+        if (virDomainCpuSetParse(conn, &str, 0,
+                                 def->cpumask, def->cpumasklen) < 0)
+            goto cleanup;
+    }
+
+
+    if (xenXMConfigGetString(conn, conf, "on_poweroff", &str, "destroy") < 0)
+        goto cleanup;
+    if ((def->onPoweroff = virDomainLifecycleTypeFromString(str)) < 0) {
+        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                   _("unexpected value %s for on_poweroff"), str);
+        goto cleanup;
+    }
+
+    if (xenXMConfigGetString(conn, conf, "on_reboot", &str, "restart") < 0)
+        goto cleanup;
+    if ((def->onReboot = virDomainLifecycleTypeFromString(str)) < 0) {
+        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                   _("unexpected value %s for on_reboot"), str);
+        goto cleanup;
+    }
+
+    if (xenXMConfigGetString(conn, conf, "on_crash", &str, "restart") < 0)
+        goto cleanup;
+    if ((def->onCrash = virDomainLifecycleTypeFromString(str)) < 0) {
+        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                   _("unexpected value %s for on_crash"), str);
+        goto cleanup;
+    }
+
+
+
+    if (hvm) {
+        if (xenXMConfigGetBool(conn, conf, "pae", &val, 0) < 0)
+            goto cleanup;
+        else if (val)
+            def->features |= (1 << VIR_DOMAIN_FEATURE_PAE);
+        if (xenXMConfigGetBool(conn, conf, "acpi", &val, 0) < 0)
+            goto cleanup;
+        else if (val)
+            def->features |= (1 << VIR_DOMAIN_FEATURE_ACPI);
+        if (xenXMConfigGetBool(conn, conf, "apic", &val, 0) < 0)
+            goto cleanup;
+        else if (val)
+            def->features |= (1 << VIR_DOMAIN_FEATURE_APIC);
+    }
+    if (xenXMConfigGetBool(conn, conf, "localtime", &def->localtime, 0) < 0)
+        goto cleanup;
+
+    if (xenXMConfigCopyStringOpt(conn, conf, "device_model", &def->emulator) < 0)
+        goto cleanup;
+
+    list = virConfGetValue(conf, "disk");
+    if (list && list->type == VIR_CONF_LIST) {
+        list = list->list;
+        while (list) {
+            char *head;
+            char *offset;
+            char *tmp;
+
+            if ((list->type != VIR_CONF_STRING) || (list->str == NULL))
+                goto skipdisk;
+            head = list->str;
+
+            if (VIR_ALLOC(disk) < 0)
+                goto no_memory;
+
+            /*
+             * Disks have 3 components, SOURCE,DEST-DEVICE,MODE
+             * eg, phy:/dev/HostVG/XenGuest1,xvda,w
+             * The SOURCE is usually prefixed with a driver type,
+             * and optionally driver sub-type
+             * The DEST-DEVICE is optionally post-fixed with disk type
+             */
+
+            /* Extract the source file path*/
+            if (!(offset = strchr(head, ',')))
+                goto skipdisk;
+            if ((offset - head) >= (PATH_MAX-1))
+                goto skipdisk;
+
+            if (offset == head) {
+                disk->src = NULL; /* No source file given, eg CDROM with no media */
+            } else {
+                if (VIR_ALLOC_N(disk->src, (offset - head) + 1) < 0)
+                    goto no_memory;
+                strncpy(disk->src, head, (offset - head));
+                disk->src[(offset-head)] = '\0';
+            }
+            head = offset + 1;
+
+            /* Remove legacy ioemu: junk */
+            if (STRPREFIX(head, "ioemu:"))
+                head = head + 6;
+
+            /* Extract the dest device name */
+            if (!(offset = strchr(head, ',')))
+                goto skipdisk;
+            if (VIR_ALLOC_N(disk->dst, (offset - head) + 1) < 0)
+                goto no_memory;
+            strncpy(disk->dst, head, (offset - head));
+            disk->dst[(offset-head)] = '\0';
+            head = offset + 1;
+
+
+            /* Extract source driver type */
+            if (disk->src) {
+                /* The main type  phy:, file:, tap: ... */
+                if ((tmp = strchr(disk->src, ':')) != NULL) {
+                    if (VIR_ALLOC_N(disk->driverName, (tmp - disk->src) + 1) < 0)
+                        goto no_memory;
+                    strncpy(disk->driverName, disk->src, (tmp - disk->src));
+                    disk->driverName[tmp - disk->src] = '\0';
+
+                    /* Strip the prefix we found off the source file name */
+                    memmove(disk->src, disk->src+(tmp-disk->src)+1,
+                            strlen(disk->src)-(tmp-disk->src));
+                }
+
+                /* And the sub-type for tap:XXX: type */
+                if (disk->driverName &&
+                    STREQ(disk->driverName, "tap")) {
+                    if (!(tmp = strchr(disk->src, ':')))
+                        goto skipdisk;
+                    if (VIR_ALLOC_N(disk->driverType, (tmp - disk->src) + 1) < 0)
+                        goto no_memory;
+                    strncpy(disk->driverType, disk->src, (tmp - disk->src));
+                    disk->driverType[tmp - disk->src] = '\0';
+
+                    /* Strip the prefix we found off the source file name */
+                    memmove(disk->src, disk->src+(tmp-disk->src)+1,
+                            strlen(disk->src)-(tmp-disk->src));
+                }
+            }
+
+            /* No source, or driver name, so fix to phy: */
+            if (!disk->driverName &&
+                !(disk->driverName = strdup("phy")))
+                goto no_memory;
+
+
+            /* phy: type indicates a block device */
+            disk->type = STREQ(disk->driverName, "phy") ?
+                VIR_DOMAIN_DISK_TYPE_BLOCK : VIR_DOMAIN_DISK_TYPE_FILE;
+
+            /* Check for a :cdrom/:disk postfix */
+            disk->device = VIR_DOMAIN_DISK_DEVICE_DISK;
+            if ((tmp = strchr(disk->dst, ':')) != NULL) {
+                if (STREQ(tmp, ":cdrom"))
+                    disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
+                tmp[0] = '\0';
+            }
+
+            if (STRPREFIX(disk->dst, "xvd") || !hvm) {
+                disk->bus = VIR_DOMAIN_DISK_BUS_XEN;
+            } else if (STRPREFIX(disk->dst, "sd")) {
+                disk->bus = VIR_DOMAIN_DISK_BUS_SCSI;
+            } else {
+                disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
+            }
+
+            if (STREQ(head, "r") ||
+                STREQ(head, "ro"))
+                disk->readonly = 1;
+            else if ((STREQ(head, "w!")) ||
+                     (STREQ(head, "!")))
+                disk->shared = 1;
+
+            /* Maintain list in sorted order according to target device name */
+            if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0)
+                goto no_memory;
+            def->disks[def->ndisks++] = disk;
+            disk = NULL;
+
+            skipdisk:
+            list = list->next;
+            virDomainDiskDefFree(disk);
+        }
+    }
+
+    if (hvm && priv->xendConfigVersion == 1) {
+        if (xenXMConfigGetString(conn, conf, "cdrom", &str, NULL) < 0)
+            goto cleanup;
+        if (str) {
+            if (VIR_ALLOC(disk) < 0)
+                goto no_memory;
+
+            disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
+            disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
+            if (!(disk->driverName = strdup("file")))
+                goto no_memory;
+            if (!(disk->src = strdup(str)))
+                goto no_memory;
+            if (!(disk->dst = strdup("hdc")))
+                goto no_memory;
+            disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
+            disk->readonly = 1;
+
+            if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0)
+                goto no_memory;
+            def->disks[def->ndisks++] = disk;
+            disk = NULL;
+        }
+    }
+
+    list = virConfGetValue(conf, "vif");
+    if (list && list->type == VIR_CONF_LIST) {
+        list = list->list;
+        while (list) {
+            char script[PATH_MAX];
+            char model[10];
+            char ip[16];
+            char mac[18];
+            char bridge[50];
+            char vifname[50];
+            char *key;
+
+            bridge[0] = '\0';
+            mac[0] = '\0';
+            script[0] = '\0';
+            ip[0] = '\0';
+            model[0] = '\0';
+            vifname[0] = '\0';
+
+            if ((list->type != VIR_CONF_STRING) || (list->str == NULL))
+                goto skipnic;
+
+            key = list->str;
+            while (key) {
+                char *data;
+                char *nextkey = strchr(key, ',');
+
+                if (!(data = strchr(key, '=')))
+                    goto skipnic;
+                data++;
+
+                if (STRPREFIX(key, "mac=")) {
+                    int len = nextkey ? (nextkey - data) : 17;
+                    if (len > 17)
+                        len = 17;
+                    strncpy(mac, data, len);
+                    mac[len] = '\0';
+                } else if (STRPREFIX(key, "bridge=")) {
+                    int len = nextkey ? (nextkey - data) : sizeof(bridge)-1;
+                    if (len > (sizeof(bridge)-1))
+                        len = sizeof(bridge)-1;
+                    strncpy(bridge, data, len);
+                    bridge[len] = '\0';
+                } else if (STRPREFIX(key, "script=")) {
+                    int len = nextkey ? (nextkey - data) : PATH_MAX-1;
+                    if (len > (PATH_MAX-1))
+                        len = PATH_MAX-1;
+                    strncpy(script, data, len);
+                    script[len] = '\0';
+                } else if (STRPREFIX(key, "model=")) {
+                    int len = nextkey ? (nextkey - data) : sizeof(model)-1;
+                    if (len > (sizeof(model)-1))
+                        len = sizeof(model)-1;
+                    strncpy(model, data, len);
+                    model[len] = '\0';
+                } else if (STRPREFIX(key, "vifname=")) {
+                    int len = nextkey ? (nextkey - data) : sizeof(vifname)-1;
+                    if (len > (sizeof(vifname)-1))
+                        len = sizeof(vifname)-1;
+                    strncpy(vifname, data, len);
+                    vifname[len] = '\0';
+                } else if (STRPREFIX(key, "ip=")) {
+                    int len = nextkey ? (nextkey - data) : 15;
+                    if (len > 15)
+                        len = 15;
+                    strncpy(ip, data, len);
+                    ip[len] = '\0';
+                }
+
+                while (nextkey && (nextkey[0] == ',' ||
+                                   nextkey[0] == ' ' ||
+                                   nextkey[0] == '\t'))
+                    nextkey++;
+                key = nextkey;
+            }
+
+            if (VIR_ALLOC(net) < 0)
+                goto cleanup;
+
+            if (mac[0]) {
+                unsigned int rawmac[6];
+                sscanf(mac, "%02x:%02x:%02x:%02x:%02x:%02x",
+                       (unsigned int*)&rawmac[0],
+                       (unsigned int*)&rawmac[1],
+                       (unsigned int*)&rawmac[2],
+                       (unsigned int*)&rawmac[3],
+                       (unsigned int*)&rawmac[4],
+                       (unsigned int*)&rawmac[5]);
+                net->mac[0] = rawmac[0];
+                net->mac[1] = rawmac[1];
+                net->mac[2] = rawmac[2];
+                net->mac[3] = rawmac[3];
+                net->mac[4] = rawmac[4];
+                net->mac[5] = rawmac[5];
+            }
+
+            if (bridge[0] || STREQ(script, "vif-bridge") ||
+                STREQ(script, "vif-vnic")) {
+                net->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
+            } else {
+                net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
+            }
+
+            if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
+                if (bridge[0] &&
+                    !(net->data.bridge.brname = strdup(bridge)))
+                    goto no_memory;
+                if (script[0] &&
+                    !(net->data.bridge.script = strdup(script)))
+                    goto no_memory;
+                if (ip[0] &&
+                    !(net->data.bridge.ipaddr = strdup(ip)))
+                    goto no_memory;
+            } else {
+                if (script[0] &&
+                    !(net->data.ethernet.script = strdup(script)))
+                    goto no_memory;
+                if (ip[0] &&
+                    !(net->data.ethernet.ipaddr = strdup(ip)))
+                    goto no_memory;
+            }
+            if (model[0] &&
+                !(net->model = strdup(model)))
+                goto no_memory;
+
+            if (vifname[0] &&
+                !(net->ifname = strdup(vifname)))
+                goto no_memory;
+
+            if (VIR_REALLOC_N(def->nets, def->nnets+1) < 0)
+                goto no_memory;
+            def->nets[def->nnets++] = net;
+            net = NULL;
+
+        skipnic:
+            list = list->next;
+            virDomainNetDefFree(net);
+        }
+    }
+
+    list = virConfGetValue(conf, "pci");
+    if (list && list->type == VIR_CONF_LIST) {
+        list = list->list;
+        while (list) {
+            char domain[5];
+            char bus[3];
+            char slot[3];
+            char func[2];
+            char *key, *nextkey;
+            int domainID;
+            int busID;
+            int slotID;
+            int funcID;
+
+            domain[0] = bus[0] = slot[0] = func[0] = '\0';
+
+            if ((list->type != VIR_CONF_STRING) || (list->str == NULL))
+                goto skippci;
+
+            /* pci=['0000:00:1b.0','0000:00:13.0'] */
+            if (!(key = list->str))
+                goto skippci;
+            if (!(nextkey = strchr(key, ':')))
+                goto skippci;
+
+            if ((nextkey - key) > (sizeof(domain)-1))
+                goto skippci;
+
+            strncpy(domain, key, sizeof(domain));
+            domain[sizeof(domain)-1] = '\0';
+
+            key = nextkey + 1;
+            if (!(nextkey = strchr(key, ':')))
+                goto skippci;
+
+            strncpy(bus, key, sizeof(bus));
+            bus[sizeof(bus)-1] = '\0';
+
+            key = nextkey + 1;
+            if (!(nextkey = strchr(key, '.')))
+                goto skippci;
+
+            strncpy(slot, key, sizeof(slot));
+            slot[sizeof(slot)-1] = '\0';
+
+            key = nextkey + 1;
+            if (strlen(key) != 1)
+                goto skippci;
+
+            strncpy(func, key, sizeof(func));
+            func[sizeof(func)-1] = '\0';
+
+            if (virStrToLong_i(domain, NULL, 16, &domainID) < 0)
+                goto skippci;
+            if (virStrToLong_i(bus, NULL, 16, &busID) < 0)
+                goto skippci;
+            if (virStrToLong_i(slot, NULL, 16, &slotID) < 0)
+                goto skippci;
+            if (virStrToLong_i(func, NULL, 16, &funcID) < 0)
+                goto skippci;
+
+            if (VIR_ALLOC(hostdev) < 0)
+                goto cleanup;
+
+            hostdev->managed = 0;
+            hostdev->source.subsys.type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI;
+            hostdev->source.subsys.u.pci.domain = domainID;
+            hostdev->source.subsys.u.pci.bus = busID;
+            hostdev->source.subsys.u.pci.slot = slotID;
+            hostdev->source.subsys.u.pci.function = funcID;
+
+            if (VIR_REALLOC_N(def->hostdevs, def->nhostdevs+1) < 0)
+                goto no_memory;
+            def->hostdevs[def->nhostdevs++] = hostdev;
+            hostdev = NULL;
+
+        skippci:
+            list = list->next;
+        }
+    }
+
+    if (hvm) {
+        if (xenXMConfigGetString(conn, conf, "usbdevice", &str, NULL) < 0)
+            goto cleanup;
+        if (str &&
+            (STREQ(str, "tablet") ||
+             STREQ(str, "mouse"))) {
+            virDomainInputDefPtr input;
+            if (VIR_ALLOC(input) < 0)
+                goto no_memory;
+            input->bus = VIR_DOMAIN_INPUT_BUS_USB;
+            input->type = STREQ(str, "tablet") ?
+                VIR_DOMAIN_INPUT_TYPE_TABLET :
+                VIR_DOMAIN_INPUT_TYPE_MOUSE;
+            if (VIR_ALLOC_N(def->inputs, 1) < 0) {
+                virDomainInputDefFree(input);
+                goto no_memory;
+            }
+            def->inputs[0] = input;
+            def->ninputs = 1;
+        }
+    }
+
+    /* HVM guests, or old PV guests use this config format */
+    if (hvm || priv->xendConfigVersion < 3) {
+        if (xenXMConfigGetBool(conn, conf, "vnc", &val, 0) < 0)
+            goto cleanup;
+
+        if (val) {
+            if (VIR_ALLOC(graphics) < 0)
+                goto no_memory;
+            graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_VNC;
+            if (xenXMConfigGetBool(conn, conf, "vncunused", &val, 1) < 0)
+                goto cleanup;
+            graphics->data.vnc.autoport = val ? 1 : 0;
+
+            if (!graphics->data.vnc.autoport) {
+                unsigned long vncdisplay;
+                if (xenXMConfigGetULong(conn, conf, "vncdisplay", &vncdisplay, 0) < 0)
+                    goto cleanup;
+                graphics->data.vnc.port = (int)vncdisplay + 5900;
+            }
+            if (xenXMConfigCopyStringOpt(conn, conf, "vnclisten", &graphics->data.vnc.listenAddr) < 0)
+                goto cleanup;
+            if (xenXMConfigCopyStringOpt(conn, conf, "vncpasswd", &graphics->data.vnc.passwd) < 0)
+                goto cleanup;
+            if (xenXMConfigCopyStringOpt(conn, conf, "keymap", &graphics->data.vnc.keymap) < 0)
+                goto cleanup;
+
+            if (VIR_ALLOC_N(def->graphics, 1) < 0)
+                goto no_memory;
+            def->graphics[0] = graphics;
+            def->ngraphics = 1;
+            graphics = NULL;
+        } else {
+            if (xenXMConfigGetBool(conn, conf, "sdl", &val, 0) < 0)
+                goto cleanup;
+            if (val) {
+                if (VIR_ALLOC(graphics) < 0)
+                    goto no_memory;
+                graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_SDL;
+                if (xenXMConfigCopyStringOpt(conn, conf, "display", &graphics->data.sdl.display) < 0)
+                    goto cleanup;
+                if (xenXMConfigCopyStringOpt(conn, conf, "xauthority", &graphics->data.sdl.xauth) < 0)
+                    goto cleanup;
+                if (VIR_ALLOC_N(def->graphics, 1) < 0)
+                    goto no_memory;
+                def->graphics[0] = graphics;
+                def->ngraphics = 1;
+                graphics = NULL;
+            }
+        }
+    }
+
+    if (!hvm && def->graphics == NULL) { /* New PV guests use this format */
+        list = virConfGetValue(conf, "vfb");
+        if (list && list->type == VIR_CONF_LIST &&
+            list->list && list->list->type == VIR_CONF_STRING &&
+            list->list->str) {
+            char vfb[MAX_VFB];
+            char *key = vfb;
+            strncpy(vfb, list->list->str, MAX_VFB-1);
+            vfb[MAX_VFB-1] = '\0';
+
+            if (VIR_ALLOC(graphics) < 0)
+                goto no_memory;
+
+            if (strstr(key, "type=sdl"))
+                graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_SDL;
+            else
+                graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_VNC;
+
+            while (key) {
+                char *data;
+                char *nextkey = strchr(key, ',');
+                char *end = nextkey;
+                if (nextkey) {
+                    *end = '\0';
+                    nextkey++;
+                }
+
+                if (!(data = strchr(key, '=')))
+                    break;
+
+                if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
+                    if (STRPREFIX(key, "vncunused=")) {
+                        if (STREQ(key + 10, "1"))
+                            graphics->data.vnc.autoport = 1;
+                    } else if (STRPREFIX(key, "vnclisten=")) {
+                        if (!(graphics->data.vnc.listenAddr = strdup(key + 10)))
+                            goto no_memory;
+                    } else if (STRPREFIX(key, "vncpasswd=")) {
+                        if (!(graphics->data.vnc.passwd = strdup(key + 10)))
+                            goto no_memory;
+                    } else if (STRPREFIX(key, "keymap=")) {
+                        if (!(graphics->data.vnc.keymap = strdup(key + 7)))
+                            goto no_memory;
+                    } else if (STRPREFIX(key, "vncdisplay=")) {
+                        graphics->data.vnc.port = strtol(key+11, NULL, 10) + 5900;
+                    }
+                } else {
+                    if (STRPREFIX(key, "display=")) {
+                        if (!(graphics->data.sdl.display = strdup(key + 8)))
+                            goto no_memory;
+                    } else if (STRPREFIX(key, "xauthority=")) {
+                        if (!(graphics->data.sdl.xauth = strdup(key + 11)))
+                            goto no_memory;
+                    }
+                }
+
+                while (nextkey && (nextkey[0] == ',' ||
+                                   nextkey[0] == ' ' ||
+                                   nextkey[0] == '\t'))
+                    nextkey++;
+                key = nextkey;
+            }
+            if (VIR_ALLOC_N(def->graphics, 1) < 0)
+                goto no_memory;
+            def->graphics[0] = graphics;
+            def->ngraphics = 1;
+            graphics = NULL;
+        }
+    }
+
+    if (hvm) {
+        virDomainChrDefPtr chr = NULL;
+
+        if (xenXMConfigGetString(conn, conf, "parallel", &str, NULL) < 0)
+            goto cleanup;
+        if (str && STRNEQ(str, "none") &&
+            !(chr = xenDaemonParseSxprChar(conn, str, NULL)))
+            goto cleanup;
+
+        if (chr) {
+            if (VIR_ALLOC_N(def->parallels, 1) < 0) {
+                virDomainChrDefFree(chr);
+                goto no_memory;
+            }
+            def->parallels[0] = chr;
+            def->nparallels++;
+            chr = NULL;
+        }
+
+        if (xenXMConfigGetString(conn, conf, "serial", &str, NULL) < 0)
+            goto cleanup;
+        if (str && STRNEQ(str, "none") &&
+            !(chr = xenDaemonParseSxprChar(conn, str, NULL)))
+            goto cleanup;
+
+        if (chr) {
+            if (VIR_ALLOC_N(def->serials, 1) < 0) {
+                virDomainChrDefFree(chr);
+                goto no_memory;
+            }
+            def->serials[0] = chr;
+            def->nserials++;
+        }
+    } else {
+        if (!(def->console = xenDaemonParseSxprChar(conn, "pty", NULL)))
+            goto cleanup;
+    }
+
+    if (hvm) {
+        if (xenXMConfigGetString(conn, conf, "soundhw", &str, NULL) < 0)
+            goto cleanup;
+
+        if (str &&
+            xenDaemonParseSxprSound(conn, def, str) < 0)
+            goto cleanup;
+    }
+
+    return def;
+
+no_memory:
+    virReportOOMError(conn);
+    /* fallthrough */
+cleanup:
+    virDomainGraphicsDefFree(graphics);
+    virDomainNetDefFree(net);
+    virDomainDiskDefFree(disk);
+    virDomainDefFree(def);
+    return NULL;
+}
+
+
+/*
+ * Turn a config record into a lump of XML describing the
+ * domain, suitable for later feeding for virDomainCreateXML
+ */
+char *xenXMDomainDumpXML(virDomainPtr domain, int flags) {
+    xenUnifiedPrivatePtr priv;
+    const char *filename;
+    xenXMConfCachePtr entry;
+    char *ret = NULL;
+
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
+        xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                   __FUNCTION__);
+        return(NULL);
+    }
+    if (domain->id != -1)
+        return (NULL);
+
+    priv = domain->conn->privateData;
+    xenUnifiedLock(priv);
+
+    if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
+        goto cleanup;
+
+    if (!(entry = virHashLookup(priv->configCache, filename)))
+        goto cleanup;
+
+    ret = virDomainDefFormat(domain->conn, entry->def, flags);
+
+cleanup:
+    xenUnifiedUnlock(priv);
+    return ret;
+}
+
+
+/*
+ * Update amount of memory in the config file
+ */
+int xenXMDomainSetMemory(virDomainPtr domain, unsigned long memory) {
+    xenUnifiedPrivatePtr priv;
+    const char *filename;
+    xenXMConfCachePtr entry;
+    int ret = -1;
+
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
+        xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                   __FUNCTION__);
+        return (-1);
+    }
+    if (domain->conn->flags & VIR_CONNECT_RO)
+        return (-1);
+    if (domain->id != -1)
+        return (-1);
+    if (memory < 1024 * MIN_XEN_GUEST_SIZE)
+        return (-1);
+
+    priv = domain->conn->privateData;
+    xenUnifiedLock(priv);
+
+    if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
+        goto cleanup;
+
+    if (!(entry = virHashLookup(priv->configCache, filename)))
+        goto cleanup;
+
+    entry->def->memory = memory;
+    if (entry->def->memory > entry->def->maxmem)
+        entry->def->memory = entry->def->maxmem;
+
+    /* If this fails, should we try to undo our changes to the
+     * in-memory representation of the config file. I say not!
+     */
+    if (xenXMConfigSaveFile(domain->conn, entry->filename, entry->def) < 0)
+        goto cleanup;
+    ret = 0;
+
+cleanup:
+    xenUnifiedUnlock(priv);
+    return ret;
+}
+
+/*
+ * Update maximum memory limit in config
+ */
+int xenXMDomainSetMaxMemory(virDomainPtr domain, unsigned long memory) {
+    xenUnifiedPrivatePtr priv;
+    const char *filename;
+    xenXMConfCachePtr entry;
+    int ret = -1;
+
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
+        xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                   __FUNCTION__);
+        return (-1);
+    }
+    if (domain->conn->flags & VIR_CONNECT_RO)
+        return (-1);
+    if (domain->id != -1)
+        return (-1);
+
+    priv = domain->conn->privateData;
+    xenUnifiedLock(priv);
+
+    if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
+        goto cleanup;
+
+    if (!(entry = virHashLookup(priv->configCache, filename)))
+        goto cleanup;
+
+    entry->def->maxmem = memory;
+    if (entry->def->memory > entry->def->maxmem)
+        entry->def->memory = entry->def->maxmem;
+
+    /* If this fails, should we try to undo our changes to the
+     * in-memory representation of the config file. I say not!
+     */
+    if (xenXMConfigSaveFile(domain->conn, entry->filename, entry->def) < 0)
+        goto cleanup;
+    ret = 0;
+
+cleanup:
+    xenUnifiedUnlock(priv);
+    return ret;
+}
+
+/*
+ * Get max memory limit from config
+ */
+unsigned long xenXMDomainGetMaxMemory(virDomainPtr domain) {
+    xenUnifiedPrivatePtr priv;
+    const char *filename;
+    xenXMConfCachePtr entry;
+    unsigned long ret = 0;
+
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
+        xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                   __FUNCTION__);
+        return (0);
+    }
+    if (domain->id != -1)
+        return (0);
+
+    priv = domain->conn->privateData;
+    xenUnifiedLock(priv);
+
+    if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
+        goto cleanup;
+
+    if (!(entry = virHashLookup(priv->configCache, filename)))
+        goto cleanup;
+
+    ret = entry->def->maxmem;
+
+cleanup:
+    xenUnifiedUnlock(priv);
+    return ret;
+}
+
+/*
+ * Set the VCPU count in config
+ */
+int xenXMDomainSetVcpus(virDomainPtr domain, unsigned int vcpus) {
+    xenUnifiedPrivatePtr priv;
+    const char *filename;
+    xenXMConfCachePtr entry;
+    int ret = -1;
+
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
+        xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                   __FUNCTION__);
+        return (-1);
+    }
+    if (domain->conn->flags & VIR_CONNECT_RO)
+        return (-1);
+    if (domain->id != -1)
+        return (-1);
+
+    priv = domain->conn->privateData;
+    xenUnifiedLock(priv);
+
+    if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
+        goto cleanup;
+
+    if (!(entry = virHashLookup(priv->configCache, filename)))
+        goto cleanup;
+
+    entry->def->vcpus = vcpus;
+
+    /* If this fails, should we try to undo our changes to the
+     * in-memory representation of the config file. I say not!
+     */
+    if (xenXMConfigSaveFile(domain->conn, entry->filename, entry->def) < 0)
+        goto cleanup;
+    ret = 0;
+
+cleanup:
+    xenUnifiedUnlock(priv);
+    return ret;
+}
+
+/**
+ * xenXMDomainPinVcpu:
+ * @domain: pointer to domain object
+ * @vcpu: virtual CPU number (reserved)
+ * @cpumap: pointer to a bit map of real CPUs (in 8-bit bytes)
+ * @maplen: length of cpumap in bytes
+ *
+ * Set the vcpu affinity in config
+ *
+ * Returns 0 for success; -1 (with errno) on error
+ */
+int xenXMDomainPinVcpu(virDomainPtr domain,
+                       unsigned int vcpu ATTRIBUTE_UNUSED,
+                       unsigned char *cpumap, int maplen)
+{
+    xenUnifiedPrivatePtr priv;
+    const char *filename;
+    xenXMConfCachePtr entry;
+    virBuffer mapbuf = VIR_BUFFER_INITIALIZER;
+    char *mapstr = NULL, *mapsave = NULL;
+    int i, j, n, comma = 0;
+    int ret = -1;
+    char *cpuset = NULL;
+    int maxcpu = XEN_MAX_PHYSICAL_CPU;
+
+    if (domain == NULL || domain->conn == NULL || domain->name == NULL
+        || cpumap == NULL || maplen < 1 || maplen > (int)sizeof(cpumap_t)) {
+        xenXMError(domain ? domain->conn : NULL, VIR_ERR_INVALID_ARG,
+                   __FUNCTION__);
+        return -1;
+    }
+    if (domain->conn->flags & VIR_CONNECT_RO) {
+        xenXMError (domain->conn, VIR_ERR_INVALID_ARG,
+                    "%s", _("read only connection"));
+        return -1;
+    }
+    if (domain->id != -1) {
+        xenXMError (domain->conn, VIR_ERR_INVALID_ARG,
+                    "%s", _("not inactive domain"));
+        return -1;
+    }
+
+    priv = domain->conn->privateData;
+    xenUnifiedLock(priv);
+
+    if (!(filename = virHashLookup(priv->nameConfigMap, domain->name))) {
+        xenXMError (domain->conn, VIR_ERR_INTERNAL_ERROR, "%s", _("virHashLookup"));
+        goto cleanup;
+    }
+    if (!(entry = virHashLookup(priv->configCache, filename))) {
+        xenXMError (domain->conn, VIR_ERR_INTERNAL_ERROR,
+                    "%s", _("can't retrieve config file for domain"));
+        goto cleanup;
+    }
+
+    /* from bit map, build character string of mapped CPU numbers */
+    for (i = 0; i < maplen; i++)
+        for (j = 0; j < 8; j++)
+            if ((cpumap[i] & (1 << j))) {
+                n = i*8 + j;
+
+                if (comma)
+                    virBufferAddLit (&mapbuf, ",");
+                comma = 1;
+
+                virBufferVSprintf (&mapbuf, "%d", n);
+            }
+
+    if (virBufferError(&mapbuf)) {
+        virReportOOMError(domain->conn);
+        goto cleanup;
+    }
+
+    mapstr = virBufferContentAndReset(&mapbuf);
+    mapsave = mapstr;
+
+    if (VIR_ALLOC_N(cpuset, maxcpu) < 0) {
+        virReportOOMError(domain->conn);
+        goto cleanup;
+    }
+    if (virDomainCpuSetParse(domain->conn,
+                             (const char **)&mapstr, 0,
+                             cpuset, maxcpu) < 0)
+        goto cleanup;
+
+    VIR_FREE(entry->def->cpumask);
+    entry->def->cpumask = cpuset;
+    entry->def->cpumasklen = maxcpu;
+    cpuset = NULL;
+
+    if (xenXMConfigSaveFile(domain->conn, entry->filename, entry->def) < 0)
+        goto cleanup;
+
+    ret = 0;
+
+ cleanup:
+    VIR_FREE(mapsave);
+    VIR_FREE(cpuset);
+    xenUnifiedUnlock(priv);
+    return (ret);
+}
+
+/*
+ * Find an inactive domain based on its name
+ */
+virDomainPtr xenXMDomainLookupByName(virConnectPtr conn, const char *domname) {
+    xenUnifiedPrivatePtr priv;
+    const char *filename;
+    xenXMConfCachePtr entry;
+    virDomainPtr ret = NULL;
+
+    if (!VIR_IS_CONNECT(conn)) {
+        xenXMError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (NULL);
+    }
+    if (domname == NULL) {
+        xenXMError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (NULL);
+    }
+
+    priv = conn->privateData;
+    xenUnifiedLock(priv);
+
+    if (!xenInotifyActive(conn) && xenXMConfigCacheRefresh (conn) < 0)
+        goto cleanup;
+
+    if (!(filename = virHashLookup(priv->nameConfigMap, domname)))
+        goto cleanup;
+
+    if (!(entry = virHashLookup(priv->configCache, filename)))
+        goto cleanup;
+
+    if (!(ret = virGetDomain(conn, domname, entry->def->uuid)))
+        goto cleanup;
+
+    /* Ensure its marked inactive, because may be cached
+       handle to a previously active domain */
+    ret->id = -1;
+
+cleanup:
+    xenUnifiedUnlock(priv);
+    return (ret);
+}
+
+
+/*
+ * Hash table iterator to search for a domain based on UUID
+ */
+static int xenXMDomainSearchForUUID(const void *payload, const char *name ATTRIBUTE_UNUSED, const void *data) {
+    const unsigned char *wantuuid = (const unsigned char *)data;
+    const xenXMConfCachePtr entry = (const xenXMConfCachePtr)payload;
+
+    if (!memcmp(entry->def->uuid, wantuuid, VIR_UUID_BUFLEN))
+        return (1);
+
+    return (0);
+}
+
+/*
+ * Find an inactive domain based on its UUID
+ */
+virDomainPtr xenXMDomainLookupByUUID(virConnectPtr conn,
+                                     const unsigned char *uuid) {
+    xenUnifiedPrivatePtr priv;
+    xenXMConfCachePtr entry;
+    virDomainPtr ret = NULL;
+
+    if (!VIR_IS_CONNECT(conn)) {
+        xenXMError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (NULL);
+    }
+    if (uuid == NULL) {
+        xenXMError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (NULL);
+    }
+
+    priv = conn->privateData;
+    xenUnifiedLock(priv);
+
+    if (!xenInotifyActive(conn) && xenXMConfigCacheRefresh (conn) < 0)
+        goto cleanup;
+
+    if (!(entry = virHashSearch(priv->configCache, xenXMDomainSearchForUUID, (const void *)uuid)))
+        goto cleanup;
+
+    if (!(ret = virGetDomain(conn, entry->def->name, uuid)))
+        goto cleanup;
+
+    /* Ensure its marked inactive, because may be cached
+       handle to a previously active domain */
+    ret->id = -1;
+
+cleanup:
+    xenUnifiedUnlock(priv);
+    return (ret);
+}
+
+
+/*
+ * Start a domain from an existing defined config file
+ */
+int xenXMDomainCreate(virDomainPtr domain) {
+    char *sexpr;
+    int ret = -1;
+    xenUnifiedPrivatePtr priv;
+    const char *filename;
+    xenXMConfCachePtr entry;
+
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+
+    if (domain->id != -1)
+        return (-1);
+
+    xenUnifiedLock(priv);
+
+    if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
+        goto error;
+
+    if (!(entry = virHashLookup(priv->configCache, filename)))
+        goto error;
+
+    if (!(sexpr = xenDaemonFormatSxpr(domain->conn, entry->def, priv->xendConfigVersion)))
+        goto error;
+
+    ret = xenDaemonDomainCreateXML(domain->conn, sexpr);
+    VIR_FREE(sexpr);
+    if (ret != 0)
+        goto error;
+
+    if ((ret = xenDaemonDomainLookupByName_ids(domain->conn, domain->name,
+                                               entry->def->uuid)) < 0)
+        goto error;
+    domain->id = ret;
+
+    if (xend_wait_for_devices(domain->conn, domain->name) < 0)
+        goto error;
+
+    if (xenDaemonDomainResume(domain) < 0)
+        goto error;
+
+    xenUnifiedUnlock(priv);
+    return (0);
+
+ error:
+    if (domain->id != -1) {
+        xenDaemonDomainDestroy(domain);
+        domain->id = -1;
+    }
+    xenUnifiedUnlock(priv);
+    return (-1);
+}
+
+
+static
+int xenXMConfigSetInt(virConfPtr conf, const char *setting, long l) {
+    virConfValuePtr value = NULL;
+
+    if (VIR_ALLOC(value) < 0)
+        return -1;
+
+    value->type = VIR_CONF_LONG;
+    value->next = NULL;
+    value->l = l;
+
+    return virConfSetValue(conf, setting, value);
+}
+
+
+static
+int xenXMConfigSetString(virConfPtr conf, const char *setting, const char *str) {
+    virConfValuePtr value = NULL;
+
+    if (VIR_ALLOC(value) < 0)
+        return -1;
+
+    value->type = VIR_CONF_STRING;
+    value->next = NULL;
+    if (!(value->str = strdup(str))) {
+        VIR_FREE(value);
+        return -1;
+    }
+
+    return virConfSetValue(conf, setting, value);
+}
+
+
+static int xenXMDomainConfigFormatDisk(virConnectPtr conn,
+                                       virConfValuePtr list,
+                                       virDomainDiskDefPtr disk,
+                                       int hvm,
+                                       int xendConfigVersion)
+{
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    virConfValuePtr val, tmp;
+    char *str;
+
+    if(disk->src) {
+        if (disk->driverName) {
+            virBufferVSprintf(&buf, "%s:", disk->driverName);
+            if (STREQ(disk->driverName, "tap"))
+                virBufferVSprintf(&buf, "%s:", disk->driverType ? disk->driverType : "aio");
+        } else {
+            virBufferVSprintf(&buf, "%s:",
+                              disk->type == VIR_DOMAIN_DISK_TYPE_FILE ?
+                              "file" : "phy");
+        }
+        virBufferVSprintf(&buf, "%s", disk->src);
+    }
+    virBufferAddLit(&buf, ",");
+    if (hvm && xendConfigVersion == 1)
+        virBufferAddLit(&buf, "ioemu:");
+
+    virBufferVSprintf(&buf, "%s", disk->dst);
+    if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM)
+        virBufferAddLit(&buf, ":cdrom");
+
+    if (disk->readonly)
+        virBufferAddLit(&buf, ",r");
+    else if (disk->shared)
+        virBufferAddLit(&buf, ",!");
+    else
+        virBufferAddLit(&buf, ",w");
+
+    if (virBufferError(&buf)) {
+        virReportOOMError(conn);
+        return -1;
+    }
+
+    if (VIR_ALLOC(val) < 0) {
+        virReportOOMError(conn);
+        goto cleanup;
+    }
+
+    val->type = VIR_CONF_STRING;
+    val->str = virBufferContentAndReset(&buf);
+    tmp = list->list;
+    while (tmp && tmp->next)
+        tmp = tmp->next;
+    if (tmp)
+        tmp->next = val;
+    else
+        list->list = val;
+
+    return 0;
+
+cleanup:
+    str = virBufferContentAndReset(&buf);
+    VIR_FREE(str);
+    return -1;
+}
+
+static int xenXMDomainConfigFormatNet(virConnectPtr conn,
+                                      virConfValuePtr list,
+                                      virDomainNetDefPtr net,
+                                      int hvm)
+{
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    virConfValuePtr val, tmp;
+    char *str;
+    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
+
+    virBufferVSprintf(&buf, "mac=%02x:%02x:%02x:%02x:%02x:%02x",
+                      net->mac[0], net->mac[1],
+                      net->mac[2], net->mac[3],
+                      net->mac[4], net->mac[5]);
+
+    switch (net->type) {
+    case VIR_DOMAIN_NET_TYPE_BRIDGE:
+        virBufferVSprintf(&buf, ",bridge=%s", net->data.bridge.brname);
+        if (net->data.bridge.ipaddr)
+            virBufferVSprintf(&buf, ",ip=%s", net->data.bridge.ipaddr);
+        virBufferVSprintf(&buf, ",script=%s", DEFAULT_VIF_SCRIPT);
+        break;
+
+    case VIR_DOMAIN_NET_TYPE_ETHERNET:
+        if (net->data.ethernet.script)
+            virBufferVSprintf(&buf, ",script=%s", net->data.ethernet.script);
+        if (net->data.ethernet.ipaddr)
+            virBufferVSprintf(&buf, ",ip=%s", net->data.ethernet.ipaddr);
+        break;
+
+    case VIR_DOMAIN_NET_TYPE_NETWORK:
+    {
+        virNetworkPtr network = virNetworkLookupByName(conn, net->data.network.name);
+        char *bridge;
+        if (!network) {
+            xenXMError(conn, VIR_ERR_NO_NETWORK, "%s",
+                       net->data.network.name);
+            return -1;
+        }
+        bridge = virNetworkGetBridgeName(network);
+        virNetworkFree(network);
+        if (!bridge) {
+            xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                       _("network %s is not active"),
+                       net->data.network.name);
+            return -1;
+        }
+
+        virBufferVSprintf(&buf, ",bridge=%s", bridge);
+        virBufferVSprintf(&buf, ",script=%s", DEFAULT_VIF_SCRIPT);
+    }
+    break;
+
+    default:
+        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                   _("unsupported network type %d"),
+                   net->type);
+        goto cleanup;
+    }
+
+    if (hvm && priv->xendConfigVersion <= XEND_CONFIG_MAX_VERS_NET_TYPE_IOEMU)
+        virBufferAddLit(&buf, ",type=ioemu");
+
+    if (net->model)
+        virBufferVSprintf(&buf, ",model=%s",
+                          net->model);
+
+    if (net->ifname)
+        virBufferVSprintf(&buf, ",vifname=%s",
+                          net->ifname);
+
+    if (virBufferError(&buf))
+        goto cleanup;
+
+    if (VIR_ALLOC(val) < 0) {
+        virReportOOMError(conn);
+        goto cleanup;
+    }
+
+    val->type = VIR_CONF_STRING;
+    val->str = virBufferContentAndReset(&buf);
+    tmp = list->list;
+    while (tmp && tmp->next)
+        tmp = tmp->next;
+    if (tmp)
+        tmp->next = val;
+    else
+        list->list = val;
+
+    return 0;
+
+cleanup:
+    str = virBufferContentAndReset(&buf);
+    VIR_FREE(str);
+    return -1;
+}
+
+
+
+static int
+xenXMDomainConfigFormatPCI(virConnectPtr conn,
+                           virConfPtr conf,
+                           virDomainDefPtr def)
+{
+
+    virConfValuePtr pciVal = NULL;
+    int hasPCI = 0;
+    int i;
+
+    for (i = 0 ; i < def->nhostdevs ; i++)
+        if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+            def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
+            hasPCI = 1;
+
+    if (!hasPCI)
+        return 0;
+
+    if (VIR_ALLOC(pciVal) < 0)
+        return -1;
+
+    pciVal->type = VIR_CONF_LIST;
+    pciVal->list = NULL;
+
+    for (i = 0 ; i < def->nhostdevs ; i++) {
+        if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+            def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
+            virConfValuePtr val, tmp;
+            char *buf;
+
+            if (virAsprintf(&buf, "%04x:%02x:%02x.%x",
+                            def->hostdevs[i]->source.subsys.u.pci.domain,
+                            def->hostdevs[i]->source.subsys.u.pci.bus,
+                            def->hostdevs[i]->source.subsys.u.pci.slot,
+                            def->hostdevs[i]->source.subsys.u.pci.function) < 0)
+                goto error;
+
+            if (VIR_ALLOC(val) < 0) {
+                VIR_FREE(buf);
+                virReportOOMError(conn);
+                goto error;
+            }
+            val->type = VIR_CONF_STRING;
+            val->str = buf;
+            tmp = pciVal->list;
+            while (tmp && tmp->next)
+                tmp = tmp->next;
+            if (tmp)
+                tmp->next = val;
+            else
+                pciVal->list = val;
+        }
+    }
+
+    if (pciVal->list != NULL) {
+        int ret = virConfSetValue(conf, "pci", pciVal);
+        pciVal = NULL;
+        if (ret < 0)
+            return -1;
+    }
+    VIR_FREE(pciVal);
+
+    return 0;
+
+error:
+    virConfFreeValue(pciVal);
+    return -1;
+}
+
+
+virConfPtr xenXMDomainConfigFormat(virConnectPtr conn,
+                                   virDomainDefPtr def) {
+    virConfPtr conf = NULL;
+    int hvm = 0, i;
+    xenUnifiedPrivatePtr priv;
+    char *cpus = NULL;
+    const char *lifecycle;
+    char uuid[VIR_UUID_STRING_BUFLEN];
+    virConfValuePtr diskVal = NULL;
+    virConfValuePtr netVal = NULL;
+
+    priv = (xenUnifiedPrivatePtr) conn->privateData;
+
+    if (!(conf = virConfNew()))
+        goto cleanup;
+
+
+    if (xenXMConfigSetString(conf, "name", def->name) < 0)
+        goto no_memory;
+
+    virUUIDFormat(def->uuid, uuid);
+    if (xenXMConfigSetString(conf, "uuid", uuid) < 0)
+        goto no_memory;
+
+    if (xenXMConfigSetInt(conf, "maxmem", def->maxmem / 1024) < 0)
+        goto no_memory;
+
+    if (xenXMConfigSetInt(conf, "memory", def->memory / 1024) < 0)
+        goto no_memory;
+
+    if (xenXMConfigSetInt(conf, "vcpus", def->vcpus) < 0)
+        goto no_memory;
+
+    if (def->cpumask &&
+        !(cpus = virDomainCpuSetFormat(conn, def->cpumask, def->cpumasklen)) < 0)
+        goto cleanup;
+
+    if (cpus &&
+        xenXMConfigSetString(conf, "cpus", cpus) < 0)
+        goto no_memory;
+    VIR_FREE(cpus);
+
+    hvm = STREQ(def->os.type, "hvm") ? 1 : 0;
+
+    if (hvm) {
+        char boot[VIR_DOMAIN_BOOT_LAST+1];
+        if (xenXMConfigSetString(conf, "builder", "hvm") < 0)
+            goto no_memory;
+
+        if (def->os.loader &&
+            xenXMConfigSetString(conf, "kernel", def->os.loader) < 0)
+            goto no_memory;
+
+        for (i = 0 ; i < def->os.nBootDevs ; i++) {
+            switch (def->os.bootDevs[i]) {
+            case VIR_DOMAIN_BOOT_FLOPPY:
+                boot[i] = 'a';
+                break;
+            case VIR_DOMAIN_BOOT_CDROM:
+                boot[i] = 'd';
+                break;
+            case VIR_DOMAIN_BOOT_NET:
+                boot[i] = 'n';
+                break;
+            case VIR_DOMAIN_BOOT_DISK:
+            default:
+                boot[i] = 'c';
+                break;
+            }
+        }
+        if (!def->os.nBootDevs) {
+            boot[0] = 'c';
+            boot[1] = '\0';
+        } else {
+            boot[def->os.nBootDevs] = '\0';
+        }
+
+        if (xenXMConfigSetString(conf, "boot", boot) < 0)
+            goto no_memory;
+
+        if (xenXMConfigSetInt(conf, "pae",
+                              (def->features &
+                               (1 << VIR_DOMAIN_FEATURE_PAE)) ? 1 : 0) < 0)
+            goto no_memory;
+
+        if (xenXMConfigSetInt(conf, "acpi",
+                              (def->features &
+                               (1 << VIR_DOMAIN_FEATURE_ACPI)) ? 1 : 0) < 0)
+            goto no_memory;
+
+        if (xenXMConfigSetInt(conf, "apic",
+                              (def->features &
+                               (1 << VIR_DOMAIN_FEATURE_APIC)) ? 1 : 0) < 0)
+            goto no_memory;
+
+
+        if (xenXMConfigSetInt(conf, "localtime", def->localtime ? 1 : 0) < 0)
+            goto no_memory;
+
+        if (priv->xendConfigVersion == 1) {
+            for (i = 0 ; i < def->ndisks ; i++) {
+                if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_CDROM &&
+                    def->disks[i]->dst &&
+                    STREQ(def->disks[i]->dst, "hdc") &&
+                    def->disks[i]->src) {
+                    if (xenXMConfigSetString(conf, "cdrom",
+                                             def->disks[i]->src) < 0)
+                        goto no_memory;
+                    break;
+                }
+            }
+        }
+
+        /* XXX floppy disks */
+    } else {
+        if (def->os.bootloader &&
+            xenXMConfigSetString(conf, "bootloader", def->os.bootloader) < 0)
+            goto no_memory;
+        if (def->os.bootloaderArgs &&
+            xenXMConfigSetString(conf, "bootloader_args", def->os.bootloaderArgs) < 0)
+            goto no_memory;
+        if (def->os.kernel &&
+            xenXMConfigSetString(conf, "kernel", def->os.kernel) < 0)
+            goto no_memory;
+        if (def->os.initrd &&
+            xenXMConfigSetString(conf, "ramdisk", def->os.initrd) < 0)
+            goto no_memory;
+        if (def->os.cmdline &&
+            xenXMConfigSetString(conf, "extra", def->os.cmdline) < 0)
+            goto no_memory;
+
+    }
+
+    if (!(lifecycle = virDomainLifecycleTypeToString(def->onPoweroff))) {
+        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                   _("unexpected lifecycle action %d"), def->onPoweroff);
+        goto cleanup;
+    }
+    if (xenXMConfigSetString(conf, "on_poweroff", lifecycle) < 0)
+        goto no_memory;
+
+
+    if (!(lifecycle = virDomainLifecycleTypeToString(def->onReboot))) {
+        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                   _("unexpected lifecycle action %d"), def->onReboot);
+        goto cleanup;
+    }
+    if (xenXMConfigSetString(conf, "on_reboot", lifecycle) < 0)
+        goto no_memory;
+
+
+    if (!(lifecycle = virDomainLifecycleTypeToString(def->onCrash))) {
+        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                   _("unexpected lifecycle action %d"), def->onCrash);
+        goto cleanup;
+    }
+    if (xenXMConfigSetString(conf, "on_crash", lifecycle) < 0)
+        goto no_memory;
+
+
+
+    if (hvm) {
+        if (def->emulator &&
+            xenXMConfigSetString(conf, "device_model", def->emulator) < 0)
+            goto no_memory;
+
+        for (i = 0 ; i < def->ninputs ; i++) {
+            if (def->inputs[i]->bus == VIR_DOMAIN_INPUT_BUS_USB) {
+                if (xenXMConfigSetInt(conf, "usb", 1) < 0)
+                    goto no_memory;
+                if (xenXMConfigSetString(conf, "usbdevice",
+                                         def->inputs[i]->type == VIR_DOMAIN_INPUT_TYPE_MOUSE ?
+                                         "mouse" : "tablet") < 0)
+                    goto no_memory;
+                break;
+            }
+        }
+    }
+
+    if (def->ngraphics == 1) {
+        if (priv->xendConfigVersion < (hvm ? 4 : XEND_CONFIG_MIN_VERS_PVFB_NEWCONF)) {
+            if (def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
+                if (xenXMConfigSetInt(conf, "sdl", 1) < 0)
+                    goto no_memory;
+                if (xenXMConfigSetInt(conf, "vnc", 0) < 0)
+                    goto no_memory;
+                if (def->graphics[0]->data.sdl.display &&
+                    xenXMConfigSetString(conf, "display",
+                                     def->graphics[0]->data.sdl.display) < 0)
+                    goto no_memory;
+                if (def->graphics[0]->data.sdl.xauth &&
+                    xenXMConfigSetString(conf, "xauthority",
+                                         def->graphics[0]->data.sdl.xauth) < 0)
+                    goto no_memory;
+            } else {
+                if (xenXMConfigSetInt(conf, "sdl", 0) < 0)
+                    goto no_memory;
+                if (xenXMConfigSetInt(conf, "vnc", 1) < 0)
+                    goto no_memory;
+                if (xenXMConfigSetInt(conf, "vncunused",
+                              def->graphics[0]->data.vnc.autoport ? 1 : 0) < 0)
+                    goto no_memory;
+                if (!def->graphics[0]->data.vnc.autoport &&
+                    xenXMConfigSetInt(conf, "vncdisplay",
+                                  def->graphics[0]->data.vnc.port - 5900) < 0)
+                    goto no_memory;
+                if (def->graphics[0]->data.vnc.listenAddr &&
+                    xenXMConfigSetString(conf, "vnclisten",
+                                    def->graphics[0]->data.vnc.listenAddr) < 0)
+                    goto no_memory;
+                if (def->graphics[0]->data.vnc.passwd &&
+                    xenXMConfigSetString(conf, "vncpasswd",
+                                        def->graphics[0]->data.vnc.passwd) < 0)
+                    goto no_memory;
+                if (def->graphics[0]->data.vnc.keymap &&
+                    xenXMConfigSetString(conf, "keymap",
+                                        def->graphics[0]->data.vnc.keymap) < 0)
+                    goto no_memory;
+            }
+        } else {
+            virConfValuePtr vfb, disp;
+            char *vfbstr = NULL;
+            virBuffer buf = VIR_BUFFER_INITIALIZER;
+            if (def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
+                virBufferAddLit(&buf, "type=sdl");
+                if (def->graphics[0]->data.sdl.display)
+                    virBufferVSprintf(&buf, ",display=%s",
+                                      def->graphics[0]->data.sdl.display);
+                if (def->graphics[0]->data.sdl.xauth)
+                    virBufferVSprintf(&buf, ",xauthority=%s",
+                                      def->graphics[0]->data.sdl.xauth);
+            } else {
+                virBufferAddLit(&buf, "type=vnc");
+                virBufferVSprintf(&buf, ",vncunused=%d",
+                                  def->graphics[0]->data.vnc.autoport ? 1 : 0);
+                if (!def->graphics[0]->data.vnc.autoport)
+                    virBufferVSprintf(&buf, ",vncdisplay=%d",
+                                      def->graphics[0]->data.vnc.port - 5900);
+                if (def->graphics[0]->data.vnc.listenAddr)
+                    virBufferVSprintf(&buf, ",vnclisten=%s",
+                                      def->graphics[0]->data.vnc.listenAddr);
+                if (def->graphics[0]->data.vnc.passwd)
+                    virBufferVSprintf(&buf, ",vncpasswd=%s",
+                                      def->graphics[0]->data.vnc.passwd);
+                if (def->graphics[0]->data.vnc.keymap)
+                    virBufferVSprintf(&buf, ",keymap=%s",
+                                      def->graphics[0]->data.vnc.keymap);
+            }
+            if (virBufferError(&buf))
+                goto no_memory;
+
+            vfbstr = virBufferContentAndReset(&buf);
+
+            if (VIR_ALLOC(vfb) < 0) {
+                VIR_FREE(vfbstr);
+                goto no_memory;
+            }
+
+            if (VIR_ALLOC(disp) < 0) {
+                VIR_FREE(vfb);
+                VIR_FREE(vfbstr);
+                goto no_memory;
+            }
+
+            vfb->type = VIR_CONF_LIST;
+            vfb->list = disp;
+            disp->type = VIR_CONF_STRING;
+            disp->str = vfbstr;
+
+            if (virConfSetValue(conf, "vfb", vfb) < 0)
+                goto no_memory;
+        }
+    }
+
+    /* analyze of the devices */
+    if (VIR_ALLOC(diskVal) < 0)
+        goto no_memory;
+    diskVal->type = VIR_CONF_LIST;
+    diskVal->list = NULL;
+
+    for (i = 0 ; i < def->ndisks ; i++) {
+        if (priv->xendConfigVersion == 1 &&
+            def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_CDROM &&
+            def->disks[i]->dst &&
+            STREQ(def->disks[i]->dst, "hdc")) {
+            continue;
+        }
+        if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY)
+            continue;
+
+        if (xenXMDomainConfigFormatDisk(conn, diskVal, def->disks[i],
+                                        hvm, priv->xendConfigVersion) < 0)
+            goto cleanup;
+    }
+    if (diskVal->list != NULL) {
+        int ret = virConfSetValue(conf, "disk", diskVal);
+        diskVal = NULL;
+        if (ret < 0)
+            goto no_memory;
+    }
+    VIR_FREE(diskVal);
+
+    if (VIR_ALLOC(netVal) < 0)
+        goto no_memory;
+    netVal->type = VIR_CONF_LIST;
+    netVal->list = NULL;
+
+    for (i = 0 ; i < def->nnets ; i++) {
+        if (xenXMDomainConfigFormatNet(conn, netVal,
+                                       def->nets[i],
+                                       hvm) < 0)
+            goto cleanup;
+    }
+    if (netVal->list != NULL) {
+        int ret = virConfSetValue(conf, "vif", netVal);
+        netVal = NULL;
+        if (ret < 0)
+            goto no_memory;
+    }
+    VIR_FREE(netVal);
+
+    if (xenXMDomainConfigFormatPCI(conn, conf, def) < 0)
+        goto cleanup;
+
+    if (hvm) {
+        if (def->nparallels) {
+            virBuffer buf = VIR_BUFFER_INITIALIZER;
+            char *str;
+            int ret;
+
+            ret = xenDaemonFormatSxprChr(conn, def->parallels[0], &buf);
+            str = virBufferContentAndReset(&buf);
+            if (ret == 0)
+                ret = xenXMConfigSetString(conf, "parallel", str);
+            VIR_FREE(str);
+            if (ret < 0)
+                goto no_memory;
+        } else {
+            if (xenXMConfigSetString(conf, "parallel", "none") < 0)
+                goto no_memory;
+        }
+
+        if (def->nserials) {
+            virBuffer buf = VIR_BUFFER_INITIALIZER;
+            char *str;
+            int ret;
+
+            ret = xenDaemonFormatSxprChr(conn, def->serials[0], &buf);
+            str = virBufferContentAndReset(&buf);
+            if (ret == 0)
+                ret = xenXMConfigSetString(conf, "serial", str);
+            VIR_FREE(str);
+            if (ret < 0)
+                goto no_memory;
+        } else {
+            if (xenXMConfigSetString(conf, "serial", "none") < 0)
+                goto no_memory;
+        }
+
+
+        if (def->sounds) {
+            virBuffer buf = VIR_BUFFER_INITIALIZER;
+            char *str = NULL;
+            int ret = xenDaemonFormatSxprSound(conn,
+                                               def,
+                                               &buf);
+            str = virBufferContentAndReset(&buf);
+            if (ret == 0)
+                ret = xenXMConfigSetString(conf, "soundhw", str);
+
+            VIR_FREE(str);
+            if (ret < 0)
+                goto no_memory;
+        }
+    }
+
+    return conf;
+
+no_memory:
+    virReportOOMError(conn);
+
+cleanup:
+    virConfFreeValue(diskVal);
+    virConfFreeValue(netVal);
+    VIR_FREE(cpus);
+    if (conf)
+        virConfFree(conf);
+    return (NULL);
+}
+
+/*
+ * Create a config file for a domain, based on an XML
+ * document describing its config
+ */
+virDomainPtr xenXMDomainDefineXML(virConnectPtr conn, const char *xml) {
+    virDomainPtr ret;
+    virDomainPtr olddomain;
+    char filename[PATH_MAX];
+    const char * oldfilename;
+    virDomainDefPtr def = NULL;
+    xenXMConfCachePtr entry = NULL;
+    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
+
+    if (!VIR_IS_CONNECT(conn)) {
+        xenXMError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (NULL);
+    }
+    if (xml == NULL) {
+        xenXMError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (NULL);
+    }
+    if (conn->flags & VIR_CONNECT_RO)
+        return (NULL);
+
+    xenUnifiedLock(priv);
+
+    if (!xenInotifyActive(conn) && xenXMConfigCacheRefresh (conn) < 0) {
+        xenUnifiedUnlock(priv);
+        return (NULL);
+    }
+
+    if (!(def = virDomainDefParseString(conn, priv->caps, xml,
+                                        VIR_DOMAIN_XML_INACTIVE))) {
+        xenUnifiedUnlock(priv);
+        return (NULL);
+    }
+
+    if (virHashLookup(priv->nameConfigMap, def->name)) {
+        /* domain exists, we will overwrite it */
+
+        if (!(oldfilename = (char *)virHashLookup(priv->nameConfigMap, def->name))) {
+            xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                       "%s", _("can't retrieve config filename for domain to overwrite"));
+            goto error;
+        }
+
+        if (!(entry = virHashLookup(priv->configCache, oldfilename))) {
+            xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                       "%s", _("can't retrieve config entry for domain to overwrite"));
+            goto error;
+        }
+
+        /* XXX wtf.com is this line for - it appears to be amemory leak */
+        if (!(olddomain = virGetDomain(conn, def->name, entry->def->uuid)))
+            goto error;
+
+        /* Remove the name -> filename mapping */
+        if (virHashRemoveEntry(priv->nameConfigMap, def->name, NULL) < 0) {
+            xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                       "%s", _("failed to remove old domain from config map"));
+            goto error;
+        }
+
+        /* Remove the config record itself */
+        if (virHashRemoveEntry(priv->configCache, oldfilename, xenXMConfigFree) < 0) {
+            xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                       "%s", _("failed to remove old domain from config map"));
+            goto error;
+        }
+
+        entry = NULL;
+    }
+
+    if ((strlen(priv->configDir) + 1 + strlen(def->name) + 1) > PATH_MAX) {
+        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                   "%s", _("config file name is too long"));
+        goto error;
+    }
+
+    strcpy(filename, priv->configDir);
+    strcat(filename, "/");
+    strcat(filename, def->name);
+
+    if (xenXMConfigSaveFile(conn, filename, def) < 0)
+        goto error;
+
+    if (VIR_ALLOC(entry) < 0) {
+        virReportOOMError(conn);
+        goto error;
+    }
+
+    if ((entry->refreshedAt = time(NULL)) == ((time_t)-1)) {
+        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                   "%s", _("unable to get current time"));
+        goto error;
+    }
+
+    memmove(entry->filename, filename, PATH_MAX);
+    entry->def = def;
+
+    if (virHashAddEntry(priv->configCache, filename, entry) < 0) {
+        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                   "%s", _("unable to store config file handle"));
+        goto error;
+    }
+
+    if (virHashAddEntry(priv->nameConfigMap, def->name, entry->filename) < 0) {
+        virHashRemoveEntry(priv->configCache, filename, NULL);
+        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                   "%s", _("unable to store config file handle"));
+        goto error;
+    }
+
+    ret = virGetDomain(conn, def->name, def->uuid);
+    xenUnifiedUnlock(priv);
+    return (ret);
+
+ error:
+    VIR_FREE(entry);
+    virDomainDefFree(def);
+    xenUnifiedUnlock(priv);
+    return (NULL);
+}
+
+/*
+ * Delete a domain from disk
+ */
+int xenXMDomainUndefine(virDomainPtr domain) {
+    xenUnifiedPrivatePtr priv;
+    const char *filename;
+    xenXMConfCachePtr entry;
+    int ret = -1;
+
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
+        xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                   __FUNCTION__);
+        return (-1);
+    }
+
+    if (domain->id != -1)
+        return (-1);
+    if (domain->conn->flags & VIR_CONNECT_RO)
+        return (-1);
+
+    priv = domain->conn->privateData;
+    xenUnifiedLock(priv);
+
+    if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
+        goto cleanup;
+
+    if (!(entry = virHashLookup(priv->configCache, filename)))
+        goto cleanup;
+
+    if (unlink(entry->filename) < 0)
+        goto cleanup;
+
+    /* Remove the name -> filename mapping */
+    if (virHashRemoveEntry(priv->nameConfigMap, domain->name, NULL) < 0)
+        goto cleanup;
+
+    /* Remove the config record itself */
+    if (virHashRemoveEntry(priv->configCache, entry->filename, xenXMConfigFree) < 0)
+        goto cleanup;
+
+    ret = 0;
+
+cleanup:
+    xenUnifiedUnlock(priv);
+    return ret;
+}
+
+struct xenXMListIteratorContext {
+    virConnectPtr conn;
+    int max;
+    int count;
+    char ** names;
+};
+
+static void xenXMListIterator(const void *payload ATTRIBUTE_UNUSED, const char *name, const void *data) {
+    struct xenXMListIteratorContext *ctx = (struct xenXMListIteratorContext *)data;
+    virDomainPtr dom = NULL;
+
+    if (ctx->count == ctx->max)
+        return;
+
+    dom = xenDaemonLookupByName(ctx->conn, name);
+    if (!dom) {
+        ctx->names[ctx->count] = strdup(name);
+        ctx->count++;
+    } else {
+        virDomainFree(dom);
+    }
+}
+
+
+/*
+ * List all defined domains, filtered to remove any which
+ * are currently running
+ */
+int xenXMListDefinedDomains(virConnectPtr conn, char **const names, int maxnames) {
+    xenUnifiedPrivatePtr priv;
+    struct xenXMListIteratorContext ctx;
+    int ret = -1;
+
+    if (!VIR_IS_CONNECT(conn)) {
+        xenXMError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (-1);
+    }
+
+    priv = conn->privateData;
+    xenUnifiedLock(priv);
+
+    if (!xenInotifyActive(conn) && xenXMConfigCacheRefresh (conn) < 0)
+        goto cleanup;
+
+    if (maxnames > virHashSize(priv->configCache))
+        maxnames = virHashSize(priv->configCache);
+
+    ctx.conn = conn;
+    ctx.count = 0;
+    ctx.max = maxnames;
+    ctx.names = names;
+
+    virHashForEach(priv->nameConfigMap, xenXMListIterator, &ctx);
+    ret = ctx.count;
+
+cleanup:
+    xenUnifiedUnlock(priv);
+    return ret;
+}
+
+/*
+ * Return the maximum number of defined domains - not filtered
+ * based on number running
+ */
+int xenXMNumOfDefinedDomains(virConnectPtr conn) {
+    xenUnifiedPrivatePtr priv;
+    int ret = -1;
+
+    if (!VIR_IS_CONNECT(conn)) {
+        xenXMError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (-1);
+    }
+
+    priv = conn->privateData;
+    xenUnifiedLock(priv);
+
+    if (!xenInotifyActive(conn) && xenXMConfigCacheRefresh (conn) < 0)
+        goto cleanup;
+
+    ret = virHashSize(priv->nameConfigMap);
+
+cleanup:
+    xenUnifiedUnlock(priv);
+    return ret;
+}
+
+
+/**
+ * xenXMDomainAttachDevice:
+ * @domain: pointer to domain object
+ * @xml: pointer to XML description of device
+ *
+ * Create a virtual device attachment to backend.
+ * XML description is translated into config file.
+ *
+ * Returns 0 in case of success, -1 in case of failure.
+ */
+static int
+xenXMDomainAttachDevice(virDomainPtr domain, const char *xml) {
+    const char *filename = NULL;
+    xenXMConfCachePtr entry = NULL;
+    int ret = -1;
+    virDomainDeviceDefPtr dev = NULL;
+    virDomainDefPtr def;
+    xenUnifiedPrivatePtr priv;
+
+    if ((!domain) || (!domain->conn) || (!domain->name) || (!xml)) {
+        xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                   __FUNCTION__);
+        return -1;
+    }
+
+    if (domain->conn->flags & VIR_CONNECT_RO)
+        return -1;
+    if (domain->id != -1)
+        return -1;
+
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+    xenUnifiedLock(priv);
+
+    if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
+        goto cleanup;
+    if (!(entry = virHashLookup(priv->configCache, filename)))
+        goto cleanup;
+    def = entry->def;
+
+    if (!(dev = virDomainDeviceDefParse(domain->conn,
+                                        priv->caps,
+                                        entry->def,
+                                        xml, VIR_DOMAIN_XML_INACTIVE)))
+        goto cleanup;
+
+    switch (dev->type) {
+    case VIR_DOMAIN_DEVICE_DISK:
+    {
+        if (virDomainDiskInsert(def, dev->data.disk) < 0) {
+            virReportOOMError(domain->conn);
+            goto cleanup;
+        }
+        dev->data.disk = NULL;
+    }
+    break;
+
+    case VIR_DOMAIN_DEVICE_NET:
+    {
+        if (VIR_REALLOC_N(def->nets, def->nnets+1) < 0) {
+            virReportOOMError(domain->conn);
+            goto cleanup;
+        }
+        def->nets[def->nnets++] = dev->data.net;
+        dev->data.net = NULL;
+        break;
+    }
+
+    default:
+        xenXMError(domain->conn, VIR_ERR_XML_ERROR,
+                   "%s", _("unknown device"));
+        goto cleanup;
+    }
+
+    /* If this fails, should we try to undo our changes to the
+     * in-memory representation of the config file. I say not!
+     */
+    if (xenXMConfigSaveFile(domain->conn, entry->filename, entry->def) < 0)
+        goto cleanup;
+
+    ret = 0;
+
+ cleanup:
+    virDomainDeviceDefFree(dev);
+    xenUnifiedUnlock(priv);
+    return ret;
+}
+
+
+/**
+ * xenXMDomainDetachDevice:
+ * @domain: pointer to domain object
+ * @xml: pointer to XML description of device
+ *
+ * Destroy a virtual device attachment to backend.
+ *
+ * Returns 0 in case of success, -1 in case of failure.
+ */
+static int
+xenXMDomainDetachDevice(virDomainPtr domain, const char *xml) {
+    const char *filename = NULL;
+    xenXMConfCachePtr entry = NULL;
+    virDomainDeviceDefPtr dev = NULL;
+    virDomainDefPtr def;
+    int ret = -1;
+    int i;
+    xenUnifiedPrivatePtr priv;
+
+    if ((!domain) || (!domain->conn) || (!domain->name) || (!xml)) {
+        xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                   __FUNCTION__);
+        return -1;
+    }
+
+
+    if (domain->conn->flags & VIR_CONNECT_RO)
+        return -1;
+    if (domain->id != -1)
+        return -1;
+
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+    xenUnifiedLock(priv);
+
+    if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
+        goto cleanup;
+    if (!(entry = virHashLookup(priv->configCache, filename)))
+        goto cleanup;
+    def = entry->def;
+
+    if (!(dev = virDomainDeviceDefParse(domain->conn,
+                                        priv->caps,
+                                        entry->def,
+                                        xml, VIR_DOMAIN_XML_INACTIVE)))
+        goto cleanup;
+
+    switch (dev->type) {
+    case VIR_DOMAIN_DEVICE_DISK:
+    {
+        for (i = 0 ; i < def->ndisks ; i++) {
+            if (def->disks[i]->dst &&
+                dev->data.disk->dst &&
+                STREQ(def->disks[i]->dst, dev->data.disk->dst)) {
+                virDomainDiskDefFree(def->disks[i]);
+                if (i < (def->ndisks - 1))
+                    memmove(def->disks + i,
+                            def->disks + i + 1,
+                            sizeof(*def->disks) *
+                            (def->ndisks - (i + 1)));
+                break;
+            }
+        }
+        break;
+    }
+
+    case VIR_DOMAIN_DEVICE_NET:
+    {
+        for (i = 0 ; i < def->nnets ; i++) {
+            if (!memcmp(def->nets[i]->mac,
+                        dev->data.net->mac,
+                        sizeof(def->nets[i]->mac))) {
+                virDomainNetDefFree(def->nets[i]);
+                if (i < (def->nnets - 1))
+                    memmove(def->nets + i,
+                            def->nets + i + 1,
+                            sizeof(*def->nets) *
+                            (def->nnets - (i + 1)));
+                break;
+            }
+        }
+        break;
+    }
+    default:
+        xenXMError(domain->conn, VIR_ERR_XML_ERROR,
+                   "%s", _("unknown device"));
+        goto cleanup;
+    }
+
+    /* If this fails, should we try to undo our changes to the
+     * in-memory representation of the config file. I say not!
+     */
+    if (xenXMConfigSaveFile(domain->conn, entry->filename, entry->def) < 0)
+        goto cleanup;
+
+    ret = 0;
+
+ cleanup:
+    virDomainDeviceDefFree(dev);
+    xenUnifiedUnlock(priv);
+    return (ret);
+}
+
+int
+xenXMDomainBlockPeek (virDomainPtr dom,
+                      const char *path ATTRIBUTE_UNUSED,
+                      unsigned long long offset ATTRIBUTE_UNUSED,
+                      size_t size ATTRIBUTE_UNUSED,
+                      void *buffer ATTRIBUTE_UNUSED)
+{
+    xenXMError (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
+
+
+static char *xenXMAutostartLinkName(virDomainPtr dom)
+{
+    char *ret;
+    virAsprintf(&ret, "/etc/xen/auto/%s", dom->name);
+    return ret;
+}
+
+static char *xenXMDomainConfigName(virDomainPtr dom)
+{
+    char *ret;
+    virAsprintf(&ret, "/etc/xen/%s", dom->name);
+    return ret;
+}
+
+int xenXMDomainGetAutostart(virDomainPtr dom, int *autostart)
+{
+    char *linkname = xenXMAutostartLinkName(dom);
+    char *config = xenXMDomainConfigName(dom);
+    int ret = -1;
+
+    if (!linkname || !config) {
+        virReportOOMError(dom->conn);
+        goto cleanup;
+    }
+
+    *autostart = virFileLinkPointsTo(linkname, config);
+    if (*autostart < 0) {
+        virReportSystemError(dom->conn, errno,
+                             _("cannot check link %s points to config %s"),
+                             linkname, config);
+        goto cleanup;
+    }
+
+    ret = 0;
+
+cleanup:
+    VIR_FREE(linkname);
+    VIR_FREE(config);
+    return ret;
+}
+
+
+int xenXMDomainSetAutostart(virDomainPtr dom, int autostart)
+{
+    char *linkname = xenXMAutostartLinkName(dom);
+    char *config = xenXMDomainConfigName(dom);
+    int ret = -1;
+
+    if (!linkname || !config) {
+        virReportOOMError(dom->conn);
+        goto cleanup;
+    }
+
+    if (autostart) {
+        if (symlink(config, linkname) < 0 &&
+            errno != EEXIST) {
+            virReportSystemError(dom->conn, errno,
+                                 _("failed to create link %s to %s"),
+                                 config, linkname);
+            goto cleanup;
+        }
+    } else {
+        if (unlink(linkname)  < 0 &&
+            errno != ENOENT) {
+            virReportSystemError(dom->conn, errno,
+                                 _("failed to remove link %s"),
+                                 linkname);
+            goto cleanup;
+        }
+    }
+    ret = 0;
+
+cleanup:
+    VIR_FREE(linkname);
+    VIR_FREE(config);
+
+    return ret;
+}
diff --git a/src/xen/xm_internal.h b/src/xen/xm_internal.h
new file mode 100644 (file)
index 0000000..7d52ac8
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * xm_internal.h: helper routines for dealing with inactive domains
+ *
+ * Copyright (C) 2006-2007 Red Hat
+ * Copyright (C) 2006 Daniel P. Berrange
+ *
+ * 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: Daniel P. Berrange <berrange@redhat.com>
+ *
+ */
+
+#ifndef _LIBVIRT_XM_INTERNAL_H_
+#define _LIBVIRT_XM_INTERNAL_H_
+
+#include "internal.h"
+#include "driver.h"
+#include "conf.h"
+#include "domain_conf.h"
+
+extern struct xenUnifiedDriver xenXMDriver;
+
+int xenXMConfigCacheRefresh (virConnectPtr conn);
+int xenXMConfigCacheAddFile(virConnectPtr conn, const char *filename);
+int xenXMConfigCacheRemoveFile(virConnectPtr conn, const char *filename);
+
+virDrvOpenStatus xenXMOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags);
+int xenXMClose(virConnectPtr conn);
+const char *xenXMGetType(virConnectPtr conn);
+int xenXMDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info);
+char *xenXMDomainDumpXML(virDomainPtr domain, int flags);
+int xenXMDomainSetMemory(virDomainPtr domain, unsigned long memory);
+int xenXMDomainSetMaxMemory(virDomainPtr domain, unsigned long memory);
+unsigned long xenXMDomainGetMaxMemory(virDomainPtr domain);
+int xenXMDomainSetVcpus(virDomainPtr domain, unsigned int vcpus);
+int xenXMDomainPinVcpu(virDomainPtr domain, unsigned int vcpu,
+                       unsigned char *cpumap, int maplen);
+virDomainPtr xenXMDomainLookupByName(virConnectPtr conn, const char *domname);
+virDomainPtr xenXMDomainLookupByUUID(virConnectPtr conn,
+                                     const unsigned char *uuid);
+
+int xenXMListDefinedDomains(virConnectPtr conn, char ** const names, int maxnames);
+int xenXMNumOfDefinedDomains(virConnectPtr conn);
+
+int xenXMDomainCreate(virDomainPtr domain);
+virDomainPtr xenXMDomainDefineXML(virConnectPtr con, const char *xml);
+int xenXMDomainUndefine(virDomainPtr domain);
+
+virConfPtr xenXMDomainConfigFormat(virConnectPtr conn, virDomainDefPtr def);
+virDomainDefPtr xenXMDomainConfigParse(virConnectPtr conn, virConfPtr conf);
+
+int xenXMDomainBlockPeek (virDomainPtr dom, const char *path, unsigned long long offset, size_t size, void *buffer);
+
+int xenXMDomainGetAutostart(virDomainPtr dom, int *autostart);
+int xenXMDomainSetAutostart(virDomainPtr dom, int autostart);
+
+#endif
diff --git a/src/xen/xs_internal.c b/src/xen/xs_internal.c
new file mode 100644 (file)
index 0000000..494728d
--- /dev/null
@@ -0,0 +1,1407 @@
+/*
+ * xs_internal.c: access to Xen Store
+ *
+ * Copyright (C) 2006, 2009 Red Hat, Inc.
+ *
+ * See COPYING.LIB for the License of this software
+ *
+ * Daniel Veillard <veillard@redhat.com>
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+
+#include <stdint.h>
+
+#include <xen/dom0_ops.h>
+#include <xen/version.h>
+#include <xen/xen.h>
+
+#include <xs.h>
+
+#include "virterror_internal.h"
+#include "datatypes.h"
+#include "driver.h"
+#include "memory.h"
+#include "event.h"
+#include "logging.h"
+#include "uuid.h"
+#include "xen_driver.h"
+#include "xs_internal.h"
+#include "xen_hypervisor.h"
+
+#define VIR_FROM_THIS VIR_FROM_XEN
+
+#ifndef PROXY
+static char *xenStoreDomainGetOSType(virDomainPtr domain);
+static void xenStoreWatchEvent(int watch, int fd, int events, void *data);
+static void xenStoreWatchListFree(xenStoreWatchListPtr list);
+
+struct xenUnifiedDriver xenStoreDriver = {
+    xenStoreOpen, /* open */
+    xenStoreClose, /* close */
+    NULL, /* version */
+    NULL, /* hostname */
+    NULL, /* nodeGetInfo */
+    NULL, /* getCapabilities */
+    xenStoreListDomains, /* listDomains */
+    NULL, /* numOfDomains */
+    NULL, /* domainCreateXML */
+    NULL, /* domainSuspend */
+    NULL, /* domainResume */
+    xenStoreDomainShutdown, /* domainShutdown */
+    xenStoreDomainReboot, /* domainReboot */
+    NULL, /* domainDestroy */
+    xenStoreDomainGetOSType, /* domainGetOSType */
+    xenStoreDomainGetMaxMemory, /* domainGetMaxMemory */
+    NULL, /* domainSetMaxMemory */
+    xenStoreDomainSetMemory, /* domainSetMemory */
+    xenStoreGetDomainInfo, /* domainGetInfo */
+    NULL, /* domainSave */
+    NULL, /* domainRestore */
+    NULL, /* domainCoreDump */
+    NULL, /* domainSetVcpus */
+    NULL, /* domainPinVcpu */
+    NULL, /* domainGetVcpus */
+    NULL, /* domainGetMaxVcpus */
+    NULL, /* listDefinedDomains */
+    NULL, /* numOfDefinedDomains */
+    NULL, /* domainCreate */
+    NULL, /* domainDefineXML */
+    NULL, /* domainUndefine */
+    NULL, /* domainAttachDevice */
+    NULL, /* domainDetachDevice */
+    NULL, /* domainGetAutostart */
+    NULL, /* domainSetAutostart */
+    NULL, /* domainGetSchedulerType */
+    NULL, /* domainGetSchedulerParameters */
+    NULL, /* domainSetSchedulerParameters */
+};
+
+#endif /* ! PROXY */
+
+#define virXenStoreError(conn, code, fmt...)                                 \
+        virReportErrorHelper(NULL, VIR_FROM_XENSTORE, code, __FILE__,      \
+                               __FUNCTION__, __LINE__, fmt)
+
+/************************************************************************
+ *                                                                     *
+ *             Helper internal APIs                                    *
+ *                                                                     *
+ ************************************************************************/
+#ifndef PROXY
+/**
+ * virConnectDoStoreList:
+ * @conn: pointer to the hypervisor connection
+ * @path: the absolute path of the directory in the store to list
+ * @nb: OUT pointer to the number of items found
+ *
+ * Internal API querying the Xenstore for a list
+ *
+ * Returns a string which must be freed by the caller or NULL in case of error
+ */
+static char **
+virConnectDoStoreList(virConnectPtr conn, const char *path,
+                      unsigned int *nb)
+{
+    xenUnifiedPrivatePtr priv;
+
+    if (conn == NULL)
+        return NULL;
+
+    priv = (xenUnifiedPrivatePtr) conn->privateData;
+    if (priv->xshandle == NULL || path == NULL || nb == NULL)
+        return (NULL);
+
+    return xs_directory (priv->xshandle, 0, path, nb);
+}
+#endif /* ! PROXY */
+
+/**
+ * virDomainDoStoreQuery:
+ * @conn: pointer to the hypervisor connection
+ * @domid: id of the domain
+ * @path: the relative path of the data in the store to retrieve
+ *
+ * Internal API querying the Xenstore for a string value.
+ *
+ * Returns a string which must be freed by the caller or NULL in case of error
+ */
+static char *
+virDomainDoStoreQuery(virConnectPtr conn, int domid, const char *path)
+{
+    char s[256];
+    unsigned int len = 0;
+    xenUnifiedPrivatePtr priv;
+
+    if (!conn)
+        return NULL;
+
+    priv = (xenUnifiedPrivatePtr) conn->privateData;
+    if (priv->xshandle == NULL)
+        return (NULL);
+
+    snprintf(s, 255, "/local/domain/%d/%s", domid, path);
+    s[255] = 0;
+
+    return xs_read(priv->xshandle, 0, &s[0], &len);
+}
+
+#ifndef PROXY
+/**
+ * virDomainDoStoreWrite:
+ * @domain: a domain object
+ * @path: the relative path of the data in the store to retrieve
+ *
+ * Internal API setting up a string value in the Xenstore
+ * Requires write access to the XenStore
+ *
+ * Returns 0 in case of success, -1 in case of failure
+ */
+static int
+virDomainDoStoreWrite(virDomainPtr domain, const char *path,
+                      const char *value)
+{
+    char s[256];
+    xenUnifiedPrivatePtr priv;
+    int ret = -1;
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain))
+        return (-1);
+
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+    if (priv->xshandle == NULL)
+        return (-1);
+    if (domain->conn->flags & VIR_CONNECT_RO)
+        return (-1);
+
+    snprintf(s, 255, "/local/domain/%d/%s", domain->id, path);
+    s[255] = 0;
+
+    if (xs_write(priv->xshandle, 0, &s[0], value, strlen(value)))
+        ret = 0;
+
+    return (ret);
+}
+
+/**
+ * virDomainGetVM:
+ * @domain: a domain object
+ *
+ * Internal API extracting a xenstore vm path.
+ *
+ * Returns the new string or NULL in case of error
+ */
+static char *
+virDomainGetVM(virDomainPtr domain)
+{
+    char *vm;
+    char query[200];
+    unsigned int len;
+    xenUnifiedPrivatePtr priv;
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain))
+        return (NULL);
+
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+    if (priv->xshandle == NULL)
+        return (NULL);
+
+    snprintf(query, 199, "/local/domain/%d/vm", virDomainGetID(domain));
+    query[199] = 0;
+
+    vm = xs_read(priv->xshandle, 0, &query[0], &len);
+
+    return (vm);
+}
+
+/**
+ * virDomainGetVMInfo:
+ * @domain: a domain object
+ * @vm: the xenstore vm path
+ * @name: the value's path
+ *
+ * Internal API extracting one information the device used
+ * by the domain from xensttore
+ *
+ * Returns the new string or NULL in case of error
+ */
+static char *
+virDomainGetVMInfo(virDomainPtr domain, const char *vm, const char *name)
+{
+    char s[256];
+    char *ret = NULL;
+    unsigned int len = 0;
+    xenUnifiedPrivatePtr priv;
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain))
+        return (NULL);
+
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+    if (priv->xshandle == NULL)
+        return (NULL);
+
+    snprintf(s, 255, "%s/%s", vm, name);
+    s[255] = 0;
+
+    ret = xs_read(priv->xshandle, 0, &s[0], &len);
+
+    return (ret);
+}
+
+#endif /* ! PROXY */
+
+/************************************************************************
+ *                                                                     *
+ *             Canonical internal APIs                                 *
+ *                                                                     *
+ ************************************************************************/
+/**
+ * xenStoreOpen:
+ * @conn: pointer to the connection block
+ * @name: URL for the target, NULL for local
+ * @flags: combination of virDrvOpenFlag(s)
+ *
+ * Connects to the Xen hypervisor.
+ *
+ * Returns 0 or -1 in case of error.
+ */
+virDrvOpenStatus
+xenStoreOpen(virConnectPtr conn,
+             virConnectAuthPtr auth ATTRIBUTE_UNUSED,
+             int flags ATTRIBUTE_UNUSED)
+{
+    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
+
+#ifdef PROXY
+    priv->xshandle = xs_daemon_open_readonly();
+#else
+    if (flags & VIR_CONNECT_RO)
+        priv->xshandle = xs_daemon_open_readonly();
+    else
+        priv->xshandle = xs_daemon_open();
+#endif /* ! PROXY */
+
+    if (priv->xshandle == NULL) {
+        /*
+         * not being able to connect via the socket as an unprivileged
+         * user is rather normal, this should fallback to the proxy (or
+         * remote) mechanism.
+         */
+        if (xenHavePrivilege()) {
+            virXenStoreError(NULL, VIR_ERR_NO_XEN,
+                                 "%s", _("failed to connect to Xen Store"));
+        }
+        return (-1);
+    }
+
+#ifndef PROXY
+    /* Init activeDomainList */
+    if (VIR_ALLOC(priv->activeDomainList) < 0) {
+        virXenStoreError(NULL, VIR_ERR_INTERNAL_ERROR,
+                                 "%s", _("failed to allocate activeDomainList"));
+        return -1;
+    }
+
+    /* Init watch list before filling in domInfoList,
+       so we can know if it is the first time through
+       when the callback fires */
+    if ( VIR_ALLOC(priv->xsWatchList) < 0 ) {
+        virXenStoreError(NULL, VIR_ERR_INTERNAL_ERROR,
+                                 "%s", _("failed to allocate xsWatchList"));
+        return -1;
+    }
+
+    /* This will get called once at start */
+    if ( xenStoreAddWatch(conn, "@releaseDomain",
+                     "releaseDomain", xenStoreDomainReleased, priv) < 0 )
+    {
+        virXenStoreError(NULL, VIR_ERR_INTERNAL_ERROR,
+                                 "%s", _("adding watch @releaseDomain"));
+        return -1;
+    }
+
+    /* The initial call of this will fill domInfoList */
+    if( xenStoreAddWatch(conn, "@introduceDomain",
+                     "introduceDomain", xenStoreDomainIntroduced, priv) < 0 )
+    {
+        virXenStoreError(NULL, VIR_ERR_INTERNAL_ERROR,
+                                 "%s", _("adding watch @introduceDomain"));
+        return -1;
+    }
+
+    /* Add an event handle */
+    if ((priv->xsWatch = virEventAddHandle(xs_fileno(priv->xshandle),
+                                           VIR_EVENT_HANDLE_READABLE,
+                                           xenStoreWatchEvent,
+                                           conn,
+                                           NULL)) < 0)
+        DEBUG0("Failed to add event handle, disabling events\n");
+
+#endif //PROXY
+    return 0;
+}
+
+/**
+ * xenStoreClose:
+ * @conn: pointer to the connection block
+ *
+ * Close the connection to the Xen hypervisor.
+ *
+ * Returns 0 in case of success or -1 in case of error.
+ */
+int
+xenStoreClose(virConnectPtr conn)
+{
+    xenUnifiedPrivatePtr priv;
+
+    if (conn == NULL) {
+        virXenStoreError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return(-1);
+    }
+
+    priv = (xenUnifiedPrivatePtr) conn->privateData;
+
+#ifndef PROXY
+    if (xenStoreRemoveWatch(conn, "@introduceDomain", "introduceDomain") < 0) {
+        DEBUG0("Warning, could not remove @introduceDomain watch");
+        /* not fatal */
+    }
+
+    if (xenStoreRemoveWatch(conn, "@releaseDomain", "releaseDomain") < 0) {
+        DEBUG0("Warning, could not remove @releaseDomain watch");
+        /* not fatal */
+    }
+
+    xenStoreWatchListFree(priv->xsWatchList);
+    priv->xsWatchList = NULL;
+    xenUnifiedDomainInfoListFree(priv->activeDomainList);
+    priv->activeDomainList = NULL;
+#endif
+    if (priv->xshandle == NULL)
+        return(-1);
+
+    if (priv->xsWatch != -1)
+        virEventRemoveHandle(priv->xsWatch);
+    xs_daemon_close(priv->xshandle);
+    priv->xshandle = NULL;
+
+    return (0);
+}
+
+#ifndef PROXY
+/**
+ * xenStoreGetDomainInfo:
+ * @domain: pointer to the domain block
+ * @info: the place where information should be stored
+ *
+ * Do an hypervisor call to get the related set of domain information.
+ *
+ * Returns 0 in case of success, -1 in case of error.
+ */
+int
+xenStoreGetDomainInfo(virDomainPtr domain, virDomainInfoPtr info)
+{
+    char *tmp, **tmp2;
+    unsigned int nb_vcpus;
+    char request[200];
+    xenUnifiedPrivatePtr priv;
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain))
+        return (-1);
+
+    if ((domain == NULL) || (domain->conn == NULL) || (info == NULL)) {
+        virXenStoreError(domain ? domain->conn : NULL, VIR_ERR_INVALID_ARG,
+                         __FUNCTION__);
+        return(-1);
+    }
+
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+    if (priv->xshandle == NULL)
+        return(-1);
+
+    if (domain->id == -1)
+        return(-1);
+
+    tmp = virDomainDoStoreQuery(domain->conn, domain->id, "running");
+    if (tmp != NULL) {
+        if (tmp[0] == '1')
+            info->state = VIR_DOMAIN_RUNNING;
+        free(tmp);
+    } else {
+        info->state = VIR_DOMAIN_NOSTATE;
+    }
+    tmp = virDomainDoStoreQuery(domain->conn, domain->id, "memory/target");
+    if (tmp != NULL) {
+        info->memory = atol(tmp);
+        info->maxMem = atol(tmp);
+        free(tmp);
+    } else {
+        info->memory = 0;
+        info->maxMem = 0;
+    }
+#if 0
+    /* doesn't seems to work */
+    tmp = virDomainDoStoreQuery(domain->conn, domain->id, "cpu_time");
+    if (tmp != NULL) {
+        info->cpuTime = atol(tmp);
+        free(tmp);
+    } else {
+        info->cpuTime = 0;
+    }
+#endif
+    snprintf(request, 199, "/local/domain/%d/cpu", domain->id);
+    request[199] = 0;
+    tmp2 = virConnectDoStoreList(domain->conn, request, &nb_vcpus);
+    if (tmp2 != NULL) {
+        info->nrVirtCpu = nb_vcpus;
+        free(tmp2);
+    }
+    return (0);
+}
+
+/**
+ * xenStoreDomainSetMemory:
+ * @domain: pointer to the domain block
+ * @memory: the max memory size in kilobytes.
+ *
+ * Change the maximum amount of memory allowed in the xen store
+ *
+ * Returns 0 in case of success, -1 in case of error.
+ */
+int
+xenStoreDomainSetMemory(virDomainPtr domain, unsigned long memory)
+{
+    int ret;
+    char value[20];
+
+    if ((domain == NULL) || (domain->conn == NULL) ||
+        (memory < 1024 * MIN_XEN_GUEST_SIZE)) {
+        virXenStoreError(domain ? domain->conn : NULL, VIR_ERR_INVALID_ARG,
+                         __FUNCTION__);
+        return(-1);
+    }
+    if (domain->id == -1)
+        return(-1);
+    if ((domain->id == 0) && (memory < (2 * MIN_XEN_GUEST_SIZE * 1024)))
+        return(-1);
+    snprintf(value, 19, "%lu", memory);
+    value[19] = 0;
+    ret = virDomainDoStoreWrite(domain, "memory/target", &value[0]);
+    if (ret < 0)
+        return (-1);
+    return (0);
+}
+
+/**
+ * xenStoreDomainGetMaxMemory:
+ * @domain: pointer to the domain block
+ *
+ * Ask the xenstore for the maximum memory allowed for a domain
+ *
+ * Returns the memory size in kilobytes or 0 in case of error.
+ */
+unsigned long
+xenStoreDomainGetMaxMemory(virDomainPtr domain)
+{
+    char *tmp;
+    unsigned long ret = 0;
+    xenUnifiedPrivatePtr priv;
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain))
+        return (ret);
+    if (domain->id == -1)
+        return(-1);
+
+    priv = domain->conn->privateData;
+    xenUnifiedLock(priv);
+    tmp = virDomainDoStoreQuery(domain->conn, domain->id, "memory/target");
+    if (tmp != NULL) {
+        ret = (unsigned long) atol(tmp);
+        VIR_FREE(tmp);
+    }
+    xenUnifiedUnlock(priv);
+    return(ret);
+}
+
+/**
+ * xenStoreNumOfDomains:
+ * @conn: pointer to the hypervisor connection
+ *
+ * Provides the number of active domains.
+ *
+ * Returns the number of domain found or -1 in case of error
+ */
+int
+xenStoreNumOfDomains(virConnectPtr conn)
+{
+    unsigned int num;
+    char **idlist;
+    int ret = -1;
+    xenUnifiedPrivatePtr priv;
+
+    if (conn == NULL) {
+        virXenStoreError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return -1;
+    }
+
+    priv = (xenUnifiedPrivatePtr) conn->privateData;
+    if (priv->xshandle == NULL) {
+        virXenStoreError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return(-1);
+    }
+    idlist = xs_directory(priv->xshandle, 0, "/local/domain", &num);
+    if (idlist) {
+        free(idlist);
+        ret = num;
+    }
+    return(ret);
+}
+
+/**
+ * xenStoreDoListDomains:
+ * @conn: pointer to the hypervisor connection
+ * @ids: array to collect the list of IDs of active domains
+ * @maxids: size of @ids
+ *
+ * Internal API: collect the list of active domains, and store
+ * their ID in @maxids. The driver lock must be held.
+ *
+ * Returns the number of domain found or -1 in case of error
+ */
+static int
+xenStoreDoListDomains(xenUnifiedPrivatePtr priv, int *ids, int maxids)
+{
+    char **idlist = NULL, *endptr;
+    unsigned int num, i;
+    int ret = -1;
+    long id;
+
+    if (priv->xshandle == NULL)
+        goto out;
+
+    idlist = xs_directory (priv->xshandle, 0, "/local/domain", &num);
+    if (idlist == NULL)
+        goto out;
+
+    for (ret = 0, i = 0; (i < num) && (ret < maxids); i++) {
+        id = strtol(idlist[i], &endptr, 10);
+        if ((endptr == idlist[i]) || (*endptr != 0))
+            goto out;
+        ids[ret++] = (int) id;
+    }
+
+out:
+    VIR_FREE (idlist);
+    return ret;
+}
+
+/**
+ * xenStoreListDomains:
+ * @conn: pointer to the hypervisor connection
+ * @ids: array to collect the list of IDs of active domains
+ * @maxids: size of @ids
+ *
+ * Collect the list of active domains, and store their ID in @maxids
+ *
+ * Returns the number of domain found or -1 in case of error
+ */
+int
+xenStoreListDomains(virConnectPtr conn, int *ids, int maxids)
+{
+    xenUnifiedPrivatePtr priv;
+    int ret;
+
+    if ((conn == NULL) || (ids == NULL)) {
+        virXenStoreError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return(-1);
+    }
+
+    priv = (xenUnifiedPrivatePtr) conn->privateData;
+
+    xenUnifiedLock(priv);
+    ret = xenStoreDoListDomains(priv, ids, maxids);
+    xenUnifiedUnlock(priv);
+
+    return(ret);
+}
+
+/**
+ * xenStoreLookupByName:
+ * @conn: A xend instance
+ * @name: The name of the domain
+ *
+ * Try to lookup a domain on the Xen Store based on its name.
+ *
+ * Returns a new domain object or NULL in case of failure
+ */
+virDomainPtr
+xenStoreLookupByName(virConnectPtr conn, const char *name)
+{
+    virDomainPtr ret = NULL;
+    unsigned int num, i, len;
+    long id = -1;
+    char **idlist = NULL, *endptr;
+    char prop[200], *tmp;
+    int found = 0;
+    struct xend_domain *xenddomain = NULL;
+    xenUnifiedPrivatePtr priv;
+
+    if ((conn == NULL) || (name == NULL)) {
+        virXenStoreError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return(NULL);
+    }
+
+    priv = (xenUnifiedPrivatePtr) conn->privateData;
+    if (priv->xshandle == NULL)
+        return(NULL);
+
+    idlist = xs_directory(priv->xshandle, 0, "/local/domain", &num);
+    if (idlist == NULL)
+        goto done;
+
+    for (i = 0; i < num; i++) {
+        id = strtol(idlist[i], &endptr, 10);
+        if ((endptr == idlist[i]) || (*endptr != 0)) {
+            goto done;
+        }
+#if 0
+        if (virConnectCheckStoreID(conn, (int) id) < 0)
+            continue;
+#endif
+        snprintf(prop, 199, "/local/domain/%s/name", idlist[i]);
+        prop[199] = 0;
+        tmp = xs_read(priv->xshandle, 0, prop, &len);
+        if (tmp != NULL) {
+            found = STREQ (name, tmp);
+            free(tmp);
+            if (found)
+                break;
+        }
+    }
+    if (!found)
+        goto done;
+
+    ret = virGetDomain(conn, name, NULL);
+    if (ret == NULL)
+        goto done;
+
+    ret->id = id;
+
+done:
+        free(xenddomain);
+        free(idlist);
+
+    return(ret);
+}
+
+/**
+ * xenStoreDomainShutdown:
+ * @domain: pointer to the Domain block
+ *
+ * Shutdown the domain, the OS is requested to properly shutdown
+ * and the domain may ignore it.  It will return immediately
+ * after queuing the request.
+ *
+ * Returns 0 in case of success, -1 in case of error.
+ */
+int
+xenStoreDomainShutdown(virDomainPtr domain)
+{
+    int ret;
+    xenUnifiedPrivatePtr priv;
+
+    if ((domain == NULL) || (domain->conn == NULL)) {
+        virXenStoreError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                         __FUNCTION__);
+        return(-1);
+    }
+    if (domain->id == -1 || domain->id == 0)
+        return(-1);
+    /*
+     * this is very hackish, the domU kernel probes for a special
+     * node in the xenstore and launch the shutdown command if found.
+     */
+    priv = domain->conn->privateData;
+    xenUnifiedLock(priv);
+    ret = virDomainDoStoreWrite(domain, "control/shutdown", "poweroff");
+    xenUnifiedUnlock(priv);
+    return ret;
+}
+
+/**
+ * xenStoreDomainReboot:
+ * @domain: pointer to the Domain block
+ * @flags: extra flags for the reboot operation, not used yet
+ *
+ * Reboot the domain, the OS is requested to properly shutdown
+ * and reboot but the domain may ignore it.  It will return immediately
+ * after queuing the request.
+ *
+ * Returns 0 in case of success, -1 in case of error.
+ */
+int
+xenStoreDomainReboot(virDomainPtr domain, unsigned int flags ATTRIBUTE_UNUSED)
+{
+    int ret;
+    xenUnifiedPrivatePtr priv;
+
+    if ((domain == NULL) || (domain->conn == NULL)) {
+        virXenStoreError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                         __FUNCTION__);
+        return(-1);
+    }
+    if (domain->id == -1 || domain->id == 0)
+        return(-1);
+    /*
+     * this is very hackish, the domU kernel probes for a special
+     * node in the xenstore and launch the shutdown command if found.
+     */
+    priv = domain->conn->privateData;
+    xenUnifiedLock(priv);
+    ret = virDomainDoStoreWrite(domain, "control/shutdown", "reboot");
+    xenUnifiedUnlock(priv);
+    return ret;
+}
+
+/*
+ * xenStoreDomainGetOSType:
+ * @domain: a domain object
+ *
+ * Get the type of domain operation system.
+ *
+ * Returns the new string or NULL in case of error, the string must be
+ *         freed by the caller.
+ */
+static char *
+xenStoreDomainGetOSType(virDomainPtr domain) {
+    char *vm, *str = NULL;
+
+    if ((domain == NULL) || (domain->conn == NULL)) {
+        virXenStoreError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                         __FUNCTION__);
+        return(NULL);
+    }
+
+    vm = virDomainGetVM(domain);
+    if (vm) {
+        xenUnifiedPrivatePtr priv = domain->conn->privateData;
+        xenUnifiedLock(priv);
+        str = virDomainGetVMInfo(domain, vm, "image/ostype");
+        xenUnifiedUnlock(priv);
+        VIR_FREE(vm);
+    }
+
+    return (str);
+}
+#endif /* ! PROXY */
+
+/**
+ * xenStoreDomainGetVNCPort:
+ * @conn: the hypervisor connection
+ * @domid: id of the domain
+ *
+ * Return the port number on which the domain is listening for VNC
+ * connections.
+ *
+ * The caller must hold the lock on the privateData
+ * associated with the 'conn' parameter.
+ *
+ * Returns the port number, -1 in case of error
+ */
+int             xenStoreDomainGetVNCPort(virConnectPtr conn, int domid) {
+    char *tmp;
+    int ret = -1;
+
+    tmp = virDomainDoStoreQuery(conn, domid, "console/vnc-port");
+    if (tmp != NULL) {
+        char *end;
+        ret = strtol(tmp, &end, 10);
+        if (ret == 0 && end == tmp)
+            ret = -1;
+        free(tmp);
+    }
+    return(ret);
+}
+
+/**
+ * xenStoreDomainGetConsolePath:
+ * @conn: the hypervisor connection
+ * @domid: id of the domain
+ *
+ * Return the path to the psuedo TTY on which the guest domain's
+ * serial console is attached.
+ *
+ * Returns the path to the serial console. It is the callers
+ * responsibilty to free() the return string. Returns NULL
+ * on error
+ *
+ * The caller must hold the lock on the privateData
+ * associated with the 'conn' parameter.
+ */
+char *          xenStoreDomainGetConsolePath(virConnectPtr conn, int domid) {
+  return virDomainDoStoreQuery(conn, domid, "console/tty");
+}
+
+#ifdef PROXY
+/*
+ * xenStoreDomainGetOSTypeID:
+ * @conn: pointer to the connection.
+ * @id: the domain id
+ *
+ * Get the type of domain operation system.
+ *
+ * The caller must hold the lock on the privateData
+ * associated with the 'conn' parameter.
+ *
+ * Returns the new string or NULL in case of error, the string must be
+ *         freed by the caller.
+ */
+char *
+xenStoreDomainGetOSTypeID(virConnectPtr conn, int id) {
+    char *vm, *str = NULL;
+    char query[200];
+    unsigned int len;
+    xenUnifiedPrivatePtr priv;
+
+    if (id < 0)
+        return(NULL);
+
+    priv = (xenUnifiedPrivatePtr) conn->privateData;
+    if (priv->xshandle == NULL)
+        return (NULL);
+
+    snprintf(query, 199, "/local/domain/%d/vm", id);
+    query[199] = 0;
+
+    vm = xs_read(priv->xshandle, 0, &query[0], &len);
+
+    if (vm) {
+        snprintf(query, 199, "%s/image/ostype", vm);
+        str = xs_read(priv->xshandle, 0, &query[0], &len);
+        free(vm);
+    }
+    if (str == NULL)
+        str = strdup("linux");
+
+
+    return (str);
+}
+#endif /* PROXY */
+
+/*
+ * xenStoreDomainGetNetworkID:
+ * @conn: pointer to the connection.
+ * @id: the domain id
+ * @mac: the mac address
+ *
+ * Get the reference (i.e. the string number) for the device on that domain
+ * which uses the given mac address
+ *
+ * The caller must hold the lock on the privateData
+ * associated with the 'conn' parameter.
+ *
+ * Returns the new string or NULL in case of error, the string must be
+ *         freed by the caller.
+ */
+char *
+xenStoreDomainGetNetworkID(virConnectPtr conn, int id, const char *mac) {
+    char dir[80], path[128], **list = NULL, *val = NULL;
+    unsigned int len, i, num;
+    char *ret = NULL;
+    xenUnifiedPrivatePtr priv;
+
+    if (id < 0)
+        return(NULL);
+
+    priv = (xenUnifiedPrivatePtr) conn->privateData;
+    if (priv->xshandle == NULL)
+        return (NULL);
+    if (mac == NULL)
+        return (NULL);
+
+    snprintf(dir, sizeof(dir), "/local/domain/0/backend/vif/%d", id);
+    list = xs_directory(priv->xshandle, 0, dir, &num);
+    if (list == NULL)
+        return(NULL);
+    for (i = 0; i < num; i++) {
+        snprintf(path, sizeof(path), "%s/%s/%s", dir, list[i], "mac");
+        if ((val = xs_read(priv->xshandle, 0, path, &len)) == NULL)
+            break;
+
+        bool match = (virMacAddrCompare(val, mac) == 0);
+
+        VIR_FREE(val);
+
+        if (match) {
+            ret = strdup(list[i]);
+            break;
+        }
+    }
+
+    VIR_FREE(list);
+    return(ret);
+}
+
+/*
+ * xenStoreDomainGetDiskID:
+ * @conn: pointer to the connection.
+ * @id: the domain id
+ * @dev: the virtual block device name
+ *
+ * Get the reference (i.e. the string number) for the device on that domain
+ * which uses the given virtual block device name
+ *
+ * The caller must hold the lock on the privateData
+ * associated with the 'conn' parameter.
+ *
+ * Returns the new string or NULL in case of error, the string must be
+ *         freed by the caller.
+ */
+char *
+xenStoreDomainGetDiskID(virConnectPtr conn, int id, const char *dev) {
+    char dir[80], path[128], **list = NULL, *val = NULL;
+    unsigned int devlen, len, i, num;
+    char *ret = NULL;
+    xenUnifiedPrivatePtr priv;
+
+    if (id < 0)
+        return(NULL);
+
+    priv = (xenUnifiedPrivatePtr) conn->privateData;
+    if (priv->xshandle == NULL)
+        return (NULL);
+    if (dev == NULL)
+        return (NULL);
+    devlen = strlen(dev);
+    if (devlen <= 0)
+        return (NULL);
+
+    snprintf(dir, sizeof(dir), "/local/domain/0/backend/vbd/%d", id);
+    list = xs_directory(priv->xshandle, 0, dir, &num);
+    if (list != NULL) {
+        for (i = 0; i < num; i++) {
+            snprintf(path, sizeof(path), "%s/%s/%s", dir, list[i], "dev");
+            val = xs_read(priv->xshandle, 0, path, &len);
+            if (val == NULL)
+                break;
+            if ((devlen != len) || memcmp(val, dev, len)) {
+                free (val);
+            } else {
+                ret = strdup(list[i]);
+                free (val);
+                free (list);
+                return (ret);
+            }
+        }
+        free (list);
+    }
+    snprintf(dir, sizeof(dir), "/local/domain/0/backend/tap/%d", id);
+    list = xs_directory(priv->xshandle, 0, dir, &num);
+    if (list != NULL) {
+        for (i = 0; i < num; i++) {
+            snprintf(path, sizeof(path), "%s/%s/%s", dir, list[i], "dev");
+            val = xs_read(priv->xshandle, 0, path, &len);
+            if (val == NULL)
+                break;
+            if ((devlen != len) || memcmp(val, dev, len)) {
+                free (val);
+            } else {
+                ret = strdup(list[i]);
+                free (val);
+                free (list);
+                return (ret);
+            }
+        }
+        free (list);
+    }
+    return (NULL);
+}
+
+/*
+ * The caller must hold the lock on the privateData
+ * associated with the 'conn' parameter.
+ */
+char *xenStoreDomainGetName(virConnectPtr conn,
+                            int id) {
+    char prop[200];
+    xenUnifiedPrivatePtr priv;
+    unsigned int len;
+
+    priv = (xenUnifiedPrivatePtr) conn->privateData;
+    if (priv->xshandle == NULL)
+        return(NULL);
+
+    snprintf(prop, 199, "/local/domain/%d/name", id);
+    prop[199] = 0;
+    return xs_read(priv->xshandle, 0, prop, &len);
+}
+
+#ifndef PROXY
+/*
+ * The caller must hold the lock on the privateData
+ * associated with the 'conn' parameter.
+ */
+int xenStoreDomainGetUUID(virConnectPtr conn,
+                          int id,
+                          unsigned char *uuid) {
+    char prop[200];
+    xenUnifiedPrivatePtr priv;
+    unsigned int len;
+    char *uuidstr;
+    int ret = 0;
+
+    priv = (xenUnifiedPrivatePtr) conn->privateData;
+    if (priv->xshandle == NULL)
+        return -1;
+
+    snprintf(prop, 199, "/local/domain/%d/vm", id);
+    prop[199] = 0;
+    // This will return something like
+    // /vm/00000000-0000-0000-0000-000000000000
+    uuidstr = xs_read(priv->xshandle, 0, prop, &len);
+
+    // remove "/vm/"
+    ret = virUUIDParse(uuidstr + 4, uuid);
+
+    VIR_FREE(uuidstr);
+
+    return ret;
+}
+
+static void
+xenStoreWatchListFree(xenStoreWatchListPtr list)
+{
+    int i;
+    for (i=0; i<list->count; i++) {
+        VIR_FREE(list->watches[i]->path);
+        VIR_FREE(list->watches[i]->token);
+        VIR_FREE(list->watches[i]);
+    }
+    VIR_FREE(list);
+}
+
+/*
+ * The caller must hold the lock on the privateData
+ * associated with the 'conn' parameter.
+ */
+int xenStoreAddWatch(virConnectPtr conn,
+                     const char *path,
+                     const char *token,
+                     xenStoreWatchCallback cb,
+                     void *opaque)
+{
+    xenStoreWatchPtr watch;
+    int n;
+    xenStoreWatchListPtr list;
+    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
+
+    if (priv->xshandle == NULL)
+        return -1;
+
+    list = priv->xsWatchList;
+    if(!list)
+        return -1;
+
+    /* check if we already have this callback on our list */
+    for (n=0; n < list->count; n++) {
+        if( STREQ(list->watches[n]->path, path) &&
+            STREQ(list->watches[n]->token, token)) {
+            virXenStoreError(NULL, VIR_ERR_INTERNAL_ERROR,
+                                 "%s", _("watch already tracked"));
+            return -1;
+        }
+    }
+
+    if (VIR_ALLOC(watch) < 0)
+        return -1;
+    watch->path   = strdup(path);
+    watch->token  = strdup(token);
+    watch->cb     = cb;
+    watch->opaque = opaque;
+
+    /* Make space on list */
+    n = list->count;
+    if (VIR_REALLOC_N(list->watches, n + 1) < 0) {
+        virXenStoreError(NULL, VIR_ERR_INTERNAL_ERROR,
+                                 "%s", _("reallocating list"));
+        VIR_FREE(watch);
+        return -1;
+    }
+
+    list->watches[n] = watch;
+    list->count++;
+
+    conn->refs++;
+
+    return xs_watch(priv->xshandle, watch->path, watch->token);
+}
+
+/*
+ * The caller must hold the lock on the privateData
+ * associated with the 'conn' parameter.
+ */
+int xenStoreRemoveWatch(virConnectPtr conn,
+                        const char *path,
+                        const char *token)
+{
+    int i;
+    xenStoreWatchListPtr list;
+    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
+
+    if (priv->xshandle == NULL)
+        return -1;
+
+    list = priv->xsWatchList;
+    if(!list)
+        return -1;
+
+    for (i = 0 ; i < list->count ; i++) {
+        if( STREQ(list->watches[i]->path, path) &&
+            STREQ(list->watches[i]->token, token)) {
+
+            if (!xs_unwatch(priv->xshandle,
+                       list->watches[i]->path,
+                       list->watches[i]->token))
+            {
+                DEBUG0("WARNING: Could not remove watch");
+                /* Not fatal, continue */
+            }
+
+            VIR_FREE(list->watches[i]->path);
+            VIR_FREE(list->watches[i]->token);
+            VIR_FREE(list->watches[i]);
+
+            if (i < (list->count - 1))
+                memmove(list->watches + i,
+                        list->watches + i + 1,
+                        sizeof(*(list->watches)) *
+                                (list->count - (i + 1)));
+
+            if (VIR_REALLOC_N(list->watches,
+                              list->count - 1) < 0) {
+                ; /* Failure to reduce memory allocation isn't fatal */
+            }
+            list->count--;
+            virUnrefConnect(conn);
+            return 0;
+        }
+    }
+    return -1;
+}
+
+static xenStoreWatchPtr
+xenStoreFindWatch(xenStoreWatchListPtr list,
+                  const char *path,
+                  const char *token)
+{
+    int i;
+    for (i = 0 ; i < list->count ; i++)
+        if( STREQ(path, list->watches[i]->path) &&
+            STREQ(token, list->watches[i]->token) )
+            return list->watches[i];
+
+    return NULL;
+}
+
+static void
+xenStoreWatchEvent(int watch ATTRIBUTE_UNUSED,
+                   int fd ATTRIBUTE_UNUSED,
+                   int events,
+                   void *data)
+{
+    char                **event;
+    char                *path;
+    char                *token;
+    unsigned int        stringCount;
+    xenStoreWatchPtr     sw;
+
+    virConnectPtr        conn = data;
+    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
+
+    if(!priv) return;
+
+    /* only set a watch on read and write events */
+    if (events & (VIR_EVENT_HANDLE_ERROR | VIR_EVENT_HANDLE_HANGUP)) return;
+
+    xenUnifiedLock(priv);
+
+    if(!priv->xshandle)
+        goto cleanup;
+
+    event = xs_read_watch(priv->xshandle, &stringCount);
+    if (!event)
+        goto cleanup;
+
+    path  = event[XS_WATCH_PATH];
+    token = event[XS_WATCH_TOKEN];
+
+    sw = xenStoreFindWatch(priv->xsWatchList, path, token);
+    if( sw )
+        sw->cb(conn, path, token, sw->opaque);
+    VIR_FREE(event);
+
+cleanup:
+    xenUnifiedUnlock(priv);
+}
+
+
+/*
+ * The domain callback for the @introduceDomain watch
+ *
+ * The lock on 'priv' is held when calling this
+ */
+int xenStoreDomainIntroduced(virConnectPtr conn,
+                             const char *path ATTRIBUTE_UNUSED,
+                             const char *token ATTRIBUTE_UNUSED,
+                             void *opaque)
+{
+    int i, j, found, missing = 0, retries = 20;
+    int new_domain_cnt;
+    int *new_domids;
+    int nread;
+
+    xenUnifiedPrivatePtr priv = opaque;
+
+retry:
+    new_domain_cnt = xenStoreNumOfDomains(conn);
+    if( VIR_ALLOC_N(new_domids,new_domain_cnt) < 0 ) {
+        virReportOOMError(NULL);
+        return -1;
+    }
+    nread = xenStoreDoListDomains(priv, new_domids, new_domain_cnt);
+    if (nread != new_domain_cnt) {
+        // mismatch. retry this read
+        VIR_FREE(new_domids);
+        goto retry;
+    }
+
+    missing = 0;
+    for (i=0 ; i < new_domain_cnt ; i++) {
+        found = 0;
+        for (j = 0 ; j < priv->activeDomainList->count ; j++) {
+            if (priv->activeDomainList->doms[j]->id == new_domids[i]) {
+                found = 1;
+                break;
+            }
+        }
+
+        if (!found) {
+            virDomainEventPtr event;
+            char *name;
+            unsigned char uuid[VIR_UUID_BUFLEN];
+
+            if (!(name = xenStoreDomainGetName(conn, new_domids[i]))) {
+                missing = 1;
+                continue;
+            }
+            if (xenStoreDomainGetUUID(conn, new_domids[i], uuid) < 0) {
+                missing = 1;
+                VIR_FREE(name);
+                continue;
+            }
+
+            event = virDomainEventNew(new_domids[i], name, uuid,
+                                      VIR_DOMAIN_EVENT_STARTED,
+                                      VIR_DOMAIN_EVENT_STARTED_BOOTED);
+            if (event)
+                xenUnifiedDomainEventDispatch(priv, event);
+
+            /* Add to the list */
+            xenUnifiedAddDomainInfo(priv->activeDomainList,
+                                    new_domids[i], name, uuid);
+
+            VIR_FREE(name);
+        }
+    }
+    VIR_FREE(new_domids);
+
+    if (missing && retries--) {
+        DEBUG0("Some domains were missing, trying again");
+        usleep(100 * 1000);
+        goto retry;
+    }
+    return 0;
+}
+
+/*
+ * The domain callback for the @destroyDomain watch
+ *
+ * The lock on 'priv' is held when calling this
+ */
+int xenStoreDomainReleased(virConnectPtr conn,
+                            const char *path  ATTRIBUTE_UNUSED,
+                            const char *token ATTRIBUTE_UNUSED,
+                            void *opaque)
+{
+    int i, j, found, removed, retries = 20;
+    int new_domain_cnt;
+    int *new_domids;
+    int nread;
+
+    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) opaque;
+
+    if(!priv->activeDomainList->count) return 0;
+
+retry:
+    new_domain_cnt = xenStoreNumOfDomains(conn);
+
+    if( VIR_ALLOC_N(new_domids,new_domain_cnt) < 0 ) {
+        virReportOOMError(NULL);
+        return -1;
+    }
+    nread = xenStoreDoListDomains(priv, new_domids, new_domain_cnt);
+    if (nread != new_domain_cnt) {
+        // mismatch. retry this read
+        VIR_FREE(new_domids);
+        goto retry;
+    }
+
+    removed = 0;
+    for (j=0 ; j < priv->activeDomainList->count ; j++) {
+        found = 0;
+        for (i=0 ; i < new_domain_cnt ; i++) {
+            if (priv->activeDomainList->doms[j]->id == new_domids[i]) {
+                found = 1;
+                break;
+            }
+        }
+
+        if (!found) {
+            virDomainEventPtr event =
+                virDomainEventNew(-1,
+                                  priv->activeDomainList->doms[j]->name,
+                                  priv->activeDomainList->doms[j]->uuid,
+                                  VIR_DOMAIN_EVENT_STOPPED,
+                                  VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
+            if (event)
+                xenUnifiedDomainEventDispatch(priv, event);
+
+            /* Remove from the list */
+            xenUnifiedRemoveDomainInfo(priv->activeDomainList,
+                                       priv->activeDomainList->doms[j]->id,
+                                       priv->activeDomainList->doms[j]->name,
+                                       priv->activeDomainList->doms[j]->uuid);
+
+            removed = 1;
+        }
+    }
+
+    VIR_FREE(new_domids);
+
+    if (!removed && retries--) {
+        DEBUG0("No domains removed, retrying");
+        usleep(100 * 1000);
+        goto retry;
+    }
+    return 0;
+}
+
+#endif //PROXY
diff --git a/src/xen/xs_internal.h b/src/xen/xs_internal.h
new file mode 100644 (file)
index 0000000..29e680f
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * xs_internal.h: internal API for access to XenStore
+ *
+ * Copyright (C) 2006 Red Hat, Inc.
+ *
+ * See COPYING.LIB for the License of this software
+ *
+ * Daniel Veillard <veillard@redhat.com>
+ */
+
+#ifndef __VIR_XS_INTERNAL_H__
+#define __VIR_XS_INTERNAL_H__
+
+#include "internal.h"
+#include "driver.h"
+
+extern struct xenUnifiedDriver xenStoreDriver;
+int xenStoreInit (void);
+
+virDrvOpenStatus       xenStoreOpen    (virConnectPtr conn,
+                                         virConnectAuthPtr auth,
+                                         int flags);
+int            xenStoreClose           (virConnectPtr conn);
+int            xenStoreGetDomainInfo   (virDomainPtr domain,
+                                         virDomainInfoPtr info);
+int            xenStoreNumOfDomains    (virConnectPtr conn);
+int            xenStoreListDomains     (virConnectPtr conn,
+                                         int *ids,
+                                         int maxids);
+virDomainPtr   xenStoreLookupByName(virConnectPtr conn,
+                                         const char *name);
+unsigned long  xenStoreGetMaxMemory    (virDomainPtr domain);
+int            xenStoreDomainSetMemory (virDomainPtr domain,
+                                         unsigned long memory);
+unsigned long  xenStoreDomainGetMaxMemory(virDomainPtr domain);
+int            xenStoreDomainShutdown  (virDomainPtr domain);
+int            xenStoreDomainReboot    (virDomainPtr domain,
+                                         unsigned int flags);
+
+/* those are entry point for the proxy */
+int             xenStoreDomainGetVNCPort(virConnectPtr conn,
+                                         int domid);
+char *          xenStoreDomainGetConsolePath(virConnectPtr conn,
+                                         int domid);
+char *         xenStoreDomainGetOSTypeID(virConnectPtr conn,
+                                         int id);
+char *         xenStoreDomainGetNetworkID(virConnectPtr conn,
+                                         int id,
+                                         const char *mac);
+char *         xenStoreDomainGetDiskID(virConnectPtr conn,
+                                         int id,
+                                         const char *dev);
+char *          xenStoreDomainGetName(virConnectPtr conn,
+                                      int id);
+int             xenStoreDomainGetUUID(virConnectPtr conn,
+                                      int id,
+                                      unsigned char *uuid);
+
+typedef int (*xenStoreWatchCallback)(virConnectPtr conn,
+                                     const char *path,
+                                     const char *token,
+                                     void *opaque);
+
+struct _xenStoreWatch {
+    char *path;
+    char *token;
+    xenStoreWatchCallback cb;
+    void *opaque;
+};
+typedef struct _xenStoreWatch xenStoreWatch;
+typedef xenStoreWatch *xenStoreWatchPtr;
+
+struct _xenStoreWatchList {
+    unsigned int count;
+    xenStoreWatchPtr *watches;
+};
+typedef struct _xenStoreWatchList xenStoreWatchList;
+typedef xenStoreWatchList *xenStoreWatchListPtr;
+
+
+int             xenStoreAddWatch(virConnectPtr conn,
+                                 const char *path,
+                                 const char *token,
+                                 xenStoreWatchCallback cb,
+                                 void *opaque);
+int             xenStoreRemoveWatch(virConnectPtr conn,
+                                    const char *path,
+                                    const char *token);
+
+/* domain events */
+int xenStoreDomainIntroduced(virConnectPtr conn,
+                             const char *path,
+                             const char *token,
+                             void *opaque);
+int xenStoreDomainReleased(virConnectPtr conn,
+                            const char *path,
+                            const char *token,
+                            void *opaque);
+
+int xenStoreDomainEventEmitted(virDomainEventType evt);
+#endif /* __VIR_XS_INTERNAL_H__ */
diff --git a/src/xen_inotify.c b/src/xen_inotify.c
deleted file mode 100644 (file)
index e312b9e..0000000
+++ /dev/null
@@ -1,492 +0,0 @@
-/*
- * xen_inofify.c: Xen notification of xml file activity in the
- *                following dirs:
- *                /etc/xen
- *                /var/lib/xend/domains
- *
- * Copyright (C) 2008 VirtualIron
- *
- * 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: Ben Guthro
- */
-#include <config.h>
-#include <dirent.h>
-#include <sys/inotify.h>
-
-#include "virterror_internal.h"
-#include "datatypes.h"
-#include "driver.h"
-#include "memory.h"
-#include "event.h"
-#include "xen_unified.h"
-#include "conf.h"
-#include "domain_conf.h"
-#include "xen_inotify.h"
-#include "xend_internal.h"
-#include "logging.h"
-#include "uuid.h"
-
-#include "xm_internal.h" /* for xenXMDomainConfigParse */
-
-#define VIR_FROM_THIS VIR_FROM_XEN_INOTIFY
-
-#define virXenInotifyError(conn, code, fmt...)                                 \
-        virReportErrorHelper(NULL, VIR_FROM_XEN_INOTIFY, code, __FILE__,      \
-                               __FUNCTION__, __LINE__, fmt)
-
-#define LIBVIRTD_DOMAINS_DIR "/var/lib/xend/domains"
-
-struct xenUnifiedDriver xenInotifyDriver = {
-    xenInotifyOpen, /* open */
-    xenInotifyClose, /* close */
-    NULL, /* version */
-    NULL, /* hostname */
-    NULL, /* nodeGetInfo */
-    NULL, /* getCapabilities */
-    NULL, /* listDomains */
-    NULL, /* numOfDomains */
-    NULL, /* domainCreateLinux */
-    NULL, /* domainSuspend */
-    NULL, /* domainResume */
-    NULL, /* domainShutdown */
-    NULL, /* domainReboot */
-    NULL, /* domainDestroy */
-    NULL, /* domainGetOSType */
-    NULL, /* domainGetMaxMemory */
-    NULL, /* domainSetMaxMemory */
-    NULL, /* domainSetMemory */
-    NULL, /* domainGetInfo */
-    NULL, /* domainSave */
-    NULL, /* domainRestore */
-    NULL, /* domainCoreDump */
-    NULL, /* domainSetVcpus */
-    NULL, /* domainPinVcpu */
-    NULL, /* domainGetVcpus */
-    NULL, /* domainGetMaxVcpus */
-    NULL, /* listDefinedDomains */
-    NULL, /* numOfDefinedDomains */
-    NULL, /* domainCreate */
-    NULL, /* domainDefineXML */
-    NULL, /* domainUndefine */
-    NULL, /* domainAttachDevice */
-    NULL, /* domainDetachDevice */
-    NULL, /* domainGetAutostart */
-    NULL, /* domainSetAutostart */
-    NULL, /* domainGetSchedulerType */
-    NULL, /* domainGetSchedulerParameters */
-    NULL, /* domainSetSchedulerParameters */
-};
-
-static int
-xenInotifyXenCacheLookup(virConnectPtr conn,
-                         const char *filename,
-                         char **name, unsigned char *uuid) {
-    xenUnifiedPrivatePtr priv = conn->privateData;
-    xenXMConfCachePtr entry;
-
-    if (!(entry = virHashLookup(priv->configCache, filename))) {
-        DEBUG("No config found for %s", filename);
-        return -1;
-    }
-
-    *name = strdup(entry->def->name);
-    memcpy(uuid, entry->def->uuid, VIR_UUID_BUFLEN);
-
-    if (!*name) {
-        DEBUG0("Error getting dom from def");
-        return -1;
-    }
-    return 0;
-}
-
-static int
-xenInotifyXendDomainsDirLookup(virConnectPtr conn, const char *filename,
-                               char **name, unsigned char *uuid) {
-    int i;
-    virDomainPtr dom;
-    const char *uuid_str;
-    unsigned char rawuuid[VIR_UUID_BUFLEN];
-    xenUnifiedPrivatePtr priv = conn->privateData;
-
-    /* xend is managing domains. we will get
-    * a filename in the manner:
-    * /var/lib/xend/domains/<uuid>/
-    */
-    uuid_str = filename + strlen(LIBVIRTD_DOMAINS_DIR) + 1;
-
-    if (virUUIDParse(uuid_str, rawuuid) < 0) {
-        virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
-                           _("parsing uuid %s"), uuid_str);
-        return -1;
-    }
-    /* call directly into xend here, as driver may not yet
-       be set during open while we are building our
-       initial list of domains */
-    DEBUG("Looking for dom with uuid: %s", uuid_str);
-    /* XXX Should not have to go via a virDomainPtr obj instance */
-    if(!(dom = xenDaemonLookupByUUID(conn, rawuuid))) {
-        /* If we are here, the domain has gone away.
-           search for, and create a domain from the stored
-           list info */
-        for (i = 0 ; i < priv->configInfoList->count ; i++) {
-            if (!memcmp(uuid, priv->configInfoList->doms[i]->uuid, VIR_UUID_BUFLEN)) {
-                *name = strdup(priv->configInfoList->doms[i]->name);
-                if (!*name) {
-                    virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
-                                       _("finding dom for %s"), uuid_str);
-                    return -1;
-                }
-                memcpy(uuid, priv->configInfoList->doms[i]->uuid, VIR_UUID_BUFLEN);
-                DEBUG0("Found dom on list");
-                return 0;
-            }
-        }
-        virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
-                           "%s", _("finding dom on config list"));
-        return -1;
-    }
-
-    if (!(*name = strdup(dom->name)))
-        return -1;
-    memcpy(uuid, dom->uuid, VIR_UUID_BUFLEN);
-    virDomainFree(dom);
-    /* succeeded too find domain by uuid */
-    return 0;
-}
-
-static int
-xenInotifyDomainLookup(virConnectPtr conn,
-                       const char *filename,
-                       char **name, unsigned char *uuid) {
-    xenUnifiedPrivatePtr priv = conn->privateData;
-    if (priv->useXenConfigCache)
-        return xenInotifyXenCacheLookup(conn, filename, name, uuid);
-    else
-        return xenInotifyXendDomainsDirLookup(conn, filename, name, uuid);
-}
-
-static virDomainEventPtr
-xenInotifyDomainEventFromFile(virConnectPtr conn,
-                              const char *filename,
-                              int type, int detail) {
-    virDomainEventPtr event;
-    char *name = NULL;
-    unsigned char uuid[VIR_UUID_BUFLEN];
-
-    if (xenInotifyDomainLookup(conn, filename, &name, uuid) < 0)
-        return NULL;
-
-    event = virDomainEventNew(-1, name, uuid, type, detail);
-    VIR_FREE(name);
-    return event;
-}
-
-static int
-xenInotifyXendDomainsDirRemoveEntry(virConnectPtr conn,
-                                    const char *fname) {
-    xenUnifiedPrivatePtr priv = conn->privateData;
-    const char *uuidstr = fname + strlen(LIBVIRTD_DOMAINS_DIR) + 1;
-    unsigned char uuid[VIR_UUID_BUFLEN];
-    int i;
-
-    if (virUUIDParse(uuidstr, uuid) < 0) {
-        virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
-                           _("parsing uuid %s"), uuidstr);
-        return -1;
-    }
-
-    /* match and remove on uuid */
-    for (i = 0 ; i < priv->configInfoList->count ; i++) {
-        if (!memcmp(uuid, priv->configInfoList->doms[i]->uuid, VIR_UUID_BUFLEN)) {
-            VIR_FREE(priv->configInfoList->doms[i]->name);
-            VIR_FREE(priv->configInfoList->doms[i]);
-
-            if (i < (priv->configInfoList->count - 1))
-                memmove(priv->configInfoList->doms + i,
-                        priv->configInfoList->doms + i + 1,
-                        sizeof(*(priv->configInfoList->doms)) *
-                                (priv->configInfoList->count - (i + 1)));
-
-            if (VIR_REALLOC_N(priv->configInfoList->doms,
-                              priv->configInfoList->count - 1) < 0) {
-                ; /* Failure to reduce memory allocation isn't fatal */
-            }
-            priv->configInfoList->count--;
-            return 0;
-        }
-    }
-    return -1;
-}
-
-static int
-xenInotifyXendDomainsDirAddEntry(virConnectPtr conn,
-                                 const char *fname) {
-    char *name = NULL;
-    unsigned char uuid[VIR_UUID_BUFLEN];
-    xenUnifiedPrivatePtr priv = conn->privateData;
-
-    if (xenInotifyDomainLookup(conn, fname, &name, uuid) < 0) {
-        virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
-                           "%s", _("Error looking up domain"));
-        return -1;
-    }
-
-    if (xenUnifiedAddDomainInfo(priv->configInfoList,
-                                -1, name, uuid) < 0) {
-        virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
-                        "%s", _("Error adding file to config cache"));
-        VIR_FREE(name);
-        return -1;
-    }
-    VIR_FREE(name);
-    return 0;
-}
-
-static int
-xenInotifyRemoveDomainConfigInfo(virConnectPtr conn,
-                                 const char *fname) {
-    xenUnifiedPrivatePtr priv = conn->privateData;
-    return priv->useXenConfigCache ?
-        xenXMConfigCacheRemoveFile(conn, fname) :
-        xenInotifyXendDomainsDirRemoveEntry(conn, fname);
-}
-
-static int
-xenInotifyAddDomainConfigInfo(virConnectPtr conn,
-                              const char *fname) {
-    xenUnifiedPrivatePtr priv = conn->privateData;
-    return priv->useXenConfigCache ?
-        xenXMConfigCacheAddFile(conn, fname) :
-        xenInotifyXendDomainsDirAddEntry(conn, fname);
-}
-
-static void
-xenInotifyEvent(int watch ATTRIBUTE_UNUSED,
-                int fd,
-                int events ATTRIBUTE_UNUSED,
-                void *data)
-{
-    char buf[1024];
-    char fname[1024];
-    struct inotify_event *e;
-    int got;
-    char *tmp, *name;
-    virConnectPtr conn = data;
-    xenUnifiedPrivatePtr priv = NULL;
-
-    DEBUG0("got inotify event");
-
-    if( conn && conn->privateData ) {
-        priv = conn->privateData;
-    } else {
-        virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
-                           "%s", _("conn, or private data is NULL"));
-        return;
-    }
-
-    xenUnifiedLock(priv);
-
-reread:
-    got = read(fd, buf, sizeof(buf));
-    if (got == -1) {
-        if (errno == EINTR)
-            goto reread;
-        goto cleanup;
-    }
-
-    tmp = buf;
-    while (got) {
-        if (got < sizeof(struct inotify_event))
-            goto cleanup; /* bad */
-
-        e = (struct inotify_event *)tmp;
-        tmp += sizeof(struct inotify_event);
-        got -= sizeof(struct inotify_event);
-
-        if (got < e->len)
-            goto cleanup;
-
-        tmp += e->len;
-        got -= e->len;
-
-        name = (char *)&(e->name);
-
-        snprintf(fname, 1024, "%s/%s",
-                 priv->configDir, name);
-
-        if (e->mask & (IN_DELETE | IN_MOVED_FROM)) {
-            virDomainEventPtr event =
-                xenInotifyDomainEventFromFile(conn, fname,
-                                              VIR_DOMAIN_EVENT_UNDEFINED,
-                                              VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
-            if (!event)
-                xenUnifiedDomainEventDispatch(conn->privateData, event);
-            else
-                virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
-                                   "%s", _("looking up dom"));
-
-            if (xenInotifyRemoveDomainConfigInfo(conn, fname) < 0 ) {
-                virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
-                                   "%s", _("Error adding file to config cache"));
-                goto cleanup;
-            }
-        } else if (e->mask & ( IN_CREATE | IN_CLOSE_WRITE | IN_MOVED_TO) ) {
-            virDomainEventPtr event;
-            if (xenInotifyAddDomainConfigInfo(conn, fname) < 0 ) {
-                virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
-                                   "%s", _("Error adding file to config cache"));
-                goto cleanup;
-            }
-
-            event = xenInotifyDomainEventFromFile(conn, fname,
-                                                  VIR_DOMAIN_EVENT_DEFINED,
-                                                  VIR_DOMAIN_EVENT_DEFINED_ADDED);
-
-            if (event)
-                xenUnifiedDomainEventDispatch(conn->privateData, event);
-            else
-                virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
-                                   "%s", _("looking up dom"));
-
-        }
-
-    }
-
-cleanup:
-    xenUnifiedUnlock(priv);
-}
-
-/**
- * xenInotifyOpen:
- * @conn: pointer to the connection block
- * @name: URL for the target, NULL for local
- * @flags: combination of virDrvOpenFlag(s)
- *
- * Connects and starts listening for inotify events
- *
- * Returns 0 or -1 in case of error.
- */
-virDrvOpenStatus
-xenInotifyOpen(virConnectPtr conn ATTRIBUTE_UNUSED,
-             virConnectAuthPtr auth ATTRIBUTE_UNUSED,
-             int flags ATTRIBUTE_UNUSED)
-{
-    DIR *dh;
-    struct dirent *ent;
-    char path[PATH_MAX];
-    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
-
-    if (priv->configDir) {
-        priv->useXenConfigCache = 1;
-    } else {
-        /* /var/lib/xend/domains/<uuid>/config.sxp */
-        priv->configDir = LIBVIRTD_DOMAINS_DIR;
-        priv->useXenConfigCache = 0;
-
-        if (VIR_ALLOC(priv->configInfoList) < 0) {
-            virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
-                               "%s", _("failed to allocate configInfoList"));
-            return -1;
-        }
-
-        /* populate initial list */
-        if (!(dh = opendir(priv->configDir))) {
-            virReportSystemError(NULL, errno,
-                                 _("cannot open directory: %s"),
-                                 priv->configDir);
-            return -1;
-        }
-        while ((ent = readdir(dh))) {
-            if (STRPREFIX(ent->d_name, "."))
-                continue;
-
-            /* Build the full file path */
-            if ((strlen(priv->configDir) + 1 +
-                 strlen(ent->d_name) + 1) > PATH_MAX)
-                continue;
-            strcpy(path, priv->configDir);
-            strcat(path, "/");
-            strcat(path, ent->d_name);
-
-            if (xenInotifyAddDomainConfigInfo(conn, path) < 0 ) {
-                virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
-                                   "%s", _("Error adding file to config list"));
-                closedir(dh);
-                return -1;
-            }
-        }
-        closedir(dh);
-    }
-
-    if ((priv->inotifyFD = inotify_init()) < 0) {
-        virReportSystemError(NULL, errno,
-                             "%s", _("initializing inotify"));
-        return -1;
-    }
-
-    DEBUG("Adding a watch on %s", priv->configDir);
-    if (inotify_add_watch(priv->inotifyFD,
-                          priv->configDir,
-                          IN_CREATE |
-                          IN_CLOSE_WRITE | IN_DELETE |
-                          IN_MOVED_TO | IN_MOVED_FROM) < 0) {
-        virReportSystemError(NULL, errno,
-                             _("adding watch on %s"),
-                             priv->configDir);
-        return -1;
-    }
-
-    DEBUG0("Building initial config cache");
-    if (priv->useXenConfigCache &&
-        xenXMConfigCacheRefresh (conn) < 0) {
-        DEBUG("Failed to enable XM config cache %s", conn->err.message);
-        return -1;
-    }
-
-    DEBUG0("Registering with event loop");
-    /* Add the handle for monitoring */
-    if ((priv->inotifyWatch = virEventAddHandle(priv->inotifyFD, VIR_EVENT_HANDLE_READABLE,
-                                                xenInotifyEvent, conn, NULL)) < 0) {
-        DEBUG0("Failed to add inotify handle, disabling events");
-    }
-
-    virConnectRef(conn);
-    return 0;
-}
-
-/**
- * xenInotifyClose:
- * @conn: pointer to the connection block
- *
- * Close and stop listening for inotify events
- *
- * Returns 0 in case of success or -1 in case of error.
- */
-int
-xenInotifyClose(virConnectPtr conn)
-{
-    xenUnifiedPrivatePtr priv = conn->privateData;
-
-    if (priv->configInfoList)
-        xenUnifiedDomainInfoListFree(priv->configInfoList);
-
-    if (priv->inotifyWatch != -1)
-        virEventRemoveHandle(priv->inotifyWatch);
-    close(priv->inotifyFD);
-    virUnrefConnect(conn);
-
-    return 0;
-}
diff --git a/src/xen_inotify.h b/src/xen_inotify.h
deleted file mode 100644 (file)
index 70bc63c..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * xen_inofify.h: Xen notification of xml files
- *
- * Copyright (C) 2008 VirtualIron
- *
- * 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: Ben Guthro
- */
-#ifndef __VIR_XEN_INOTIFY_H__
-#define __VIR_XEN_INOTIFY_H__
-
-#include "internal.h"
-#include "driver.h"
-
-extern struct xenUnifiedDriver xenInotifyDriver;
-
-virDrvOpenStatus       xenInotifyOpen  (virConnectPtr conn,
-                                         virConnectAuthPtr auth,
-                                         int flags);
-int            xenInotifyClose         (virConnectPtr conn);
-#endif
diff --git a/src/xen_internal.c b/src/xen_internal.c
deleted file mode 100644 (file)
index 30fd8bd..0000000
+++ /dev/null
@@ -1,3457 +0,0 @@
-/*
- * xen_internal.c: direct access to Xen hypervisor level
- *
- * Copyright (C) 2005, 2006, 2007, 2008, 2009 Red Hat, Inc.
- *
- * See COPYING.LIB for the License of this software
- *
- * Daniel Veillard <veillard@redhat.com>
- */
-
-#include <config.h>
-
-#include <stdio.h>
-#include <string.h>
-/* required for uint8_t, uint32_t, etc ... */
-#include <stdint.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <sys/ioctl.h>
-#include <limits.h>
-#include <stdint.h>
-#include <regex.h>
-#include <errno.h>
-#include <sys/utsname.h>
-
-#ifdef __sun
-#include <sys/systeminfo.h>
-
-#include <priv.h>
-
-#ifndef PRIV_XVM_CONTROL
-#define PRIV_XVM_CONTROL ((const char *)"xvm_control")
-#endif
-
-#endif /* __sun */
-
-/* required for dom0_getdomaininfo_t */
-#include <xen/dom0_ops.h>
-#include <xen/version.h>
-#ifdef HAVE_XEN_LINUX_PRIVCMD_H
-#include <xen/linux/privcmd.h>
-#else
-#ifdef HAVE_XEN_SYS_PRIVCMD_H
-#include <xen/sys/privcmd.h>
-#endif
-#endif
-
-/* required for shutdown flags */
-#include <xen/sched.h>
-
-#include "virterror_internal.h"
-#include "logging.h"
-#include "datatypes.h"
-#include "driver.h"
-#include "util.h"
-#include "xen_unified.h"
-#include "xen_internal.h"
-#include "xs_internal.h"
-#include "stats_linux.h"
-#include "xend_internal.h"
-#include "buf.h"
-#include "capabilities.h"
-#include "memory.h"
-
-#define VIR_FROM_THIS VIR_FROM_XEN
-
-/*
- * so far there is 2 versions of the structures usable for doing
- * hypervisor calls.
- */
-/* the old one */
-typedef struct v0_hypercall_struct {
-    unsigned long op;
-    unsigned long arg[5];
-} v0_hypercall_t;
-
-#ifdef __linux__
-#define XEN_V0_IOCTL_HYPERCALL_CMD \
-        _IOC(_IOC_NONE, 'P', 0, sizeof(v0_hypercall_t))
-/* the new one */
-typedef struct v1_hypercall_struct
-{
-    uint64_t op;
-    uint64_t arg[5];
-} v1_hypercall_t;
-#define XEN_V1_IOCTL_HYPERCALL_CMD                  \
-    _IOC(_IOC_NONE, 'P', 0, sizeof(v1_hypercall_t))
-typedef v1_hypercall_t hypercall_t;
-#elif defined(__sun)
-typedef privcmd_hypercall_t hypercall_t;
-#else
-#error "unsupported platform"
-#endif
-
-#ifndef __HYPERVISOR_sysctl
-#define __HYPERVISOR_sysctl 35
-#endif
-#ifndef __HYPERVISOR_domctl
-#define __HYPERVISOR_domctl 36
-#endif
-
-#ifdef WITH_RHEL5_API
-#define SYS_IFACE_MIN_VERS_NUMA 3
-#else
-#define SYS_IFACE_MIN_VERS_NUMA 4
-#endif
-
-static int xen_ioctl_hypercall_cmd = 0;
-static int initialized = 0;
-static int in_init = 0;
-static int hv_version = 0;
-static int hypervisor_version = 2;
-static int sys_interface_version = -1;
-static int dom_interface_version = -1;
-static int kb_per_pages = 0;
-
-/* Regular expressions used by xenHypervisorGetCapabilities, and
- * compiled once by xenHypervisorInit.  Note that these are POSIX.2
- * extended regular expressions (regex(7)).
- */
-static const char *flags_hvm_re = "^flags[[:blank:]]+:.* (vmx|svm)[[:space:]]";
-static regex_t flags_hvm_rec;
-static const char *flags_pae_re = "^flags[[:blank:]]+:.* pae[[:space:]]";
-static regex_t flags_pae_rec;
-static const char *xen_cap_re = "(xen|hvm)-[[:digit:]]+\\.[[:digit:]]+-(x86_32|x86_64|ia64|powerpc64)(p|be)?";
-static regex_t xen_cap_rec;
-
-/*
- * The content of the structures for a getdomaininfolist system hypercall
- */
-#ifndef DOMFLAGS_DYING
-#define DOMFLAGS_DYING     (1<<0) /* Domain is scheduled to die.             */
-#define DOMFLAGS_HVM       (1<<1) /* Domain is HVM                           */
-#define DOMFLAGS_SHUTDOWN  (1<<2) /* The guest OS has shut down.             */
-#define DOMFLAGS_PAUSED    (1<<3) /* Currently paused by control software.   */
-#define DOMFLAGS_BLOCKED   (1<<4) /* Currently blocked pending an event.     */
-#define DOMFLAGS_RUNNING   (1<<5) /* Domain is currently running.            */
-#define DOMFLAGS_CPUMASK      255 /* CPU to which this domain is bound.      */
-#define DOMFLAGS_CPUSHIFT       8
-#define DOMFLAGS_SHUTDOWNMASK 255 /* DOMFLAGS_SHUTDOWN guest-supplied code.  */
-#define DOMFLAGS_SHUTDOWNSHIFT 16
-#endif
-
-/*
- * These flags explain why a system is in the state of "shutdown".  Normally,
- * They are defined in xen/sched.h
- */
-#ifndef SHUTDOWN_poweroff
-#define SHUTDOWN_poweroff   0  /* Domain exited normally. Clean up and kill. */
-#define SHUTDOWN_reboot     1  /* Clean up, kill, and then restart.          */
-#define SHUTDOWN_suspend    2  /* Clean up, save suspend info, kill.         */
-#define SHUTDOWN_crash      3  /* Tell controller we've crashed.             */
-#endif
-
-#define XEN_V0_OP_GETDOMAININFOLIST    38
-#define XEN_V1_OP_GETDOMAININFOLIST    38
-#define XEN_V2_OP_GETDOMAININFOLIST    6
-
-struct xen_v0_getdomaininfo {
-    domid_t  domain;   /* the domain number */
-    uint32_t flags;    /* flags, see before */
-    uint64_t tot_pages;        /* total number of pages used */
-    uint64_t max_pages;        /* maximum number of pages allowed */
-    unsigned long shared_info_frame; /* MFN of shared_info struct */
-    uint64_t cpu_time;  /* CPU time used */
-    uint32_t nr_online_vcpus;  /* Number of VCPUs currently online. */
-    uint32_t max_vcpu_id; /* Maximum VCPUID in use by this domain. */
-    uint32_t ssidref;
-    xen_domain_handle_t handle;
-};
-typedef struct xen_v0_getdomaininfo xen_v0_getdomaininfo;
-
-struct xen_v2_getdomaininfo {
-    domid_t  domain;   /* the domain number */
-    uint32_t flags;    /* flags, see before */
-    uint64_t tot_pages;        /* total number of pages used */
-    uint64_t max_pages;        /* maximum number of pages allowed */
-    uint64_t shared_info_frame; /* MFN of shared_info struct */
-    uint64_t cpu_time;  /* CPU time used */
-    uint32_t nr_online_vcpus;  /* Number of VCPUs currently online. */
-    uint32_t max_vcpu_id; /* Maximum VCPUID in use by this domain. */
-    uint32_t ssidref;
-    xen_domain_handle_t handle;
-};
-typedef struct xen_v2_getdomaininfo xen_v2_getdomaininfo;
-
-
-/* As of Hypervisor Call v2,  DomCtl v5 we are now 8-byte aligned
-   even on 32-bit archs when dealing with uint64_t */
-#define ALIGN_64 __attribute__((aligned(8)))
-
-struct xen_v2d5_getdomaininfo {
-    domid_t  domain;   /* the domain number */
-    uint32_t flags;    /* flags, see before */
-    uint64_t tot_pages ALIGN_64;       /* total number of pages used */
-    uint64_t max_pages ALIGN_64;       /* maximum number of pages allowed */
-    uint64_t shared_info_frame ALIGN_64; /* MFN of shared_info struct */
-    uint64_t cpu_time ALIGN_64;  /* CPU time used */
-    uint32_t nr_online_vcpus;  /* Number of VCPUs currently online. */
-    uint32_t max_vcpu_id; /* Maximum VCPUID in use by this domain. */
-    uint32_t ssidref;
-    xen_domain_handle_t handle;
-};
-typedef struct xen_v2d5_getdomaininfo xen_v2d5_getdomaininfo;
-
-union xen_getdomaininfo {
-    struct xen_v0_getdomaininfo v0;
-    struct xen_v2_getdomaininfo v2;
-    struct xen_v2d5_getdomaininfo v2d5;
-};
-typedef union xen_getdomaininfo xen_getdomaininfo;
-
-union xen_getdomaininfolist {
-    struct xen_v0_getdomaininfo *v0;
-    struct xen_v2_getdomaininfo *v2;
-    struct xen_v2d5_getdomaininfo *v2d5;
-};
-typedef union xen_getdomaininfolist xen_getdomaininfolist;
-
-
-struct xen_v2_getschedulerid {
-    uint32_t sched_id; /* Get Scheduler ID from Xen */
-};
-typedef struct xen_v2_getschedulerid xen_v2_getschedulerid;
-
-
-union xen_getschedulerid {
-    struct xen_v2_getschedulerid *v2;
-};
-typedef union xen_getschedulerid xen_getschedulerid;
-
-struct xen_v2s4_availheap {
-    uint32_t min_bitwidth;  /* Smallest address width (zero if don't care). */
-    uint32_t max_bitwidth;  /* Largest address width (zero if don't care). */
-    int32_t  node;          /* NUMA node (-1 for sum across all nodes). */
-    uint64_t avail_bytes;   /* Bytes available in the specified region. */
-};
-
-typedef struct xen_v2s4_availheap  xen_v2s4_availheap;
-
-struct xen_v2s5_availheap {
-    uint32_t min_bitwidth;  /* Smallest address width (zero if don't care). */
-    uint32_t max_bitwidth;  /* Largest address width (zero if don't care). */
-    int32_t  node;          /* NUMA node (-1 for sum across all nodes). */
-    uint64_t avail_bytes ALIGN_64;   /* Bytes available in the specified region. */
-};
-
-typedef struct xen_v2s5_availheap  xen_v2s5_availheap;
-
-
-#define XEN_GETDOMAININFOLIST_ALLOC(domlist, size)                      \
-    (hypervisor_version < 2 ?                                           \
-     (VIR_ALLOC_N(domlist.v0, (size)) == 0) :                           \
-     (dom_interface_version < 5 ?                                       \
-      (VIR_ALLOC_N(domlist.v2, (size)) == 0) :                          \
-      (VIR_ALLOC_N(domlist.v2d5, (size)) == 0)))
-
-#define XEN_GETDOMAININFOLIST_FREE(domlist)            \
-    (hypervisor_version < 2 ?                          \
-     VIR_FREE(domlist.v0) :                            \
-     (dom_interface_version < 5 ?                      \
-      VIR_FREE(domlist.v2) :                           \
-      VIR_FREE(domlist.v2d5)))
-
-#define XEN_GETDOMAININFOLIST_CLEAR(domlist, size)            \
-    (hypervisor_version < 2 ?                                 \
-     memset(domlist.v0, 0, sizeof(*domlist.v0) * size) :      \
-     (dom_interface_version < 5 ?                             \
-      memset(domlist.v2, 0, sizeof(*domlist.v2) * size) :     \
-      memset(domlist.v2d5, 0, sizeof(*domlist.v2d5) * size)))
-
-#define XEN_GETDOMAININFOLIST_DOMAIN(domlist, n)    \
-    (hypervisor_version < 2 ?                       \
-     domlist.v0[n].domain :                         \
-     (dom_interface_version < 5 ?                   \
-      domlist.v2[n].domain :                        \
-      domlist.v2d5[n].domain))
-
-#define XEN_GETDOMAININFOLIST_UUID(domlist, n)      \
-    (hypervisor_version < 2 ?                       \
-     domlist.v0[n].handle :                         \
-     (dom_interface_version < 5 ?                   \
-      domlist.v2[n].handle :                        \
-      domlist.v2d5[n].handle))
-
-#define XEN_GETDOMAININFOLIST_DATA(domlist)        \
-    (hypervisor_version < 2 ?                      \
-     (void*)(domlist->v0) :                        \
-     (dom_interface_version < 5 ?                  \
-      (void*)(domlist->v2) :                       \
-      (void*)(domlist->v2d5)))
-
-#define XEN_GETDOMAININFO_SIZE                     \
-    (hypervisor_version < 2 ?                      \
-     sizeof(xen_v0_getdomaininfo) :                \
-     (dom_interface_version < 5 ?                  \
-      sizeof(xen_v2_getdomaininfo) :               \
-      sizeof(xen_v2d5_getdomaininfo)))
-
-#define XEN_GETDOMAININFO_CLEAR(dominfo)                           \
-    (hypervisor_version < 2 ?                                      \
-     memset(&(dominfo.v0), 0, sizeof(xen_v0_getdomaininfo)) :      \
-     (dom_interface_version < 5 ?                                  \
-      memset(&(dominfo.v2), 0, sizeof(xen_v2_getdomaininfo)) :     \
-      memset(&(dominfo.v2d5), 0, sizeof(xen_v2d5_getdomaininfo))))
-
-#define XEN_GETDOMAININFO_DOMAIN(dominfo)       \
-    (hypervisor_version < 2 ?                   \
-     dominfo.v0.domain :                        \
-     (dom_interface_version < 5 ?               \
-      dominfo.v2.domain :                       \
-      dominfo.v2d5.domain))
-
-#define XEN_GETDOMAININFO_CPUTIME(dominfo)      \
-    (hypervisor_version < 2 ?                   \
-     dominfo.v0.cpu_time :                      \
-     (dom_interface_version < 5 ?               \
-      dominfo.v2.cpu_time :                     \
-      dominfo.v2d5.cpu_time))
-
-#define XEN_GETDOMAININFO_CPUCOUNT(dominfo)     \
-    (hypervisor_version < 2 ?                   \
-     dominfo.v0.nr_online_vcpus :               \
-     (dom_interface_version < 5 ?               \
-      dominfo.v2.nr_online_vcpus :              \
-      dominfo.v2d5.nr_online_vcpus))
-
-#define XEN_GETDOMAININFO_MAXCPUID(dominfo)  \
-    (hypervisor_version < 2 ?                   \
-     dominfo.v0.max_vcpu_id :                   \
-     (dom_interface_version < 5 ?               \
-      dominfo.v2.max_vcpu_id :                  \
-      dominfo.v2d5.max_vcpu_id))
-
-#define XEN_GETDOMAININFO_FLAGS(dominfo)        \
-    (hypervisor_version < 2 ?                   \
-     dominfo.v0.flags :                         \
-     (dom_interface_version < 5 ?               \
-      dominfo.v2.flags :                        \
-      dominfo.v2d5.flags))
-
-#define XEN_GETDOMAININFO_TOT_PAGES(dominfo)    \
-    (hypervisor_version < 2 ?                   \
-     dominfo.v0.tot_pages :                     \
-     (dom_interface_version < 5 ?               \
-      dominfo.v2.tot_pages :                    \
-      dominfo.v2d5.tot_pages))
-
-#define XEN_GETDOMAININFO_MAX_PAGES(dominfo)    \
-    (hypervisor_version < 2 ?                   \
-     dominfo.v0.max_pages :                     \
-     (dom_interface_version < 5 ?               \
-      dominfo.v2.max_pages :                    \
-      dominfo.v2d5.max_pages))
-
-#define XEN_GETDOMAININFO_UUID(dominfo)         \
-    (hypervisor_version < 2 ?                   \
-     dominfo.v0.handle :                        \
-     (dom_interface_version < 5 ?               \
-      dominfo.v2.handle :                       \
-      dominfo.v2d5.handle))
-
-
-static int
-lock_pages(void *addr, size_t len)
-{
-#ifdef __linux__
-        return (mlock(addr, len));
-#elif defined(__sun)
-        return (0);
-#endif
-}
-
-static int
-unlock_pages(void *addr, size_t len)
-{
-#ifdef __linux__
-        return (munlock(addr, len));
-#elif defined(__sun)
-        return (0);
-#endif
-}
-
-
-struct xen_v0_getdomaininfolistop {
-    domid_t   first_domain;
-    uint32_t  max_domains;
-    struct xen_v0_getdomaininfo *buffer;
-    uint32_t  num_domains;
-};
-typedef struct xen_v0_getdomaininfolistop xen_v0_getdomaininfolistop;
-
-
-struct xen_v2_getdomaininfolistop {
-    domid_t   first_domain;
-    uint32_t  max_domains;
-    struct xen_v2_getdomaininfo *buffer;
-    uint32_t  num_domains;
-};
-typedef struct xen_v2_getdomaininfolistop xen_v2_getdomaininfolistop;
-
-/* As of HV version 2, sysctl version 3 the *buffer pointer is 64-bit aligned */
-struct xen_v2s3_getdomaininfolistop {
-    domid_t   first_domain;
-    uint32_t  max_domains;
-#ifdef __BIG_ENDIAN__
-    struct {
-        int __pad[(sizeof (long long) - sizeof (struct xen_v2d5_getdomaininfo *)) / sizeof (int)];
-        struct xen_v2d5_getdomaininfo *v;
-    } buffer;
-#else
-    union {
-        struct xen_v2d5_getdomaininfo *v;
-        uint64_t pad ALIGN_64;
-    } buffer;
-#endif
-    uint32_t  num_domains;
-};
-typedef struct xen_v2s3_getdomaininfolistop xen_v2s3_getdomaininfolistop;
-
-
-
-struct xen_v0_domainop {
-    domid_t   domain;
-};
-typedef struct xen_v0_domainop xen_v0_domainop;
-
-/*
- * The information for a destroydomain system hypercall
- */
-#define XEN_V0_OP_DESTROYDOMAIN        9
-#define XEN_V1_OP_DESTROYDOMAIN        9
-#define XEN_V2_OP_DESTROYDOMAIN        2
-
-/*
- * The information for a pausedomain system hypercall
- */
-#define XEN_V0_OP_PAUSEDOMAIN  10
-#define XEN_V1_OP_PAUSEDOMAIN  10
-#define XEN_V2_OP_PAUSEDOMAIN  3
-
-/*
- * The information for an unpausedomain system hypercall
- */
-#define XEN_V0_OP_UNPAUSEDOMAIN        11
-#define XEN_V1_OP_UNPAUSEDOMAIN        11
-#define XEN_V2_OP_UNPAUSEDOMAIN        4
-
-/*
- * The information for an setmaxmem system hypercall
- */
-#define XEN_V0_OP_SETMAXMEM    28
-#define XEN_V1_OP_SETMAXMEM    28
-#define XEN_V2_OP_SETMAXMEM    11
-
-struct xen_v0_setmaxmem {
-    domid_t    domain;
-    uint64_t   maxmem;
-};
-typedef struct xen_v0_setmaxmem xen_v0_setmaxmem;
-typedef struct xen_v0_setmaxmem xen_v1_setmaxmem;
-
-struct xen_v2_setmaxmem {
-    uint64_t   maxmem;
-};
-typedef struct xen_v2_setmaxmem xen_v2_setmaxmem;
-
-struct xen_v2d5_setmaxmem {
-    uint64_t   maxmem ALIGN_64;
-};
-typedef struct xen_v2d5_setmaxmem xen_v2d5_setmaxmem;
-
-/*
- * The information for an setmaxvcpu system hypercall
- */
-#define XEN_V0_OP_SETMAXVCPU   41
-#define XEN_V1_OP_SETMAXVCPU   41
-#define XEN_V2_OP_SETMAXVCPU   15
-
-struct xen_v0_setmaxvcpu {
-    domid_t    domain;
-    uint32_t   maxvcpu;
-};
-typedef struct xen_v0_setmaxvcpu xen_v0_setmaxvcpu;
-typedef struct xen_v0_setmaxvcpu xen_v1_setmaxvcpu;
-
-struct xen_v2_setmaxvcpu {
-    uint32_t   maxvcpu;
-};
-typedef struct xen_v2_setmaxvcpu xen_v2_setmaxvcpu;
-
-/*
- * The information for an setvcpumap system hypercall
- * Note that between 1 and 2 the limitation to 64 physical CPU was lifted
- * hence the difference in structures
- */
-#define XEN_V0_OP_SETVCPUMAP   20
-#define XEN_V1_OP_SETVCPUMAP   20
-#define XEN_V2_OP_SETVCPUMAP   9
-
-struct xen_v0_setvcpumap {
-    domid_t    domain;
-    uint32_t   vcpu;
-    cpumap_t    cpumap;
-};
-typedef struct xen_v0_setvcpumap xen_v0_setvcpumap;
-typedef struct xen_v0_setvcpumap xen_v1_setvcpumap;
-
-struct xen_v2_cpumap {
-    uint8_t    *bitmap;
-    uint32_t    nr_cpus;
-};
-struct xen_v2_setvcpumap {
-    uint32_t   vcpu;
-    struct xen_v2_cpumap cpumap;
-};
-typedef struct xen_v2_setvcpumap xen_v2_setvcpumap;
-
-/* HV version 2, Dom version 5 requires 64-bit alignment */
-struct xen_v2d5_cpumap {
-#ifdef __BIG_ENDIAN__
-    struct {
-        int __pad[(sizeof (long long) - sizeof (uint8_t *)) / sizeof (int)];
-        uint8_t *v;
-    } bitmap;
-#else
-    union {
-        uint8_t    *v;
-        uint64_t   pad ALIGN_64;
-    } bitmap;
-#endif
-    uint32_t    nr_cpus;
-};
-struct xen_v2d5_setvcpumap {
-    uint32_t   vcpu;
-    struct xen_v2d5_cpumap cpumap;
-};
-typedef struct xen_v2d5_setvcpumap xen_v2d5_setvcpumap;
-
-/*
- * The information for an vcpuinfo system hypercall
- */
-#define XEN_V0_OP_GETVCPUINFO   43
-#define XEN_V1_OP_GETVCPUINFO  43
-#define XEN_V2_OP_GETVCPUINFO   14
-
-struct xen_v0_vcpuinfo {
-    domid_t    domain;         /* owner's domain */
-    uint32_t   vcpu;           /* the vcpu number */
-    uint8_t    online;         /* seen as on line */
-    uint8_t    blocked;        /* blocked on event */
-    uint8_t    running;        /* scheduled on CPU */
-    uint64_t    cpu_time;      /* nanosecond of CPU used */
-    uint32_t   cpu;            /* current mapping */
-    cpumap_t   cpumap;         /* deprecated in V2 */
-};
-typedef struct xen_v0_vcpuinfo xen_v0_vcpuinfo;
-typedef struct xen_v0_vcpuinfo xen_v1_vcpuinfo;
-
-struct xen_v2_vcpuinfo {
-    uint32_t   vcpu;           /* the vcpu number */
-    uint8_t    online;         /* seen as on line */
-    uint8_t    blocked;        /* blocked on event */
-    uint8_t    running;        /* scheduled on CPU */
-    uint64_t    cpu_time;      /* nanosecond of CPU used */
-    uint32_t   cpu;            /* current mapping */
-};
-typedef struct xen_v2_vcpuinfo xen_v2_vcpuinfo;
-
-struct xen_v2d5_vcpuinfo {
-    uint32_t   vcpu;           /* the vcpu number */
-    uint8_t    online;         /* seen as on line */
-    uint8_t    blocked;        /* blocked on event */
-    uint8_t    running;        /* scheduled on CPU */
-    uint64_t    cpu_time ALIGN_64; /* nanosecond of CPU used */
-    uint32_t   cpu;            /* current mapping */
-};
-typedef struct xen_v2d5_vcpuinfo xen_v2d5_vcpuinfo;
-
-/*
- * from V2 the pinning of a vcpu is read with a separate call
- */
-#define XEN_V2_OP_GETVCPUMAP   25
-typedef struct xen_v2_setvcpumap xen_v2_getvcpumap;
-typedef struct xen_v2d5_setvcpumap xen_v2d5_getvcpumap;
-
-/*
- * from V2 we get the scheduler information
- */
-#define XEN_V2_OP_GETSCHEDULERID       4
-
-/*
- * from V2 we get the available heap information
- */
-#define XEN_V2_OP_GETAVAILHEAP         9
-
-/*
- * from V2 we get the scheduler parameter
- */
-#define XEN_V2_OP_SCHEDULER            16
-/* Scheduler types. */
-#define XEN_SCHEDULER_SEDF       4
-#define XEN_SCHEDULER_CREDIT     5
-/* get/set scheduler parameters */
-#define XEN_DOMCTL_SCHEDOP_putinfo 0
-#define XEN_DOMCTL_SCHEDOP_getinfo 1
-
-struct xen_v2_setschedinfo {
-    uint32_t sched_id;
-    uint32_t cmd;
-    union {
-        struct xen_domctl_sched_sedf {
-            uint64_t period ALIGN_64;
-            uint64_t slice  ALIGN_64;
-            uint64_t latency ALIGN_64;
-            uint32_t extratime;
-            uint32_t weight;
-        } sedf;
-        struct xen_domctl_sched_credit {
-            uint16_t weight;
-            uint16_t cap;
-        } credit;
-    } u;
-};
-typedef struct xen_v2_setschedinfo xen_v2_setschedinfo;
-typedef struct xen_v2_setschedinfo xen_v2_getschedinfo;
-
-
-/*
- * The hypercall operation structures also have changed on
- * changeset 86d26e6ec89b
- */
-/* the old structure */
-struct xen_op_v0 {
-    uint32_t cmd;
-    uint32_t interface_version;
-    union {
-        xen_v0_getdomaininfolistop getdomaininfolist;
-        xen_v0_domainop          domain;
-        xen_v0_setmaxmem         setmaxmem;
-        xen_v0_setmaxvcpu        setmaxvcpu;
-        xen_v0_setvcpumap        setvcpumap;
-        xen_v0_vcpuinfo          getvcpuinfo;
-        uint8_t padding[128];
-    } u;
-};
-typedef struct xen_op_v0 xen_op_v0;
-typedef struct xen_op_v0 xen_op_v1;
-
-/* the new structure for systems operations */
-struct xen_op_v2_sys {
-    uint32_t cmd;
-    uint32_t interface_version;
-    union {
-        xen_v2_getdomaininfolistop   getdomaininfolist;
-        xen_v2s3_getdomaininfolistop getdomaininfolists3;
-        xen_v2_getschedulerid        getschedulerid;
-        xen_v2s4_availheap           availheap;
-        xen_v2s5_availheap           availheap5;
-        uint8_t padding[128];
-    } u;
-};
-typedef struct xen_op_v2_sys xen_op_v2_sys;
-
-/* the new structure for domains operation */
-struct xen_op_v2_dom {
-    uint32_t cmd;
-    uint32_t interface_version;
-    domid_t  domain;
-    union {
-        xen_v2_setmaxmem         setmaxmem;
-        xen_v2d5_setmaxmem       setmaxmemd5;
-        xen_v2_setmaxvcpu        setmaxvcpu;
-        xen_v2_setvcpumap        setvcpumap;
-        xen_v2d5_setvcpumap      setvcpumapd5;
-        xen_v2_vcpuinfo          getvcpuinfo;
-        xen_v2d5_vcpuinfo        getvcpuinfod5;
-        xen_v2_getvcpumap        getvcpumap;
-        xen_v2d5_getvcpumap      getvcpumapd5;
-        xen_v2_setschedinfo      setschedinfo;
-        xen_v2_getschedinfo      getschedinfo;
-        uint8_t padding[128];
-    } u;
-};
-typedef struct xen_op_v2_dom xen_op_v2_dom;
-
-
-#ifdef __linux__
-#define XEN_HYPERVISOR_SOCKET  "/proc/xen/privcmd"
-#define HYPERVISOR_CAPABILITIES        "/sys/hypervisor/properties/capabilities"
-#elif defined(__sun)
-#define XEN_HYPERVISOR_SOCKET  "/dev/xen/privcmd"
-#else
-#error "unsupported platform"
-#endif
-
-#ifndef PROXY
-static unsigned long xenHypervisorGetMaxMemory(virDomainPtr domain);
-#endif
-
-#ifndef PROXY
-struct xenUnifiedDriver xenHypervisorDriver = {
-    xenHypervisorOpen, /* open */
-    xenHypervisorClose, /* close */
-    xenHypervisorGetVersion, /* version */
-    NULL, /* hostname */
-    NULL, /* nodeGetInfo */
-    xenHypervisorGetCapabilities, /* getCapabilities */
-    xenHypervisorListDomains, /* listDomains */
-    xenHypervisorNumOfDomains, /* numOfDomains */
-    NULL, /* domainCreateXML */
-    xenHypervisorPauseDomain, /* domainSuspend */
-    xenHypervisorResumeDomain, /* domainResume */
-    NULL, /* domainShutdown */
-    NULL, /* domainReboot */
-    xenHypervisorDestroyDomain, /* domainDestroy */
-    xenHypervisorDomainGetOSType, /* domainGetOSType */
-    xenHypervisorGetMaxMemory, /* domainGetMaxMemory */
-    xenHypervisorSetMaxMemory, /* domainSetMaxMemory */
-    NULL, /* domainSetMemory */
-    xenHypervisorGetDomainInfo, /* domainGetInfo */
-    NULL, /* domainSave */
-    NULL, /* domainRestore */
-    NULL, /* domainCoreDump */
-    xenHypervisorSetVcpus, /* domainSetVcpus */
-    xenHypervisorPinVcpu, /* domainPinVcpu */
-    xenHypervisorGetVcpus, /* domainGetVcpus */
-    xenHypervisorGetVcpuMax, /* domainGetMaxVcpus */
-    NULL, /* listDefinedDomains */
-    NULL, /* numOfDefinedDomains */
-    NULL, /* domainCreate */
-    NULL, /* domainDefineXML */
-    NULL, /* domainUndefine */
-    NULL, /* domainAttachDevice */
-    NULL, /* domainDetachDevice */
-    NULL, /* domainGetAutostart */
-    NULL, /* domainSetAutostart */
-    xenHypervisorGetSchedulerType, /* domainGetSchedulerType */
-    xenHypervisorGetSchedulerParameters, /* domainGetSchedulerParameters */
-    xenHypervisorSetSchedulerParameters, /* domainSetSchedulerParameters */
-};
-#endif /* !PROXY */
-
-#define virXenError(conn, code, fmt...)                                      \
-        if (in_init == 0)                                                    \
-            virReportErrorHelper(conn, VIR_FROM_XEN, code, __FILE__,       \
-                                   __FUNCTION__, __LINE__, fmt)
-
-#ifndef PROXY
-
-/**
- * virXenErrorFunc:
- * @conn: connection, if known
- * @error: the error number
- * @func: the function failing
- * @info: extra information string
- * @value: extra information number
- *
- * Handle an error at the xend daemon interface
- */
-static void
-virXenErrorFunc(virConnectPtr conn,
-                virErrorNumber error, const char *func, const char *info,
-                int value)
-{
-    char fullinfo[1000];
-    const char *errmsg;
-
-    if ((error == VIR_ERR_OK) || (in_init != 0))
-        return;
-
-
-    errmsg =virErrorMsg(error, info);
-    if (func != NULL) {
-        snprintf(fullinfo, 999, "%s: %s", func, info);
-        fullinfo[999] = 0;
-        virRaiseError(conn, NULL, NULL, VIR_FROM_XEN, error, VIR_ERR_ERROR,
-                        errmsg, fullinfo, NULL, value, 0, errmsg, fullinfo,
-                        value);
-    } else {
-        virRaiseError(conn, NULL, NULL, VIR_FROM_XEN, error, VIR_ERR_ERROR,
-                        errmsg, info, NULL, value, 0, errmsg, info,
-                        value);
-    }
-}
-
-#endif /* PROXY */
-
-/**
- * xenHypervisorDoV0Op:
- * @handle: the handle to the Xen hypervisor
- * @op: pointer to the hypervisor operation structure
- *
- * Do an hypervisor operation though the old interface,
- * this leads to an hypervisor call through ioctl.
- *
- * Returns 0 in case of success and -1 in case of error.
- */
-static int
-xenHypervisorDoV0Op(int handle, xen_op_v0 * op)
-{
-    int ret;
-    v0_hypercall_t hc;
-
-    memset(&hc, 0, sizeof(hc));
-    op->interface_version = hv_version << 8;
-    hc.op = __HYPERVISOR_dom0_op;
-    hc.arg[0] = (unsigned long) op;
-
-    if (lock_pages(op, sizeof(dom0_op_t)) < 0) {
-        virXenError(NULL, VIR_ERR_XEN_CALL, " locking");
-        return (-1);
-    }
-
-    ret = ioctl(handle, xen_ioctl_hypercall_cmd, (unsigned long) &hc);
-    if (ret < 0) {
-        virXenError(NULL, VIR_ERR_XEN_CALL, " ioctl %d",
-                    xen_ioctl_hypercall_cmd);
-    }
-
-    if (unlock_pages(op, sizeof(dom0_op_t)) < 0) {
-        virXenError(NULL, VIR_ERR_XEN_CALL, " releasing");
-        ret = -1;
-    }
-
-    if (ret < 0)
-        return (-1);
-
-    return (0);
-}
-/**
- * xenHypervisorDoV1Op:
- * @handle: the handle to the Xen hypervisor
- * @op: pointer to the hypervisor operation structure
- *
- * Do an hypervisor v1 operation, this leads to an hypervisor call through
- * ioctl.
- *
- * Returns 0 in case of success and -1 in case of error.
- */
-static int
-xenHypervisorDoV1Op(int handle, xen_op_v1* op)
-{
-    int ret;
-    hypercall_t hc;
-
-    memset(&hc, 0, sizeof(hc));
-    op->interface_version = DOM0_INTERFACE_VERSION;
-    hc.op = __HYPERVISOR_dom0_op;
-    hc.arg[0] = (unsigned long) op;
-
-    if (lock_pages(op, sizeof(dom0_op_t)) < 0) {
-        virXenError(NULL, VIR_ERR_XEN_CALL, " locking");
-        return (-1);
-    }
-
-    ret = ioctl(handle, xen_ioctl_hypercall_cmd, (unsigned long) &hc);
-    if (ret < 0) {
-        virXenError(NULL, VIR_ERR_XEN_CALL, " ioctl %d",
-                    xen_ioctl_hypercall_cmd);
-    }
-
-    if (unlock_pages(op, sizeof(dom0_op_t)) < 0) {
-        virXenError(NULL, VIR_ERR_XEN_CALL, " releasing");
-        ret = -1;
-    }
-
-    if (ret < 0)
-        return (-1);
-
-    return (0);
-}
-
-/**
- * xenHypervisorDoV2Sys:
- * @handle: the handle to the Xen hypervisor
- * @op: pointer to the hypervisor operation structure
- *
- * Do an hypervisor v2 system operation, this leads to an hypervisor
- * call through ioctl.
- *
- * Returns 0 in case of success and -1 in case of error.
- */
-static int
-xenHypervisorDoV2Sys(int handle, xen_op_v2_sys* op)
-{
-    int ret;
-    hypercall_t hc;
-
-    memset(&hc, 0, sizeof(hc));
-    op->interface_version = sys_interface_version;
-    hc.op = __HYPERVISOR_sysctl;
-    hc.arg[0] = (unsigned long) op;
-
-    if (lock_pages(op, sizeof(dom0_op_t)) < 0) {
-        virXenError(NULL, VIR_ERR_XEN_CALL, " locking");
-        return (-1);
-    }
-
-    ret = ioctl(handle, xen_ioctl_hypercall_cmd, (unsigned long) &hc);
-    if (ret < 0) {
-        virXenError(NULL, VIR_ERR_XEN_CALL, " sys ioctl %d",
-                                            xen_ioctl_hypercall_cmd);
-    }
-
-    if (unlock_pages(op, sizeof(dom0_op_t)) < 0) {
-        virXenError(NULL, VIR_ERR_XEN_CALL, " releasing");
-        ret = -1;
-    }
-
-    if (ret < 0)
-        return (-1);
-
-    return (0);
-}
-
-/**
- * xenHypervisorDoV2Dom:
- * @handle: the handle to the Xen hypervisor
- * @op: pointer to the hypervisor domain operation structure
- *
- * Do an hypervisor v2 domain operation, this leads to an hypervisor
- * call through ioctl.
- *
- * Returns 0 in case of success and -1 in case of error.
- */
-static int
-xenHypervisorDoV2Dom(int handle, xen_op_v2_dom* op)
-{
-    int ret;
-    hypercall_t hc;
-
-    memset(&hc, 0, sizeof(hc));
-    op->interface_version = dom_interface_version;
-    hc.op = __HYPERVISOR_domctl;
-    hc.arg[0] = (unsigned long) op;
-
-    if (lock_pages(op, sizeof(dom0_op_t)) < 0) {
-        virXenError(NULL, VIR_ERR_XEN_CALL, " locking");
-        return (-1);
-    }
-
-    ret = ioctl(handle, xen_ioctl_hypercall_cmd, (unsigned long) &hc);
-    if (ret < 0) {
-        virXenError(NULL, VIR_ERR_XEN_CALL, " ioctl %d",
-                    xen_ioctl_hypercall_cmd);
-    }
-
-    if (unlock_pages(op, sizeof(dom0_op_t)) < 0) {
-        virXenError(NULL, VIR_ERR_XEN_CALL, " releasing");
-        ret = -1;
-    }
-
-    if (ret < 0)
-        return (-1);
-
-    return (0);
-}
-
-/**
- * virXen_getdomaininfolist:
- * @handle: the hypervisor handle
- * @first_domain: first domain in the range
- * @maxids: maximum number of domains to list
- * @dominfos: output structures
- *
- * Do a low level hypercall to list existing domains information
- *
- * Returns the number of domains or -1 in case of failure
- */
-static int
-virXen_getdomaininfolist(int handle, int first_domain, int maxids,
-                         xen_getdomaininfolist *dominfos)
-{
-    int ret = -1;
-
-    if (lock_pages(XEN_GETDOMAININFOLIST_DATA(dominfos),
-              XEN_GETDOMAININFO_SIZE * maxids) < 0) {
-        virXenError(NULL, VIR_ERR_XEN_CALL, " locking");
-        return (-1);
-    }
-    if (hypervisor_version > 1) {
-        xen_op_v2_sys op;
-
-        memset(&op, 0, sizeof(op));
-        op.cmd = XEN_V2_OP_GETDOMAININFOLIST;
-
-        if (sys_interface_version < 3) {
-            op.u.getdomaininfolist.first_domain = (domid_t) first_domain;
-            op.u.getdomaininfolist.max_domains = maxids;
-            op.u.getdomaininfolist.buffer = dominfos->v2;
-            op.u.getdomaininfolist.num_domains = maxids;
-        } else {
-            op.u.getdomaininfolists3.first_domain = (domid_t) first_domain;
-            op.u.getdomaininfolists3.max_domains = maxids;
-            op.u.getdomaininfolists3.buffer.v = dominfos->v2d5;
-            op.u.getdomaininfolists3.num_domains = maxids;
-        }
-        ret = xenHypervisorDoV2Sys(handle, &op);
-
-        if (ret == 0) {
-            if (sys_interface_version < 3)
-                ret = op.u.getdomaininfolist.num_domains;
-            else
-                ret = op.u.getdomaininfolists3.num_domains;
-        }
-    } else if (hypervisor_version == 1) {
-        xen_op_v1 op;
-
-        memset(&op, 0, sizeof(op));
-        op.cmd = XEN_V1_OP_GETDOMAININFOLIST;
-        op.u.getdomaininfolist.first_domain = (domid_t) first_domain;
-        op.u.getdomaininfolist.max_domains = maxids;
-        op.u.getdomaininfolist.buffer = dominfos->v0;
-        op.u.getdomaininfolist.num_domains = maxids;
-        ret = xenHypervisorDoV1Op(handle, &op);
-        if (ret == 0)
-            ret = op.u.getdomaininfolist.num_domains;
-    } else if (hypervisor_version == 0) {
-        xen_op_v0 op;
-
-        memset(&op, 0, sizeof(op));
-        op.cmd = XEN_V0_OP_GETDOMAININFOLIST;
-        op.u.getdomaininfolist.first_domain = (domid_t) first_domain;
-        op.u.getdomaininfolist.max_domains = maxids;
-        op.u.getdomaininfolist.buffer = dominfos->v0;
-        op.u.getdomaininfolist.num_domains = maxids;
-        ret = xenHypervisorDoV0Op(handle, &op);
-        if (ret == 0)
-            ret = op.u.getdomaininfolist.num_domains;
-    }
-    if (unlock_pages(XEN_GETDOMAININFOLIST_DATA(dominfos),
-                XEN_GETDOMAININFO_SIZE * maxids) < 0) {
-        virXenError(NULL, VIR_ERR_XEN_CALL, " release");
-        ret = -1;
-    }
-    return(ret);
-}
-
-static int
-virXen_getdomaininfo(int handle, int first_domain,
-                     xen_getdomaininfo *dominfo) {
-    xen_getdomaininfolist dominfos;
-
-    if (hypervisor_version < 2) {
-        dominfos.v0 = &(dominfo->v0);
-    } else {
-        dominfos.v2 = &(dominfo->v2);
-    }
-
-    return virXen_getdomaininfolist(handle, first_domain, 1, &dominfos);
-}
-
-
-#ifndef PROXY
-/**
- * xenHypervisorGetSchedulerType:
- * @domain: pointer to the Xen Hypervisor block
- * @nparams:give a number of scheduler parameters.
- *
- * Do a low level hypercall to get scheduler type
- *
- * Returns scheduler name or NULL in case of failure
- */
-char *
-xenHypervisorGetSchedulerType(virDomainPtr domain, int *nparams)
-{
-    char *schedulertype = NULL;
-    xenUnifiedPrivatePtr priv;
-
-    if ((domain == NULL) || (domain->conn == NULL)) {
-        virXenErrorFunc(NULL, VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
-                        "domain or conn is NULL", 0);
-        return NULL;
-    }
-
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-    if (priv->handle < 0) {
-        virXenErrorFunc(domain->conn, VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
-                        "priv->handle invalid", 0);
-        return NULL;
-    }
-    if (domain->id < 0) {
-        virXenError(domain->conn, VIR_ERR_OPERATION_INVALID,
-                    "%s", _("domain is not running"));
-        return NULL;
-    }
-
-    /*
-     * Support only dom_interface_version >=5
-     * (Xen3.1.0 or later)
-     * TODO: check on Xen 3.0.3
-     */
-    if (dom_interface_version < 5) {
-        virXenErrorFunc(domain->conn, VIR_ERR_NO_XEN, __FUNCTION__,
-                        "unsupported in dom interface < 5", 0);
-        return NULL;
-    }
-
-    if (hypervisor_version > 1) {
-        xen_op_v2_sys op;
-        int ret;
-
-        memset(&op, 0, sizeof(op));
-        op.cmd = XEN_V2_OP_GETSCHEDULERID;
-        ret = xenHypervisorDoV2Sys(priv->handle, &op);
-        if (ret < 0)
-            return(NULL);
-
-        switch (op.u.getschedulerid.sched_id){
-            case XEN_SCHEDULER_SEDF:
-                schedulertype = strdup("sedf");
-                if (nparams)
-                    *nparams = 6;
-                break;
-            case XEN_SCHEDULER_CREDIT:
-                schedulertype = strdup("credit");
-                if (nparams)
-                    *nparams = 2;
-                break;
-            default:
-                break;
-        }
-    }
-
-    return schedulertype;
-}
-
-static const char *str_weight = "weight";
-static const char *str_cap = "cap";
-
-/**
- * xenHypervisorGetSchedulerParameters:
- * @domain: pointer to the Xen Hypervisor block
- * @params: pointer to scheduler parameters.
- *     This memory area should be allocated before calling.
- * @nparams:this parameter should be same as
- *     a given number of scheduler parameters.
- *     from xenHypervisorGetSchedulerType().
- *
- * Do a low level hypercall to get scheduler parameters
- *
- * Returns 0 or -1 in case of failure
- */
-int
-xenHypervisorGetSchedulerParameters(virDomainPtr domain,
-                                    virSchedParameterPtr params, int *nparams)
-{
-    xenUnifiedPrivatePtr priv;
-
-    if ((domain == NULL) || (domain->conn == NULL)) {
-        virXenErrorFunc(NULL, VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
-                        "domain or conn is NULL", 0);
-        return -1;
-    }
-
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-    if (priv->handle < 0) {
-        virXenErrorFunc(domain->conn, VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
-                        "priv->handle invalid", 0);
-        return -1;
-    }
-    if (domain->id < 0) {
-        virXenError(domain->conn, VIR_ERR_OPERATION_INVALID,
-                    "%s", _("domain is not running"));
-        return -1;
-    }
-
-    /*
-     * Support only dom_interface_version >=5
-     * (Xen3.1.0 or later)
-     * TODO: check on Xen 3.0.3
-     */
-    if (dom_interface_version < 5) {
-        virXenErrorFunc(domain->conn, VIR_ERR_NO_XEN, __FUNCTION__,
-                        "unsupported in dom interface < 5", 0);
-        return -1;
-    }
-
-    if (hypervisor_version > 1) {
-        xen_op_v2_sys op_sys;
-        xen_op_v2_dom op_dom;
-        int ret;
-
-        memset(&op_sys, 0, sizeof(op_sys));
-        op_sys.cmd = XEN_V2_OP_GETSCHEDULERID;
-        ret = xenHypervisorDoV2Sys(priv->handle, &op_sys);
-        if (ret < 0)
-            return -1;
-
-        switch (op_sys.u.getschedulerid.sched_id){
-            case XEN_SCHEDULER_SEDF:
-                /* TODO: Implement for Xen/SEDF */
-                TODO
-                return(-1);
-            case XEN_SCHEDULER_CREDIT:
-                if (*nparams < 2)
-                    return(-1);
-                memset(&op_dom, 0, sizeof(op_dom));
-                op_dom.cmd = XEN_V2_OP_SCHEDULER;
-                op_dom.domain = (domid_t) domain->id;
-                op_dom.u.getschedinfo.sched_id = XEN_SCHEDULER_CREDIT;
-                op_dom.u.getschedinfo.cmd = XEN_DOMCTL_SCHEDOP_getinfo;
-                ret = xenHypervisorDoV2Dom(priv->handle, &op_dom);
-                if (ret < 0)
-                    return(-1);
-
-                strncpy (params[0].field, str_weight, VIR_DOMAIN_SCHED_FIELD_LENGTH);
-                params[0].field[VIR_DOMAIN_SCHED_FIELD_LENGTH-1] = '\0';
-                params[0].type = VIR_DOMAIN_SCHED_FIELD_UINT;
-                params[0].value.ui = op_dom.u.getschedinfo.u.credit.weight;
-
-                strncpy (params[1].field, str_cap, VIR_DOMAIN_SCHED_FIELD_LENGTH);
-                params[1].field[VIR_DOMAIN_SCHED_FIELD_LENGTH-1] = '\0';
-                params[1].type = VIR_DOMAIN_SCHED_FIELD_UINT;
-                params[1].value.ui = op_dom.u.getschedinfo.u.credit.cap;
-
-                *nparams = 2;
-                break;
-            default:
-                virXenErrorFunc(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
-                        "Unknown scheduler", op_sys.u.getschedulerid.sched_id);
-                return -1;
-        }
-    }
-
-    return 0;
-}
-
-/**
- * xenHypervisorSetSchedulerParameters:
- * @domain: pointer to the Xen Hypervisor block
- * @nparams:give a number of scheduler setting parameters .
- *
- * Do a low level hypercall to set scheduler parameters
- *
- * Returns 0 or -1 in case of failure
- */
-int
-xenHypervisorSetSchedulerParameters(virDomainPtr domain,
-                                 virSchedParameterPtr params, int nparams)
-{
-    int i;
-    unsigned int val;
-    xenUnifiedPrivatePtr priv;
-    char buf[256];
-
-    if ((domain == NULL) || (domain->conn == NULL)) {
-        virXenErrorFunc (NULL, VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
-                         "domain or conn is NULL", 0);
-        return -1;
-    }
-
-    if ((nparams == 0) || (params == NULL)) {
-        virXenErrorFunc (domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
-                         "Noparameters given", 0);
-        return(-1);
-    }
-
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-    if (priv->handle < 0) {
-        virXenErrorFunc(domain->conn, VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
-                        "priv->handle invalid", 0);
-        return -1;
-    }
-    if (domain->id < 0) {
-        virXenError(domain->conn, VIR_ERR_OPERATION_INVALID,
-                    "%s", _("domain is not running"));
-        return -1;
-    }
-
-    /*
-     * Support only dom_interface_version >=5
-     * (Xen3.1.0 or later)
-     * TODO: check on Xen 3.0.3
-     */
-    if (dom_interface_version < 5) {
-        virXenErrorFunc(domain->conn, VIR_ERR_NO_XEN, __FUNCTION__,
-                        "unsupported in dom interface < 5", 0);
-        return -1;
-    }
-
-    if (hypervisor_version > 1) {
-        xen_op_v2_sys op_sys;
-        xen_op_v2_dom op_dom;
-        int ret;
-
-        memset(&op_sys, 0, sizeof(op_sys));
-        op_sys.cmd = XEN_V2_OP_GETSCHEDULERID;
-        ret = xenHypervisorDoV2Sys(priv->handle, &op_sys);
-        if (ret == -1) return -1;
-
-        switch (op_sys.u.getschedulerid.sched_id){
-        case XEN_SCHEDULER_SEDF:
-            /* TODO: Implement for Xen/SEDF */
-            TODO
-            return(-1);
-        case XEN_SCHEDULER_CREDIT: {
-            memset(&op_dom, 0, sizeof(op_dom));
-            op_dom.cmd = XEN_V2_OP_SCHEDULER;
-            op_dom.domain = (domid_t) domain->id;
-            op_dom.u.getschedinfo.sched_id = XEN_SCHEDULER_CREDIT;
-            op_dom.u.getschedinfo.cmd = XEN_DOMCTL_SCHEDOP_putinfo;
-
-            /*
-             * credit scheduler parameters
-             * following values do not change the parameters
-             */
-            op_dom.u.getschedinfo.u.credit.weight = 0;
-            op_dom.u.getschedinfo.u.credit.cap    = (uint16_t)~0U;
-
-            for (i = 0; i < nparams; i++) {
-                memset(&buf, 0, sizeof(buf));
-                if (STREQ (params[i].field, str_weight) &&
-                    params[i].type == VIR_DOMAIN_SCHED_FIELD_UINT) {
-                    val = params[i].value.ui;
-                    if ((val < 1) || (val > USHRT_MAX)) {
-                        snprintf(buf, sizeof(buf), _("Credit scheduler weight parameter (%d) is out of range (1-65535)"), val);
-                        virXenErrorFunc (domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__, buf, val);
-                        return(-1);
-                    }
-                    op_dom.u.getschedinfo.u.credit.weight = val;
-                } else if (STREQ (params[i].field, str_cap) &&
-                    params[i].type == VIR_DOMAIN_SCHED_FIELD_UINT) {
-                    val = params[i].value.ui;
-                    if (val > USHRT_MAX) {
-                        snprintf(buf, sizeof(buf), _("Credit scheduler cap parameter (%d) is out of range (0-65535)"), val);
-                        virXenErrorFunc (domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__, buf, val);
-                        return(-1);
-                    }
-                    op_dom.u.getschedinfo.u.credit.cap = val;
-                } else {
-                    virXenErrorFunc (domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
-                                     "Credit scheduler accepts 'cap' and 'weight' integer parameters",
-                                     0);
-                    return(-1);
-                }
-            }
-
-            ret = xenHypervisorDoV2Dom(priv->handle, &op_dom);
-            if (ret < 0)
-                return -1;
-            break;
-        }
-        default:
-            virXenErrorFunc(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
-                        "Unknown scheduler", op_sys.u.getschedulerid.sched_id);
-            return -1;
-        }
-    }
-
-    return 0;
-}
-
-
-int
-xenHypervisorDomainBlockStats (virDomainPtr dom,
-                               const char *path,
-                               struct _virDomainBlockStats *stats)
-{
-#ifdef __linux__
-    xenUnifiedPrivatePtr priv;
-    int ret;
-
-    priv = (xenUnifiedPrivatePtr) dom->conn->privateData;
-    xenUnifiedLock(priv);
-    /* Need to lock because it hits the xenstore handle :-( */
-    ret = xenLinuxDomainBlockStats (priv, dom, path, stats);
-    xenUnifiedUnlock(priv);
-    return ret;
-#else
-    virXenErrorFunc (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__,
-                     "block statistics not supported on this platform",
-                     dom->id);
-    return -1;
-#endif
-}
-
-/* Paths have the form vif<domid>.<n> (this interface checks that
- * <domid> is the real domain ID and returns an error if not).
- *
- * In future we may allow you to query bridge stats (virbrX or
- * xenbrX), but that will probably be through a separate
- * virNetwork interface, as yet not decided.
- */
-int
-xenHypervisorDomainInterfaceStats (virDomainPtr dom,
-                                   const char *path,
-                                   struct _virDomainInterfaceStats *stats)
-{
-#ifdef __linux__
-    int rqdomid, device;
-
-    /* Verify that the vif requested is one belonging to the current
-     * domain.
-     */
-    if (sscanf (path, "vif%d.%d", &rqdomid, &device) != 2) {
-        virXenErrorFunc (dom->conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
-                         "invalid path, should be vif<domid>.<n>.", 0);
-        return -1;
-    }
-    if (rqdomid != dom->id) {
-        virXenErrorFunc (dom->conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
-                         "invalid path, vif<domid> should match this domain ID", 0);
-        return -1;
-    }
-
-    return linuxDomainInterfaceStats (dom->conn, path, stats);
-#else
-    virXenErrorFunc (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__,
-                     "/proc/net/dev: Interface not found", 0);
-    return -1;
-#endif
-}
-
-/**
- * virXen_pausedomain:
- * @handle: the hypervisor handle
- * @id: the domain id
- *
- * Do a low level hypercall to pause the domain
- *
- * Returns 0 or -1 in case of failure
- */
-static int
-virXen_pausedomain(int handle, int id)
-{
-    int ret = -1;
-
-    if (hypervisor_version > 1) {
-        xen_op_v2_dom op;
-
-        memset(&op, 0, sizeof(op));
-        op.cmd = XEN_V2_OP_PAUSEDOMAIN;
-        op.domain = (domid_t) id;
-        ret = xenHypervisorDoV2Dom(handle, &op);
-    } else if (hypervisor_version == 1) {
-        xen_op_v1 op;
-
-        memset(&op, 0, sizeof(op));
-        op.cmd = XEN_V1_OP_PAUSEDOMAIN;
-        op.u.domain.domain = (domid_t) id;
-        ret = xenHypervisorDoV1Op(handle, &op);
-    } else if (hypervisor_version == 0) {
-        xen_op_v0 op;
-
-        memset(&op, 0, sizeof(op));
-        op.cmd = XEN_V0_OP_PAUSEDOMAIN;
-        op.u.domain.domain = (domid_t) id;
-        ret = xenHypervisorDoV0Op(handle, &op);
-    }
-    return(ret);
-}
-
-/**
- * virXen_unpausedomain:
- * @handle: the hypervisor handle
- * @id: the domain id
- *
- * Do a low level hypercall to unpause the domain
- *
- * Returns 0 or -1 in case of failure
- */
-static int
-virXen_unpausedomain(int handle, int id)
-{
-    int ret = -1;
-
-    if (hypervisor_version > 1) {
-        xen_op_v2_dom op;
-
-        memset(&op, 0, sizeof(op));
-        op.cmd = XEN_V2_OP_UNPAUSEDOMAIN;
-        op.domain = (domid_t) id;
-        ret = xenHypervisorDoV2Dom(handle, &op);
-    } else if (hypervisor_version == 1) {
-        xen_op_v1 op;
-
-        memset(&op, 0, sizeof(op));
-        op.cmd = XEN_V1_OP_UNPAUSEDOMAIN;
-        op.u.domain.domain = (domid_t) id;
-        ret = xenHypervisorDoV1Op(handle, &op);
-    } else if (hypervisor_version == 0) {
-        xen_op_v0 op;
-
-        memset(&op, 0, sizeof(op));
-        op.cmd = XEN_V0_OP_UNPAUSEDOMAIN;
-        op.u.domain.domain = (domid_t) id;
-        ret = xenHypervisorDoV0Op(handle, &op);
-    }
-    return(ret);
-}
-
-/**
- * virXen_destroydomain:
- * @handle: the hypervisor handle
- * @id: the domain id
- *
- * Do a low level hypercall to destroy the domain
- *
- * Returns 0 or -1 in case of failure
- */
-static int
-virXen_destroydomain(int handle, int id)
-{
-    int ret = -1;
-
-    if (hypervisor_version > 1) {
-        xen_op_v2_dom op;
-
-        memset(&op, 0, sizeof(op));
-        op.cmd = XEN_V2_OP_DESTROYDOMAIN;
-        op.domain = (domid_t) id;
-        ret = xenHypervisorDoV2Dom(handle, &op);
-    } else if (hypervisor_version == 1) {
-        xen_op_v1 op;
-
-        memset(&op, 0, sizeof(op));
-        op.cmd = XEN_V1_OP_DESTROYDOMAIN;
-        op.u.domain.domain = (domid_t) id;
-        ret = xenHypervisorDoV1Op(handle, &op);
-    } else if (hypervisor_version == 0) {
-        xen_op_v0 op;
-
-        memset(&op, 0, sizeof(op));
-        op.cmd = XEN_V0_OP_DESTROYDOMAIN;
-        op.u.domain.domain = (domid_t) id;
-        ret = xenHypervisorDoV0Op(handle, &op);
-    }
-    return(ret);
-}
-
-/**
- * virXen_setmaxmem:
- * @handle: the hypervisor handle
- * @id: the domain id
- * @memory: the amount of memory in kilobytes
- *
- * Do a low level hypercall to change the max memory amount
- *
- * Returns 0 or -1 in case of failure
- */
-static int
-virXen_setmaxmem(int handle, int id, unsigned long memory)
-{
-    int ret = -1;
-
-    if (hypervisor_version > 1) {
-        xen_op_v2_dom op;
-
-        memset(&op, 0, sizeof(op));
-        op.cmd = XEN_V2_OP_SETMAXMEM;
-        op.domain = (domid_t) id;
-        if (dom_interface_version < 5)
-            op.u.setmaxmem.maxmem = memory;
-        else
-            op.u.setmaxmemd5.maxmem = memory;
-        ret = xenHypervisorDoV2Dom(handle, &op);
-    } else if (hypervisor_version == 1) {
-        xen_op_v1 op;
-
-        memset(&op, 0, sizeof(op));
-        op.cmd = XEN_V1_OP_SETMAXMEM;
-        op.u.setmaxmem.domain = (domid_t) id;
-        op.u.setmaxmem.maxmem = memory;
-        ret = xenHypervisorDoV1Op(handle, &op);
-    } else if (hypervisor_version == 0) {
-        xen_op_v0 op;
-
-        memset(&op, 0, sizeof(op));
-        op.cmd = XEN_V0_OP_SETMAXMEM;
-        op.u.setmaxmem.domain = (domid_t) id;
-        op.u.setmaxmem.maxmem = memory;
-        ret = xenHypervisorDoV0Op(handle, &op);
-    }
-    return(ret);
-}
-
-/**
- * virXen_setmaxvcpus:
- * @handle: the hypervisor handle
- * @id: the domain id
- * @vcpus: the numbers of vcpus
- *
- * Do a low level hypercall to change the max vcpus amount
- *
- * Returns 0 or -1 in case of failure
- */
-static int
-virXen_setmaxvcpus(int handle, int id, unsigned int vcpus)
-{
-    int ret = -1;
-
-    if (hypervisor_version > 1) {
-        xen_op_v2_dom op;
-
-        memset(&op, 0, sizeof(op));
-        op.cmd = XEN_V2_OP_SETMAXVCPU;
-        op.domain = (domid_t) id;
-        op.u.setmaxvcpu.maxvcpu = vcpus;
-        ret = xenHypervisorDoV2Dom(handle, &op);
-    } else if (hypervisor_version == 1) {
-        xen_op_v1 op;
-
-        memset(&op, 0, sizeof(op));
-        op.cmd = XEN_V1_OP_SETMAXVCPU;
-        op.u.setmaxvcpu.domain = (domid_t) id;
-        op.u.setmaxvcpu.maxvcpu = vcpus;
-        ret = xenHypervisorDoV1Op(handle, &op);
-    } else if (hypervisor_version == 0) {
-        xen_op_v0 op;
-
-        memset(&op, 0, sizeof(op));
-        op.cmd = XEN_V0_OP_SETMAXVCPU;
-        op.u.setmaxvcpu.domain = (domid_t) id;
-        op.u.setmaxvcpu.maxvcpu = vcpus;
-        ret = xenHypervisorDoV0Op(handle, &op);
-    }
-    return(ret);
-}
-
-/**
- * virXen_setvcpumap:
- * @handle: the hypervisor handle
- * @id: the domain id
- * @vcpu: the vcpu to map
- * @cpumap: the bitmap for this vcpu
- * @maplen: the size of the bitmap in bytes
- *
- * Do a low level hypercall to change the pinning for vcpu
- *
- * Returns 0 or -1 in case of failure
- */
-static int
-virXen_setvcpumap(int handle, int id, unsigned int vcpu,
-                  unsigned char * cpumap, int maplen)
-{
-    int ret = -1;
-    unsigned char *new = NULL;
-    unsigned char *bitmap = NULL;
-    uint32_t nr_cpus;
-
-    if (hypervisor_version > 1) {
-        xen_op_v2_dom op;
-
-        if (lock_pages(cpumap, maplen) < 0) {
-            virXenError(NULL, VIR_ERR_XEN_CALL, " locking");
-            return (-1);
-        }
-        memset(&op, 0, sizeof(op));
-        op.cmd = XEN_V2_OP_SETVCPUMAP;
-        op.domain = (domid_t) id;
-
-        /* The allocated memory to cpumap must be 'sizeof(uint64_t)' byte *
-         * for Xen, and also nr_cpus must be 'sizeof(uint64_t) * 8'       */
-        if (maplen < 8) {
-            if (VIR_ALLOC_N(new, sizeof(uint64_t)) < 0) {
-                virReportOOMError(NULL);
-                return (-1);
-            }
-            memcpy(new, cpumap, maplen);
-            bitmap = new;
-            nr_cpus = sizeof(uint64_t) * 8;
-        } else {
-            bitmap = cpumap;
-            nr_cpus = maplen * 8;
-        }
-
-        if (dom_interface_version < 5) {
-            op.u.setvcpumap.vcpu = vcpu;
-            op.u.setvcpumap.cpumap.bitmap = bitmap;
-            op.u.setvcpumap.cpumap.nr_cpus = nr_cpus;
-        } else {
-            op.u.setvcpumapd5.vcpu = vcpu;
-            op.u.setvcpumapd5.cpumap.bitmap.v = bitmap;
-            op.u.setvcpumapd5.cpumap.nr_cpus = nr_cpus;
-        }
-        ret = xenHypervisorDoV2Dom(handle, &op);
-        VIR_FREE(new);
-
-        if (unlock_pages(cpumap, maplen) < 0) {
-            virXenError(NULL, VIR_ERR_XEN_CALL, " release");
-            ret = -1;
-        }
-    } else {
-        cpumap_t xen_cpumap; /* limited to 64 CPUs in old hypervisors */
-        uint64_t *pm = &xen_cpumap;
-        int j;
-
-        if ((maplen > (int)sizeof(cpumap_t)) || (sizeof(cpumap_t) & 7))
-            return (-1);
-
-        memset(pm, 0, sizeof(cpumap_t));
-        for (j = 0; j < maplen; j++)
-            *(pm + (j / 8)) |= cpumap[j] << (8 * (j & 7));
-
-        if (hypervisor_version == 1) {
-            xen_op_v1 op;
-
-            memset(&op, 0, sizeof(op));
-            op.cmd = XEN_V1_OP_SETVCPUMAP;
-            op.u.setvcpumap.domain = (domid_t) id;
-            op.u.setvcpumap.vcpu = vcpu;
-            op.u.setvcpumap.cpumap = xen_cpumap;
-            ret = xenHypervisorDoV1Op(handle, &op);
-        } else if (hypervisor_version == 0) {
-            xen_op_v0 op;
-
-            memset(&op, 0, sizeof(op));
-            op.cmd = XEN_V0_OP_SETVCPUMAP;
-            op.u.setvcpumap.domain = (domid_t) id;
-            op.u.setvcpumap.vcpu = vcpu;
-            op.u.setvcpumap.cpumap = xen_cpumap;
-            ret = xenHypervisorDoV0Op(handle, &op);
-        }
-    }
-    return(ret);
-}
-#endif /* !PROXY*/
-
-/**
- * virXen_getvcpusinfo:
- * @handle: the hypervisor handle
- * @id: the domain id
- * @vcpu: the vcpu to map
- * @cpumap: the bitmap for this vcpu
- * @maplen: the size of the bitmap in bytes
- *
- * Do a low level hypercall to change the pinning for vcpu
- *
- * Returns 0 or -1 in case of failure
- */
-static int
-virXen_getvcpusinfo(int handle, int id, unsigned int vcpu, virVcpuInfoPtr ipt,
-                    unsigned char *cpumap, int maplen)
-{
-    int ret = -1;
-
-    if (hypervisor_version > 1) {
-        xen_op_v2_dom op;
-
-        memset(&op, 0, sizeof(op));
-        op.cmd = XEN_V2_OP_GETVCPUINFO;
-        op.domain = (domid_t) id;
-        if (dom_interface_version < 5)
-            op.u.getvcpuinfo.vcpu = (uint16_t) vcpu;
-        else
-            op.u.getvcpuinfod5.vcpu = (uint16_t) vcpu;
-        ret = xenHypervisorDoV2Dom(handle, &op);
-
-        if (ret < 0)
-            return(-1);
-        ipt->number = vcpu;
-        if (dom_interface_version < 5) {
-            if (op.u.getvcpuinfo.online) {
-                if (op.u.getvcpuinfo.running)
-                    ipt->state = VIR_VCPU_RUNNING;
-                if (op.u.getvcpuinfo.blocked)
-                    ipt->state = VIR_VCPU_BLOCKED;
-            } else
-                ipt->state = VIR_VCPU_OFFLINE;
-
-            ipt->cpuTime = op.u.getvcpuinfo.cpu_time;
-            ipt->cpu = op.u.getvcpuinfo.online ? (int)op.u.getvcpuinfo.cpu : -1;
-        } else {
-            if (op.u.getvcpuinfod5.online) {
-                if (op.u.getvcpuinfod5.running)
-                    ipt->state = VIR_VCPU_RUNNING;
-                if (op.u.getvcpuinfod5.blocked)
-                    ipt->state = VIR_VCPU_BLOCKED;
-            } else
-                ipt->state = VIR_VCPU_OFFLINE;
-
-            ipt->cpuTime = op.u.getvcpuinfod5.cpu_time;
-            ipt->cpu = op.u.getvcpuinfod5.online ? (int)op.u.getvcpuinfod5.cpu : -1;
-        }
-        if ((cpumap != NULL) && (maplen > 0)) {
-            if (lock_pages(cpumap, maplen) < 0) {
-                virXenError(NULL, VIR_ERR_XEN_CALL, " locking");
-                return (-1);
-            }
-            memset(cpumap, 0, maplen);
-            memset(&op, 0, sizeof(op));
-            op.cmd = XEN_V2_OP_GETVCPUMAP;
-            op.domain = (domid_t) id;
-            if (dom_interface_version < 5) {
-                op.u.getvcpumap.vcpu = vcpu;
-                op.u.getvcpumap.cpumap.bitmap = cpumap;
-                op.u.getvcpumap.cpumap.nr_cpus = maplen * 8;
-            } else {
-                op.u.getvcpumapd5.vcpu = vcpu;
-                op.u.getvcpumapd5.cpumap.bitmap.v = cpumap;
-                op.u.getvcpumapd5.cpumap.nr_cpus = maplen * 8;
-            }
-            ret = xenHypervisorDoV2Dom(handle, &op);
-            if (unlock_pages(cpumap, maplen) < 0) {
-                virXenError(NULL, VIR_ERR_XEN_CALL, " release");
-                ret = -1;
-            }
-        }
-    } else {
-        int mapl = maplen;
-        int cpu;
-
-        if (maplen > (int)sizeof(cpumap_t))
-            mapl = (int)sizeof(cpumap_t);
-
-        if (hypervisor_version == 1) {
-            xen_op_v1 op;
-
-            memset(&op, 0, sizeof(op));
-            op.cmd = XEN_V1_OP_GETVCPUINFO;
-            op.u.getvcpuinfo.domain = (domid_t) id;
-            op.u.getvcpuinfo.vcpu = vcpu;
-            ret = xenHypervisorDoV1Op(handle, &op);
-            if (ret < 0)
-                return(-1);
-            ipt->number = vcpu;
-            if (op.u.getvcpuinfo.online) {
-                if (op.u.getvcpuinfo.running) ipt->state = VIR_VCPU_RUNNING;
-                if (op.u.getvcpuinfo.blocked) ipt->state = VIR_VCPU_BLOCKED;
-            }
-            else ipt->state = VIR_VCPU_OFFLINE;
-            ipt->cpuTime = op.u.getvcpuinfo.cpu_time;
-            ipt->cpu = op.u.getvcpuinfo.online ? (int)op.u.getvcpuinfo.cpu : -1;
-            if ((cpumap != NULL) && (maplen > 0)) {
-                for (cpu = 0; cpu < (mapl * 8); cpu++) {
-                    if (op.u.getvcpuinfo.cpumap & ((uint64_t)1<<cpu))
-                        VIR_USE_CPU(cpumap, cpu);
-                }
-            }
-        } else if (hypervisor_version == 0) {
-            xen_op_v1 op;
-
-            memset(&op, 0, sizeof(op));
-            op.cmd = XEN_V0_OP_GETVCPUINFO;
-            op.u.getvcpuinfo.domain = (domid_t) id;
-            op.u.getvcpuinfo.vcpu = vcpu;
-            ret = xenHypervisorDoV0Op(handle, &op);
-            if (ret < 0)
-                return(-1);
-            ipt->number = vcpu;
-            if (op.u.getvcpuinfo.online) {
-                if (op.u.getvcpuinfo.running) ipt->state = VIR_VCPU_RUNNING;
-                if (op.u.getvcpuinfo.blocked) ipt->state = VIR_VCPU_BLOCKED;
-            }
-            else ipt->state = VIR_VCPU_OFFLINE;
-            ipt->cpuTime = op.u.getvcpuinfo.cpu_time;
-            ipt->cpu = op.u.getvcpuinfo.online ? (int)op.u.getvcpuinfo.cpu : -1;
-            if ((cpumap != NULL) && (maplen > 0)) {
-                for (cpu = 0; cpu < (mapl * 8); cpu++) {
-                    if (op.u.getvcpuinfo.cpumap & ((uint64_t)1<<cpu))
-                        VIR_USE_CPU(cpumap, cpu);
-                }
-            }
-        }
-    }
-    return(ret);
-}
-
-/**
- * xenHypervisorInit:
- *
- * Initialize the hypervisor layer. Try to detect the kind of interface
- * used i.e. pre or post changeset 10277
- */
-int
-xenHypervisorInit(void)
-{
-    int fd, ret, cmd, errcode;
-    hypercall_t hc;
-    v0_hypercall_t v0_hc;
-    xen_getdomaininfo info;
-    virVcpuInfoPtr ipt = NULL;
-
-    if (initialized) {
-        if (hypervisor_version == -1)
-            return (-1);
-        return(0);
-    }
-    initialized = 1;
-    in_init = 1;
-
-    /* Compile regular expressions used by xenHypervisorGetCapabilities.
-     * Note that errors here are really internal errors since these
-     * regexps should never fail to compile.
-     */
-    errcode = regcomp (&flags_hvm_rec, flags_hvm_re, REG_EXTENDED);
-    if (errcode != 0) {
-        char error[100];
-        regerror (errcode, &flags_hvm_rec, error, sizeof error);
-        regfree (&flags_hvm_rec);
-        virXenError (NULL, VIR_ERR_INTERNAL_ERROR, "%s", error);
-        in_init = 0;
-        return -1;
-    }
-    errcode = regcomp (&flags_pae_rec, flags_pae_re, REG_EXTENDED);
-    if (errcode != 0) {
-        char error[100];
-        regerror (errcode, &flags_pae_rec, error, sizeof error);
-        regfree (&flags_pae_rec);
-        regfree (&flags_hvm_rec);
-        virXenError (NULL, VIR_ERR_INTERNAL_ERROR, "%s", error);
-        in_init = 0;
-        return -1;
-    }
-    errcode = regcomp (&xen_cap_rec, xen_cap_re, REG_EXTENDED);
-    if (errcode != 0) {
-        char error[100];
-        regerror (errcode, &xen_cap_rec, error, sizeof error);
-        regfree (&xen_cap_rec);
-        regfree (&flags_pae_rec);
-        regfree (&flags_hvm_rec);
-        virXenError (NULL, VIR_ERR_INTERNAL_ERROR, "%s", error);
-        in_init = 0;
-        return -1;
-    }
-
-    /* Xen hypervisor version detection begins. */
-    ret = open(XEN_HYPERVISOR_SOCKET, O_RDWR);
-    if (ret < 0) {
-        hypervisor_version = -1;
-        return(-1);
-    }
-    fd = ret;
-
-    /*
-     * The size of the hypervisor call block changed July 2006
-     * this detect if we are using the new or old hypercall_t structure
-     */
-    hc.op = __HYPERVISOR_xen_version;
-    hc.arg[0] = (unsigned long) XENVER_version;
-    hc.arg[1] = 0;
-
-    cmd = IOCTL_PRIVCMD_HYPERCALL;
-    ret = ioctl(fd, cmd, (unsigned long) &hc);
-
-    if ((ret != -1) && (ret != 0)) {
-        DEBUG("Using new hypervisor call: %X\n", ret);
-        hv_version = ret;
-        xen_ioctl_hypercall_cmd = cmd;
-        goto detect_v2;
-    }
-
-#ifndef __sun
-    /*
-     * check if the old hypercall are actually working
-     */
-    v0_hc.op = __HYPERVISOR_xen_version;
-    v0_hc.arg[0] = (unsigned long) XENVER_version;
-    v0_hc.arg[1] = 0;
-    cmd = _IOC(_IOC_NONE, 'P', 0, sizeof(v0_hypercall_t));
-    ret = ioctl(fd, cmd, (unsigned long) &v0_hc);
-    if ((ret != -1) && (ret != 0)) {
-        DEBUG("Using old hypervisor call: %X\n", ret);
-        hv_version = ret;
-        xen_ioctl_hypercall_cmd = cmd;
-        hypervisor_version = 0;
-        goto done;
-    }
-#endif
-
-    /*
-     * we failed to make any hypercall
-     */
-
-    hypervisor_version = -1;
-    virXenError(NULL, VIR_ERR_XEN_CALL, " ioctl %lu",
-                (unsigned long) IOCTL_PRIVCMD_HYPERCALL);
-    close(fd);
-    in_init = 0;
-    return(-1);
-
- detect_v2:
-    /*
-     * The hypercalls were refactored into 3 different section in August 2006
-     * Try to detect if we are running a version post 3.0.2 with the new ones
-     * or the old ones
-     */
-    hypervisor_version = 2;
-
-    if (VIR_ALLOC(ipt) < 0) {
-        virReportOOMError(NULL);
-        return(-1);
-    }
-    /* Currently consider RHEL5.0 Fedora7, xen-3.1, and xen-unstable */
-    sys_interface_version = 2; /* XEN_SYSCTL_INTERFACE_VERSION */
-    if (virXen_getdomaininfo(fd, 0, &info) == 1) {
-        /* RHEL 5.0 */
-        dom_interface_version = 3; /* XEN_DOMCTL_INTERFACE_VERSION */
-        if (virXen_getvcpusinfo(fd, 0, 0, ipt, NULL, 0) == 0){
-            DEBUG0("Using hypervisor call v2, sys ver2 dom ver3\n");
-            goto done;
-        }
-        /* Fedora 7 */
-        dom_interface_version = 4; /* XEN_DOMCTL_INTERFACE_VERSION */
-        if (virXen_getvcpusinfo(fd, 0, 0, ipt, NULL, 0) == 0){
-            DEBUG0("Using hypervisor call v2, sys ver2 dom ver4\n");
-            goto done;
-        }
-    }
-
-    sys_interface_version = 3; /* XEN_SYSCTL_INTERFACE_VERSION */
-    if (virXen_getdomaininfo(fd, 0, &info) == 1) {
-        /* xen-3.1 */
-        dom_interface_version = 5; /* XEN_DOMCTL_INTERFACE_VERSION */
-        if (virXen_getvcpusinfo(fd, 0, 0, ipt, NULL, 0) == 0){
-            DEBUG0("Using hypervisor call v2, sys ver3 dom ver5\n");
-            goto done;
-        }
-    }
-
-    sys_interface_version = 4; /* XEN_SYSCTL_INTERFACE_VERSION */
-    if (virXen_getdomaininfo(fd, 0, &info) == 1) {
-        /* Fedora 8 */
-        dom_interface_version = 5; /* XEN_DOMCTL_INTERFACE_VERSION */
-        if (virXen_getvcpusinfo(fd, 0, 0, ipt, NULL, 0) == 0){
-            DEBUG0("Using hypervisor call v2, sys ver4 dom ver5\n");
-            goto done;
-        }
-    }
-
-    sys_interface_version = 6; /* XEN_SYSCTL_INTERFACE_VERSION */
-    if (virXen_getdomaininfo(fd, 0, &info) == 1) {
-        /* Xen 3.2, Fedora 9 */
-        dom_interface_version = 5; /* XEN_DOMCTL_INTERFACE_VERSION */
-        if (virXen_getvcpusinfo(fd, 0, 0, ipt, NULL, 0) == 0){
-            DEBUG0("Using hypervisor call v2, sys ver6 dom ver5\n");
-            goto done;
-        }
-    }
-
-    hypervisor_version = 1;
-    sys_interface_version = -1;
-    if (virXen_getdomaininfo(fd, 0, &info) == 1) {
-        DEBUG0("Using hypervisor call v1\n");
-        goto done;
-    }
-
-    /*
-     * we failed to make the getdomaininfolist hypercall
-     */
-
-    DEBUG0("Failed to find any Xen hypervisor method\n");
-    hypervisor_version = -1;
-    virXenError(NULL, VIR_ERR_XEN_CALL, " ioctl %lu",
-                (unsigned long)IOCTL_PRIVCMD_HYPERCALL);
-    close(fd);
-    in_init = 0;
-    VIR_FREE(ipt);
-    return(-1);
-
- done:
-    close(fd);
-    in_init = 0;
-    VIR_FREE(ipt);
-    return(0);
-}
-
-/**
- * xenHypervisorOpen:
- * @conn: pointer to the connection block
- * @name: URL for the target, NULL for local
- * @flags: combination of virDrvOpenFlag(s)
- *
- * Connects to the Xen hypervisor.
- *
- * Returns 0 or -1 in case of error.
- */
-virDrvOpenStatus
-xenHypervisorOpen(virConnectPtr conn,
-                  virConnectAuthPtr auth ATTRIBUTE_UNUSED,
-                  int flags ATTRIBUTE_UNUSED)
-{
-    int ret;
-    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
-
-    if (initialized == 0)
-        if (xenHypervisorInit() == -1)
-            return -1;
-
-    priv->handle = -1;
-
-    ret = open(XEN_HYPERVISOR_SOCKET, O_RDWR);
-    if (ret < 0) {
-        virXenError(conn, VIR_ERR_NO_XEN, "%s", XEN_HYPERVISOR_SOCKET);
-        return (-1);
-    }
-
-    priv->handle = ret;
-
-    return(0);
-}
-
-/**
- * xenHypervisorClose:
- * @conn: pointer to the connection block
- *
- * Close the connection to the Xen hypervisor.
- *
- * Returns 0 in case of success or -1 in case of error.
- */
-int
-xenHypervisorClose(virConnectPtr conn)
-{
-    int ret;
-    xenUnifiedPrivatePtr priv;
-
-    if (conn == NULL)
-        return (-1);
-
-    priv = (xenUnifiedPrivatePtr) conn->privateData;
-
-    if (priv->handle < 0)
-        return -1;
-
-    ret = close(priv->handle);
-    if (ret < 0)
-        return (-1);
-
-    return (0);
-}
-
-
-/**
- * xenHypervisorGetVersion:
- * @conn: pointer to the connection block
- * @hvVer: where to store the version
- *
- * Call the hypervisor to extracts his own internal API version
- *
- * Returns 0 in case of success, -1 in case of error
- */
-int
-xenHypervisorGetVersion(virConnectPtr conn, unsigned long *hvVer)
-{
-    xenUnifiedPrivatePtr priv;
-
-    if (conn == NULL)
-        return -1;
-    priv = (xenUnifiedPrivatePtr) conn->privateData;
-    if (priv->handle < 0 || hvVer == NULL)
-        return (-1);
-    *hvVer = (hv_version >> 16) * 1000000 + (hv_version & 0xFFFF) * 1000;
-    return(0);
-}
-
-struct guest_arch {
-    const char *model;
-    int bits;
-    int hvm;
-    int pae;
-    int nonpae;
-    int ia64_be;
-};
-
-
-static virCapsPtr
-xenHypervisorBuildCapabilities(virConnectPtr conn,
-                               const char *hostmachine,
-                               int host_pae,
-                               const char *hvm_type,
-                               struct guest_arch *guest_archs,
-                               int nr_guest_archs) {
-    virCapsPtr caps;
-    int i;
-    int hv_major = hv_version >> 16;
-    int hv_minor = hv_version & 0xFFFF;
-
-    if ((caps = virCapabilitiesNew(hostmachine, 1, 1)) == NULL)
-        goto no_memory;
-
-    virCapabilitiesSetMacPrefix(caps, (unsigned char[]){ 0x00, 0x16, 0x3e });
-
-    if (hvm_type && STRNEQ(hvm_type, "") &&
-        virCapabilitiesAddHostFeature(caps, hvm_type) < 0)
-        goto no_memory;
-    if (host_pae &&
-        virCapabilitiesAddHostFeature(caps, "pae") < 0)
-        goto no_memory;
-
-
-    if (virCapabilitiesAddHostMigrateTransport(caps,
-                                               "xenmigr") < 0)
-        goto no_memory;
-
-
-    if (sys_interface_version >= SYS_IFACE_MIN_VERS_NUMA) {
-        if (xenDaemonNodeGetTopology(conn, caps) != 0) {
-            virCapabilitiesFree(caps);
-            return NULL;
-        }
-    }
-
-    for (i = 0; i < nr_guest_archs; ++i) {
-        virCapsGuestPtr guest;
-        char const *const xen_machines[] = {guest_archs[i].hvm ? "xenfv" : "xenpv"};
-        virCapsGuestMachinePtr *machines;
-
-        if ((machines = virCapabilitiesAllocMachines(xen_machines, 1)) == NULL)
-            goto no_memory;
-
-        if ((guest = virCapabilitiesAddGuest(caps,
-                                             guest_archs[i].hvm ? "hvm" : "xen",
-                                             guest_archs[i].model,
-                                             guest_archs[i].bits,
-                                             (STREQ(hostmachine, "x86_64") ?
-                                              "/usr/lib64/xen/bin/qemu-dm" :
-                                              "/usr/lib/xen/bin/qemu-dm"),
-                                             (guest_archs[i].hvm ?
-                                              "/usr/lib/xen/boot/hvmloader" :
-                                              NULL),
-                                             1,
-                                             machines)) == NULL) {
-            virCapabilitiesFreeMachines(machines, 1);
-            goto no_memory;
-        }
-        machines = NULL;
-
-        if (virCapabilitiesAddGuestDomain(guest,
-                                          "xen",
-                                          NULL,
-                                          NULL,
-                                          0,
-                                          NULL) == NULL)
-            goto no_memory;
-
-        if (guest_archs[i].pae &&
-            virCapabilitiesAddGuestFeature(guest,
-                                           "pae",
-                                           1,
-                                           0) == NULL)
-            goto no_memory;
-
-        if (guest_archs[i].nonpae &&
-            virCapabilitiesAddGuestFeature(guest,
-                                           "nonpae",
-                                           1,
-                                           0) == NULL)
-            goto no_memory;
-
-        if (guest_archs[i].ia64_be &&
-            virCapabilitiesAddGuestFeature(guest,
-                                           "ia64_be",
-                                           1,
-                                           0) == NULL)
-            goto no_memory;
-
-        if (guest_archs[i].hvm) {
-            if (virCapabilitiesAddGuestFeature(guest,
-                                               "acpi",
-                                               1, 1) == NULL)
-                goto no_memory;
-
-            // In Xen 3.1.0, APIC is always on and can't be toggled
-            if (virCapabilitiesAddGuestFeature(guest,
-                                               "apic",
-                                               1,
-                                               (hv_major > 3 &&
-                                                hv_minor > 0 ?
-                                                0 : 1)) == NULL)
-                goto no_memory;
-        }
-    }
-
-    return caps;
-
- no_memory:
-    virCapabilitiesFree(caps);
-    return NULL;
-}
-
-#ifdef __sun
-
-static int
-get_cpu_flags(virConnectPtr conn, const char **hvm, int *pae, int *longmode)
-{
-    struct {
-        uint32_t r_eax, r_ebx, r_ecx, r_edx;
-    } regs;
-
-    char tmpbuf[20];
-    int ret = 0;
-    int fd;
-
-    /* returns -1, errno 22 if in 32-bit mode */
-    *longmode = (sysinfo(SI_ARCHITECTURE_64, tmpbuf, sizeof(tmpbuf)) != -1);
-
-    if ((fd = open("/dev/cpu/self/cpuid", O_RDONLY)) == -1 ||
-        pread(fd, &regs, sizeof(regs), 0) != sizeof(regs)) {
-        char ebuf[1024];
-        virXenError(conn, VIR_ERR_SYSTEM_ERROR,
-            "couldn't read CPU flags: %s", virStrerror(errno, ebuf, sizeof ebuf));
-        goto out;
-    }
-
-    *pae = 0;
-    *hvm = "";
-
-    if (STREQLEN((const char *)&regs.r_ebx, "AuthcAMDenti", 12)) {
-        if (pread(fd, &regs, sizeof (regs), 0x80000001) == sizeof (regs)) {
-            /* Read secure virtual machine bit (bit 2 of ECX feature ID) */
-            if ((regs.r_ecx >> 2) & 1) {
-                *hvm = "svm";
-            }
-            if ((regs.r_edx >> 6) & 1)
-                *pae = 1;
-        }
-    } else if (STREQLEN((const char *)&regs.r_ebx, "GenuntelineI", 12)) {
-        if (pread(fd, &regs, sizeof (regs), 0x00000001) == sizeof (regs)) {
-            /* Read VMXE feature bit (bit 5 of ECX feature ID) */
-            if ((regs.r_ecx >> 5) & 1)
-                *hvm = "vmx";
-            if ((regs.r_edx >> 6) & 1)
-                *pae = 1;
-        }
-    }
-
-    ret = 1;
-
-out:
-    if (fd != -1)
-        close(fd);
-    return ret;
-}
-
-static virCapsPtr
-xenHypervisorMakeCapabilitiesSunOS(virConnectPtr conn)
-{
-    struct guest_arch guest_arches[32];
-    int i = 0;
-    virCapsPtr caps = NULL;
-    struct utsname utsname;
-    int pae, longmode;
-    const char *hvm;
-
-    if (!get_cpu_flags(conn, &hvm, &pae, &longmode))
-        return NULL;
-
-    /* Really, this never fails - look at the man-page. */
-    uname (&utsname);
-
-    guest_arches[i].model = "i686";
-    guest_arches[i].bits = 32;
-    guest_arches[i].hvm = 0;
-    guest_arches[i].pae = pae;
-    guest_arches[i].nonpae = !pae;
-    guest_arches[i].ia64_be = 0;
-    i++;
-
-    if (longmode) {
-        guest_arches[i].model = "x86_64";
-        guest_arches[i].bits = 64;
-        guest_arches[i].hvm = 0;
-        guest_arches[i].pae = 0;
-        guest_arches[i].nonpae = 0;
-        guest_arches[i].ia64_be = 0;
-        i++;
-    }
-
-    if (hvm[0] != '\0') {
-        guest_arches[i].model = "i686";
-        guest_arches[i].bits = 32;
-        guest_arches[i].hvm = 1;
-        guest_arches[i].pae = pae;
-        guest_arches[i].nonpae = 1;
-        guest_arches[i].ia64_be = 0;
-        i++;
-
-        if (longmode) {
-            guest_arches[i].model = "x86_64";
-            guest_arches[i].bits = 64;
-            guest_arches[i].hvm = 1;
-            guest_arches[i].pae = 0;
-            guest_arches[i].nonpae = 0;
-            guest_arches[i].ia64_be = 0;
-            i++;
-        }
-    }
-
-    if ((caps = xenHypervisorBuildCapabilities(conn,
-                                               utsname.machine,
-                                               pae, hvm,
-                                               guest_arches, i)) == NULL)
-        virReportOOMError(NULL);
-
-    return caps;
-}
-
-#endif /* __sun */
-
-/**
- * xenHypervisorMakeCapabilitiesInternal:
- * @conn: pointer to the connection block
- * @cpuinfo: file handle containing /proc/cpuinfo data, or NULL
- * @capabilities: file handle containing /sys/hypervisor/properties/capabilities data, or NULL
- *
- * Return the capabilities of this hypervisor.
- */
-virCapsPtr
-xenHypervisorMakeCapabilitiesInternal(virConnectPtr conn,
-                                      const char *hostmachine,
-                                      FILE *cpuinfo, FILE *capabilities)
-{
-    char line[1024], *str, *token;
-    regmatch_t subs[4];
-    char *saveptr = NULL;
-    int i;
-
-    char hvm_type[4] = ""; /* "vmx" or "svm" (or "" if not in CPU). */
-    int host_pae = 0;
-    struct guest_arch guest_archs[32];
-    int nr_guest_archs = 0;
-    virCapsPtr caps = NULL;
-
-    memset(guest_archs, 0, sizeof(guest_archs));
-
-    /* /proc/cpuinfo: flags: Intel calls HVM "vmx", AMD calls it "svm".
-     * It's not clear if this will work on IA64, let alone other
-     * architectures and non-Linux. (XXX)
-     */
-    if (cpuinfo) {
-        while (fgets (line, sizeof line, cpuinfo)) {
-            if (regexec (&flags_hvm_rec, line, sizeof(subs)/sizeof(regmatch_t), subs, 0) == 0
-                && subs[0].rm_so != -1) {
-                strncpy (hvm_type,
-                         &line[subs[1].rm_so], subs[1].rm_eo-subs[1].rm_so+1);
-                hvm_type[subs[1].rm_eo-subs[1].rm_so] = '\0';
-            } else if (regexec (&flags_pae_rec, line, 0, NULL, 0) == 0)
-                host_pae = 1;
-        }
-    }
-
-    /* Most of the useful info is in /sys/hypervisor/properties/capabilities
-     * which is documented in the code in xen-unstable.hg/xen/arch/.../setup.c.
-     *
-     * It is a space-separated list of supported guest architectures.
-     *
-     * For x86:
-     *    TYP-VER-ARCH[p]
-     *    ^   ^   ^    ^
-     *    |   |   |    +-- PAE supported
-     *    |   |   +------- x86_32 or x86_64
-     *    |   +----------- the version of Xen, eg. "3.0"
-     *    +--------------- "xen" or "hvm" for para or full virt respectively
-     *
-     * For PPC this file appears to be always empty (?)
-     *
-     * For IA64:
-     *    TYP-VER-ARCH[be]
-     *    ^   ^   ^    ^
-     *    |   |   |    +-- Big-endian supported
-     *    |   |   +------- always "ia64"
-     *    |   +----------- the version of Xen, eg. "3.0"
-     *    +--------------- "xen" or "hvm" for para or full virt respectively
-     */
-
-    /* Expecting one line in this file - ignore any more. */
-    if ((capabilities) && (fgets (line, sizeof line, capabilities))) {
-        /* Split the line into tokens.  strtok_r is OK here because we "own"
-         * this buffer.  Parse out the features from each token.
-         */
-        for (str = line, nr_guest_archs = 0;
-             nr_guest_archs < sizeof guest_archs / sizeof guest_archs[0]
-                 && (token = strtok_r (str, " ", &saveptr)) != NULL;
-             str = NULL) {
-
-            if (regexec (&xen_cap_rec, token, sizeof subs / sizeof subs[0],
-                         subs, 0) == 0) {
-                int hvm = STRPREFIX(&token[subs[1].rm_so], "hvm");
-                const char *model;
-                int bits, pae = 0, nonpae = 0, ia64_be = 0;
-
-                if (STRPREFIX(&token[subs[2].rm_so], "x86_32")) {
-                    model = "i686";
-                    bits = 32;
-                    if (subs[3].rm_so != -1 &&
-                        STRPREFIX(&token[subs[3].rm_so], "p"))
-                        pae = 1;
-                    else
-                        nonpae = 1;
-                }
-                else if (STRPREFIX(&token[subs[2].rm_so], "x86_64")) {
-                    model = "x86_64";
-                    bits = 64;
-                }
-                else if (STRPREFIX(&token[subs[2].rm_so], "ia64")) {
-                    model = "ia64";
-                    bits = 64;
-                    if (subs[3].rm_so != -1 &&
-                        STRPREFIX(&token[subs[3].rm_so], "be"))
-                        ia64_be = 1;
-                }
-                else if (STRPREFIX(&token[subs[2].rm_so], "powerpc64")) {
-                    model = "ppc64";
-                    bits = 64;
-                } else {
-                    /* XXX surely no other Xen archs exist  */
-                    continue;
-                }
-
-                /* Search for existing matching (model,hvm) tuple */
-                for (i = 0 ; i < nr_guest_archs ; i++) {
-                    if (STREQ(guest_archs[i].model, model) &&
-                        guest_archs[i].hvm == hvm) {
-                        break;
-                    }
-                }
-
-                /* Too many arch flavours - highly unlikely ! */
-                if (i >= ARRAY_CARDINALITY(guest_archs))
-                    continue;
-                /* Didn't find a match, so create a new one */
-                if (i == nr_guest_archs)
-                    nr_guest_archs++;
-
-                guest_archs[i].model = model;
-                guest_archs[i].bits = bits;
-                guest_archs[i].hvm = hvm;
-
-                /* Careful not to overwrite a previous positive
-                   setting with a negative one here - some archs
-                   can do both pae & non-pae, but Xen reports
-                   separately capabilities so we're merging archs */
-                if (pae)
-                    guest_archs[i].pae = pae;
-                if (nonpae)
-                    guest_archs[i].nonpae = nonpae;
-                if (ia64_be)
-                    guest_archs[i].ia64_be = ia64_be;
-            }
-        }
-    }
-
-    if ((caps = xenHypervisorBuildCapabilities(conn,
-                                               hostmachine,
-                                               host_pae,
-                                               hvm_type,
-                                               guest_archs,
-                                               nr_guest_archs)) == NULL)
-        goto no_memory;
-
-    return caps;
-
- no_memory:
-    virReportOOMError(NULL);
-    virCapabilitiesFree(caps);
-    return NULL;
-}
-
-/**
- * xenHypervisorMakeCapabilities:
- *
- * Return the capabilities of this hypervisor.
- */
-virCapsPtr
-xenHypervisorMakeCapabilities(virConnectPtr conn)
-{
-#ifdef __sun
-    return xenHypervisorMakeCapabilitiesSunOS(conn);
-#else
-    virCapsPtr caps;
-    FILE *cpuinfo, *capabilities;
-    struct utsname utsname;
-
-    /* Really, this never fails - look at the man-page. */
-    uname (&utsname);
-
-    cpuinfo = fopen ("/proc/cpuinfo", "r");
-    if (cpuinfo == NULL) {
-        if (errno != ENOENT) {
-            virReportSystemError(conn, errno,
-                                 _("cannot read file %s"),
-                                 "/proc/cpuinfo");
-            return NULL;
-        }
-    }
-
-    capabilities = fopen ("/sys/hypervisor/properties/capabilities", "r");
-    if (capabilities == NULL) {
-        if (errno != ENOENT) {
-            fclose(cpuinfo);
-            virReportSystemError(conn, errno,
-                                 _("cannot read file %s"),
-                                 "/sys/hypervisor/properties/capabilities");
-            return NULL;
-        }
-    }
-
-    caps = xenHypervisorMakeCapabilitiesInternal(conn,
-                                                 utsname.machine,
-                                                 cpuinfo,
-                                                 capabilities);
-
-    if (cpuinfo)
-        fclose(cpuinfo);
-    if (capabilities)
-        fclose(capabilities);
-
-    return caps;
-#endif /* __sun */
-}
-
-
-
-/**
- * xenHypervisorGetCapabilities:
- * @conn: pointer to the connection block
- *
- * Return the capabilities of this hypervisor.
- */
-char *
-xenHypervisorGetCapabilities (virConnectPtr conn)
-{
-    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
-    char *xml;
-
-    if (!(xml = virCapabilitiesFormatXML(priv->caps))) {
-        virReportOOMError(conn);
-        return NULL;
-    }
-
-    return xml;
-}
-
-
-/**
- * xenHypervisorNumOfDomains:
- * @conn: pointer to the connection block
- *
- * Provides the number of active domains.
- *
- * Returns the number of domain found or -1 in case of error
- */
-int
-xenHypervisorNumOfDomains(virConnectPtr conn)
-{
-    xen_getdomaininfolist dominfos;
-    int ret, nbids;
-    static int last_maxids = 2;
-    int maxids = last_maxids;
-    xenUnifiedPrivatePtr priv;
-
-    if (conn == NULL)
-        return -1;
-    priv = (xenUnifiedPrivatePtr) conn->privateData;
-    if (priv->handle < 0)
-        return (-1);
-
- retry:
-    if (!(XEN_GETDOMAININFOLIST_ALLOC(dominfos, maxids))) {
-        virReportOOMError(conn);
-        return(-1);
-    }
-
-    XEN_GETDOMAININFOLIST_CLEAR(dominfos, maxids);
-
-    ret = virXen_getdomaininfolist(priv->handle, 0, maxids, &dominfos);
-
-    XEN_GETDOMAININFOLIST_FREE(dominfos);
-
-    if (ret < 0)
-        return (-1);
-
-    nbids = ret;
-    /* Can't possibly have more than 65,000 concurrent guests
-     * so limit how many times we try, to avoid increasing
-     * without bound & thus allocating all of system memory !
-     * XXX I'll regret this comment in a few years time ;-)
-     */
-    if (nbids == maxids) {
-        if (maxids < 65000) {
-            last_maxids *= 2;
-            maxids *= 2;
-            goto retry;
-        }
-        nbids = -1;
-    }
-    if ((nbids < 0) || (nbids > maxids))
-        return(-1);
-    return(nbids);
-}
-
-/**
- * xenHypervisorListDomains:
- * @conn: pointer to the connection block
- * @ids: array to collect the list of IDs of active domains
- * @maxids: size of @ids
- *
- * Collect the list of active domains, and store their ID in @maxids
- *
- * Returns the number of domain found or -1 in case of error
- */
-int
-xenHypervisorListDomains(virConnectPtr conn, int *ids, int maxids)
-{
-    xen_getdomaininfolist dominfos;
-    int ret, nbids, i;
-    xenUnifiedPrivatePtr priv;
-
-    if (conn == NULL)
-        return -1;
-
-    priv = (xenUnifiedPrivatePtr) conn->privateData;
-    if (priv->handle < 0 ||
-        (ids == NULL) || (maxids < 0))
-        return (-1);
-
-    if (maxids == 0)
-        return(0);
-
-    if (!(XEN_GETDOMAININFOLIST_ALLOC(dominfos, maxids))) {
-        virReportOOMError(conn);
-        return(-1);
-    }
-
-    XEN_GETDOMAININFOLIST_CLEAR(dominfos, maxids);
-    memset(ids, 0, maxids * sizeof(int));
-
-    ret = virXen_getdomaininfolist(priv->handle, 0, maxids, &dominfos);
-
-    if (ret < 0) {
-        XEN_GETDOMAININFOLIST_FREE(dominfos);
-        return (-1);
-    }
-
-    nbids = ret;
-    if ((nbids < 0) || (nbids > maxids)) {
-        XEN_GETDOMAININFOLIST_FREE(dominfos);
-        return(-1);
-    }
-
-    for (i = 0;i < nbids;i++) {
-        ids[i] = XEN_GETDOMAININFOLIST_DOMAIN(dominfos, i);
-    }
-
-    XEN_GETDOMAININFOLIST_FREE(dominfos);
-    return (nbids);
-}
-
-
-#ifndef PROXY
-char *
-xenHypervisorDomainGetOSType (virDomainPtr dom)
-{
-    xenUnifiedPrivatePtr priv;
-    xen_getdomaininfo dominfo;
-
-    priv = (xenUnifiedPrivatePtr) dom->conn->privateData;
-    if (priv->handle < 0)
-        return (NULL);
-
-    /* HV's earlier than 3.1.0 don't include the HVM flags in guests status*/
-    if (hypervisor_version < 2 ||
-        dom_interface_version < 4)
-        return (NULL);
-
-    XEN_GETDOMAININFO_CLEAR(dominfo);
-
-    if (virXen_getdomaininfo(priv->handle, dom->id, &dominfo) < 0)
-        return (NULL);
-
-    if (XEN_GETDOMAININFO_DOMAIN(dominfo) != dom->id)
-        return (NULL);
-
-    if (XEN_GETDOMAININFO_FLAGS(dominfo) & DOMFLAGS_HVM)
-        return strdup("hvm");
-    return strdup("linux");
-}
-
-virDomainPtr
-xenHypervisorLookupDomainByID(virConnectPtr conn,
-                              int id)
-{
-    xenUnifiedPrivatePtr priv;
-    xen_getdomaininfo dominfo;
-    virDomainPtr ret;
-    char *name;
-
-    priv = (xenUnifiedPrivatePtr) conn->privateData;
-    if (priv->handle < 0)
-        return (NULL);
-
-    XEN_GETDOMAININFO_CLEAR(dominfo);
-
-    if (virXen_getdomaininfo(priv->handle, id, &dominfo) < 0)
-        return (NULL);
-
-    if (XEN_GETDOMAININFO_DOMAIN(dominfo) != id)
-        return (NULL);
-
-    xenUnifiedLock(priv);
-    name = xenStoreDomainGetName(conn, id);
-    xenUnifiedUnlock(priv);
-    if (!name)
-        return (NULL);
-
-    ret = virGetDomain(conn, name, XEN_GETDOMAININFO_UUID(dominfo));
-    if (ret)
-        ret->id = id;
-    VIR_FREE(name);
-    return ret;
-}
-
-
-virDomainPtr
-xenHypervisorLookupDomainByUUID(virConnectPtr conn,
-                                const unsigned char *uuid)
-{
-    xen_getdomaininfolist dominfos;
-    xenUnifiedPrivatePtr priv;
-    virDomainPtr ret;
-    char *name;
-    int maxids = 100, nids, i, id;
-
-    priv = (xenUnifiedPrivatePtr) conn->privateData;
-    if (priv->handle < 0)
-        return (NULL);
-
- retry:
-    if (!(XEN_GETDOMAININFOLIST_ALLOC(dominfos, maxids))) {
-        virReportOOMError(conn);
-        return(NULL);
-    }
-
-    XEN_GETDOMAININFOLIST_CLEAR(dominfos, maxids);
-
-    nids = virXen_getdomaininfolist(priv->handle, 0, maxids, &dominfos);
-
-    if (nids < 0) {
-        XEN_GETDOMAININFOLIST_FREE(dominfos);
-        return (NULL);
-    }
-
-    /* Can't possibly have more than 65,000 concurrent guests
-     * so limit how many times we try, to avoid increasing
-     * without bound & thus allocating all of system memory !
-     * XXX I'll regret this comment in a few years time ;-)
-     */
-    if (nids == maxids) {
-        XEN_GETDOMAININFOLIST_FREE(dominfos);
-        if (maxids < 65000) {
-            maxids *= 2;
-            goto retry;
-        }
-        return (NULL);
-    }
-
-    id = -1;
-    for (i = 0 ; i < nids ; i++) {
-        if (memcmp(XEN_GETDOMAININFOLIST_UUID(dominfos, i), uuid, VIR_UUID_BUFLEN) == 0) {
-            id = XEN_GETDOMAININFOLIST_DOMAIN(dominfos, i);
-            break;
-        }
-    }
-    XEN_GETDOMAININFOLIST_FREE(dominfos);
-
-    if (id == -1)
-        return (NULL);
-
-    xenUnifiedLock(priv);
-    name = xenStoreDomainGetName(conn, id);
-    xenUnifiedUnlock(priv);
-    if (!name)
-        return (NULL);
-
-    ret = virGetDomain(conn, name, uuid);
-    if (ret)
-        ret->id = id;
-    VIR_FREE(name);
-    return ret;
-}
-#endif
-
-/**
- * xenHypervisorGetMaxVcpus:
- *
- * Returns the maximum of CPU defined by Xen.
- */
-int
-xenHypervisorGetMaxVcpus(virConnectPtr conn,
-                         const char *type ATTRIBUTE_UNUSED)
-{
-    xenUnifiedPrivatePtr priv;
-
-    if (conn == NULL)
-        return -1;
-    priv = (xenUnifiedPrivatePtr) conn->privateData;
-    if (priv->handle < 0)
-        return (-1);
-
-    return MAX_VIRT_CPUS;
-}
-
-/**
- * xenHypervisorGetDomMaxMemory:
- * @conn: connection data
- * @id: domain id
- *
- * Retrieve the maximum amount of physical memory allocated to a
- * domain.
- *
- * Returns the memory size in kilobytes or 0 in case of error.
- */
-unsigned long
-xenHypervisorGetDomMaxMemory(virConnectPtr conn, int id)
-{
-    xenUnifiedPrivatePtr priv;
-    xen_getdomaininfo dominfo;
-    int ret;
-
-    if (conn == NULL)
-        return 0;
-
-    priv = (xenUnifiedPrivatePtr) conn->privateData;
-    if (priv->handle < 0)
-        return 0;
-
-    if (kb_per_pages == 0) {
-        kb_per_pages = sysconf(_SC_PAGESIZE) / 1024;
-        if (kb_per_pages <= 0)
-            kb_per_pages = 4;
-    }
-
-    XEN_GETDOMAININFO_CLEAR(dominfo);
-
-    ret = virXen_getdomaininfo(priv->handle, id, &dominfo);
-
-    if ((ret < 0) || (XEN_GETDOMAININFO_DOMAIN(dominfo) != id))
-        return (0);
-
-    return((unsigned long) XEN_GETDOMAININFO_MAX_PAGES(dominfo) * kb_per_pages);
-}
-
-#ifndef PROXY
-/**
- * xenHypervisorGetMaxMemory:
- * @domain: a domain object or NULL
- *
- * Retrieve the maximum amount of physical memory allocated to a
- * domain. If domain is NULL, then this get the amount of memory reserved
- * to Domain0 i.e. the domain where the application runs.
- *
- * Returns the memory size in kilobytes or 0 in case of error.
- */
-static unsigned long
-xenHypervisorGetMaxMemory(virDomainPtr domain)
-{
-    xenUnifiedPrivatePtr priv;
-
-    if ((domain == NULL) || (domain->conn == NULL))
-        return 0;
-
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-    if (priv->handle < 0 || domain->id < 0)
-        return (0);
-
-    return(xenHypervisorGetDomMaxMemory(domain->conn, domain->id));
-}
-#endif
-
-/**
- * xenHypervisorGetDomInfo:
- * @conn: connection data
- * @id: the domain ID
- * @info: the place where information should be stored
- *
- * Do an hypervisor call to get the related set of domain information.
- *
- * Returns 0 in case of success, -1 in case of error.
- */
-int
-xenHypervisorGetDomInfo(virConnectPtr conn, int id, virDomainInfoPtr info)
-{
-    xenUnifiedPrivatePtr priv;
-    xen_getdomaininfo dominfo;
-    int ret;
-    uint32_t domain_flags, domain_state, domain_shutdown_cause;
-
-    if (kb_per_pages == 0) {
-        kb_per_pages = sysconf(_SC_PAGESIZE) / 1024;
-        if (kb_per_pages <= 0)
-            kb_per_pages = 4;
-    }
-
-    if (conn == NULL)
-        return -1;
-
-    priv = (xenUnifiedPrivatePtr) conn->privateData;
-    if (priv->handle < 0 || info == NULL)
-        return (-1);
-
-    memset(info, 0, sizeof(virDomainInfo));
-    XEN_GETDOMAININFO_CLEAR(dominfo);
-
-    ret = virXen_getdomaininfo(priv->handle, id, &dominfo);
-
-    if ((ret < 0) || (XEN_GETDOMAININFO_DOMAIN(dominfo) != id))
-        return (-1);
-
-    domain_flags = XEN_GETDOMAININFO_FLAGS(dominfo);
-    domain_flags &= ~DOMFLAGS_HVM; /* Mask out HVM flags */
-    domain_state = domain_flags & 0xFF; /* Mask out high bits */
-    switch (domain_state) {
-        case DOMFLAGS_DYING:
-            info->state = VIR_DOMAIN_SHUTDOWN;
-            break;
-        case DOMFLAGS_SHUTDOWN:
-            /* The domain is shutdown.  Determine the cause. */
-            domain_shutdown_cause = domain_flags >> DOMFLAGS_SHUTDOWNSHIFT;
-            switch (domain_shutdown_cause) {
-                case SHUTDOWN_crash:
-                    info->state = VIR_DOMAIN_CRASHED;
-                    break;
-                default:
-                    info->state = VIR_DOMAIN_SHUTOFF;
-            }
-            break;
-        case DOMFLAGS_PAUSED:
-            info->state = VIR_DOMAIN_PAUSED;
-            break;
-        case DOMFLAGS_BLOCKED:
-            info->state = VIR_DOMAIN_BLOCKED;
-            break;
-        case DOMFLAGS_RUNNING:
-            info->state = VIR_DOMAIN_RUNNING;
-            break;
-        default:
-            info->state = VIR_DOMAIN_NOSTATE;
-    }
-
-    /*
-     * the API brings back the cpu time in nanoseconds,
-     * convert to microseconds, same thing convert to
-     * kilobytes from page counts
-     */
-    info->cpuTime = XEN_GETDOMAININFO_CPUTIME(dominfo);
-    info->memory = XEN_GETDOMAININFO_TOT_PAGES(dominfo) * kb_per_pages;
-    info->maxMem = XEN_GETDOMAININFO_MAX_PAGES(dominfo);
-    if(info->maxMem != UINT_MAX)
-        info->maxMem *= kb_per_pages;
-    info->nrVirtCpu = XEN_GETDOMAININFO_CPUCOUNT(dominfo);
-    return (0);
-}
-
-/**
- * xenHypervisorGetDomainInfo:
- * @domain: pointer to the domain block
- * @info: the place where information should be stored
- *
- * Do an hypervisor call to get the related set of domain information.
- *
- * Returns 0 in case of success, -1 in case of error.
- */
-int
-xenHypervisorGetDomainInfo(virDomainPtr domain, virDomainInfoPtr info)
-{
-    xenUnifiedPrivatePtr priv;
-
-    if ((domain == NULL) || (domain->conn == NULL))
-        return -1;
-
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-    if (priv->handle < 0 || info == NULL ||
-        (domain->id < 0))
-        return (-1);
-
-    return(xenHypervisorGetDomInfo(domain->conn, domain->id, info));
-
-}
-
-#ifndef PROXY
-/**
- * xenHypervisorNodeGetCellsFreeMemory:
- * @conn: pointer to the hypervisor connection
- * @freeMems: pointer to the array of unsigned long long
- * @startCell: index of first cell to return freeMems info on.
- * @maxCells: Maximum number of cells for which freeMems information can
- *            be returned.
- *
- * This call returns the amount of free memory in one or more NUMA cells.
- * The @freeMems array must be allocated by the caller and will be filled
- * with the amount of free memory in kilobytes for each cell requested,
- * starting with startCell (in freeMems[0]), up to either
- * (startCell + maxCells), or the number of additional cells in the node,
- * whichever is smaller.
- *
- * Returns the number of entries filled in freeMems, or -1 in case of error.
- */
-int
-xenHypervisorNodeGetCellsFreeMemory(virConnectPtr conn, unsigned long long *freeMems,
-                                    int startCell, int maxCells)
-{
-    xen_op_v2_sys op_sys;
-    int i, j, ret;
-    xenUnifiedPrivatePtr priv;
-
-    if (conn == NULL) {
-        virXenErrorFunc (conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
-                        "invalid argument", 0);
-        return -1;
-    }
-
-    priv = conn->privateData;
-
-    if (priv->nbNodeCells < 0) {
-        virXenErrorFunc (conn, VIR_ERR_XEN_CALL, __FUNCTION__,
-                         "cannot determine actual number of cells",0);
-        return(-1);
-    }
-
-    if ((maxCells < 1) || (startCell >= priv->nbNodeCells)) {
-        virXenErrorFunc (conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
-                        "invalid argument", 0);
-        return -1;
-    }
-
-    /*
-     * Support only sys_interface_version >=4
-     */
-    if (sys_interface_version < SYS_IFACE_MIN_VERS_NUMA) {
-        virXenErrorFunc (conn, VIR_ERR_XEN_CALL, __FUNCTION__,
-                        "unsupported in sys interface < 4", 0);
-        return -1;
-    }
-
-    if (priv->handle < 0) {
-        virXenErrorFunc (conn, VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
-                        "priv->handle invalid", 0);
-        return -1;
-    }
-
-    memset(&op_sys, 0, sizeof(op_sys));
-    op_sys.cmd = XEN_V2_OP_GETAVAILHEAP;
-
-    for (i = startCell, j = 0;(i < priv->nbNodeCells) && (j < maxCells);i++,j++) {
-        if (sys_interface_version >= 5)
-            op_sys.u.availheap5.node = i;
-        else
-            op_sys.u.availheap.node = i;
-        ret = xenHypervisorDoV2Sys(priv->handle, &op_sys);
-        if (ret < 0) {
-            return(-1);
-        }
-        if (sys_interface_version >= 5)
-            freeMems[j] = op_sys.u.availheap5.avail_bytes;
-        else
-            freeMems[j] = op_sys.u.availheap.avail_bytes;
-    }
-    return (j);
-}
-
-
-/**
- * xenHypervisorPauseDomain:
- * @domain: pointer to the domain block
- *
- * Do an hypervisor call to pause the given domain
- *
- * Returns 0 in case of success, -1 in case of error.
- */
-int
-xenHypervisorPauseDomain(virDomainPtr domain)
-{
-    int ret;
-    xenUnifiedPrivatePtr priv;
-
-    if ((domain == NULL) || (domain->conn == NULL))
-        return -1;
-
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-    if (priv->handle < 0 || domain->id < 0)
-        return (-1);
-
-    ret = virXen_pausedomain(priv->handle, domain->id);
-    if (ret < 0)
-        return (-1);
-    return (0);
-}
-
-/**
- * xenHypervisorResumeDomain:
- * @domain: pointer to the domain block
- *
- * Do an hypervisor call to resume the given domain
- *
- * Returns 0 in case of success, -1 in case of error.
- */
-int
-xenHypervisorResumeDomain(virDomainPtr domain)
-{
-    int ret;
-    xenUnifiedPrivatePtr priv;
-
-    if ((domain == NULL) || (domain->conn == NULL))
-        return -1;
-
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-    if (priv->handle < 0 || domain->id < 0)
-        return (-1);
-
-    ret = virXen_unpausedomain(priv->handle, domain->id);
-    if (ret < 0)
-        return (-1);
-    return (0);
-}
-
-/**
- * xenHypervisorDestroyDomain:
- * @domain: pointer to the domain block
- *
- * Do an hypervisor call to destroy the given domain
- *
- * Returns 0 in case of success, -1 in case of error.
- */
-int
-xenHypervisorDestroyDomain(virDomainPtr domain)
-{
-    int ret;
-    xenUnifiedPrivatePtr priv;
-
-    if (domain == NULL || domain->conn == NULL)
-        return -1;
-
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-    if (priv->handle < 0 || domain->id < 0)
-        return (-1);
-
-    ret = virXen_destroydomain(priv->handle, domain->id);
-    if (ret < 0)
-        return (-1);
-    return (0);
-}
-
-/**
- * xenHypervisorSetMaxMemory:
- * @domain: pointer to the domain block
- * @memory: the max memory size in kilobytes.
- *
- * Do an hypervisor call to change the maximum amount of memory used
- *
- * Returns 0 in case of success, -1 in case of error.
- */
-int
-xenHypervisorSetMaxMemory(virDomainPtr domain, unsigned long memory)
-{
-    int ret;
-    xenUnifiedPrivatePtr priv;
-
-    if (domain == NULL || domain->conn == NULL)
-        return -1;
-
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-    if (priv->handle < 0 || domain->id < 0)
-        return (-1);
-
-    ret = virXen_setmaxmem(priv->handle, domain->id, memory);
-    if (ret < 0)
-        return (-1);
-    return (0);
-}
-#endif /* PROXY */
-
-#ifndef PROXY
-/**
- * xenHypervisorSetVcpus:
- * @domain: pointer to domain object
- * @nvcpus: the new number of virtual CPUs for this domain
- *
- * Dynamically change the number of virtual CPUs used by the domain.
- *
- * Returns 0 in case of success, -1 in case of failure.
- */
-
-int
-xenHypervisorSetVcpus(virDomainPtr domain, unsigned int nvcpus)
-{
-    int ret;
-    xenUnifiedPrivatePtr priv;
-
-    if (domain == NULL || domain->conn == NULL)
-        return -1;
-
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-    if (priv->handle < 0 || domain->id < 0 || nvcpus < 1)
-        return (-1);
-
-    ret = virXen_setmaxvcpus(priv->handle, domain->id, nvcpus);
-    if (ret < 0)
-        return (-1);
-    return (0);
-}
-
-/**
- * xenHypervisorPinVcpu:
- * @domain: pointer to domain object
- * @vcpu: virtual CPU number
- * @cpumap: pointer to a bit map of real CPUs (in 8-bit bytes)
- * @maplen: length of cpumap in bytes
- *
- * Dynamically change the real CPUs which can be allocated to a virtual CPU.
- *
- * Returns 0 in case of success, -1 in case of failure.
- */
-
-int
-xenHypervisorPinVcpu(virDomainPtr domain, unsigned int vcpu,
-                     unsigned char *cpumap, int maplen)
-{
-    int ret;
-    xenUnifiedPrivatePtr priv;
-
-    if (domain == NULL || domain->conn == NULL)
-        return -1;
-
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-    if (priv->handle < 0 || (domain->id < 0) ||
-        (cpumap == NULL) || (maplen < 1))
-        return (-1);
-
-    ret = virXen_setvcpumap(priv->handle, domain->id, vcpu,
-                            cpumap, maplen);
-    if (ret < 0)
-        return (-1);
-    return (0);
-}
-#endif
-
-/**
- * virDomainGetVcpus:
- * @domain: pointer to domain object, or NULL for Domain0
- * @info: pointer to an array of virVcpuInfo structures (OUT)
- * @maxinfo: number of structures in info array
- * @cpumaps: pointer to an bit map of real CPUs for all vcpus of this domain (in 8-bit bytes) (OUT)
- *     If cpumaps is NULL, then no cpumap information is returned by the API.
- *     It's assumed there is <maxinfo> cpumap in cpumaps array.
- *     The memory allocated to cpumaps must be (maxinfo * maplen) bytes
- *     (ie: calloc(maxinfo, maplen)).
- *     One cpumap inside cpumaps has the format described in virDomainPinVcpu() API.
- * @maplen: number of bytes in one cpumap, from 1 up to size of CPU map in
- *     underlying virtualization system (Xen...).
- *
- * Extract information about virtual CPUs of domain, store it in info array
- * and also in cpumaps if this pointer isn't NULL.
- *
- * Returns the number of info filled in case of success, -1 in case of failure.
- */
-#ifndef PROXY
-int
-xenHypervisorGetVcpus(virDomainPtr domain, virVcpuInfoPtr info, int maxinfo,
-                      unsigned char *cpumaps, int maplen)
-{
-    xen_getdomaininfo dominfo;
-    int ret;
-    xenUnifiedPrivatePtr priv;
-    virVcpuInfoPtr ipt;
-    int nbinfo, i;
-
-    if (domain == NULL || domain->conn == NULL)
-        return -1;
-
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-    if (priv->handle < 0 || (domain->id < 0) ||
-        (info == NULL) || (maxinfo < 1) ||
-        (sizeof(cpumap_t) & 7))
-        return (-1);
-    if ((cpumaps != NULL) && (maplen < 1))
-        return -1;
-
-    /* first get the number of virtual CPUs in this domain */
-    XEN_GETDOMAININFO_CLEAR(dominfo);
-    ret = virXen_getdomaininfo(priv->handle, domain->id,
-                               &dominfo);
-
-    if ((ret < 0) || (XEN_GETDOMAININFO_DOMAIN(dominfo) != domain->id))
-        return (-1);
-    nbinfo = XEN_GETDOMAININFO_CPUCOUNT(dominfo) + 1;
-    if (nbinfo > maxinfo) nbinfo = maxinfo;
-
-    if (cpumaps != NULL)
-        memset(cpumaps, 0, maxinfo * maplen);
-
-    for (i = 0, ipt = info; i < nbinfo; i++, ipt++) {
-        if ((cpumaps != NULL) && (i < maxinfo)) {
-            ret = virXen_getvcpusinfo(priv->handle, domain->id, i,
-                                      ipt,
-                                      (unsigned char *)VIR_GET_CPUMAP(cpumaps, maplen, i),
-                                      maplen);
-            if (ret < 0)
-                return(-1);
-        } else {
-            ret = virXen_getvcpusinfo(priv->handle, domain->id, i,
-                                      ipt, NULL, 0);
-            if (ret < 0)
-                return(-1);
-        }
-    }
-    return nbinfo;
-}
-#endif /* PROXY */
-
-/**
- * xenHypervisorGetVcpuMax:
- *
- *  Returns the maximum number of virtual CPUs supported for
- *  the guest VM. If the guest is inactive, this is the maximum
- *  of CPU defined by Xen. If the guest is running this reflect
- *  the maximum number of virtual CPUs the guest was booted with.
- */
-int
-xenHypervisorGetVcpuMax(virDomainPtr domain)
-{
-    xen_getdomaininfo dominfo;
-    int ret;
-    int maxcpu;
-    xenUnifiedPrivatePtr priv;
-
-    if (domain == NULL || domain->conn == NULL)
-        return -1;
-
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-    if (priv->handle < 0)
-        return (-1);
-
-    /* inactive domain */
-    if (domain->id < 0) {
-        maxcpu = MAX_VIRT_CPUS;
-    } else {
-        XEN_GETDOMAININFO_CLEAR(dominfo);
-        ret = virXen_getdomaininfo(priv->handle, domain->id,
-                                   &dominfo);
-
-        if ((ret < 0) || (XEN_GETDOMAININFO_DOMAIN(dominfo) != domain->id))
-            return (-1);
-        maxcpu = XEN_GETDOMAININFO_MAXCPUID(dominfo) + 1;
-    }
-
-    return maxcpu;
-}
-
-/**
- * xenHavePrivilege()
- *
- * Return true if the current process should be able to connect to Xen.
- */
-int
-xenHavePrivilege()
-{
-#ifdef __sun
-    return priv_ineffect (PRIV_XVM_CONTROL);
-#else
-    return access(XEN_HYPERVISOR_SOCKET, R_OK) == 0;
-#endif
-}
diff --git a/src/xen_internal.h b/src/xen_internal.h
deleted file mode 100644 (file)
index 766f676..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * xen_internal.h: internal API for direct access to Xen hypervisor level
- *
- * Copyright (C) 2005 Red Hat, Inc.
- *
- * See COPYING.LIB for the License of this software
- *
- * Daniel Veillard <veillard@redhat.com>
- */
-
-#ifndef __VIR_XEN_INTERNAL_H__
-#define __VIR_XEN_INTERNAL_H__
-
-#include <libxml/uri.h>
-
-#include "internal.h"
-#include "capabilities.h"
-#include "driver.h"
-
-extern struct xenUnifiedDriver xenHypervisorDriver;
-int    xenHypervisorInit                 (void);
-
-virCapsPtr xenHypervisorMakeCapabilities (virConnectPtr conn);
-
-/* The following calls are made directly by the Xen proxy: */
-
-virDomainPtr
-        xenHypervisorLookupDomainByID   (virConnectPtr conn,
-                                         int id);
-virDomainPtr
-        xenHypervisorLookupDomainByUUID (virConnectPtr conn,
-                                         const unsigned char *uuid);
-char *
-        xenHypervisorDomainGetOSType    (virDomainPtr dom);
-
-virDrvOpenStatus
-        xenHypervisorOpen               (virConnectPtr conn,
-                                         virConnectAuthPtr auth,
-                                         int flags);
-int     xenHypervisorClose              (virConnectPtr conn);
-int     xenHypervisorGetVersion         (virConnectPtr conn,
-                                         unsigned long *hvVer);
-virCapsPtr
-        xenHypervisorMakeCapabilitiesInternal(virConnectPtr conn,
-                                              const char *hostmachine,
-                                              FILE *cpuinfo,
-                                              FILE *capabilities);
-char *
-        xenHypervisorGetCapabilities    (virConnectPtr conn);
-unsigned long
-        xenHypervisorGetDomMaxMemory    (virConnectPtr conn,
-                                         int id);
-int     xenHypervisorNumOfDomains       (virConnectPtr conn);
-int     xenHypervisorListDomains        (virConnectPtr conn,
-                                         int *ids,
-                                         int maxids);
-int     xenHypervisorGetMaxVcpus        (virConnectPtr conn,
-                                         const char *type);
-int     xenHypervisorDestroyDomain      (virDomainPtr domain);
-int     xenHypervisorResumeDomain       (virDomainPtr domain);
-int     xenHypervisorPauseDomain        (virDomainPtr domain);
-int     xenHypervisorGetDomainInfo        (virDomainPtr domain,
-                                         virDomainInfoPtr info);
-int     xenHypervisorGetDomInfo         (virConnectPtr conn,
-                                         int id,
-                                         virDomainInfoPtr info);
-int     xenHypervisorSetMaxMemory       (virDomainPtr domain,
-                                         unsigned long memory);
-int     xenHypervisorCheckID            (virConnectPtr conn,
-                                         int id);
-int     xenHypervisorSetVcpus           (virDomainPtr domain,
-                                         unsigned int nvcpus);
-int     xenHypervisorPinVcpu            (virDomainPtr domain,
-                                         unsigned int vcpu,
-                                         unsigned char *cpumap,
-                                         int maplen);
-int     xenHypervisorGetVcpus           (virDomainPtr domain,
-                                         virVcpuInfoPtr info,
-                                         int maxinfo,
-                                         unsigned char *cpumaps,
-                                         int maplen);
-int     xenHypervisorGetVcpuMax         (virDomainPtr domain);
-
-char *  xenHypervisorGetSchedulerType   (virDomainPtr domain,
-                                         int *nparams);
-
-int     xenHypervisorGetSchedulerParameters(virDomainPtr domain,
-                                         virSchedParameterPtr params,
-                                         int *nparams);
-
-int     xenHypervisorSetSchedulerParameters(virDomainPtr domain,
-                                         virSchedParameterPtr params,
-                                         int nparams);
-
-int     xenHypervisorDomainBlockStats   (virDomainPtr domain,
-                                         const char *path,
-                                         struct _virDomainBlockStats *stats);
-int     xenHypervisorDomainInterfaceStats (virDomainPtr domain,
-                                         const char *path,
-                                         struct _virDomainInterfaceStats *stats);
-
-int     xenHypervisorNodeGetCellsFreeMemory(virConnectPtr conn,
-                                          unsigned long long *freeMems,
-                                          int startCell,
-                                          int maxCells);
-
-int    xenHavePrivilege(void);
-
-#endif                          /* __VIR_XEN_INTERNAL_H__ */
diff --git a/src/xen_unified.c b/src/xen_unified.c
deleted file mode 100644 (file)
index dfa9ca5..0000000
+++ /dev/null
@@ -1,1917 +0,0 @@
-/*
- * xen_unified.c: Unified Xen driver.
- *
- * Copyright (C) 2007, 2008, 2009 Red Hat, Inc.
- *
- * See COPYING.LIB for the License of this software
- *
- * Richard W.M. Jones <rjones@redhat.com>
- */
-
-#include <config.h>
-
-/* Note:
- *
- * This driver provides a unified interface to the five
- * separate underlying Xen drivers (xen_internal, proxy_internal,
- * xend_internal, xs_internal and xm_internal).  Historically
- * the body of libvirt.c handled the five Xen drivers,
- * and contained Xen-specific code.
- */
-
-#include <stdint.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <xen/dom0_ops.h>
-#include <libxml/uri.h>
-
-#include "virterror_internal.h"
-#include "logging.h"
-#include "datatypes.h"
-#include "xen_unified.h"
-
-#include "xen_internal.h"
-#include "proxy_internal.h"
-#include "xend_internal.h"
-#include "xs_internal.h"
-#include "xm_internal.h"
-#if WITH_XEN_INOTIFY
-#include "xen_inotify.h"
-#endif
-#include "xml.h"
-#include "util.h"
-#include "memory.h"
-#include "node_device_conf.h"
-#include "pci.h"
-
-#define VIR_FROM_THIS VIR_FROM_XEN
-
-static int
-xenUnifiedNodeGetInfo (virConnectPtr conn, virNodeInfoPtr info);
-static int
-xenUnifiedDomainGetMaxVcpus (virDomainPtr dom);
-static int
-xenUnifiedDomainGetVcpus (virDomainPtr dom,
-                          virVcpuInfoPtr info, int maxinfo,
-                          unsigned char *cpumaps, int maplen);
-
-/* The five Xen drivers below us. */
-static struct xenUnifiedDriver const * const drivers[XEN_UNIFIED_NR_DRIVERS] = {
-    [XEN_UNIFIED_HYPERVISOR_OFFSET] = &xenHypervisorDriver,
-    [XEN_UNIFIED_PROXY_OFFSET] = &xenProxyDriver,
-    [XEN_UNIFIED_XEND_OFFSET] = &xenDaemonDriver,
-    [XEN_UNIFIED_XS_OFFSET] = &xenStoreDriver,
-    [XEN_UNIFIED_XM_OFFSET] = &xenXMDriver,
-#if WITH_XEN_INOTIFY
-    [XEN_UNIFIED_INOTIFY_OFFSET] = &xenInotifyDriver,
-#endif
-};
-
-static int inside_daemon;
-
-#define xenUnifiedError(conn, code, fmt...)                                  \
-        virReportErrorHelper(conn, VIR_FROM_XEN, code, __FILE__,           \
-                               __FUNCTION__, __LINE__, fmt)
-
-/**
- * xenNumaInit:
- * @conn: pointer to the hypervisor connection
- *
- * Initializer for previous variables. We currently assume that
- * the number of physical CPU and the number of NUMA cell is fixed
- * until reboot which might be false in future Xen implementations.
- */
-static void
-xenNumaInit(virConnectPtr conn) {
-    virNodeInfo nodeInfo;
-    xenUnifiedPrivatePtr priv;
-    int ret;
-
-    ret = xenUnifiedNodeGetInfo(conn, &nodeInfo);
-    if (ret < 0)
-        return;
-
-    priv = conn->privateData;
-
-    priv->nbNodeCells = nodeInfo.nodes;
-    priv->nbNodeCpus = nodeInfo.cpus;
-}
-
-
-/**
- * xenDomainUsedCpus:
- * @dom: the domain
- *
- * Analyze which set of CPUs are used by the domain and
- * return a string providing the ranges.
- *
- * Returns the string which needs to be freed by the caller or
- *         NULL if the domain uses all CPU or in case of error.
- */
-char *
-xenDomainUsedCpus(virDomainPtr dom)
-{
-    char *res = NULL;
-    int ncpus;
-    int nb_vcpu;
-    char *cpulist = NULL;
-    unsigned char *cpumap = NULL;
-    size_t cpumaplen;
-    int nb = 0;
-    int n, m;
-    virVcpuInfoPtr cpuinfo = NULL;
-    virNodeInfo nodeinfo;
-    xenUnifiedPrivatePtr priv;
-
-    if (!VIR_IS_CONNECTED_DOMAIN(dom))
-        return (NULL);
-
-    priv = dom->conn->privateData;
-
-    if (priv->nbNodeCpus <= 0)
-        return(NULL);
-    nb_vcpu = xenUnifiedDomainGetMaxVcpus(dom);
-    if (nb_vcpu <= 0)
-        return(NULL);
-    if (xenUnifiedNodeGetInfo(dom->conn, &nodeinfo) < 0)
-        return(NULL);
-
-    if (VIR_ALLOC_N(cpulist, priv->nbNodeCpus) < 0)
-        goto done;
-    if (VIR_ALLOC_N(cpuinfo, nb_vcpu) < 0)
-        goto done;
-    cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo));
-    if (xalloc_oversized(nb_vcpu, cpumaplen) ||
-        VIR_ALLOC_N(cpumap, nb_vcpu * cpumaplen) < 0)
-        goto done;
-
-    if ((ncpus = xenUnifiedDomainGetVcpus(dom, cpuinfo, nb_vcpu,
-                                          cpumap, cpumaplen)) >= 0) {
-        for (n = 0 ; n < ncpus ; n++) {
-            for (m = 0 ; m < priv->nbNodeCpus; m++) {
-                if ((cpulist[m] == 0) &&
-                    (VIR_CPU_USABLE(cpumap, cpumaplen, n, m))) {
-                    cpulist[m] = 1;
-                    nb++;
-                    /* if all CPU are used just return NULL */
-                    if (nb == priv->nbNodeCpus)
-                        goto done;
-
-                }
-            }
-        }
-        res = virDomainCpuSetFormat(dom->conn, cpulist, priv->nbNodeCpus);
-    }
-
-done:
-    VIR_FREE(cpulist);
-    VIR_FREE(cpumap);
-    VIR_FREE(cpuinfo);
-    return(res);
-}
-
-#ifdef WITH_LIBVIRTD
-
-static int
-xenInitialize (int privileged ATTRIBUTE_UNUSED)
-{
-    inside_daemon = 1;
-    return 0;
-}
-
-static virStateDriver state_driver = {
-    .initialize = xenInitialize,
-};
-
-#endif
-
-/*----- Dispatch functions. -----*/
-
-/* These dispatch functions follow the model used historically
- * by libvirt.c -- trying each low-level Xen driver in turn
- * until one succeeds.  However since we know what low-level
- * drivers can perform which functions, it is probably better
- * in future to optimise these dispatch functions to just call
- * the single function (or small number of appropriate functions)
- * in the low level drivers directly.
- */
-
-static int
-xenUnifiedProbe (void)
-{
-#ifdef __linux__
-    if (virFileExists("/proc/xen"))
-        return 1;
-#endif
-#ifdef __sun
-    FILE *fh;
-
-    if (fh = fopen("/dev/xen/domcaps", "r")) {
-        fclose(fh);
-        return 1;
-    }
-#endif
-    return 0;
-}
-
-static virDrvOpenStatus
-xenUnifiedOpen (virConnectPtr conn, virConnectAuthPtr auth, int flags)
-{
-    int i, ret = VIR_DRV_OPEN_DECLINED;
-    xenUnifiedPrivatePtr priv;
-    virDomainEventCallbackListPtr cbList;
-
-#ifdef __sun
-    /*
-     * Only the libvirtd instance can open this driver.
-     * Everything else falls back to the remote driver.
-     */
-    if (!inside_daemon)
-        return VIR_DRV_OPEN_DECLINED;
-#endif
-
-    if (conn->uri == NULL) {
-        if (!xenUnifiedProbe())
-            return VIR_DRV_OPEN_DECLINED;
-
-        conn->uri = xmlParseURI("xen:///");
-        if (!conn->uri) {
-            virReportOOMError (NULL);
-            return VIR_DRV_OPEN_ERROR;
-        }
-    } else {
-        if (conn->uri->scheme) {
-            /* Decline any scheme which isn't "xen://" or "http://". */
-            if (STRCASENEQ(conn->uri->scheme, "xen") &&
-                STRCASENEQ(conn->uri->scheme, "http"))
-                return VIR_DRV_OPEN_DECLINED;
-
-
-            /* Return an error if the path isn't '' or '/' */
-            if (conn->uri->path &&
-                STRNEQ(conn->uri->path, "") &&
-                STRNEQ(conn->uri->path, "/")) {
-                xenUnifiedError(NULL, VIR_ERR_INTERNAL_ERROR,
-                                _("unexpected Xen URI path '%s', try xen:///"),
-                                conn->uri->path);
-                return VIR_DRV_OPEN_ERROR;
-            }
-
-            /* Decline any xen:// URI with a server specified, allowing remote
-             * driver to handle, but keep any http:/// URIs */
-            if (STRCASEEQ(conn->uri->scheme, "xen") &&
-                conn->uri->server)
-                return VIR_DRV_OPEN_DECLINED;
-        } else {
-            /* Special case URI for Xen driver only:
-             *
-             * Treat a plain path as a Xen UNIX socket path, and give
-             * error unless path is absolute
-             */
-            if (!conn->uri->path || conn->uri->path[0] != '/') {
-                xenUnifiedError(NULL, VIR_ERR_INTERNAL_ERROR,
-                                _("unexpected Xen URI path '%s', try ///var/lib/xen/xend-socket"),
-                                NULLSTR(conn->uri->path));
-                return VIR_DRV_OPEN_ERROR;
-            }
-        }
-    }
-
-    /* We now know the URI is definitely for this driver, so beyond
-     * here, don't return DECLINED, always use ERROR */
-
-    /* Allocate per-connection private data. */
-    if (VIR_ALLOC(priv) < 0) {
-        virReportOOMError (NULL);
-        return VIR_DRV_OPEN_ERROR;
-    }
-    if (virMutexInit(&priv->lock) < 0) {
-        xenUnifiedError (NULL, VIR_ERR_INTERNAL_ERROR,
-                         "%s", _("cannot initialise mutex"));
-        VIR_FREE(priv);
-        return VIR_DRV_OPEN_ERROR;
-    }
-
-    /* Allocate callback list */
-    if (VIR_ALLOC(cbList) < 0) {
-        virReportOOMError (NULL);
-        virMutexDestroy(&priv->lock);
-        VIR_FREE(priv);
-        return VIR_DRV_OPEN_ERROR;
-    }
-    conn->privateData = priv;
-
-    priv->domainEventCallbacks = cbList;
-
-    priv->handle = -1;
-    priv->xendConfigVersion = -1;
-    priv->xshandle = NULL;
-    priv->proxy = -1;
-
-
-    /* Hypervisor is only run with privilege & required to succeed */
-    if (xenHavePrivilege()) {
-        DEBUG0("Trying hypervisor sub-driver");
-        if (drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->open(conn, auth, flags) ==
-            VIR_DRV_OPEN_SUCCESS) {
-            DEBUG0("Activated hypervisor sub-driver");
-            priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET] = 1;
-        }
-    }
-
-    /* XenD is required to succeed if privileged.
-     * If it fails as non-root, then the proxy driver may take over
-     */
-    DEBUG0("Trying XenD sub-driver");
-    if (drivers[XEN_UNIFIED_XEND_OFFSET]->open(conn, auth, flags) ==
-        VIR_DRV_OPEN_SUCCESS) {
-        DEBUG0("Activated XenD sub-driver");
-        priv->opened[XEN_UNIFIED_XEND_OFFSET] = 1;
-
-        /* XenD is active, so try the xm & xs drivers too, both requird to
-         * succeed if root, optional otherwise */
-        if (priv->xendConfigVersion <= 2) {
-            DEBUG0("Trying XM sub-driver");
-            if (drivers[XEN_UNIFIED_XM_OFFSET]->open(conn, auth, flags) ==
-                VIR_DRV_OPEN_SUCCESS) {
-                DEBUG0("Activated XM sub-driver");
-                priv->opened[XEN_UNIFIED_XM_OFFSET] = 1;
-            }
-        }
-        DEBUG0("Trying XS sub-driver");
-        if (drivers[XEN_UNIFIED_XS_OFFSET]->open(conn, auth, flags) ==
-            VIR_DRV_OPEN_SUCCESS) {
-            DEBUG0("Activated XS sub-driver");
-            priv->opened[XEN_UNIFIED_XS_OFFSET] = 1;
-        } else {
-            if (xenHavePrivilege())
-                goto fail; /* XS is mandatory when privileged */
-        }
-    } else {
-        if (xenHavePrivilege()) {
-            goto fail; /* XenD is mandatory when privileged */
-        } else {
-#if WITH_PROXY
-            DEBUG0("Trying proxy sub-driver");
-            if (drivers[XEN_UNIFIED_PROXY_OFFSET]->open(conn, auth, flags) ==
-                VIR_DRV_OPEN_SUCCESS) {
-                DEBUG0("Activated proxy sub-driver");
-                priv->opened[XEN_UNIFIED_PROXY_OFFSET] = 1;
-            } else {
-                goto fail; /* Proxy is mandatory if XenD failed */
-            }
-#else
-            DEBUG0("Handing off for remote driver");
-            ret = VIR_DRV_OPEN_DECLINED; /* Let remote_driver try instead */
-            goto clean;
-#endif
-        }
-    }
-
-    xenNumaInit(conn);
-
-    if (!(priv->caps = xenHypervisorMakeCapabilities(conn))) {
-        DEBUG0("Failed to make capabilities");
-        goto fail;
-    }
-
-#if WITH_XEN_INOTIFY
-    if (xenHavePrivilege()) {
-        DEBUG0("Trying Xen inotify sub-driver");
-        if (drivers[XEN_UNIFIED_INOTIFY_OFFSET]->open(conn, auth, flags) ==
-            VIR_DRV_OPEN_SUCCESS) {
-            DEBUG0("Activated Xen inotify sub-driver");
-            priv->opened[XEN_UNIFIED_INOTIFY_OFFSET] = 1;
-        }
-    }
-#endif
-
-    return VIR_DRV_OPEN_SUCCESS;
-
-fail:
-    ret = VIR_DRV_OPEN_ERROR;
-#ifndef WITH_PROXY
-clean:
-#endif
-    DEBUG0("Failed to activate a mandatory sub-driver");
-    for (i = 0 ; i < XEN_UNIFIED_NR_DRIVERS ; i++)
-        if (priv->opened[i]) drivers[i]->close(conn);
-    virMutexDestroy(&priv->lock);
-    VIR_FREE(priv);
-    conn->privateData = NULL;
-    return ret;
-}
-
-#define GET_PRIVATE(conn) \
-    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) (conn)->privateData
-
-static int
-xenUnifiedClose (virConnectPtr conn)
-{
-    GET_PRIVATE(conn);
-    int i;
-
-    virCapabilitiesFree(priv->caps);
-    virDomainEventCallbackListFree(priv->domainEventCallbacks);
-
-    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
-        if (priv->opened[i] && drivers[i]->close)
-            (void) drivers[i]->close (conn);
-
-    virMutexDestroy(&priv->lock);
-    VIR_FREE(conn->privateData);
-
-    return 0;
-}
-
-
-#define HV_VERSION ((DOM0_INTERFACE_VERSION >> 24) * 1000000 +         \
-                    ((DOM0_INTERFACE_VERSION >> 16) & 0xFF) * 1000 +   \
-                    (DOM0_INTERFACE_VERSION & 0xFFFF))
-
-unsigned long xenUnifiedVersion(void)
-{
-    return HV_VERSION;
-}
-
-
-static const char *
-xenUnifiedType (virConnectPtr conn)
-{
-    GET_PRIVATE(conn);
-    int i;
-
-    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
-        if (priv->opened[i])
-            return "Xen";
-
-    return NULL;
-}
-
-/* Which features are supported by this driver? */
-static int
-xenUnifiedSupportsFeature (virConnectPtr conn ATTRIBUTE_UNUSED, int feature)
-{
-    switch (feature) {
-    case VIR_DRV_FEATURE_MIGRATION_V1: return 1;
-    default: return 0;
-    }
-}
-
-static int
-xenUnifiedGetVersion (virConnectPtr conn, unsigned long *hvVer)
-{
-    GET_PRIVATE(conn);
-    int i;
-
-    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
-        if (priv->opened[i] &&
-            drivers[i]->version &&
-            drivers[i]->version (conn, hvVer) == 0)
-            return 0;
-
-    return -1;
-}
-
-/* NB: Even if connected to the proxy, we're still on the
- * same machine.
- */
-static char *
-xenUnifiedGetHostname (virConnectPtr conn)
-{
-    char *result;
-
-    result = virGetHostname();
-    if (result == NULL) {
-        virReportSystemError(conn, errno,
-                             "%s", _("cannot lookup hostname"));
-        return NULL;
-    }
-    /* Caller frees this string. */
-    return result;
-}
-
-static int
-xenUnifiedGetMaxVcpus (virConnectPtr conn, const char *type)
-{
-    GET_PRIVATE(conn);
-
-    if (type && STRCASENEQ (type, "Xen")) {
-        xenUnifiedError (conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return -1;
-    }
-
-    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET])
-        return xenHypervisorGetMaxVcpus (conn, type);
-    else {
-        xenUnifiedError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
-        return -1;
-    }
-}
-
-static int
-xenUnifiedNodeGetInfo (virConnectPtr conn, virNodeInfoPtr info)
-{
-    GET_PRIVATE(conn);
-    int i;
-
-    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
-        if (priv->opened[i] &&
-            drivers[i]->nodeGetInfo &&
-            drivers[i]->nodeGetInfo (conn, info) == 0)
-            return 0;
-
-    return -1;
-}
-
-static char *
-xenUnifiedGetCapabilities (virConnectPtr conn)
-{
-    xenUnifiedPrivatePtr priv = conn->privateData;
-    char *xml;
-
-    if (!(xml = virCapabilitiesFormatXML(priv->caps))) {
-        virReportOOMError(conn);
-        return NULL;
-    }
-
-    return xml;
-}
-
-static int
-xenUnifiedListDomains (virConnectPtr conn, int *ids, int maxids)
-{
-    GET_PRIVATE(conn);
-    int ret;
-
-    /* Try xenstore. */
-    if (priv->opened[XEN_UNIFIED_XS_OFFSET]) {
-        ret = xenStoreListDomains (conn, ids, maxids);
-        if (ret >= 0) return ret;
-    }
-
-    /* Try HV. */
-    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET]) {
-        ret = xenHypervisorListDomains (conn, ids, maxids);
-        if (ret >= 0) return ret;
-    }
-
-    /* Try xend. */
-    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
-        ret = xenDaemonListDomains (conn, ids, maxids);
-        if (ret >= 0) return ret;
-    }
-
-    /* Try proxy. */
-    if (priv->opened[XEN_UNIFIED_PROXY_OFFSET]) {
-        ret = xenProxyListDomains (conn, ids, maxids);
-        if (ret >= 0) return ret;
-    }
-    return -1;
-}
-
-static int
-xenUnifiedNumOfDomains (virConnectPtr conn)
-{
-    GET_PRIVATE(conn);
-    int i, ret;
-
-    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
-        if (priv->opened[i] && drivers[i]->numOfDomains) {
-            ret = drivers[i]->numOfDomains (conn);
-            if (ret >= 0) return ret;
-        }
-
-    return -1;
-}
-
-static virDomainPtr
-xenUnifiedDomainCreateXML (virConnectPtr conn,
-                           const char *xmlDesc, unsigned int flags)
-{
-    GET_PRIVATE(conn);
-    int i;
-    virDomainPtr ret;
-
-    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
-        if (priv->opened[i] && drivers[i]->domainCreateXML) {
-            ret = drivers[i]->domainCreateXML (conn, xmlDesc, flags);
-            if (ret) return ret;
-        }
-
-    return NULL;
-}
-
-/* Assumption made in underlying drivers:
- * If the domain is "not found" and there is no other error, then
- * the Lookup* functions return a NULL but do not set virterror.
- */
-static virDomainPtr
-xenUnifiedDomainLookupByID (virConnectPtr conn, int id)
-{
-    GET_PRIVATE(conn);
-    virDomainPtr ret;
-
-    /* Reset any connection-level errors in virterror first, in case
-     * there is one hanging around from a previous call.
-     */
-    virConnResetLastError (conn);
-
-    /* Try hypervisor/xenstore combo. */
-    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET]) {
-        ret = xenHypervisorLookupDomainByID (conn, id);
-        if (ret || conn->err.code != VIR_ERR_OK)
-            return ret;
-    }
-
-    /* Try proxy. */
-    if (priv->opened[XEN_UNIFIED_PROXY_OFFSET]) {
-        ret = xenProxyLookupByID (conn, id);
-        if (ret || conn->err.code != VIR_ERR_OK)
-            return ret;
-    }
-
-    /* Try xend. */
-    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
-        ret = xenDaemonLookupByID (conn, id);
-        if (ret || conn->err.code != VIR_ERR_OK)
-            return ret;
-    }
-
-    /* Not found. */
-    xenUnifiedError (conn, VIR_ERR_NO_DOMAIN, __FUNCTION__);
-    return NULL;
-}
-
-static virDomainPtr
-xenUnifiedDomainLookupByUUID (virConnectPtr conn,
-                              const unsigned char *uuid)
-{
-    GET_PRIVATE(conn);
-    virDomainPtr ret;
-
-    /* Reset any connection-level errors in virterror first, in case
-     * there is one hanging around from a previous call.
-     */
-    virConnResetLastError (conn);
-
-    /* Try hypervisor/xenstore combo. */
-    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET]) {
-        ret = xenHypervisorLookupDomainByUUID (conn, uuid);
-        if (ret || conn->err.code != VIR_ERR_OK)
-            return ret;
-    }
-
-    /* Try proxy. */
-    if (priv->opened[XEN_UNIFIED_PROXY_OFFSET]) {
-        ret = xenProxyLookupByUUID (conn, uuid);
-        if (ret || conn->err.code != VIR_ERR_OK)
-            return ret;
-    }
-
-    /* Try xend. */
-    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
-        ret = xenDaemonLookupByUUID (conn, uuid);
-        if (ret || conn->err.code != VIR_ERR_OK)
-            return ret;
-    }
-
-    /* Try XM for inactive domains. */
-    if (priv->opened[XEN_UNIFIED_XM_OFFSET]) {
-        ret = xenXMDomainLookupByUUID (conn, uuid);
-        if (ret || conn->err.code != VIR_ERR_OK)
-            return ret;
-    }
-
-    /* Not found. */
-    xenUnifiedError (conn, VIR_ERR_NO_DOMAIN, __FUNCTION__);
-    return NULL;
-}
-
-static virDomainPtr
-xenUnifiedDomainLookupByName (virConnectPtr conn,
-                              const char *name)
-{
-    GET_PRIVATE(conn);
-    virDomainPtr ret;
-
-    /* Reset any connection-level errors in virterror first, in case
-     * there is one hanging around from a previous call.
-     */
-    virConnResetLastError (conn);
-
-    /* Try proxy. */
-    if (priv->opened[XEN_UNIFIED_PROXY_OFFSET]) {
-        ret = xenProxyLookupByName (conn, name);
-        if (ret || conn->err.code != VIR_ERR_OK)
-            return ret;
-    }
-
-    /* Try xend. */
-    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
-        ret = xenDaemonLookupByName (conn, name);
-        if (ret || conn->err.code != VIR_ERR_OK)
-            return ret;
-    }
-
-    /* Try xenstore for inactive domains. */
-    if (priv->opened[XEN_UNIFIED_XS_OFFSET]) {
-        ret = xenStoreLookupByName (conn, name);
-        if (ret || conn->err.code != VIR_ERR_OK)
-            return ret;
-    }
-
-    /* Try XM for inactive domains. */
-    if (priv->opened[XEN_UNIFIED_XM_OFFSET]) {
-        ret = xenXMDomainLookupByName (conn, name);
-        if (ret || conn->err.code != VIR_ERR_OK)
-            return ret;
-    }
-
-    /* Not found. */
-    xenUnifiedError (conn, VIR_ERR_NO_DOMAIN, __FUNCTION__);
-    return NULL;
-}
-
-static int
-xenUnifiedDomainSuspend (virDomainPtr dom)
-{
-    GET_PRIVATE(dom->conn);
-    int i;
-
-    /* Try non-hypervisor methods first, then hypervisor direct method
-     * as a last resort.
-     */
-    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
-        if (i != XEN_UNIFIED_HYPERVISOR_OFFSET &&
-            priv->opened[i] &&
-            drivers[i]->domainSuspend &&
-            drivers[i]->domainSuspend (dom) == 0)
-            return 0;
-
-    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET] &&
-        drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->domainSuspend &&
-        drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->domainSuspend (dom) == 0)
-        return 0;
-
-    return -1;
-}
-
-static int
-xenUnifiedDomainResume (virDomainPtr dom)
-{
-    GET_PRIVATE(dom->conn);
-    int i;
-
-    /* Try non-hypervisor methods first, then hypervisor direct method
-     * as a last resort.
-     */
-    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
-        if (i != XEN_UNIFIED_HYPERVISOR_OFFSET &&
-            priv->opened[i] &&
-            drivers[i]->domainResume &&
-            drivers[i]->domainResume (dom) == 0)
-            return 0;
-
-    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET] &&
-        drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->domainResume &&
-        drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->domainResume (dom) == 0)
-        return 0;
-
-    return -1;
-}
-
-static int
-xenUnifiedDomainShutdown (virDomainPtr dom)
-{
-    GET_PRIVATE(dom->conn);
-    int i;
-
-    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
-        if (priv->opened[i] &&
-            drivers[i]->domainShutdown &&
-            drivers[i]->domainShutdown (dom) == 0)
-            return 0;
-
-    return -1;
-}
-
-static int
-xenUnifiedDomainReboot (virDomainPtr dom, unsigned int flags)
-{
-    GET_PRIVATE(dom->conn);
-    int i;
-
-    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
-        if (priv->opened[i] &&
-            drivers[i]->domainReboot &&
-            drivers[i]->domainReboot (dom, flags) == 0)
-            return 0;
-
-    return -1;
-}
-
-static int
-xenUnifiedDomainDestroy (virDomainPtr dom)
-{
-    GET_PRIVATE(dom->conn);
-    int i;
-
-    /* Try non-hypervisor methods first, then hypervisor direct method
-     * as a last resort.
-     */
-    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
-        if (i != XEN_UNIFIED_HYPERVISOR_OFFSET &&
-            priv->opened[i] &&
-            drivers[i]->domainDestroy &&
-            drivers[i]->domainDestroy (dom) == 0)
-            return 0;
-
-    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET] &&
-        drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->domainDestroy &&
-        drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->domainDestroy (dom) == 0)
-        return 0;
-
-    return -1;
-}
-
-static char *
-xenUnifiedDomainGetOSType (virDomainPtr dom)
-{
-    GET_PRIVATE(dom->conn);
-    int i;
-    char *ret;
-
-    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
-        if (priv->opened[i] && drivers[i]->domainGetOSType) {
-            ret = drivers[i]->domainGetOSType (dom);
-            if (ret) return ret;
-        }
-
-    return NULL;
-}
-
-static unsigned long
-xenUnifiedDomainGetMaxMemory (virDomainPtr dom)
-{
-    GET_PRIVATE(dom->conn);
-    int i;
-    unsigned long ret;
-
-    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
-        if (priv->opened[i] && drivers[i]->domainGetMaxMemory) {
-            ret = drivers[i]->domainGetMaxMemory (dom);
-            if (ret != 0) return ret;
-        }
-
-    return 0;
-}
-
-static int
-xenUnifiedDomainSetMaxMemory (virDomainPtr dom, unsigned long memory)
-{
-    GET_PRIVATE(dom->conn);
-    int i;
-
-    /* Prefer xend for setting max memory */
-    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
-        if (xenDaemonDomainSetMaxMemory (dom, memory) == 0)
-            return 0;
-    }
-
-    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
-        if (i != XEN_UNIFIED_XEND_OFFSET &&
-            priv->opened[i] &&
-            drivers[i]->domainSetMaxMemory &&
-            drivers[i]->domainSetMaxMemory (dom, memory) == 0)
-            return 0;
-
-    return -1;
-}
-
-static int
-xenUnifiedDomainSetMemory (virDomainPtr dom, unsigned long memory)
-{
-    GET_PRIVATE(dom->conn);
-    int i;
-
-    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
-        if (priv->opened[i] &&
-            drivers[i]->domainSetMemory &&
-            drivers[i]->domainSetMemory (dom, memory) == 0)
-            return 0;
-
-    return -1;
-}
-
-static int
-xenUnifiedDomainGetInfo (virDomainPtr dom, virDomainInfoPtr info)
-{
-    GET_PRIVATE(dom->conn);
-    int i;
-
-    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
-        if (priv->opened[i] &&
-            drivers[i]->domainGetInfo &&
-            drivers[i]->domainGetInfo (dom, info) == 0)
-            return 0;
-
-    return -1;
-}
-
-static int
-xenUnifiedDomainSave (virDomainPtr dom, const char *to)
-{
-    GET_PRIVATE(dom->conn);
-    int i;
-
-    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
-        if (priv->opened[i] &&
-            drivers[i]->domainSave &&
-            drivers[i]->domainSave (dom, to) == 0)
-            return 0;
-
-    return -1;
-}
-
-static int
-xenUnifiedDomainRestore (virConnectPtr conn, const char *from)
-{
-    GET_PRIVATE(conn);
-    int i;
-
-    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
-        if (priv->opened[i] &&
-            drivers[i]->domainRestore &&
-            drivers[i]->domainRestore (conn, from) == 0)
-            return 0;
-
-    return -1;
-}
-
-static int
-xenUnifiedDomainCoreDump (virDomainPtr dom, const char *to, int flags)
-{
-    GET_PRIVATE(dom->conn);
-    int i;
-
-    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
-        if (priv->opened[i] &&
-            drivers[i]->domainCoreDump &&
-            drivers[i]->domainCoreDump (dom, to, flags) == 0)
-            return 0;
-
-    return -1;
-}
-
-static int
-xenUnifiedDomainSetVcpus (virDomainPtr dom, unsigned int nvcpus)
-{
-    GET_PRIVATE(dom->conn);
-    int i;
-
-    /* Try non-hypervisor methods first, then hypervisor direct method
-     * as a last resort.
-     */
-    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
-        if (i != XEN_UNIFIED_HYPERVISOR_OFFSET &&
-            priv->opened[i] &&
-            drivers[i]->domainSetVcpus &&
-            drivers[i]->domainSetVcpus (dom, nvcpus) == 0)
-            return 0;
-
-    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET] &&
-        drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->domainSetVcpus &&
-        drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->domainSetVcpus (dom, nvcpus) == 0)
-        return 0;
-
-    return -1;
-}
-
-static int
-xenUnifiedDomainPinVcpu (virDomainPtr dom, unsigned int vcpu,
-                         unsigned char *cpumap, int maplen)
-{
-    GET_PRIVATE(dom->conn);
-    int i;
-
-    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
-        if (priv->opened[i] &&
-            drivers[i]->domainPinVcpu &&
-            drivers[i]->domainPinVcpu (dom, vcpu, cpumap, maplen) == 0)
-            return 0;
-
-    return -1;
-}
-
-static int
-xenUnifiedDomainGetVcpus (virDomainPtr dom,
-                          virVcpuInfoPtr info, int maxinfo,
-                          unsigned char *cpumaps, int maplen)
-{
-    GET_PRIVATE(dom->conn);
-    int i, ret;
-
-    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
-        if (priv->opened[i] && drivers[i]->domainGetVcpus) {
-            ret = drivers[i]->domainGetVcpus (dom, info, maxinfo, cpumaps, maplen);
-            if (ret > 0)
-                return ret;
-        }
-    return -1;
-}
-
-static int
-xenUnifiedDomainGetMaxVcpus (virDomainPtr dom)
-{
-    GET_PRIVATE(dom->conn);
-    int i, ret;
-
-    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
-        if (priv->opened[i] && drivers[i]->domainGetMaxVcpus) {
-            ret = drivers[i]->domainGetMaxVcpus (dom);
-            if (ret != 0) return ret;
-        }
-
-    return -1;
-}
-
-static char *
-xenUnifiedDomainDumpXML (virDomainPtr dom, int flags)
-{
-    GET_PRIVATE(dom->conn);
-
-    if (dom->id == -1 && priv->xendConfigVersion < 3 ) {
-        if (priv->opened[XEN_UNIFIED_XM_OFFSET])
-            return xenXMDomainDumpXML(dom, flags);
-    } else {
-        if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
-            char *cpus, *res;
-            xenUnifiedLock(priv);
-            cpus = xenDomainUsedCpus(dom);
-            xenUnifiedUnlock(priv);
-            res = xenDaemonDomainDumpXML(dom, flags, cpus);
-            VIR_FREE(cpus);
-            return(res);
-        }
-        if (priv->opened[XEN_UNIFIED_PROXY_OFFSET])
-            return xenProxyDomainDumpXML(dom, flags);
-    }
-
-    xenUnifiedError (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
-    return NULL;
-}
-
-
-static char *
-xenUnifiedDomainXMLFromNative(virConnectPtr conn,
-                              const char *format,
-                              const char *config,
-                              unsigned int flags ATTRIBUTE_UNUSED)
-{
-    virDomainDefPtr def = NULL;
-    char *ret = NULL;
-    virConfPtr conf = NULL;
-    GET_PRIVATE(conn);
-
-    if (STRNEQ(format, XEN_CONFIG_FORMAT_XM) &&
-        STRNEQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
-        xenUnifiedError(conn, VIR_ERR_INVALID_ARG,
-                        _("unsupported config type %s"), format);
-        return NULL;
-    }
-
-    if (STREQ(format, XEN_CONFIG_FORMAT_XM)) {
-        conf = virConfReadMem(config, strlen(config), 0);
-        if (!conf)
-            goto cleanup;
-
-        def = xenXMDomainConfigParse(conn, conf);
-    } else if (STREQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
-        def = xenDaemonParseSxprString(conn, config, priv->xendConfigVersion);
-    }
-    if (!def)
-        goto cleanup;
-
-    ret = virDomainDefFormat(conn, def, 0);
-
-cleanup:
-    virDomainDefFree(def);
-    return ret;
-}
-
-
-#define MAX_CONFIG_SIZE (1024 * 65)
-static char *
-xenUnifiedDomainXMLToNative(virConnectPtr conn,
-                            const char *format,
-                            const char *xmlData,
-                            unsigned int flags ATTRIBUTE_UNUSED)
-{
-    virDomainDefPtr def = NULL;
-    char *ret = NULL;
-    virConfPtr conf = NULL;
-    GET_PRIVATE(conn);
-
-    if (STRNEQ(format, XEN_CONFIG_FORMAT_XM) &&
-        STRNEQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
-        xenUnifiedError(conn, VIR_ERR_INVALID_ARG,
-                        _("unsupported config type %s"), format);
-        goto cleanup;
-    }
-
-    if (!(def = virDomainDefParseString(conn,
-                                        priv->caps,
-                                        xmlData,
-                                        0)))
-        goto cleanup;
-
-    if (STREQ(format, XEN_CONFIG_FORMAT_XM)) {
-        int len = MAX_CONFIG_SIZE;
-        conf = xenXMDomainConfigFormat(conn, def);
-        if (!conf)
-            goto cleanup;
-
-        if (VIR_ALLOC_N(ret, len) < 0) {
-            virReportOOMError(conn);
-            goto cleanup;
-        }
-
-        if (virConfWriteMem(ret, &len, conf) < 0) {
-            VIR_FREE(ret);
-            goto cleanup;
-        }
-    } else if (STREQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
-        ret = xenDaemonFormatSxpr(conn, def, priv->xendConfigVersion);
-    }
-
-cleanup:
-    virDomainDefFree(def);
-    if (conf)
-        virConfFree(conf);
-    return ret;
-}
-
-
-static int
-xenUnifiedDomainMigratePrepare (virConnectPtr dconn,
-                                char **cookie,
-                                int *cookielen,
-                                const char *uri_in,
-                                char **uri_out,
-                                unsigned long flags,
-                                const char *dname,
-                                unsigned long resource)
-{
-    GET_PRIVATE(dconn);
-
-    if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
-        return xenDaemonDomainMigratePrepare (dconn, cookie, cookielen,
-                                              uri_in, uri_out,
-                                              flags, dname, resource);
-
-    xenUnifiedError (dconn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
-    return -1;
-}
-
-static int
-xenUnifiedDomainMigratePerform (virDomainPtr dom,
-                                const char *cookie,
-                                int cookielen,
-                                const char *uri,
-                                unsigned long flags,
-                                const char *dname,
-                                unsigned long resource)
-{
-    GET_PRIVATE(dom->conn);
-
-    if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
-        return xenDaemonDomainMigratePerform (dom, cookie, cookielen, uri,
-                                              flags, dname, resource);
-
-    xenUnifiedError (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
-    return -1;
-}
-
-static virDomainPtr
-xenUnifiedDomainMigrateFinish (virConnectPtr dconn,
-                               const char *dname,
-                               const char *cookie ATTRIBUTE_UNUSED,
-                               int cookielen ATTRIBUTE_UNUSED,
-                               const char *uri ATTRIBUTE_UNUSED,
-                               unsigned long flags ATTRIBUTE_UNUSED)
-{
-    return xenUnifiedDomainLookupByName (dconn, dname);
-}
-
-static int
-xenUnifiedListDefinedDomains (virConnectPtr conn, char **const names,
-                              int maxnames)
-{
-    GET_PRIVATE(conn);
-    int i;
-    int ret;
-
-    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
-        if (priv->opened[i] && drivers[i]->listDefinedDomains) {
-            ret = drivers[i]->listDefinedDomains (conn, names, maxnames);
-            if (ret >= 0) return ret;
-        }
-
-    return -1;
-}
-
-static int
-xenUnifiedNumOfDefinedDomains (virConnectPtr conn)
-{
-    GET_PRIVATE(conn);
-    int i;
-    int ret;
-
-    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
-        if (priv->opened[i] && drivers[i]->numOfDefinedDomains) {
-            ret = drivers[i]->numOfDefinedDomains (conn);
-            if (ret >= 0) return ret;
-        }
-
-    return -1;
-}
-
-static int
-xenUnifiedDomainCreate (virDomainPtr dom)
-{
-    GET_PRIVATE(dom->conn);
-    int i;
-
-    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
-        if (priv->opened[i] && drivers[i]->domainCreate &&
-            drivers[i]->domainCreate (dom) == 0)
-            return 0;
-
-    return -1;
-}
-
-static virDomainPtr
-xenUnifiedDomainDefineXML (virConnectPtr conn, const char *xml)
-{
-    GET_PRIVATE(conn);
-    int i;
-    virDomainPtr ret;
-
-    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
-        if (priv->opened[i] && drivers[i]->domainDefineXML) {
-            ret = drivers[i]->domainDefineXML (conn, xml);
-            if (ret) return ret;
-        }
-
-    return NULL;
-}
-
-static int
-xenUnifiedDomainUndefine (virDomainPtr dom)
-{
-    GET_PRIVATE(dom->conn);
-    int i;
-
-    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
-        if (priv->opened[i] && drivers[i]->domainUndefine &&
-            drivers[i]->domainUndefine (dom) == 0)
-            return 0;
-
-    return -1;
-}
-
-static int
-xenUnifiedDomainAttachDevice (virDomainPtr dom, const char *xml)
-{
-    GET_PRIVATE(dom->conn);
-    int i;
-
-    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
-        if (priv->opened[i] && drivers[i]->domainAttachDevice &&
-            drivers[i]->domainAttachDevice (dom, xml) == 0)
-            return 0;
-
-    return -1;
-}
-
-static int
-xenUnifiedDomainDetachDevice (virDomainPtr dom, const char *xml)
-{
-    GET_PRIVATE(dom->conn);
-    int i;
-
-    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
-        if (priv->opened[i] && drivers[i]->domainDetachDevice &&
-            drivers[i]->domainDetachDevice (dom, xml) == 0)
-            return 0;
-
-    return -1;
-}
-
-static int
-xenUnifiedDomainGetAutostart (virDomainPtr dom, int *autostart)
-{
-    GET_PRIVATE(dom->conn);
-
-    if (priv->xendConfigVersion < 3) {
-        if (priv->opened[XEN_UNIFIED_XM_OFFSET])
-            return xenXMDomainGetAutostart(dom, autostart);
-    } else {
-        if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
-            return xenDaemonDomainGetAutostart(dom, autostart);
-    }
-
-    xenUnifiedError (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
-    return -1;
-}
-
-static int
-xenUnifiedDomainSetAutostart (virDomainPtr dom, int autostart)
-{
-    GET_PRIVATE(dom->conn);
-
-    if (priv->xendConfigVersion < 3) {
-        if (priv->opened[XEN_UNIFIED_XM_OFFSET])
-            return xenXMDomainSetAutostart(dom, autostart);
-    } else {
-        if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
-            return xenDaemonDomainSetAutostart(dom, autostart);
-    }
-
-    xenUnifiedError (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
-    return -1;
-}
-
-static char *
-xenUnifiedDomainGetSchedulerType (virDomainPtr dom, int *nparams)
-{
-    GET_PRIVATE(dom->conn);
-    int i;
-    char *schedulertype;
-
-    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; i++) {
-        if (priv->opened[i] && drivers[i]->domainGetSchedulerType) {
-            schedulertype = drivers[i]->domainGetSchedulerType (dom, nparams);
-            if (schedulertype != NULL)
-                return(schedulertype);
-        }
-    }
-    return(NULL);
-}
-
-static int
-xenUnifiedDomainGetSchedulerParameters (virDomainPtr dom,
-                    virSchedParameterPtr params, int *nparams)
-{
-    GET_PRIVATE(dom->conn);
-    int i, ret;
-
-    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i) {
-        if (priv->opened[i] && drivers[i]->domainGetSchedulerParameters) {
-           ret = drivers[i]->domainGetSchedulerParameters(dom, params, nparams);
-           if (ret == 0)
-               return(0);
-        }
-    }
-    return(-1);
-}
-
-static int
-xenUnifiedDomainSetSchedulerParameters (virDomainPtr dom,
-                    virSchedParameterPtr params, int nparams)
-{
-    GET_PRIVATE(dom->conn);
-    int i, ret;
-
-    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i) {
-        if (priv->opened[i] && drivers[i]->domainSetSchedulerParameters) {
-           ret = drivers[i]->domainSetSchedulerParameters(dom, params, nparams);
-           if (ret == 0)
-               return 0;
-        }
-    }
-
-    return(-1);
-}
-
-static int
-xenUnifiedDomainBlockStats (virDomainPtr dom, const char *path,
-                            struct _virDomainBlockStats *stats)
-{
-    GET_PRIVATE (dom->conn);
-
-    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET])
-        return xenHypervisorDomainBlockStats (dom, path, stats);
-
-    xenUnifiedError (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
-    return -1;
-}
-
-static int
-xenUnifiedDomainInterfaceStats (virDomainPtr dom, const char *path,
-                                struct _virDomainInterfaceStats *stats)
-{
-    GET_PRIVATE (dom->conn);
-
-    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET])
-        return xenHypervisorDomainInterfaceStats (dom, path, stats);
-
-    xenUnifiedError (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
-    return -1;
-}
-
-static int
-xenUnifiedDomainBlockPeek (virDomainPtr dom, const char *path,
-                           unsigned long long offset, size_t size,
-                           void *buffer, unsigned int flags ATTRIBUTE_UNUSED)
-{
-    int r;
-    GET_PRIVATE (dom->conn);
-
-    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
-        r = xenDaemonDomainBlockPeek (dom, path, offset, size, buffer);
-        if (r != -2) return r;
-        /* r == -2 means declined, so fall through to XM driver ... */
-    }
-
-    if (priv->opened[XEN_UNIFIED_XM_OFFSET]) {
-        if (xenXMDomainBlockPeek (dom, path, offset, size, buffer) == 0)
-            return 0;
-    }
-
-    xenUnifiedError (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
-    return -1;
-}
-
-static int
-xenUnifiedNodeGetCellsFreeMemory (virConnectPtr conn, unsigned long long *freeMems,
-                                  int startCell, int maxCells)
-{
-    GET_PRIVATE (conn);
-
-    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET])
-        return xenHypervisorNodeGetCellsFreeMemory (conn, freeMems,
-                                                    startCell, maxCells);
-
-    xenUnifiedError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
-    return -1;
-}
-
-static unsigned long long
-xenUnifiedNodeGetFreeMemory (virConnectPtr conn)
-{
-    unsigned long long freeMem = 0;
-    int ret;
-    GET_PRIVATE (conn);
-
-    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET]) {
-        ret = xenHypervisorNodeGetCellsFreeMemory (conn, &freeMem,
-                                                    -1, 1);
-        if (ret != 1)
-            return (0);
-        return(freeMem);
-    }
-
-    xenUnifiedError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
-    return(0);
-}
-
-static int
-xenUnifiedDomainEventRegister (virConnectPtr conn,
-                               virConnectDomainEventCallback callback,
-                               void *opaque,
-                               void (*freefunc)(void *))
-{
-    GET_PRIVATE (conn);
-
-    int ret;
-    xenUnifiedLock(priv);
-
-    if (priv->xsWatch == -1) {
-        xenUnifiedError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
-        xenUnifiedUnlock(priv);
-        return -1;
-    }
-
-    ret = virDomainEventCallbackListAdd(conn, priv->domainEventCallbacks,
-                                        callback, opaque, freefunc);
-
-    if (ret == 0)
-        conn->refs++;
-
-    xenUnifiedUnlock(priv);
-    return (ret);
-}
-
-static int
-xenUnifiedDomainEventDeregister (virConnectPtr conn,
-                                 virConnectDomainEventCallback callback)
-{
-    int ret;
-    GET_PRIVATE (conn);
-    xenUnifiedLock(priv);
-
-    if (priv->xsWatch == -1) {
-        xenUnifiedError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
-        xenUnifiedUnlock(priv);
-        return -1;
-    }
-
-    if (priv->domainEventDispatching)
-        ret = virDomainEventCallbackListMarkDelete(conn, priv->domainEventCallbacks,
-                                                   callback);
-    else
-        ret = virDomainEventCallbackListRemove(conn, priv->domainEventCallbacks,
-                                               callback);
-
-    if (ret == 0)
-        virUnrefConnect(conn);
-
-    xenUnifiedUnlock(priv);
-    return ret;
-}
-
-
-static int
-xenUnifiedNodeDeviceGetPciInfo (virNodeDevicePtr dev,
-                           unsigned *domain,
-                           unsigned *bus,
-                           unsigned *slot,
-                           unsigned *function)
-{
-    virNodeDeviceDefPtr def = NULL;
-    virNodeDevCapsDefPtr cap;
-    char *xml = NULL;
-    int ret = -1;
-
-    xml = virNodeDeviceGetXMLDesc(dev, 0);
-    if (!xml)
-        goto out;
-
-    def = virNodeDeviceDefParseString(dev->conn, xml, EXISTING_DEVICE);
-    if (!def)
-        goto out;
-
-    cap = def->caps;
-    while (cap) {
-        if (cap->type == VIR_NODE_DEV_CAP_PCI_DEV) {
-            *domain   = cap->data.pci_dev.domain;
-            *bus      = cap->data.pci_dev.bus;
-            *slot     = cap->data.pci_dev.slot;
-            *function = cap->data.pci_dev.function;
-            break;
-        }
-
-        cap = cap->next;
-    }
-
-    if (!cap) {
-        xenUnifiedError(dev->conn, VIR_ERR_INVALID_ARG,
-                        _("device %s is not a PCI device"), dev->name);
-        goto out;
-    }
-
-    ret = 0;
-out:
-    virNodeDeviceDefFree(def);
-    VIR_FREE(xml);
-    return ret;
-}
-
-static int
-xenUnifiedNodeDeviceDettach (virNodeDevicePtr dev)
-{
-    pciDevice *pci;
-    unsigned domain, bus, slot, function;
-    int ret = -1;
-
-    if (xenUnifiedNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
-        return -1;
-
-    pci = pciGetDevice(dev->conn, domain, bus, slot, function);
-    if (!pci)
-        return -1;
-
-    if (pciDettachDevice(dev->conn, pci) < 0)
-        goto out;
-
-    ret = 0;
-out:
-    pciFreeDevice(dev->conn, pci);
-    return ret;
-}
-
-static int
-xenUnifiedNodeDeviceReAttach (virNodeDevicePtr dev)
-{
-    pciDevice *pci;
-    unsigned domain, bus, slot, function;
-    int ret = -1;
-
-    if (xenUnifiedNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
-        return -1;
-
-    pci = pciGetDevice(dev->conn, domain, bus, slot, function);
-    if (!pci)
-        return -1;
-
-    if (pciReAttachDevice(dev->conn, pci) < 0)
-        goto out;
-
-    ret = 0;
-out:
-    pciFreeDevice(dev->conn, pci);
-    return ret;
-}
-
-static int
-xenUnifiedNodeDeviceReset (virNodeDevicePtr dev)
-{
-    pciDevice *pci;
-    unsigned domain, bus, slot, function;
-    int ret = -1;
-
-    if (xenUnifiedNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
-        return -1;
-
-    pci = pciGetDevice(dev->conn, domain, bus, slot, function);
-    if (!pci)
-        return -1;
-
-    if (pciResetDevice(dev->conn, pci, NULL) < 0)
-        goto out;
-
-    ret = 0;
-out:
-    pciFreeDevice(dev->conn, pci);
-    return ret;
-}
-
-
-/*----- Register with libvirt.c, and initialise Xen drivers. -----*/
-
-/* The interface which we export upwards to libvirt.c. */
-static virDriver xenUnifiedDriver = {
-    VIR_DRV_XEN_UNIFIED,
-    "Xen",
-    xenUnifiedOpen, /* open */
-    xenUnifiedClose, /* close */
-    xenUnifiedSupportsFeature, /* supports_feature */
-    xenUnifiedType, /* type */
-    xenUnifiedGetVersion, /* version */
-    xenUnifiedGetHostname, /* getHostname */
-    xenUnifiedGetMaxVcpus, /* getMaxVcpus */
-    xenUnifiedNodeGetInfo, /* nodeGetInfo */
-    xenUnifiedGetCapabilities, /* getCapabilities */
-    xenUnifiedListDomains, /* listDomains */
-    xenUnifiedNumOfDomains, /* numOfDomains */
-    xenUnifiedDomainCreateXML, /* domainCreateXML */
-    xenUnifiedDomainLookupByID, /* domainLookupByID */
-    xenUnifiedDomainLookupByUUID, /* domainLookupByUUID */
-    xenUnifiedDomainLookupByName, /* domainLookupByName */
-    xenUnifiedDomainSuspend, /* domainSuspend */
-    xenUnifiedDomainResume, /* domainResume */
-    xenUnifiedDomainShutdown, /* domainShutdown */
-    xenUnifiedDomainReboot, /* domainReboot */
-    xenUnifiedDomainDestroy, /* domainDestroy */
-    xenUnifiedDomainGetOSType, /* domainGetOSType */
-    xenUnifiedDomainGetMaxMemory, /* domainGetMaxMemory */
-    xenUnifiedDomainSetMaxMemory, /* domainSetMaxMemory */
-    xenUnifiedDomainSetMemory, /* domainSetMemory */
-    xenUnifiedDomainGetInfo, /* domainGetInfo */
-    xenUnifiedDomainSave, /* domainSave */
-    xenUnifiedDomainRestore, /* domainRestore */
-    xenUnifiedDomainCoreDump, /* domainCoreDump */
-    xenUnifiedDomainSetVcpus, /* domainSetVcpus */
-    xenUnifiedDomainPinVcpu, /* domainPinVcpu */
-    xenUnifiedDomainGetVcpus, /* domainGetVcpus */
-    xenUnifiedDomainGetMaxVcpus, /* domainGetMaxVcpus */
-    NULL, /* domainGetSecurityLabel */
-    NULL, /* nodeGetSecurityModel */
-    xenUnifiedDomainDumpXML, /* domainDumpXML */
-    xenUnifiedDomainXMLFromNative, /* domainXmlFromNative */
-    xenUnifiedDomainXMLToNative, /* domainXmlToNative */
-    xenUnifiedListDefinedDomains, /* listDefinedDomains */
-    xenUnifiedNumOfDefinedDomains, /* numOfDefinedDomains */
-    xenUnifiedDomainCreate, /* domainCreate */
-    xenUnifiedDomainDefineXML, /* domainDefineXML */
-    xenUnifiedDomainUndefine, /* domainUndefine */
-    xenUnifiedDomainAttachDevice, /* domainAttachDevice */
-    xenUnifiedDomainDetachDevice, /* domainDetachDevice */
-    xenUnifiedDomainGetAutostart, /* domainGetAutostart */
-    xenUnifiedDomainSetAutostart, /* domainSetAutostart */
-    xenUnifiedDomainGetSchedulerType, /* domainGetSchedulerType */
-    xenUnifiedDomainGetSchedulerParameters, /* domainGetSchedulerParameters */
-    xenUnifiedDomainSetSchedulerParameters, /* domainSetSchedulerParameters */
-    xenUnifiedDomainMigratePrepare, /* domainMigratePrepare */
-    xenUnifiedDomainMigratePerform, /* domainMigratePerform */
-    xenUnifiedDomainMigrateFinish, /* domainMigrateFinish */
-    xenUnifiedDomainBlockStats, /* domainBlockStats */
-    xenUnifiedDomainInterfaceStats, /* domainInterfaceStats */
-    xenUnifiedDomainBlockPeek, /* domainBlockPeek */
-    NULL, /* domainMemoryPeek */
-    xenUnifiedNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */
-    xenUnifiedNodeGetFreeMemory, /* getFreeMemory */
-    xenUnifiedDomainEventRegister, /* domainEventRegister */
-    xenUnifiedDomainEventDeregister, /* domainEventDeregister */
-    NULL, /* domainMigratePrepare2 */
-    NULL, /* domainMigrateFinish2 */
-    xenUnifiedNodeDeviceDettach, /* nodeDeviceDettach */
-    xenUnifiedNodeDeviceReAttach, /* nodeDeviceReAttach */
-    xenUnifiedNodeDeviceReset, /* nodeDeviceReset */
-};
-
-/**
- * xenRegister:
- *
- * Register xen related drivers
- *
- * Returns the driver priority or -1 in case of error.
- */
-int
-xenRegister (void)
-{
-    /* Ignore failures here. */
-    (void) xenHypervisorInit ();
-
-#ifdef WITH_LIBVIRTD
-    if (virRegisterStateDriver (&state_driver) == -1) return -1;
-#endif
-
-    return virRegisterDriver (&xenUnifiedDriver);
-}
-
-/**
- * xenUnifiedDomainInfoListFree:
- *
- * Free the Domain Info List
- */
-void
-xenUnifiedDomainInfoListFree(xenUnifiedDomainInfoListPtr list)
-{
-    int i;
-
-    if (list == NULL)
-        return;
-
-    for (i=0; i<list->count; i++) {
-        VIR_FREE(list->doms[i]->name);
-        VIR_FREE(list->doms[i]);
-    }
-    VIR_FREE(list);
-}
-
-/**
- * xenUnifiedAddDomainInfo:
- *
- * Add name and uuid to the domain info list
- *
- * Returns: 0 on success, -1 on failure
- */
-int
-xenUnifiedAddDomainInfo(xenUnifiedDomainInfoListPtr list,
-                        int id, char *name,
-                        unsigned char *uuid)
-{
-    xenUnifiedDomainInfoPtr info;
-    int n;
-
-    /* check if we already have this callback on our list */
-    for (n=0; n < list->count; n++) {
-        if (STREQ(list->doms[n]->name, name) &&
-            !memcmp(list->doms[n]->uuid, uuid, VIR_UUID_BUFLEN)) {
-            DEBUG0("WARNING: dom already tracked");
-            return -1;
-        }
-    }
-
-    if (VIR_ALLOC(info) < 0)
-        goto memory_error;
-    if (!(info->name = strdup(name)))
-        goto memory_error;
-
-    memcpy(info->uuid, uuid, VIR_UUID_BUFLEN);
-    info->id = id;
-
-    /* Make space on list */
-    n = list->count;
-    if (VIR_REALLOC_N(list->doms, n + 1) < 0) {
-        goto memory_error;
-    }
-
-    list->doms[n] = info;
-    list->count++;
-    return 0;
-memory_error:
-    virReportOOMError (NULL);
-    if (info)
-        VIR_FREE(info->name);
-    VIR_FREE(info);
-    return -1;
-}
-
-/**
- * xenUnifiedRemoveDomainInfo:
- *
- * Removes name and uuid to the domain info list
- *
- * Returns: 0 on success, -1 on failure
- */
-int
-xenUnifiedRemoveDomainInfo(xenUnifiedDomainInfoListPtr list,
-                           int id, char *name,
-                           unsigned char *uuid)
-{
-    int i;
-    for (i = 0 ; i < list->count ; i++) {
-        if( list->doms[i]->id == id &&
-            STREQ(list->doms[i]->name, name) &&
-            !memcmp(list->doms[i]->uuid, uuid, VIR_UUID_BUFLEN)) {
-
-            VIR_FREE(list->doms[i]->name);
-            VIR_FREE(list->doms[i]);
-
-            if (i < (list->count - 1))
-                memmove(list->doms + i,
-                        list->doms + i + 1,
-                        sizeof(*(list->doms)) *
-                                (list->count - (i + 1)));
-
-            if (VIR_REALLOC_N(list->doms,
-                              list->count - 1) < 0) {
-                ; /* Failure to reduce memory allocation isn't fatal */
-            }
-            list->count--;
-
-            return 0;
-        }
-    }
-    return -1;
-}
-
-static void
-xenUnifiedDomainEventDispatchFunc(virConnectPtr conn,
-                                  virDomainEventPtr event,
-                                  virConnectDomainEventCallback cb,
-                                  void *cbopaque,
-                                  void *opaque)
-{
-    xenUnifiedPrivatePtr priv = opaque;
-
-    /*
-     * Release the lock while the callback is running so that
-     * we're re-entrant safe for callback work - the callback
-     * may want to invoke other virt functions & we have already
-     * protected the one piece of state we have - the callback
-     * list
-     */
-    xenUnifiedUnlock(priv);
-    virDomainEventDispatchDefaultFunc(conn, event, cb, cbopaque, NULL);
-    xenUnifiedLock(priv);
-}
-
-/**
- * xenUnifiedDomainEventDispatch:
- * @priv: the connection to dispatch events on
- * @event: the event to dispatch
- *
- * Dispatch domain events to registered callbacks
- *
- * The caller must hold the lock in 'priv' before invoking
- *
- */
-void xenUnifiedDomainEventDispatch (xenUnifiedPrivatePtr priv,
-                                    virDomainEventPtr event)
-{
-    if (!priv)
-        return;
-
-    priv->domainEventDispatching = 1;
-
-    if (priv->domainEventCallbacks) {
-        virDomainEventDispatch(event,
-                               priv->domainEventCallbacks,
-                               xenUnifiedDomainEventDispatchFunc,
-                               priv);
-
-        /* Purge any deleted callbacks */
-        virDomainEventCallbackListPurgeMarked(priv->domainEventCallbacks);
-    }
-
-    virDomainEventFree(event);
-
-    priv->domainEventDispatching = 0;
-}
-
-void xenUnifiedLock(xenUnifiedPrivatePtr priv)
-{
-    virMutexLock(&priv->lock);
-}
-
-void xenUnifiedUnlock(xenUnifiedPrivatePtr priv)
-{
-    virMutexUnlock(&priv->lock);
-}
diff --git a/src/xen_unified.h b/src/xen_unified.h
deleted file mode 100644 (file)
index 9cc877b..0000000
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * xen_unified.c: Unified Xen driver.
- *
- * Copyright (C) 2007 Red Hat, Inc.
- *
- * See COPYING.LIB for the License of this software
- *
- * Richard W.M. Jones <rjones@redhat.com>
- */
-
-#ifndef __VIR_XEN_UNIFIED_H__
-#define __VIR_XEN_UNIFIED_H__
-
-#include "internal.h"
-#include "capabilities.h"
-#include "driver.h"
-#include "domain_conf.h"
-#include "xs_internal.h"
-#if WITH_XEN_INOTIFY
-#include "xen_inotify.h"
-#endif
-#include "domain_event.h"
-#include "hash.h"
-
-#ifndef HAVE_WINSOCK2_H
-#include <sys/un.h>
-#include <netinet/in.h>
-#else
-#include <winsock2.h>
-#endif
-
-extern int xenRegister (void);
-
-#define XEN_UNIFIED_HYPERVISOR_OFFSET 0
-#define XEN_UNIFIED_PROXY_OFFSET 1
-#define XEN_UNIFIED_XEND_OFFSET 2
-#define XEN_UNIFIED_XS_OFFSET 3
-#define XEN_UNIFIED_XM_OFFSET 4
-
-#if WITH_XEN_INOTIFY
-#define XEN_UNIFIED_INOTIFY_OFFSET 5
-#define XEN_UNIFIED_NR_DRIVERS 6
-#else
-#define XEN_UNIFIED_NR_DRIVERS 5
-#endif
-
-#define MIN_XEN_GUEST_SIZE 64  /* 64 megabytes */
-
-#define XEN_CONFIG_FORMAT_XM    "xen-xm"
-#define XEN_CONFIG_FORMAT_SEXPR "xen-sxpr"
-
-/* _xenUnifiedDriver:
- *
- * Entry points into the underlying Xen drivers.  This structure
- * will eventually go away and instead xen unified will make direct
- * calls to the underlying Xen drivers.
- *
- * To reiterate - the goal is to remove elements from this structure
- * until it is empty, replacing indirect calls through this
- * structure with direct calls in xen_unified.c.
- */
-struct xenUnifiedDriver {
-        virDrvOpen                     open;
-        virDrvClose                    close;
-        virDrvGetVersion               version;
-    virDrvGetHostname       getHostname;
-        virDrvNodeGetInfo              nodeGetInfo;
-        virDrvGetCapabilities          getCapabilities;
-        virDrvListDomains              listDomains;
-        virDrvNumOfDomains             numOfDomains;
-        virDrvDomainCreateXML          domainCreateXML;
-        virDrvDomainSuspend            domainSuspend;
-        virDrvDomainResume             domainResume;
-        virDrvDomainShutdown           domainShutdown;
-        virDrvDomainReboot             domainReboot;
-        virDrvDomainDestroy            domainDestroy;
-        virDrvDomainGetOSType          domainGetOSType;
-        virDrvDomainGetMaxMemory       domainGetMaxMemory;
-        virDrvDomainSetMaxMemory       domainSetMaxMemory;
-        virDrvDomainSetMemory          domainSetMemory;
-        virDrvDomainGetInfo            domainGetInfo;
-        virDrvDomainSave               domainSave;
-        virDrvDomainRestore            domainRestore;
-        virDrvDomainCoreDump           domainCoreDump;
-        virDrvDomainSetVcpus           domainSetVcpus;
-        virDrvDomainPinVcpu            domainPinVcpu;
-        virDrvDomainGetVcpus           domainGetVcpus;
-        virDrvDomainGetMaxVcpus                domainGetMaxVcpus;
-        virDrvListDefinedDomains       listDefinedDomains;
-        virDrvNumOfDefinedDomains      numOfDefinedDomains;
-        virDrvDomainCreate             domainCreate;
-        virDrvDomainDefineXML           domainDefineXML;
-        virDrvDomainUndefine            domainUndefine;
-        virDrvDomainAttachDevice       domainAttachDevice;
-        virDrvDomainDetachDevice       domainDetachDevice;
-        virDrvDomainGetAutostart       domainGetAutostart;
-        virDrvDomainSetAutostart       domainSetAutostart;
-        virDrvDomainGetSchedulerType   domainGetSchedulerType;
-        virDrvDomainGetSchedulerParameters domainGetSchedulerParameters;
-        virDrvDomainSetSchedulerParameters domainSetSchedulerParameters;
-};
-
-typedef struct xenXMConfCache *xenXMConfCachePtr;
-typedef struct xenXMConfCache {
-    time_t refreshedAt;
-    char filename[PATH_MAX];
-    virDomainDefPtr def;
-} xenXMConfCache;
-
-/* xenUnifiedDomainInfoPtr:
- * The minimal state we have about active domains
- * This is the minmal info necessary to still get a
- * virDomainPtr when the domain goes away
- */
-struct _xenUnifiedDomainInfo {
-    int  id;
-    char *name;
-    unsigned char uuid[VIR_UUID_BUFLEN];
-};
-typedef struct _xenUnifiedDomainInfo xenUnifiedDomainInfo;
-typedef xenUnifiedDomainInfo *xenUnifiedDomainInfoPtr;
-
-struct _xenUnifiedDomainInfoList {
-    unsigned int count;
-    xenUnifiedDomainInfoPtr *doms;
-};
-typedef struct _xenUnifiedDomainInfoList xenUnifiedDomainInfoList;
-typedef xenUnifiedDomainInfoList *xenUnifiedDomainInfoListPtr;
-
-/* xenUnifiedPrivatePtr:
- *
- * Per-connection private data, stored in conn->privateData.  All Xen
- * low-level drivers access parts of this structure.
- */
-struct _xenUnifiedPrivate {
-    virMutex lock;
-
-    /* These initial vars are initialized in Open method
-     * and readonly thereafter, so can be used without
-     * holding the lock
-     */
-    virCapsPtr caps;
-    int handle;                        /* Xen hypervisor handle */
-
-    int xendConfigVersion;      /* XenD config version */
-
-    /* connection to xend */
-    struct sockaddr_storage addr;
-    socklen_t addrlen;
-    int addrfamily;
-    int addrprotocol;
-
-    /* Keep track of the drivers which opened.  We keep a yes/no flag
-     * here for each driver, corresponding to the array drivers in
-     * xen_unified.c.
-     */
-    int opened[XEN_UNIFIED_NR_DRIVERS];
-
-
-    /*
-     * Everything from this point onwards must be protected
-     * by the lock when used
-     */
-
-    struct xs_handle *xshandle; /* handle to talk to the xenstore */
-
-    int proxy;                  /* fd of proxy. */
-
-
-    /* A list of xenstore watches */
-    xenStoreWatchListPtr xsWatchList;
-    int xsWatch;
-    /* A list of active domain name/uuids */
-    xenUnifiedDomainInfoListPtr activeDomainList;
-
-    /* NUMA topology info cache */
-    int nbNodeCells;
-    int nbNodeCpus;
-
-    /* An list of callbacks */
-    virDomainEventCallbackListPtr domainEventCallbacks;
-    int domainEventDispatching;
-
-    /* Location of config files, either /etc
-     * or /var/lib/xen */
-    const char *configDir;
-
-#if WITH_XEN_INOTIFY
-    /* The inotify fd */
-    int inotifyFD;
-    int inotifyWatch;
-
-    int  useXenConfigCache ;
-    xenUnifiedDomainInfoListPtr configInfoList;
-#endif
-
-    /* For the 'xm' driver */
-    /* Primary config file name -> virDomainDef map */
-    virHashTablePtr configCache;
-    /* Domain name to config file name */
-    virHashTablePtr nameConfigMap;
-    /* So we don't refresh too often */
-    time_t lastRefresh;
-};
-
-typedef struct _xenUnifiedPrivate *xenUnifiedPrivatePtr;
-
-char *xenDomainUsedCpus(virDomainPtr dom);
-
-void xenUnifiedDomainInfoListFree(xenUnifiedDomainInfoListPtr info);
-int  xenUnifiedAddDomainInfo(xenUnifiedDomainInfoListPtr info,
-                             int id, char *name,
-                             unsigned char *uuid);
-int  xenUnifiedRemoveDomainInfo(xenUnifiedDomainInfoListPtr info,
-                                int id, char *name,
-                                unsigned char *uuid);
-void xenUnifiedDomainEventDispatch (xenUnifiedPrivatePtr priv,
-                                    virDomainEventPtr event);
-unsigned long xenUnifiedVersion(void);
-
-#ifndef PROXY
-void xenUnifiedLock(xenUnifiedPrivatePtr priv);
-void xenUnifiedUnlock(xenUnifiedPrivatePtr priv);
-#else
-#define xenUnifiedLock(p) do {} while(0)
-#define xenUnifiedUnlock(p) do {} while(0)
-#endif
-
-#endif /* __VIR_XEN_UNIFIED_H__ */
diff --git a/src/xend_internal.c b/src/xend_internal.c
deleted file mode 100644 (file)
index 7f55116..0000000
+++ /dev/null
@@ -1,5914 +0,0 @@
-/*
- * xend_internal.c: access to Xen though the Xen Daemon interface
- *
- * Copyright (C) 2005
- *
- *      Anthony Liguori <aliguori@us.ibm.com>
- *
- *  This file is subject to the terms and conditions of the GNU Lesser General
- *  Public License. See the file COPYING.LIB in the main directory of this
- *  archive for more details.
- */
-
-#include <config.h>
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/errno.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <math.h>
-#include <stdarg.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <libxml/uri.h>
-#include <errno.h>
-
-#include "virterror_internal.h"
-#include "logging.h"
-#include "datatypes.h"
-#include "xend_internal.h"
-#include "driver.h"
-#include "util.h"
-#include "sexpr.h"
-#include "buf.h"
-#include "uuid.h"
-#include "xen_unified.h"
-#include "xen_internal.h"
-#include "xs_internal.h" /* To extract VNC port & Serial console TTY */
-#include "memory.h"
-
-/* required for cpumap_t */
-#include <xen/dom0_ops.h>
-
-#define VIR_FROM_THIS VIR_FROM_XEND
-
-#ifndef PROXY
-
-/*
- * The number of Xen scheduler parameters
- */
-#define XEN_SCHED_SEDF_NPARAM   6
-#define XEN_SCHED_CRED_NPARAM   2
-
-#endif /* PROXY */
-
-#ifdef WITH_RHEL5_API
-#define XEND_CONFIG_MAX_VERS_NET_TYPE_IOEMU 0
-#define XEND_CONFIG_MIN_VERS_PVFB_NEWCONF 2
-#else
-#define XEND_CONFIG_MAX_VERS_NET_TYPE_IOEMU 3
-#define XEND_CONFIG_MIN_VERS_PVFB_NEWCONF 3
-#endif
-
-
-#ifndef PROXY
-static int
-xenDaemonFormatSxprDisk(virConnectPtr conn ATTRIBUTE_UNUSED,
-                        virDomainDiskDefPtr def,
-                        virBufferPtr buf,
-                        int hvm,
-                        int xendConfigVersion,
-                        int isAttach);
-static int
-xenDaemonFormatSxprNet(virConnectPtr conn ATTRIBUTE_UNUSED,
-                       virDomainNetDefPtr def,
-                       virBufferPtr buf,
-                       int hvm,
-                       int xendConfigVersion,
-                       int isAttach);
-static int
-xenDaemonFormatSxprOnePCI(virConnectPtr conn,
-                          virDomainHostdevDefPtr def,
-                          virBufferPtr buf);
-
-static int
-virDomainXMLDevID(virDomainPtr domain,
-                  virDomainDeviceDefPtr dev,
-                  char *class,
-                  char *ref,
-                  int ref_len);
-#endif
-
-#define virXendError(conn, code, fmt...)                                     \
-        virReportErrorHelper(conn, VIR_FROM_XEND, code, __FILE__,          \
-                               __FUNCTION__, __LINE__, fmt)
-
-#define virXendErrorInt(conn, code, ival)                                    \
-        virXendError(conn, code, "%d", ival)
-
-/**
- * do_connect:
- * @xend: pointer to the Xen Daemon structure
- *
- * Internal routine to (re)connect to the daemon
- *
- * Returns the socket file descriptor or -1 in case of error
- */
-static int
-do_connect(virConnectPtr xend)
-{
-    int s;
-    int serrno;
-    int no_slow_start = 1;
-    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) xend->privateData;
-
-    s = socket(priv->addrfamily, SOCK_STREAM, priv->addrprotocol);
-    if (s == -1) {
-        virXendError(xend, VIR_ERR_INTERNAL_ERROR,
-                     "%s", _("failed to create a socket"));
-        return -1;
-    }
-
-    /*
-     * try to desactivate slow-start
-     */
-    setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (void *)&no_slow_start,
-               sizeof(no_slow_start));
-
-
-    if (connect(s, (struct sockaddr *)&priv->addr, priv->addrlen) == -1) {
-        serrno = errno;
-        close(s);
-        errno = serrno;
-        s = -1;
-
-        /*
-         * Connecting to XenD when privileged is mandatory, so log this
-         * error
-         */
-        if (xenHavePrivilege()) {
-            virXendError(xend, VIR_ERR_INTERNAL_ERROR,
-                         "%s", _("failed to connect to xend"));
-        }
-    }
-
-    return s;
-}
-
-/**
- * wr_sync:
- * @xend: the xend connection object
- * @fd:  the file descriptor
- * @buffer: the I/O buffer
- * @size: the size of the I/O
- * @do_read: write operation if 0, read operation otherwise
- *
- * Do a synchronous read or write on the file descriptor
- *
- * Returns the number of bytes exchanged, or -1 in case of error
- */
-static size_t
-wr_sync(virConnectPtr xend, int fd, void *buffer, size_t size, int do_read)
-{
-    size_t offset = 0;
-
-    while (offset < size) {
-        ssize_t len;
-
-        if (do_read) {
-            len = read(fd, ((char *) buffer) + offset, size - offset);
-        } else {
-            len = write(fd, ((char *) buffer) + offset, size - offset);
-        }
-
-        /* recoverable error, retry  */
-        if ((len == -1) && ((errno == EAGAIN) || (errno == EINTR))) {
-            continue;
-        }
-
-        /* eof */
-        if (len == 0) {
-            break;
-        }
-
-        /* unrecoverable error */
-        if (len == -1) {
-            if (do_read)
-                virXendError(xend, VIR_ERR_INTERNAL_ERROR,
-                             "%s", _("failed to read from Xen Daemon"));
-            else
-                virXendError(xend, VIR_ERR_INTERNAL_ERROR,
-                             "%s", _("failed to read from Xen Daemon"));
-
-            return (-1);
-        }
-
-        offset += len;
-    }
-
-    return offset;
-}
-
-/**
- * sread:
- * @xend: the xend connection object
- * @fd:  the file descriptor
- * @buffer: the I/O buffer
- * @size: the size of the I/O
- *
- * Internal routine to do a synchronous read
- *
- * Returns the number of bytes read, or -1 in case of error
- */
-static ssize_t
-sread(virConnectPtr xend, int fd, void *buffer, size_t size)
-{
-    return wr_sync(xend, fd, buffer, size, 1);
-}
-
-/**
- * swrite:
- * @xend: the xend connection object
- * @fd:  the file descriptor
- * @buffer: the I/O buffer
- * @size: the size of the I/O
- *
- * Internal routine to do a synchronous write
- *
- * Returns the number of bytes written, or -1 in case of error
- */
-static ssize_t
-swrite(virConnectPtr xend, int fd, const void *buffer, size_t size)
-{
-    return wr_sync(xend, fd, (void *) buffer, size, 0);
-}
-
-/**
- * swrites:
- * @xend: the xend connection object
- * @fd:  the file descriptor
- * @string: the string to write
- *
- * Internal routine to do a synchronous write of a string
- *
- * Returns the number of bytes written, or -1 in case of error
- */
-static ssize_t
-swrites(virConnectPtr xend, int fd, const char *string)
-{
-    return swrite(xend, fd, string, strlen(string));
-}
-
-/**
- * sreads:
- * @xend: the xend connection object
- * @fd:  the file descriptor
- * @buffer: the I/O buffer
- * @n_buffer: the size of the I/O buffer
- *
- * Internal routine to do a synchronous read of a line
- *
- * Returns the number of bytes read, or -1 in case of error
- */
-static ssize_t
-sreads(virConnectPtr xend, int fd, char *buffer, size_t n_buffer)
-{
-    size_t offset;
-
-    if (n_buffer < 1)
-        return (-1);
-
-    for (offset = 0; offset < (n_buffer - 1); offset++) {
-        ssize_t ret;
-
-        ret = sread(xend, fd, buffer + offset, 1);
-        if (ret == 0)
-            break;
-        else if (ret == -1)
-            return ret;
-
-        if (buffer[offset] == '\n') {
-            offset++;
-            break;
-        }
-    }
-    buffer[offset] = 0;
-
-    return offset;
-}
-
-static int
-istartswith(const char *haystack, const char *needle)
-{
-    return STRCASEEQLEN(haystack, needle, strlen(needle));
-}
-
-
-/**
- * xend_req:
- * @xend: the xend connection object
- * @fd: the file descriptor
- * @content: the buffer to store the content
- * @n_content: the size of the buffer
- *
- * Read the HTTP response from a Xen Daemon request.
- *
- * Returns the HTTP return code.
- */
-static int
-xend_req(virConnectPtr xend, int fd, char *content, size_t n_content)
-{
-    char buffer[4096];
-    int content_length = -1;
-    int retcode = 0;
-
-    while (sreads(xend, fd, buffer, sizeof(buffer)) > 0) {
-        if (STREQ(buffer, "\r\n"))
-            break;
-
-        if (istartswith(buffer, "Content-Length: "))
-            content_length = atoi(buffer + 16);
-        else if (istartswith(buffer, "HTTP/1.1 "))
-            retcode = atoi(buffer + 9);
-    }
-
-    if (content_length > -1) {
-        ssize_t ret;
-
-        if ((unsigned int) content_length > (n_content + 1))
-            content_length = n_content - 1;
-
-        ret = sread(xend, fd, content, content_length);
-        if (ret < 0)
-            return -1;
-
-        content[ret] = 0;
-    } else {
-        content[0] = 0;
-    }
-
-    return retcode;
-}
-
-/**
- * xend_get:
- * @xend: pointer to the Xen Daemon structure
- * @path: the path used for the HTTP request
- * @content: the buffer to store the content
- * @n_content: the size of the buffer
- *
- * Do an HTTP GET RPC with the Xen Daemon
- *
- * Returns the HTTP return code or -1 in case or error.
- */
-static int
-xend_get(virConnectPtr xend, const char *path,
-         char *content, size_t n_content)
-{
-    int ret;
-    int s = do_connect(xend);
-
-    if (s == -1)
-        return s;
-
-    swrites(xend, s, "GET ");
-    swrites(xend, s, path);
-    swrites(xend, s, " HTTP/1.1\r\n");
-
-    swrites(xend, s,
-            "Host: localhost:8000\r\n"
-            "Accept-Encoding: identity\r\n"
-            "Content-Type: application/x-www-form-urlencoded\r\n" "\r\n");
-
-    ret = xend_req(xend, s, content, n_content);
-    close(s);
-
-    if (((ret < 0) || (ret >= 300)) &&
-        ((ret != 404) || (!STRPREFIX(path, "/xend/domain/")))) {
-        virXendError(xend, VIR_ERR_GET_FAILED,
-                     _("%d status from xen daemon: %s:%s"),
-                     ret, path, content);
-    }
-
-    return ret;
-}
-
-#ifndef PROXY
-/**
- * xend_post:
- * @xend: pointer to the Xen Daemon structure
- * @path: the path used for the HTTP request
- * @ops: the information sent for the POST
- * @content: the buffer to store the content
- * @n_content: the size of the buffer
- *
- * Do an HTTP POST RPC with the Xen Daemon, this usually makes changes at the
- * Xen level.
- *
- * Returns the HTTP return code or -1 in case or error.
- */
-static int
-xend_post(virConnectPtr xend, const char *path, const char *ops,
-          char *content, size_t n_content)
-{
-    char buffer[100];
-    int ret;
-    int s = do_connect(xend);
-
-    if (s == -1)
-        return s;
-
-    swrites(xend, s, "POST ");
-    swrites(xend, s, path);
-    swrites(xend, s, " HTTP/1.1\r\n");
-
-    swrites(xend, s,
-            "Host: localhost:8000\r\n"
-            "Accept-Encoding: identity\r\n"
-            "Content-Type: application/x-www-form-urlencoded\r\n"
-            "Content-Length: ");
-    snprintf(buffer, sizeof(buffer), "%d", (int) strlen(ops));
-    swrites(xend ,s, buffer);
-    swrites(xend, s, "\r\n\r\n");
-    swrites(xend, s, ops);
-
-    ret = xend_req(xend, s, content, n_content);
-    close(s);
-
-    if ((ret < 0) || (ret >= 300)) {
-        virXendError(xend, VIR_ERR_POST_FAILED,
-                     _("xend_post: error from xen daemon: %s"), content);
-    } else if ((ret == 202) && (strstr(content, "failed") != NULL)) {
-        virXendError(xend, VIR_ERR_POST_FAILED,
-                     _("xend_post: error from xen daemon: %s"), content);
-        ret = -1;
-    } else if (((ret >= 200) && (ret <= 202)) && (strstr(content, "xend.err") != NULL)) {
-        /* This is to catch case of things like 'virsh dump Domain-0 foo'
-         * which returns a success code, but the word 'xend.err'
-         * in body to indicate error :-(
-         */
-        virXendError(xend, VIR_ERR_POST_FAILED,
-                     _("xend_post: error from xen daemon: %s"), content);
-        ret = -1;
-    }
-
-    return ret;
-}
-#endif /* ! PROXY */
-
-
-/**
- * http2unix:
- * @xend: the xend connection object
- * @ret: the http return code
- *
- * Convert the HTTP return code to 0/-1 and set errno if needed
- *
- * Return -1 in case of error code 0 otherwise
- */
-static int
-http2unix(virConnectPtr xend, int ret)
-{
-    switch (ret) {
-        case -1:
-            break;
-        case 200:
-        case 201:
-        case 202:
-            return 0;
-        case 404:
-            errno = ESRCH;
-            break;
-        case 500:
-            errno = EIO;
-            break;
-        default:
-            virXendErrorInt(xend, VIR_ERR_HTTP_ERROR, ret);
-            errno = EINVAL;
-            break;
-    }
-    return -1;
-}
-
-#ifndef PROXY
-/**
- * xend_op_ext:
- * @xend: pointer to the Xen Daemon structure
- * @path: path for the object
- * @error: buffer for the error output
- * @n_error: size of @error
- * @key: the key for the operation
- * @ap: input values to pass to the operation
- *
- * internal routine to run a POST RPC operation to the Xen Daemon
- *
- * Returns 0 in case of success, -1 in case of failure.
- */
-static int
-xend_op_ext(virConnectPtr xend, const char *path, char *error,
-            size_t n_error, const char *key, va_list ap)
-{
-    const char *k = key, *v;
-    virBuffer buf = VIR_BUFFER_INITIALIZER;
-    int ret;
-    char *content;
-
-    while (k) {
-        v = va_arg(ap, const char *);
-
-        virBufferVSprintf(&buf, "%s", k);
-        virBufferVSprintf(&buf, "%s", "=");
-        virBufferVSprintf(&buf, "%s", v);
-        k = va_arg(ap, const char *);
-
-        if (k)
-            virBufferVSprintf(&buf, "%s", "&");
-    }
-
-    if (virBufferError(&buf)) {
-        virReportOOMError(NULL);
-        return -1;
-    }
-
-    content = virBufferContentAndReset(&buf);
-    ret = http2unix(xend, xend_post(xend, path, content, error, n_error));
-    VIR_FREE(content);
-
-    return ret;
-}
-
-
-/**
- * xend_op:
- * @xend: pointer to the Xen Daemon structure
- * @name: the domain name target of this operation
- * @error: buffer for the error output
- * @n_error: size of @error
- * @key: the key for the operation
- * @ap: input values to pass to the operation
- * @...: input values to pass to the operation
- *
- * internal routine to run a POST RPC operation to the Xen Daemon targetting
- * a given domain.
- *
- * Returns 0 in case of success, -1 in case of failure.
- */
-static int
-xend_op(virConnectPtr xend, const char *name, const char *key, ...)
-{
-    char buffer[1024];
-    char error[1024];
-    va_list ap;
-    int ret;
-
-    snprintf(buffer, sizeof(buffer), "/xend/domain/%s", name);
-
-    va_start(ap, key);
-    ret = xend_op_ext(xend, buffer, error, sizeof(error), key, ap);
-    va_end(ap);
-
-    return ret;
-}
-
-#endif /* ! PROXY */
-
-/**
- * sexpr_get:
- * @xend: pointer to the Xen Daemon structure
- * @fmt: format string for the path of the operation
- * @...: extra data to build the path of the operation
- *
- * Internal routine to run a simple GET RPC operation to the Xen Daemon
- *
- * Returns a parsed S-Expression in case of success, NULL in case of failure
- */
-static struct sexpr *sexpr_get(virConnectPtr xend, const char *fmt, ...)
-  ATTRIBUTE_FMT_PRINTF(2,3);
-
-static struct sexpr *
-sexpr_get(virConnectPtr xend, const char *fmt, ...)
-{
-    char buffer[4096];
-    char path[1024];
-    va_list ap;
-    int ret;
-
-    va_start(ap, fmt);
-    vsnprintf(path, sizeof(path), fmt, ap);
-    va_end(ap);
-
-    ret = xend_get(xend, path, buffer, sizeof(buffer));
-    ret = http2unix(xend ,ret);
-    if (ret == -1)
-        return NULL;
-
-    return string2sexpr(buffer);
-}
-
-/**
- * sexpr_int:
- * @sexpr: an S-Expression
- * @name: the name for the value
- *
- * convenience function to lookup an int value in the S-Expression
- *
- * Returns the value found or 0 if not found (but may not be an error).
- * This function suffers from the flaw that zero is both a correct
- * return value and an error indicator: careful!
- */
-static int
-sexpr_int(const struct sexpr *sexpr, const char *name)
-{
-    const char *value = sexpr_node(sexpr, name);
-
-    if (value) {
-        return strtol(value, NULL, 0);
-    }
-    return 0;
-}
-
-
-/**
- * sexpr_float:
- * @sexpr: an S-Expression
- * @name: the name for the value
- *
- * convenience function to lookup a float value in the S-Expression
- *
- * Returns the value found or 0 if not found (but may not be an error)
- */
-static double
-sexpr_float(const struct sexpr *sexpr, const char *name)
-{
-    const char *value = sexpr_node(sexpr, name);
-
-    if (value) {
-        return strtod(value, NULL);
-    }
-    return 0;
-}
-
-/**
- * sexpr_u64:
- * @sexpr: an S-Expression
- * @name: the name for the value
- *
- * convenience function to lookup a 64bits unsigned int value in the
- * S-Expression
- *
- * Returns the value found or 0 if not found (but may not be an error)
- */
-static uint64_t
-sexpr_u64(const struct sexpr *sexpr, const char *name)
-{
-    const char *value = sexpr_node(sexpr, name);
-
-    if (value) {
-        return strtoll(value, NULL, 0);
-    }
-    return 0;
-}
-
-
-/**
- * sexpr_uuid:
- * @ptr: where to store the UUID, incremented
- * @sexpr: an S-Expression
- * @name: the name for the value
- *
- * convenience function to lookup an UUID value from the S-Expression
- *
- * Returns a -1 on error, 0 on success
- */
-static int
-sexpr_uuid(unsigned char *ptr, const struct sexpr *node, const char *path)
-{
-    const char *r = sexpr_node(node, path);
-    if (!r)
-        return -1;
-    return virUUIDParse(r, ptr);
-}
-
-
-#ifndef PROXY
-/**
- * urlencode:
- * @string: the input URL
- *
- * Encode an URL see RFC 2396 and following
- *
- * Returns the new string or NULL in case of error.
- */
-static char *
-urlencode(const char *string)
-{
-    size_t len = strlen(string);
-    char *buffer;
-    char *ptr;
-    size_t i;
-
-    if (VIR_ALLOC_N(buffer, len * 3 + 1) < 0) {
-        virReportOOMError(NULL);
-        return (NULL);
-    }
-    ptr = buffer;
-    for (i = 0; i < len; i++) {
-        switch (string[i]) {
-            case ' ':
-            case '\n':
-                snprintf(ptr, 4, "%%%02x", string[i]);
-                ptr += 3;
-                break;
-            default:
-                *ptr = string[i];
-                ptr++;
-        }
-    }
-
-    *ptr = 0;
-
-    return buffer;
-}
-#endif /* ! PROXY */
-
-/* PUBLIC FUNCTIONS */
-
-/**
- * xenDaemonOpen_unix:
- * @conn: an existing virtual connection block
- * @path: the path for the Xen Daemon socket
- *
- * Creates a localhost Xen Daemon connection
- * Note: this doesn't try to check if the connection actually works
- *
- * Returns 0 in case of success, -1 in case of error.
- */
-int
-xenDaemonOpen_unix(virConnectPtr conn, const char *path)
-{
-    struct sockaddr_un *addr;
-    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
-
-    if ((conn == NULL) || (path == NULL))
-        return (-1);
-
-    memset(&priv->addr, 0, sizeof(priv->addr));
-    priv->addrfamily = AF_UNIX;
-    /*
-     * This must be zero on Solaris at least for AF_UNIX (which should
-     * really be PF_UNIX, but doesn't matter).
-     */
-    priv->addrprotocol = 0;
-    priv->addrlen = sizeof(struct sockaddr_un);
-
-    addr = (struct sockaddr_un *)&priv->addr;
-    addr->sun_family = AF_UNIX;
-    memset(addr->sun_path, 0, sizeof(addr->sun_path));
-    strncpy(addr->sun_path, path, sizeof(addr->sun_path));
-
-    return (0);
-}
-
-#ifndef PROXY
-/**
- * xenDaemonOpen_tcp:
- * @conn: an existing virtual connection block
- * @host: the host name for the Xen Daemon
- * @port: the port
- *
- * Creates a possibly remote Xen Daemon connection
- * Note: this doesn't try to check if the connection actually works
- *
- * Returns 0 in case of success, -1 in case of error.
- */
-static int
-xenDaemonOpen_tcp(virConnectPtr conn, const char *host, const char *port)
-{
-    xenUnifiedPrivatePtr priv;
-    struct addrinfo *res, *r;
-    struct addrinfo hints;
-    int saved_errno = EINVAL;
-    int ret;
-
-    if ((conn == NULL) || (host == NULL) || (port == NULL))
-        return (-1);
-
-    priv = (xenUnifiedPrivatePtr) conn->privateData;
-
-    priv->addrlen = 0;
-    memset(&priv->addr, 0, sizeof(priv->addr));
-
-    // http://people.redhat.com/drepper/userapi-ipv6.html
-    memset (&hints, 0, sizeof hints);
-    hints.ai_socktype = SOCK_STREAM;
-    hints.ai_flags = AI_ADDRCONFIG;
-
-    ret = getaddrinfo (host, port, &hints, &res);
-    if (ret != 0) {
-        virXendError(NULL, VIR_ERR_UNKNOWN_HOST,
-                     _("unable to resolve hostname '%s': %s"),
-                     host, gai_strerror (ret));
-        return -1;
-    }
-
-    /* Try to connect to each returned address in turn. */
-    for (r = res; r; r = r->ai_next) {
-        int sock;
-
-        sock = socket (r->ai_family, SOCK_STREAM, r->ai_protocol);
-        if (sock == -1) {
-            saved_errno = errno;
-            continue;
-        }
-
-        if (connect (sock, r->ai_addr, r->ai_addrlen) == -1) {
-            saved_errno = errno;
-            close (sock);
-            continue;
-        }
-
-        priv->addrlen = r->ai_addrlen;
-        priv->addrfamily = r->ai_family;
-        priv->addrprotocol = r->ai_protocol;
-        memcpy(&priv->addr,
-               r->ai_addr,
-               r->ai_addrlen);
-        close(sock);
-        break;
-    }
-
-    freeaddrinfo (res);
-
-    if (!priv->addrlen) {
-        /* Don't raise error when unprivileged, since proxy takes over */
-        if (xenHavePrivilege())
-            virReportSystemError(conn, saved_errno,
-                                 _("unable to connect to '%s:%s'"),
-                                 host, port);
-        return -1;
-    }
-
-    return 0;
-}
-
-
-/**
- * xend_wait_for_devices:
- * @xend: pointer to the Xem Daemon block
- * @name: name for the domain
- *
- * Block the domain until all the virtual devices are ready. This operation
- * is needed when creating a domain before resuming it.
- *
- * Returns 0 in case of success, -1 (with errno) in case of error.
- */
-int
-xend_wait_for_devices(virConnectPtr xend, const char *name)
-{
-    return xend_op(xend, name, "op", "wait_for_devices", NULL);
-}
-
-
-#endif /* PROXY */
-
-
-/**
- * xenDaemonListDomainsOld:
- * @xend: pointer to the Xem Daemon block
- *
- * This method will return an array of names of currently running
- * domains.  The memory should be released will a call to free().
- *
- * Returns a list of names or NULL in case of error.
- */
-char **
-xenDaemonListDomainsOld(virConnectPtr xend)
-{
-    size_t extra = 0;
-    struct sexpr *root = NULL;
-    char **ret = NULL;
-    int count = 0;
-    int i;
-    char *ptr;
-    struct sexpr *_for_i, *node;
-
-    root = sexpr_get(xend, "/xend/domain");
-    if (root == NULL)
-        goto error;
-
-    for (_for_i = root, node = root->u.s.car; _for_i->kind == SEXPR_CONS;
-         _for_i = _for_i->u.s.cdr, node = _for_i->u.s.car) {
-        if (node->kind != SEXPR_VALUE)
-            continue;
-        extra += strlen(node->u.value) + 1;
-        count++;
-    }
-
-    /*
-     * We can'tuse the normal allocation routines as we are mixing
-     * an array of char * at the beginning followed by an array of char
-     * ret points to the NULL terminated array of char *
-     * ptr points to the current string after that array but in the same
-     * allocated block
-     */
-    if (virAlloc((void *)&ptr,
-                 (count + 1) * sizeof(char *) + extra * sizeof(char)) < 0)
-        goto error;
-
-    ret = (char **) ptr;
-    ptr += sizeof(char *) * (count + 1);
-
-    i = 0;
-    for (_for_i = root, node = root->u.s.car; _for_i->kind == SEXPR_CONS;
-         _for_i = _for_i->u.s.cdr, node = _for_i->u.s.car) {
-        if (node->kind != SEXPR_VALUE)
-            continue;
-        ret[i] = ptr;
-        strcpy(ptr, node->u.value);
-        ptr += strlen(node->u.value) + 1;
-        i++;
-    }
-
-    ret[i] = NULL;
-
-  error:
-    sexpr_free(root);
-    return ret;
-}
-
-#ifndef PROXY
-/**
- * xenDaemonDomainCreateXML:
- * @xend: A xend instance
- * @sexpr: An S-Expr description of the domain.
- *
- * This method will create a domain based the passed in description.  The
- * domain will be paused after creation and must be unpaused with
- * xenDaemonResumeDomain() to begin execution.
- * This method may be deprecated once switching to XML-RPC based communcations
- * with xend.
- *
- * Returns 0 for success, -1 (with errno) on error
- */
-
-int
-xenDaemonDomainCreateXML(virConnectPtr xend, const char *sexpr)
-{
-    int ret, serrno;
-    char *ptr;
-
-    ptr = urlencode(sexpr);
-    if (ptr == NULL) {
-        /* this should be caught at the interface but ... */
-        virXendError(xend, VIR_ERR_INTERNAL_ERROR,
-                     "%s", _("failed to urlencode the create S-Expr"));
-        return (-1);
-    }
-
-    ret = xend_op(xend, "", "op", "create", "config", ptr, NULL);
-
-    serrno = errno;
-    VIR_FREE(ptr);
-    errno = serrno;
-
-    return ret;
-}
-#endif /* ! PROXY */
-
-/**
- * xenDaemonDomainLookupByName_ids:
- * @xend: A xend instance
- * @domname: The name of the domain
- * @uuid: return value for the UUID if not NULL
- *
- * This method looks up the id of a domain
- *
- * Returns the id on success; -1 (with errno) on error
- */
-int
-xenDaemonDomainLookupByName_ids(virConnectPtr xend, const char *domname,
-                                unsigned char *uuid)
-{
-    struct sexpr *root;
-    const char *value;
-    int ret = -1;
-
-    if (uuid != NULL)
-        memset(uuid, 0, VIR_UUID_BUFLEN);
-    root = sexpr_get(xend, "/xend/domain/%s?detail=1", domname);
-    if (root == NULL)
-        goto error;
-
-    value = sexpr_node(root, "domain/domid");
-    if (value == NULL) {
-        virXendError(xend, VIR_ERR_INTERNAL_ERROR,
-                     "%s", _("domain information incomplete, missing domid"));
-        goto error;
-    }
-    ret = strtol(value, NULL, 0);
-    if ((ret == 0) && (value[0] != '0')) {
-        virXendError(xend, VIR_ERR_INTERNAL_ERROR,
-                     "%s", _("domain information incorrect domid not numeric"));
-        ret = -1;
-    } else if (uuid != NULL) {
-        if (sexpr_uuid(uuid, root, "domain/uuid") < 0) {
-            virXendError(xend, VIR_ERR_INTERNAL_ERROR,
-                         "%s", _("domain information incomplete, missing uuid"));
-        }
-    }
-
-  error:
-    sexpr_free(root);
-    return (ret);
-}
-
-
-/**
- * xenDaemonDomainLookupByID:
- * @xend: A xend instance
- * @id: The id of the domain
- * @name: return value for the name if not NULL
- * @uuid: return value for the UUID if not NULL
- *
- * This method looks up the name of a domain based on its id
- *
- * Returns the 0 on success; -1 (with errno) on error
- */
-int
-xenDaemonDomainLookupByID(virConnectPtr xend,
-                          int id,
-                          char **domname,
-                          unsigned char *uuid)
-{
-    const char *name = NULL;
-    struct sexpr *root;
-
-    memset(uuid, 0, VIR_UUID_BUFLEN);
-
-    root = sexpr_get(xend, "/xend/domain/%d?detail=1", id);
-    if (root == NULL)
-      goto error;
-
-    name = sexpr_node(root, "domain/name");
-    if (name == NULL) {
-      virXendError(xend, VIR_ERR_INTERNAL_ERROR,
-                   "%s", _("domain information incomplete, missing name"));
-      goto error;
-    }
-    if (domname)
-      *domname = strdup(name);
-
-    if (sexpr_uuid(uuid, root, "domain/uuid") < 0) {
-      virXendError(xend, VIR_ERR_INTERNAL_ERROR,
-                   "%s", _("domain information incomplete, missing uuid"));
-      goto error;
-    }
-
-    sexpr_free(root);
-    return (0);
-
-error:
-    sexpr_free(root);
-    if (domname)
-        VIR_FREE(*domname);
-    return (-1);
-}
-
-
-#ifndef PROXY
-static int
-xend_detect_config_version(virConnectPtr conn) {
-    struct sexpr *root;
-    const char *value;
-    xenUnifiedPrivatePtr priv;
-
-    if (!VIR_IS_CONNECT(conn)) {
-        virXendError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return (-1);
-    }
-
-    priv = (xenUnifiedPrivatePtr) conn->privateData;
-
-    root = sexpr_get(conn, "/xend/node/");
-    if (root == NULL)
-        return (-1);
-
-    value = sexpr_node(root, "node/xend_config_format");
-
-    if (value) {
-        priv->xendConfigVersion = strtol(value, NULL, 10);
-    }  else {
-        /* Xen prior to 3.0.3 did not have the xend_config_format
-           field, and is implicitly version 1. */
-        priv->xendConfigVersion = 1;
-    }
-    sexpr_free(root);
-    return (0);
-}
-
-#endif /* PROXY */
-
-/*****************************************************************
- ******
- ****** Parsing of SEXPR into virDomainDef objects
- ******
- *****************************************************************/
-
-/**
- * xenDaemonParseSxprOS
- * @xend: the xend connection object
- * @node: the root of the parsed S-Expression
- * @def: the domain config
- * @hvm: true or 1 if no contains HVM S-Expression
- * @bootloader: true or 1 if a bootloader is defined
- *
- * Parse the xend sexp for description of os and append it to buf.
- *
- * Returns 0 in case of success and -1 in case of error
- */
-static int
-xenDaemonParseSxprOS(virConnectPtr xend,
-                     const struct sexpr *node,
-                     virDomainDefPtr def,
-                     int hvm)
-{
-    if (hvm) {
-        if (sexpr_node_copy(node, "domain/image/hvm/loader", &def->os.loader) < 0)
-            goto no_memory;
-        if (def->os.loader == NULL) {
-            if (sexpr_node_copy(node, "domain/image/hvm/kernel", &def->os.loader) < 0)
-                goto no_memory;
-
-            if (def->os.loader == NULL) {
-                virXendError(xend, VIR_ERR_INTERNAL_ERROR,
-                             "%s", _("domain information incomplete, missing HVM loader"));
-                return(-1);
-            }
-        } else {
-            if (sexpr_node_copy(node, "domain/image/hvm/kernel", &def->os.kernel) < 0)
-                goto no_memory;
-            if (sexpr_node_copy(node, "domain/image/hvm/ramdisk", &def->os.initrd) < 0)
-                goto no_memory;
-            if (sexpr_node_copy(node, "domain/image/hvm/args", &def->os.cmdline) < 0)
-                goto no_memory;
-            if (sexpr_node_copy(node, "domain/image/hvm/root", &def->os.root) < 0)
-                goto no_memory;
-        }
-    } else {
-        if (sexpr_node_copy(node, "domain/image/linux/kernel", &def->os.kernel) < 0)
-            goto no_memory;
-        if (sexpr_node_copy(node, "domain/image/linux/ramdisk", &def->os.initrd) < 0)
-            goto no_memory;
-        if (sexpr_node_copy(node, "domain/image/linux/args", &def->os.cmdline) < 0)
-            goto no_memory;
-        if (sexpr_node_copy(node, "domain/image/linux/root", &def->os.root) < 0)
-            goto no_memory;
-    }
-
-    /* If HVM kenrel == loader, then old xend, so kill off kernel */
-    if (hvm &&
-        def->os.kernel &&
-        STREQ(def->os.kernel, def->os.loader)) {
-        VIR_FREE(def->os.kernel);
-    }
-
-    if (!def->os.kernel &&
-        hvm) {
-        const char *boot = sexpr_node(node, "domain/image/hvm/boot");
-        if ((boot != NULL) && (boot[0] != 0)) {
-            while (*boot &&
-                   def->os.nBootDevs < VIR_DOMAIN_BOOT_LAST) {
-                if (*boot == 'a')
-                    def->os.bootDevs[def->os.nBootDevs++] = VIR_DOMAIN_BOOT_FLOPPY;
-                else if (*boot == 'c')
-                    def->os.bootDevs[def->os.nBootDevs++] = VIR_DOMAIN_BOOT_DISK;
-                else if (*boot == 'd')
-                    def->os.bootDevs[def->os.nBootDevs++] = VIR_DOMAIN_BOOT_CDROM;
-                else if (*boot == 'n')
-                    def->os.bootDevs[def->os.nBootDevs++] = VIR_DOMAIN_BOOT_NET;
-                boot++;
-            }
-        }
-    }
-
-    if (!hvm &&
-        !def->os.kernel &&
-        !def->os.bootloader) {
-        virXendError(xend, VIR_ERR_INTERNAL_ERROR,
-                     "%s", _("domain information incomplete, missing kernel & bootloader"));
-        return -1;
-    }
-
-    return 0;
-
-no_memory:
-    virReportOOMError(xend);
-    return -1;
-}
-
-
-int
-xend_parse_sexp_desc_char(virConnectPtr conn,
-                          virBufferPtr buf,
-                          const char *devtype,
-                          int portNum,
-                          const char *value,
-                          const char *tty)
-{
-    const char *type;
-    int telnet = 0;
-    char *bindPort = NULL;
-    char *bindHost = NULL;
-    char *connectPort = NULL;
-    char *connectHost = NULL;
-    char *path = NULL;
-    int ret = -1;
-
-    if (value[0] == '/') {
-        type = "dev";
-    } else if (STRPREFIX(value, "null")) {
-        type = "null";
-        value = NULL;
-    } else if (STRPREFIX(value, "vc")) {
-        type = "vc";
-        value = NULL;
-    } else if (STRPREFIX(value, "pty")) {
-        type = "pty";
-        value = NULL;
-    } else if (STRPREFIX(value, "stdio")) {
-        type = "stdio";
-        value = NULL;
-    } else if (STRPREFIX(value, "file:")) {
-        type = "file";
-        value += sizeof("file:")-1;
-    } else if (STRPREFIX(value, "pipe:")) {
-        type = "pipe";
-        value += sizeof("pipe:")-1;
-    } else if (STRPREFIX(value, "tcp:")) {
-        type = "tcp";
-        value += sizeof("tcp:")-1;
-    } else if (STRPREFIX(value, "telnet:")) {
-        type = "tcp";
-        value += sizeof("telnet:")-1;
-        telnet = 1;
-    } else if (STRPREFIX(value, "udp:")) {
-        type = "udp";
-        value += sizeof("udp:")-1;
-    } else if (STRPREFIX(value, "unix:")) {
-        type = "unix";
-        value += sizeof("unix:")-1;
-    } else {
-        virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                     "%s", _("Unknown char device type"));
-        return -1;
-    }
-
-    /* Compat with legacy  <console tty='/dev/pts/5'/> syntax */
-    if (STREQ(devtype, "console") &&
-        STREQ(type, "pty") &&
-        tty != NULL) {
-        virBufferVSprintf(buf, "    <%s type='%s' tty='%s'>\n",
-                          devtype, type, tty);
-    } else {
-        virBufferVSprintf(buf, "    <%s type='%s'>\n",
-                          devtype, type);
-    }
-
-    if (STREQ(type, "null") ||
-        STREQ(type, "vc") ||
-        STREQ(type, "stdio")) {
-        /* no source needed */
-    } else if (STREQ(type, "pty")) {
-        if (tty)
-            virBufferVSprintf(buf, "      <source path='%s'/>\n",
-                              tty);
-    } else if (STREQ(type, "file") ||
-               STREQ(type, "pipe")) {
-        virBufferVSprintf(buf, "      <source path='%s'/>\n",
-                          value);
-    } else if (STREQ(type, "tcp")) {
-        const char *offset = strchr(value, ':');
-        const char *offset2;
-        const char *mode, *protocol;
-
-        if (offset == NULL) {
-            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                         "%s", _("malformed char device string"));
-            goto error;
-        }
-
-        if (offset != value &&
-            (bindHost = strndup(value, offset - value)) == NULL)
-            goto no_memory;
-
-        offset2 = strchr(offset, ',');
-        if (offset2 == NULL)
-            bindPort = strdup(offset+1);
-        else
-            bindPort = strndup(offset+1, offset2-(offset+1));
-        if (bindPort == NULL)
-            goto no_memory;
-
-        if (offset2 && strstr(offset2, ",listen"))
-            mode = "bind";
-        else
-            mode = "connect";
-        protocol = telnet ? "telnet":"raw";
-
-        if (bindHost) {
-            virBufferVSprintf(buf,
-                              "      <source mode='%s' host='%s' service='%s'/>\n",
-                              mode, bindHost, bindPort);
-        } else {
-            virBufferVSprintf(buf,
-                              "      <source mode='%s' service='%s'/>\n",
-                              mode, bindPort);
-        }
-        virBufferVSprintf(buf,
-                          "      <protocol type='%s'/>\n",
-                          protocol);
-    } else if (STREQ(type, "udp")) {
-        const char *offset = strchr(value, ':');
-        const char *offset2, *offset3;
-
-        if (offset == NULL) {
-            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                         "%s", _("malformed char device string"));
-            goto error;
-        }
-
-        if (offset != value &&
-            (connectHost = strndup(value, offset - value)) == NULL)
-            goto no_memory;
-
-        offset2 = strchr(offset, '@');
-        if (offset2 != NULL) {
-            if ((connectPort = strndup(offset + 1, offset2-(offset+1))) == NULL)
-                goto no_memory;
-
-            offset3 = strchr(offset2, ':');
-            if (offset3 == NULL) {
-                virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                             "%s", _("malformed char device string"));
-                goto error;
-            }
-
-            if (offset3 > (offset2 + 1) &&
-                (bindHost = strndup(offset2 + 1, offset3 - (offset2+1))) == NULL)
-                goto no_memory;
-
-            if ((bindPort = strdup(offset3 + 1)) == NULL)
-                goto no_memory;
-        } else {
-            if ((connectPort = strdup(offset + 1)) == NULL)
-                goto no_memory;
-        }
-
-        if (connectPort) {
-            if (connectHost) {
-                virBufferVSprintf(buf,
-                                  "      <source mode='connect' host='%s' service='%s'/>\n",
-                                  connectHost, connectPort);
-            } else {
-                virBufferVSprintf(buf,
-                                  "      <source mode='connect' service='%s'/>\n",
-                                  connectPort);
-            }
-        }
-        if (bindPort) {
-            if (bindHost) {
-                virBufferVSprintf(buf,
-                                  "      <source mode='bind' host='%s' service='%s'/>\n",
-                                  bindHost, bindPort);
-            } else {
-                virBufferVSprintf(buf,
-                                  "      <source mode='bind' service='%s'/>\n",
-                                  bindPort);
-            }
-        }
-
-    } else if (STREQ(type, "unix")) {
-        const char *offset = strchr(value, ',');
-        int dolisten = 0;
-        if (offset)
-            path = strndup(value, (offset - value));
-        else
-            path = strdup(value);
-        if (path == NULL)
-            goto no_memory;
-
-        if (offset != NULL &&
-            strstr(offset, ",listen") != NULL)
-            dolisten = 1;
-
-        virBufferVSprintf(buf, "      <source mode='%s' path='%s'/>\n",
-                          dolisten ? "bind" : "connect", path);
-    }
-
-    virBufferVSprintf(buf, "      <target port='%d'/>\n",
-                      portNum);
-
-    virBufferVSprintf(buf, "    </%s>\n",
-                      devtype);
-
-    ret = 0;
-
-    if (ret == -1) {
-no_memory:
-        virReportOOMError(conn);
-    }
-
-error:
-
-    VIR_FREE(path);
-    VIR_FREE(bindHost);
-    VIR_FREE(bindPort);
-    VIR_FREE(connectHost);
-    VIR_FREE(connectPort);
-
-    return ret;
-}
-
-virDomainChrDefPtr
-xenDaemonParseSxprChar(virConnectPtr conn,
-                       const char *value,
-                       const char *tty)
-{
-    char prefix[10];
-    char *tmp;
-    virDomainChrDefPtr def;
-
-    if (VIR_ALLOC(def) < 0) {
-        virReportOOMError(conn);
-        return NULL;
-    }
-
-    strncpy(prefix, value, sizeof(prefix)-1);
-    NUL_TERMINATE(prefix);
-
-    if (value[0] == '/') {
-        def->type = VIR_DOMAIN_CHR_TYPE_DEV;
-    } else {
-        if ((tmp = strchr(prefix, ':')) != NULL) {
-            *tmp = '\0';
-            value += (tmp - prefix) + 1;
-        }
-
-        if (STREQ(prefix, "telnet")) {
-            def->type = VIR_DOMAIN_CHR_TYPE_TCP;
-            def->data.tcp.protocol = VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET;
-        } else {
-            if ((def->type = virDomainChrTypeFromString(prefix)) < 0) {
-                virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                             _("unknown chr device type '%s'"), prefix);
-                goto error;
-            }
-        }
-    }
-
-    /* Compat with legacy  <console tty='/dev/pts/5'/> syntax */
-    switch (def->type) {
-    case VIR_DOMAIN_CHR_TYPE_PTY:
-        if (tty != NULL &&
-            !(def->data.file.path = strdup(tty)))
-            goto no_memory;
-        break;
-
-    case VIR_DOMAIN_CHR_TYPE_FILE:
-    case VIR_DOMAIN_CHR_TYPE_PIPE:
-        if (!(def->data.file.path = strdup(value)))
-            goto no_memory;
-        break;
-
-    case VIR_DOMAIN_CHR_TYPE_TCP:
-    {
-        const char *offset = strchr(value, ':');
-        const char *offset2;
-
-        if (offset == NULL) {
-            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                         "%s", _("malformed char device string"));
-            goto error;
-        }
-
-        if (offset != value &&
-            (def->data.tcp.host = strndup(value, offset - value)) == NULL)
-            goto no_memory;
-
-        offset2 = strchr(offset, ',');
-        if (offset2 == NULL)
-            def->data.tcp.service = strdup(offset+1);
-        else
-            def->data.tcp.service = strndup(offset+1, offset2-(offset+1));
-        if (def->data.tcp.service == NULL)
-            goto no_memory;
-
-        if (offset2 && strstr(offset2, ",listen"))
-            def->data.tcp.listen = 1;
-    }
-    break;
-
-    case VIR_DOMAIN_CHR_TYPE_UDP:
-    {
-        const char *offset = strchr(value, ':');
-        const char *offset2, *offset3;
-
-        if (offset == NULL) {
-            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                         "%s", _("malformed char device string"));
-            goto error;
-        }
-
-        if (offset != value &&
-            (def->data.udp.connectHost = strndup(value, offset - value)) == NULL)
-            goto no_memory;
-
-        offset2 = strchr(offset, '@');
-        if (offset2 != NULL) {
-            if ((def->data.udp.connectService = strndup(offset + 1, offset2-(offset+1))) == NULL)
-                goto no_memory;
-
-            offset3 = strchr(offset2, ':');
-            if (offset3 == NULL) {
-                virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                             "%s", _("malformed char device string"));
-                goto error;
-            }
-
-            if (offset3 > (offset2 + 1) &&
-                (def->data.udp.bindHost = strndup(offset2 + 1, offset3 - (offset2+1))) == NULL)
-                goto no_memory;
-
-            if ((def->data.udp.bindService = strdup(offset3 + 1)) == NULL)
-                goto no_memory;
-        } else {
-            if ((def->data.udp.connectService = strdup(offset + 1)) == NULL)
-                goto no_memory;
-        }
-    }
-    break;
-
-    case VIR_DOMAIN_CHR_TYPE_UNIX:
-    {
-        const char *offset = strchr(value, ',');
-        if (offset)
-            def->data.nix.path = strndup(value, (offset - value));
-        else
-            def->data.nix.path = strdup(value);
-        if (def->data.nix.path == NULL)
-            goto no_memory;
-
-        if (offset != NULL &&
-            strstr(offset, ",listen") != NULL)
-            def->data.nix.listen = 1;
-    }
-    break;
-    }
-
-    return def;
-
-no_memory:
-    virReportOOMError(conn);
-error:
-    virDomainChrDefFree(def);
-    return NULL;
-}
-
-/**
- * xend_parse_sexp_desc_disks
- * @conn: connection
- * @root: root sexpr
- * @xendConfigVersion: version of xend
- *
- * This parses out block devices from the domain sexpr
- *
- * Returns 0 if successful or -1 if failed.
- */
-static int
-xenDaemonParseSxprDisks(virConnectPtr conn,
-                        virDomainDefPtr def,
-                        const struct sexpr *root,
-                        int hvm,
-                        int xendConfigVersion)
-{
-    const struct sexpr *cur, *node;
-    virDomainDiskDefPtr disk = NULL;
-
-    for (cur = root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
-        node = cur->u.s.car;
-        /* Normally disks are in a (device (vbd ...)) block
-           but blktap disks ended up in a differently named
-           (device (tap ....)) block.... */
-        if (sexpr_lookup(node, "device/vbd") ||
-            sexpr_lookup(node, "device/tap")) {
-            char *offset;
-            const char *src = NULL;
-            const char *dst = NULL;
-            const char *mode = NULL;
-
-            /* Again dealing with (vbd...) vs (tap ...) differences */
-            if (sexpr_lookup(node, "device/vbd")) {
-                src = sexpr_node(node, "device/vbd/uname");
-                dst = sexpr_node(node, "device/vbd/dev");
-                mode = sexpr_node(node, "device/vbd/mode");
-            } else {
-                src = sexpr_node(node, "device/tap/uname");
-                dst = sexpr_node(node, "device/tap/dev");
-                mode = sexpr_node(node, "device/tap/mode");
-            }
-
-            if (VIR_ALLOC(disk) < 0)
-                goto no_memory;
-
-            if (dst == NULL) {
-                virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                             "%s", _("domain information incomplete, vbd has no dev"));
-                goto error;
-            }
-
-            if (src == NULL) {
-                /* There is a case without the uname to the CD-ROM device */
-                offset = strchr(dst, ':');
-                if (!offset ||
-                    !hvm ||
-                    STRNEQ(offset, ":cdrom")) {
-                    virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                                 "%s", _("domain information incomplete, vbd has no src"));
-                    goto error;
-                }
-            }
-
-            if (src != NULL) {
-                offset = strchr(src, ':');
-                if (!offset) {
-                    virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                                 "%s", _("cannot parse vbd filename, missing driver name"));
-                    goto error;
-                }
-
-                if (VIR_ALLOC_N(disk->driverName, (offset-src)+1) < 0)
-                    goto no_memory;
-                strncpy(disk->driverName, src, (offset-src));
-                disk->driverName[offset-src] = '\0';
-
-                src = offset + 1;
-
-                if (STREQ (disk->driverName, "tap")) {
-                    offset = strchr(src, ':');
-                    if (!offset) {
-                        virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                                     "%s", _("cannot parse vbd filename, missing driver type"));
-                        goto error;
-                    }
-
-                    if (VIR_ALLOC_N(disk->driverType, (offset-src)+1)< 0)
-                        goto no_memory;
-                    strncpy(disk->driverType, src, (offset-src));
-                    disk->driverType[offset-src] = '\0';
-
-                    src = offset + 1;
-                    /* Its possible to use blktap driver for block devs
-                       too, but kinda pointless because blkback is better,
-                       so we assume common case here. If blktap becomes
-                       omnipotent, we can revisit this, perhaps stat()'ing
-                       the src file in question */
-                    disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
-                } else if (STREQ(disk->driverName, "phy")) {
-                    disk->type = VIR_DOMAIN_DISK_TYPE_BLOCK;
-                } else if (STREQ(disk->driverName, "file")) {
-                    disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
-                }
-            } else {
-                /* No CDROM media so can't really tell. We'll just
-                   call if a FILE for now and update when media
-                   is inserted later */
-                disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
-            }
-
-            if (STREQLEN (dst, "ioemu:", 6))
-                dst += 6;
-
-            disk->device = VIR_DOMAIN_DISK_DEVICE_DISK;
-            /* New style disk config from Xen >= 3.0.3 */
-            if (xendConfigVersion > 1) {
-                offset = strrchr(dst, ':');
-                if (offset) {
-                    if (STREQ (offset, ":cdrom")) {
-                        disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
-                    } else if (STREQ (offset, ":disk")) {
-                        /* The default anyway */
-                    } else {
-                        /* Unknown, lets pretend its a disk too */
-                    }
-                    offset[0] = '\0';
-                }
-            }
-
-            if (!(disk->dst = strdup(dst)))
-                goto no_memory;
-            if (src &&
-                !(disk->src = strdup(src)))
-                goto no_memory;
-
-            if (STRPREFIX(disk->dst, "xvd"))
-                disk->bus = VIR_DOMAIN_DISK_BUS_XEN;
-            else if (STRPREFIX(disk->dst, "hd"))
-                disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
-            else if (STRPREFIX(disk->dst, "sd"))
-                disk->bus = VIR_DOMAIN_DISK_BUS_SCSI;
-            else
-                disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
-
-            if (mode &&
-                strchr(mode, 'r'))
-                disk->readonly = 1;
-            if (mode &&
-                strchr(mode, '!'))
-                disk->shared = 1;
-
-            if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0)
-                goto no_memory;
-
-            def->disks[def->ndisks++] = disk;
-            disk = NULL;
-        }
-    }
-
-    return 0;
-
-no_memory:
-    virReportOOMError(conn);
-
-error:
-    virDomainDiskDefFree(disk);
-    return -1;
-}
-
-
-static int
-xenDaemonParseSxprNets(virConnectPtr conn,
-                       virDomainDefPtr def,
-                       const struct sexpr *root)
-{
-    virDomainNetDefPtr net = NULL;
-    const struct sexpr *cur, *node;
-    const char *tmp;
-    int vif_index = 0;
-
-    for (cur = root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
-        node = cur->u.s.car;
-        if (sexpr_lookup(node, "device/vif")) {
-            const char *tmp2, *model;
-            char buf[50];
-            tmp2 = sexpr_node(node, "device/vif/script");
-            tmp = sexpr_node(node, "device/vif/bridge");
-            model = sexpr_node(node, "device/vif/model");
-
-            if (VIR_ALLOC(net) < 0)
-                goto no_memory;
-
-            if (tmp != NULL ||
-                (tmp2 != NULL && STREQ(tmp2, DEFAULT_VIF_SCRIPT))) {
-                net->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
-                /* XXX virtual network reverse resolve */
-
-                if (tmp &&
-                    !(net->data.bridge.brname = strdup(tmp)))
-                    goto no_memory;
-                if (tmp2 &&
-                    net->type == VIR_DOMAIN_NET_TYPE_BRIDGE &&
-                    !(net->data.bridge.script = strdup(tmp2)))
-                    goto no_memory;
-                tmp = sexpr_node(node, "device/vif/ip");
-                if (tmp &&
-                    !(net->data.bridge.ipaddr = strdup(tmp)))
-                    goto no_memory;
-            } else {
-                net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
-                if (tmp2 &&
-                    !(net->data.ethernet.script = strdup(tmp2)))
-                    goto no_memory;
-                tmp = sexpr_node(node, "device/vif/ip");
-                if (tmp &&
-                    !(net->data.ethernet.ipaddr = strdup(tmp)))
-                    goto no_memory;
-            }
-
-            tmp = sexpr_node(node, "device/vif/vifname");
-            if (!tmp) {
-                snprintf(buf, sizeof(buf), "vif%d.%d", def->id, vif_index);
-                tmp = buf;
-            }
-            if (!(net->ifname = strdup(tmp)))
-                goto no_memory;
-
-            tmp = sexpr_node(node, "device/vif/mac");
-            if (tmp) {
-                unsigned int mac[6];
-                if (sscanf(tmp, "%02x:%02x:%02x:%02x:%02x:%02x",
-                           (unsigned int*)&mac[0],
-                           (unsigned int*)&mac[1],
-                           (unsigned int*)&mac[2],
-                           (unsigned int*)&mac[3],
-                           (unsigned int*)&mac[4],
-                           (unsigned int*)&mac[5]) != 6) {
-                    virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                                 _("malformed mac address '%s'"),
-                                 tmp);
-                    goto cleanup;
-                }
-                net->mac[0] = mac[0];
-                net->mac[1] = mac[1];
-                net->mac[2] = mac[2];
-                net->mac[3] = mac[3];
-                net->mac[4] = mac[4];
-                net->mac[5] = mac[5];
-            }
-
-            if (model &&
-                !(net->model = strdup(model)))
-                goto no_memory;
-
-            if (VIR_REALLOC_N(def->nets, def->nnets + 1) < 0)
-                goto no_memory;
-
-            def->nets[def->nnets++] = net;
-            vif_index++;
-        }
-    }
-
-    return 0;
-
-no_memory:
-    virReportOOMError(conn);
-cleanup:
-    virDomainNetDefFree(net);
-    return -1;
-}
-
-
-int
-xenDaemonParseSxprSound(virConnectPtr conn,
-                        virDomainDefPtr def,
-                        const char *str)
-{
-    if (STREQ(str, "all")) {
-        int i;
-
-        /*
-         * Special compatability code for Xen with a bogus
-         * sound=all in config.
-         *
-         * NB delibrately, don't include all possible
-         * sound models anymore, just the 2 that were
-         * historically present in Xen's QEMU.
-         *
-         * ie just es1370 + sb16.
-         *
-         * Hence use of MODEL_ES1370 + 1, instead of MODEL_LAST
-         */
-
-        if (VIR_ALLOC_N(def->sounds,
-                        VIR_DOMAIN_SOUND_MODEL_ES1370 + 1) < 0)
-            goto no_memory;
-
-
-        for (i = 0 ; i < (VIR_DOMAIN_SOUND_MODEL_ES1370 + 1) ; i++) {
-            virDomainSoundDefPtr sound;
-            if (VIR_ALLOC(sound) < 0)
-                goto no_memory;
-            sound->model = i;
-            def->sounds[def->nsounds++] = sound;
-        }
-    } else {
-        char model[10];
-        const char *offset = str, *offset2;
-
-        do {
-            int len;
-            virDomainSoundDefPtr sound;
-            offset2 = strchr(offset, ',');
-            if (offset2)
-                len = (offset2 - offset);
-            else
-                len = strlen(offset);
-            if (len > (sizeof(model)-1)) {
-                virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                                 _("unexpected sound model %s"), offset);
-                goto error;
-            }
-            strncpy(model, offset, len);
-            model[len] = '\0';
-
-            if (VIR_ALLOC(sound) < 0)
-                goto no_memory;
-
-            if ((sound->model = virDomainSoundModelTypeFromString(model)) < 0) {
-                VIR_FREE(sound);
-                goto error;
-            }
-
-            if (VIR_REALLOC_N(def->sounds, def->nsounds+1) < 0) {
-                virDomainSoundDefFree(sound);
-                goto no_memory;
-            }
-
-            def->sounds[def->nsounds++] = sound;
-            offset = offset2 ? offset2 + 1 : NULL;
-        } while (offset);
-    }
-
-    return 0;
-
-no_memory:
-    virReportOOMError(conn);
-error:
-    return -1;
-}
-
-
-static int
-xenDaemonParseSxprUSB(virConnectPtr conn,
-                      virDomainDefPtr def,
-                      const struct sexpr *root)
-{
-    struct sexpr *cur, *node;
-    const char *tmp;
-
-    for (cur = sexpr_lookup(root, "domain/image/hvm"); cur && cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
-        node = cur->u.s.car;
-        if (sexpr_lookup(node, "usbdevice")) {
-            tmp = sexpr_node(node, "usbdevice");
-            if (tmp && *tmp) {
-                if (STREQ(tmp, "tablet") ||
-                    STREQ(tmp, "mouse")) {
-                    virDomainInputDefPtr input;
-                    if (VIR_ALLOC(input) < 0)
-                        goto no_memory;
-                    input->bus = VIR_DOMAIN_INPUT_BUS_USB;
-                    if (STREQ(tmp, "tablet"))
-                        input->type = VIR_DOMAIN_INPUT_TYPE_TABLET;
-                    else
-                        input->type = VIR_DOMAIN_INPUT_TYPE_MOUSE;
-
-                    if (VIR_REALLOC_N(def->inputs, def->ninputs+1) < 0) {
-                        VIR_FREE(input);
-                        goto no_memory;
-                    }
-                    def->inputs[def->ninputs++] = input;
-                } else {
-                    /* XXX Handle other non-input USB devices later */
-                }
-            }
-        }
-    }
-    return 0;
-
-no_memory:
-    virReportOOMError(conn);
-    return -1;
-}
-
-static int
-xenDaemonParseSxprGraphicsOld(virConnectPtr conn,
-                              virDomainDefPtr def,
-                              const struct sexpr *root,
-                              int hvm,
-                              int xendConfigVersion)
-{
-#ifndef PROXY
-    xenUnifiedPrivatePtr priv = conn->privateData;
-#endif
-    const char *tmp;
-    virDomainGraphicsDefPtr graphics = NULL;
-
-    if ((tmp = sexpr_fmt_node(root, "domain/image/%s/vnc", hvm ? "hvm" : "linux")) &&
-        tmp[0] == '1') {
-        /* Graphics device (HVM, or old (pre-3.0.4) style PV VNC config) */
-        int port;
-        const char *listenAddr = sexpr_fmt_node(root, "domain/image/%s/vnclisten", hvm ? "hvm" : "linux");
-        const char *vncPasswd = sexpr_fmt_node(root, "domain/image/%s/vncpasswd", hvm ? "hvm" : "linux");
-        const char *keymap = sexpr_fmt_node(root, "domain/image/%s/keymap", hvm ? "hvm" : "linux");
-        const char *unused = sexpr_fmt_node(root, "domain/image/%s/vncunused", hvm ? "hvm" : "linux");
-
-        xenUnifiedLock(priv);
-        port = xenStoreDomainGetVNCPort(conn, def->id);
-        xenUnifiedUnlock(priv);
-
-        if (VIR_ALLOC(graphics) < 0)
-            goto no_memory;
-
-        graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_VNC;
-        /* For Xen >= 3.0.3, don't generate a fixed port mapping
-         * because it will almost certainly be wrong ! Just leave
-         * it as -1 which lets caller see that the VNC server isn't
-         * present yet. Subsquent dumps of the XML will eventually
-         * find the port in XenStore once VNC server has started
-         */
-        if (port == -1 && xendConfigVersion < 2)
-            port = 5900 + def->id;
-
-        if ((unused && STREQ(unused, "1")) || port == -1)
-            graphics->data.vnc.autoport = 1;
-        graphics->data.vnc.port = port;
-
-        if (listenAddr &&
-            !(graphics->data.vnc.listenAddr = strdup(listenAddr)))
-            goto no_memory;
-
-        if (vncPasswd &&
-            !(graphics->data.vnc.passwd = strdup(vncPasswd)))
-            goto no_memory;
-
-        if (keymap &&
-            !(graphics->data.vnc.keymap = strdup(keymap)))
-            goto no_memory;
-
-        if (VIR_ALLOC_N(def->graphics, 1) < 0)
-            goto no_memory;
-        def->graphics[0] = graphics;
-        def->ngraphics = 1;
-        graphics = NULL;
-    } else if ((tmp = sexpr_fmt_node(root, "domain/image/%s/sdl", hvm ? "hvm" : "linux")) &&
-               tmp[0] == '1') {
-        /* Graphics device (HVM, or old (pre-3.0.4) style PV sdl config) */
-        const char *display = sexpr_fmt_node(root, "domain/image/%s/display", hvm ? "hvm" : "linux");
-        const char *xauth = sexpr_fmt_node(root, "domain/image/%s/xauthority", hvm ? "hvm" : "linux");
-
-        if (VIR_ALLOC(graphics) < 0)
-            goto no_memory;
-
-        graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_SDL;
-        if (display &&
-            !(graphics->data.sdl.display = strdup(display)))
-            goto no_memory;
-        if (xauth &&
-            !(graphics->data.sdl.xauth = strdup(xauth)))
-            goto no_memory;
-
-        if (VIR_ALLOC_N(def->graphics, 1) < 0)
-            goto no_memory;
-        def->graphics[0] = graphics;
-        def->ngraphics = 1;
-        graphics = NULL;
-    }
-
-    return 0;
-
-no_memory:
-    virReportOOMError(conn);
-    virDomainGraphicsDefFree(graphics);
-    return -1;
-}
-
-
-static int
-xenDaemonParseSxprGraphicsNew(virConnectPtr conn,
-                              virDomainDefPtr def,
-                              const struct sexpr *root)
-{
-#ifndef PROXY
-    xenUnifiedPrivatePtr priv = conn->privateData;
-#endif
-    virDomainGraphicsDefPtr graphics = NULL;
-    const struct sexpr *cur, *node;
-    const char *tmp;
-
-    /* append network devices and framebuffer */
-    for (cur = root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
-        node = cur->u.s.car;
-        if (sexpr_lookup(node, "device/vfb")) {
-            /* New style graphics config for PV guests in >= 3.0.4,
-             * or for HVM guests in >= 3.0.5 */
-            if (sexpr_node(node, "device/vfb/type")) {
-                tmp = sexpr_node(node, "device/vfb/type");
-            } else if (sexpr_node(node, "device/vfb/vnc")) {
-                tmp = "vnc";
-            } else if (sexpr_node(node, "device/vfb/sdl")) {
-                tmp = "sdl";
-            } else {
-                tmp = "unknown";
-            }
-
-            if (VIR_ALLOC(graphics) < 0)
-                goto no_memory;
-
-            if ((graphics->type = virDomainGraphicsTypeFromString(tmp)) < 0) {
-                virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                             _("unknown graphics type '%s'"), tmp);
-                goto error;
-            }
-
-            if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
-                const char *display = sexpr_node(node, "device/vfb/display");
-                const char *xauth = sexpr_node(node, "device/vfb/xauthority");
-                if (display &&
-                    !(graphics->data.sdl.display = strdup(display)))
-                    goto no_memory;
-                if (xauth &&
-                    !(graphics->data.sdl.xauth = strdup(xauth)))
-                    goto no_memory;
-            } else {
-                int port;
-                const char *listenAddr = sexpr_node(node, "device/vfb/vnclisten");
-                const char *vncPasswd = sexpr_node(node, "device/vfb/vncpasswd");
-                const char *keymap = sexpr_node(node, "device/vfb/keymap");
-                const char *unused = sexpr_node(node, "device/vfb/vncunused");
-
-                xenUnifiedLock(priv);
-                port = xenStoreDomainGetVNCPort(conn, def->id);
-                xenUnifiedUnlock(priv);
-
-                // Didn't find port entry in xenstore
-                if (port == -1) {
-                    const char *str = sexpr_node(node, "device/vfb/vncdisplay");
-                    int val;
-                    if (str != NULL && virStrToLong_i(str, NULL, 0, &val) == 0)
-                        port = val;
-                }
-
-                if ((unused && STREQ(unused, "1")) || port == -1)
-                    graphics->data.vnc.autoport = 1;
-
-                if (port >= 0 && port < 5900)
-                    port += 5900;
-                graphics->data.vnc.port = port;
-
-                if (listenAddr &&
-                    !(graphics->data.vnc.listenAddr = strdup(listenAddr)))
-                    goto no_memory;
-
-                if (vncPasswd &&
-                    !(graphics->data.vnc.passwd = strdup(vncPasswd)))
-                    goto no_memory;
-
-                if (keymap &&
-                    !(graphics->data.vnc.keymap = strdup(keymap)))
-                    goto no_memory;
-            }
-
-            if (VIR_ALLOC_N(def->graphics, 1) < 0)
-                goto no_memory;
-            def->graphics[0] = graphics;
-            def->ngraphics = 1;
-            graphics = NULL;
-            break;
-        }
-    }
-
-    return 0;
-
-no_memory:
-    virReportOOMError(conn);
-error:
-    virDomainGraphicsDefFree(graphics);
-    return -1;
-}
-
-/**
- * xenDaemonParseSxprPCI
- * @conn: connection
- * @root: root sexpr
- *
- * This parses out block devices from the domain sexpr
- *
- * Returns 0 if successful or -1 if failed.
- */
-static int
-xenDaemonParseSxprPCI(virConnectPtr conn,
-                      virDomainDefPtr def,
-                      const struct sexpr *root)
-{
-    const struct sexpr *cur, *tmp = NULL, *node;
-    virDomainHostdevDefPtr dev = NULL;
-
-    /*
-     * With the (domain ...) block we have the following odd setup
-     *
-     * (device
-     *    (pci
-     *       (dev (domain 0x0000) (bus 0x00) (slot 0x1b) (func 0x0))
-     *       (dev (domain 0x0000) (bus 0x00) (slot 0x13) (func 0x0))
-     *    )
-     * )
-     *
-     * Normally there is one (device ...) block per device, but in
-     * wierd world of Xen PCI, once (device ...) covers multiple
-     * devices.
-     */
-
-    for (cur = root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
-        node = cur->u.s.car;
-        if ((tmp = sexpr_lookup(node, "device/pci")) != NULL)
-            break;
-    }
-
-    if (!tmp)
-        return 0;
-
-    for (cur = tmp; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
-        const char *domain = NULL;
-        const char *bus = NULL;
-        const char *slot = NULL;
-        const char *func = NULL;
-        int domainID;
-        int busID;
-        int slotID;
-        int funcID;
-
-        node = cur->u.s.car;
-        if (!sexpr_lookup(node, "dev"))
-            continue;
-
-        if (!(domain = sexpr_node(node, "dev/domain"))) {
-            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                         "%s", _("missing PCI domain"));
-            goto error;
-        }
-        if (!(bus = sexpr_node(node, "dev/bus"))) {
-            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                         "%s", _("missing PCI bus"));
-            goto error;
-        }
-        if (!(slot = sexpr_node(node, "dev/slot"))) {
-            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                         "%s", _("missing PCI slot"));
-            goto error;
-        }
-        if (!(func = sexpr_node(node, "dev/func"))) {
-            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                         "%s", _("missing PCI func"));
-            goto error;
-        }
-
-        if (virStrToLong_i(domain, NULL, 0, &domainID) < 0) {
-            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                         _("cannot parse PCI domain '%s'"), domain);
-            goto error;
-        }
-        if (virStrToLong_i(bus, NULL, 0, &busID) < 0) {
-            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                         _("cannot parse PCI bus '%s'"), bus);
-            goto error;
-        }
-        if (virStrToLong_i(slot, NULL, 0, &slotID) < 0) {
-            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                         _("cannot parse PCI slot '%s'"), slot);
-            goto error;
-        }
-        if (virStrToLong_i(func, NULL, 0, &funcID) < 0) {
-            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                         _("cannot parse PCI func '%s'"), func);
-            goto error;
-        }
-
-        if (VIR_ALLOC(dev) < 0)
-            goto no_memory;
-
-        dev->mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS;
-        dev->managed = 0;
-        dev->source.subsys.type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI;
-        dev->source.subsys.u.pci.domain = domainID;
-        dev->source.subsys.u.pci.bus = busID;
-        dev->source.subsys.u.pci.slot = slotID;
-        dev->source.subsys.u.pci.function = funcID;
-
-        if (VIR_REALLOC_N(def->hostdevs, def->nhostdevs+1) < 0) {
-            goto no_memory;
-        }
-
-        def->hostdevs[def->nhostdevs++] = dev;
-    }
-
-    return 0;
-
-no_memory:
-    virReportOOMError(conn);
-
-error:
-    virDomainHostdevDefFree(dev);
-    return -1;
-}
-
-
-/**
- * xenDaemonParseSxpr:
- * @conn: the connection associated with the XML
- * @root: the root of the parsed S-Expression
- * @xendConfigVersion: version of xend
- * @cpus: set of cpus the domain may be pinned to
- *
- * Parse the xend sexp description and turn it into the XML format similar
- * to the one unsed for creation.
- *
- * Returns the 0 terminated XML string or NULL in case of error.
- *         the caller must free() the returned value.
- */
-static virDomainDefPtr
-xenDaemonParseSxpr(virConnectPtr conn,
-                   const struct sexpr *root,
-                   int xendConfigVersion,
-                   const char *cpus)
-{
-#ifndef PROXY
-    xenUnifiedPrivatePtr priv = conn->privateData;
-#endif
-    const char *tmp;
-    virDomainDefPtr def;
-    int hvm = 0;
-    char *tty = NULL;
-
-    if (VIR_ALLOC(def) < 0)
-        goto no_memory;
-
-    tmp = sexpr_node(root, "domain/domid");
-    if (tmp == NULL && xendConfigVersion < 3) { /* Old XenD, domid was mandatory */
-        virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                     "%s", _("domain information incomplete, missing id"));
-        goto error;
-    }
-    def->virtType = VIR_DOMAIN_VIRT_XEN;
-    if (tmp)
-        def->id = sexpr_int(root, "domain/domid");
-    else
-        def->id = -1;
-
-    if (sexpr_node_copy(root, "domain/name", &def->name) < 0)
-        goto no_memory;
-    if (def->name == NULL) {
-        virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                     "%s", _("domain information incomplete, missing name"));
-        goto error;
-    }
-
-    tmp = sexpr_node(root, "domain/uuid");
-    if (tmp == NULL) {
-        virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                     "%s", _("domain information incomplete, missing name"));
-        goto error;
-    }
-    virUUIDParse(tmp, def->uuid);
-
-    hvm = sexpr_lookup(root, "domain/image/hvm") ? 1 : 0;
-    if (!hvm) {
-        if (sexpr_node_copy(root, "domain/bootloader",
-                            &def->os.bootloader) < 0)
-            goto no_memory;
-
-        if (!def->os.bootloader &&
-            sexpr_has(root, "domain/bootloader") &&
-            (def->os.bootloader = strdup("")) == NULL)
-            goto no_memory;
-
-        if (def->os.bootloader &&
-            sexpr_node_copy(root, "domain/bootloader_args",
-                            &def->os.bootloaderArgs) < 0)
-            goto no_memory;
-    }
-
-    if (!(def->os.type = strdup(hvm ? "hvm" : "linux")))
-        goto no_memory;
-
-    if (def->id != 0) {
-        if (sexpr_lookup(root, "domain/image")) {
-            if (xenDaemonParseSxprOS(conn, root, def, hvm) < 0)
-                goto error;
-        }
-    }
-
-    def->maxmem = (unsigned long) (sexpr_u64(root, "domain/maxmem") << 10);
-    def->memory = (unsigned long) (sexpr_u64(root, "domain/memory") << 10);
-    if (def->memory > def->maxmem)
-        def->maxmem = def->memory;
-
-    if (cpus != NULL) {
-        def->cpumasklen = VIR_DOMAIN_CPUMASK_LEN;
-        if (VIR_ALLOC_N(def->cpumask, def->cpumasklen) < 0) {
-            virReportOOMError(conn);
-            goto error;
-        }
-
-        if (virDomainCpuSetParse(conn, &cpus,
-                                 0, def->cpumask,
-                                 def->cpumasklen) < 0) {
-            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                         _("invalid CPU mask %s"), cpus);
-            goto error;
-        }
-    }
-
-    def->vcpus = sexpr_int(root, "domain/vcpus");
-
-    tmp = sexpr_node(root, "domain/on_poweroff");
-    if (tmp != NULL) {
-        if ((def->onPoweroff = virDomainLifecycleTypeFromString(tmp)) < 0) {
-            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                         _("unknown lifecycle type %s"), tmp);
-            goto error;
-        }
-    } else
-        def->onPoweroff = VIR_DOMAIN_LIFECYCLE_DESTROY;
-
-    tmp = sexpr_node(root, "domain/on_reboot");
-    if (tmp != NULL) {
-        if ((def->onReboot = virDomainLifecycleTypeFromString(tmp)) < 0) {
-            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                         _("unknown lifecycle type %s"), tmp);
-            goto error;
-        }
-    } else
-        def->onReboot = VIR_DOMAIN_LIFECYCLE_RESTART;
-
-    tmp = sexpr_node(root, "domain/on_crash");
-    if (tmp != NULL) {
-        if ((def->onCrash = virDomainLifecycleTypeFromString(tmp)) < 0) {
-            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                         _("unknown lifecycle type %s"), tmp);
-            goto error;
-        }
-    } else
-        def->onCrash = VIR_DOMAIN_LIFECYCLE_DESTROY;
-
-
-    if (hvm) {
-        if (sexpr_int(root, "domain/image/hvm/acpi"))
-            def->features |= (1 << VIR_DOMAIN_FEATURE_ACPI);
-        if (sexpr_int(root, "domain/image/hvm/apic"))
-            def->features |= (1 << VIR_DOMAIN_FEATURE_APIC);
-        if (sexpr_int(root, "domain/image/hvm/pae"))
-            def->features |= (1 << VIR_DOMAIN_FEATURE_PAE);
-
-        /* Old XenD only allows localtime here for HVM */
-        if (sexpr_int(root, "domain/image/hvm/localtime"))
-            def->localtime = 1;
-    }
-
-    /* Current XenD allows localtime here, for PV and HVM */
-    if (sexpr_int(root, "domain/localtime"))
-        def->localtime = 1;
-
-    if (sexpr_node_copy(root, hvm ?
-                        "domain/image/hvm/device_model" :
-                        "domain/image/linux/device_model",
-                        &def->emulator) < 0)
-        goto no_memory;
-
-    /* append block devices */
-    if (xenDaemonParseSxprDisks(conn, def, root, hvm, xendConfigVersion) < 0)
-        goto error;
-
-    if (xenDaemonParseSxprNets(conn, def, root) < 0)
-        goto error;
-
-    if (xenDaemonParseSxprPCI(conn, def, root) < 0)
-        goto error;
-
-    /* New style graphics device config */
-    if (xenDaemonParseSxprGraphicsNew(conn, def, root) < 0)
-        goto error;
-
-    /* Graphics device (HVM <= 3.0.4, or PV <= 3.0.3) vnc config */
-    if ((def->ngraphics == 0) &&
-        xenDaemonParseSxprGraphicsOld(conn, def, root, hvm, xendConfigVersion) < 0)
-        goto error;
-
-
-    /* Old style cdrom config from Xen <= 3.0.2 */
-    if (hvm &&
-        xendConfigVersion == 1) {
-        tmp = sexpr_node(root, "domain/image/hvm/cdrom");
-        if ((tmp != NULL) && (tmp[0] != 0)) {
-            virDomainDiskDefPtr disk;
-            if (VIR_ALLOC(disk) < 0)
-                goto no_memory;
-            if (!(disk->src = strdup(tmp))) {
-                virDomainDiskDefFree(disk);
-                goto no_memory;
-            }
-            disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
-            disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
-            if (!(disk->dst = strdup("hdc"))) {
-                virDomainDiskDefFree(disk);
-                goto no_memory;
-            }
-            if (!(disk->driverName = strdup("file"))) {
-                virDomainDiskDefFree(disk);
-                goto no_memory;
-            }
-            disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
-            disk->readonly = 1;
-
-            if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0) {
-                virDomainDiskDefFree(disk);
-                goto no_memory;
-            }
-            def->disks[def->ndisks++] = disk;
-        }
-    }
-
-
-    /* Floppy disk config */
-    if (hvm) {
-        const char *const fds[] = { "fda", "fdb" };
-        int i;
-        for (i = 0 ; i < ARRAY_CARDINALITY(fds) ; i++) {
-            tmp = sexpr_fmt_node(root, "domain/image/hvm/%s", fds[i]);
-            if ((tmp != NULL) && (tmp[0] != 0)) {
-                virDomainDiskDefPtr disk;
-                if (VIR_ALLOC(disk) < 0)
-                    goto no_memory;
-                if (!(disk->src = strdup(tmp))) {
-                    VIR_FREE(disk);
-                    goto no_memory;
-                }
-                disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
-                disk->device = VIR_DOMAIN_DISK_DEVICE_FLOPPY;
-                if (!(disk->dst = strdup(fds[i]))) {
-                    virDomainDiskDefFree(disk);
-                    goto no_memory;
-                }
-                if (!(disk->driverName = strdup("file"))) {
-                    virDomainDiskDefFree(disk);
-                    goto no_memory;
-                }
-                disk->bus = VIR_DOMAIN_DISK_BUS_FDC;
-
-                if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0) {
-                    virDomainDiskDefFree(disk);
-                    goto no_memory;
-                }
-                def->disks[def->ndisks++] = disk;
-            }
-        }
-    }
-
-    /* in case of HVM we have USB device emulation */
-    if (hvm &&
-        xenDaemonParseSxprUSB(conn, def, root) < 0)
-        goto error;
-
-    /* Character device config */
-    xenUnifiedLock(priv);
-    tty = xenStoreDomainGetConsolePath(conn, def->id);
-    xenUnifiedUnlock(priv);
-    if (hvm) {
-        tmp = sexpr_node(root, "domain/image/hvm/serial");
-        if (tmp && STRNEQ(tmp, "none")) {
-            virDomainChrDefPtr chr;
-            if ((chr = xenDaemonParseSxprChar(conn, tmp, tty)) == NULL)
-                goto error;
-            if (VIR_REALLOC_N(def->serials, def->nserials+1) < 0) {
-                virDomainChrDefFree(chr);
-                goto no_memory;
-            }
-            def->serials[def->nserials++] = chr;
-        }
-        tmp = sexpr_node(root, "domain/image/hvm/parallel");
-        if (tmp && STRNEQ(tmp, "none")) {
-            virDomainChrDefPtr chr;
-            /* XXX does XenD stuff parallel port tty info into xenstore somewhere ? */
-            if ((chr = xenDaemonParseSxprChar(conn, tmp, NULL)) == NULL)
-                goto error;
-            if (VIR_REALLOC_N(def->parallels, def->nparallels+1) < 0) {
-                virDomainChrDefFree(chr);
-                goto no_memory;
-            }
-            def->parallels[def->nparallels++] = chr;
-        }
-    } else {
-        /* Fake a paravirt console, since that's not in the sexpr */
-        if (!(def->console = xenDaemonParseSxprChar(conn, "pty", tty)))
-            goto error;
-    }
-    VIR_FREE(tty);
-
-
-    /* Sound device config */
-    if (hvm &&
-        (tmp = sexpr_node(root, "domain/image/hvm/soundhw")) != NULL &&
-        *tmp) {
-        if (xenDaemonParseSxprSound(conn, def, tmp) < 0)
-            goto error;
-    }
-
-    return def;
-
-no_memory:
-    virReportOOMError(conn);
-error:
-    VIR_FREE(tty);
-    virDomainDefFree(def);
-    return NULL;
-}
-
-virDomainDefPtr
-xenDaemonParseSxprString(virConnectPtr conn,
-                         const char *sexpr,
-                         int xendConfigVersion)
-{
-    struct sexpr *root = string2sexpr(sexpr);
-    virDomainDefPtr def;
-
-    if (!root)
-        return NULL;
-
-    def = xenDaemonParseSxpr(conn, root, xendConfigVersion, NULL);
-
-    sexpr_free(root);
-
-    return def;
-}
-
-
-/**
- * sexpr_to_xend_domain_info:
- * @root: an S-Expression describing a domain
- * @info: a info data structure to fill=up
- *
- * Internal routine filling up the info structure with the values from
- * the domain root provided.
- *
- * Returns 0 in case of success, -1 in case of error
- */
-static int
-sexpr_to_xend_domain_info(virDomainPtr domain, const struct sexpr *root,
-                          virDomainInfoPtr info)
-{
-    const char *flags;
-
-
-    if ((root == NULL) || (info == NULL))
-        return (-1);
-
-    info->memory = sexpr_u64(root, "domain/memory") << 10;
-    info->maxMem = sexpr_u64(root, "domain/maxmem") << 10;
-    flags = sexpr_node(root, "domain/state");
-
-    if (flags) {
-        if (strchr(flags, 'c'))
-            info->state = VIR_DOMAIN_CRASHED;
-        else if (strchr(flags, 's'))
-            info->state = VIR_DOMAIN_SHUTOFF;
-        else if (strchr(flags, 'd'))
-            info->state = VIR_DOMAIN_SHUTDOWN;
-        else if (strchr(flags, 'p'))
-            info->state = VIR_DOMAIN_PAUSED;
-        else if (strchr(flags, 'b'))
-            info->state = VIR_DOMAIN_BLOCKED;
-        else if (strchr(flags, 'r'))
-            info->state = VIR_DOMAIN_RUNNING;
-    } else {
-        /* Inactive domains don't have a state reported, so
-           mark them SHUTOFF, rather than NOSTATE */
-        if (domain->id < 0)
-            info->state = VIR_DOMAIN_SHUTOFF;
-        else
-            info->state = VIR_DOMAIN_NOSTATE;
-    }
-    info->cpuTime = sexpr_float(root, "domain/cpu_time") * 1000000000;
-    info->nrVirtCpu = sexpr_int(root, "domain/vcpus");
-    return (0);
-}
-
-/**
- * sexpr_to_xend_node_info:
- * @root: an S-Expression describing a domain
- * @info: a info data structure to fill up
- *
- * Internal routine filling up the info structure with the values from
- * the node root provided.
- *
- * Returns 0 in case of success, -1 in case of error
- */
-static int
-sexpr_to_xend_node_info(const struct sexpr *root, virNodeInfoPtr info)
-{
-    const char *machine;
-
-
-    if ((root == NULL) || (info == NULL))
-        return (-1);
-
-    machine = sexpr_node(root, "node/machine");
-    if (machine == NULL) {
-        info->model[0] = 0;
-    } else {
-        snprintf(&info->model[0], sizeof(info->model) - 1, "%s", machine);
-        info->model[sizeof(info->model) - 1] = 0;
-    }
-    info->memory = (unsigned long) sexpr_u64(root, "node/total_memory") << 10;
-
-    info->cpus = sexpr_int(root, "node/nr_cpus");
-    info->mhz = sexpr_int(root, "node/cpu_mhz");
-    info->nodes = sexpr_int(root, "node/nr_nodes");
-    info->sockets = sexpr_int(root, "node/sockets_per_node");
-    info->cores = sexpr_int(root, "node/cores_per_socket");
-    info->threads = sexpr_int(root, "node/threads_per_core");
-
-    /* Xen 3.2.0 replaces sockets_per_node with 'nr_cpus'.
-     * Old Xen calculated sockets_per_node using its internal
-     * nr_cpus / (nodes*cores*threads), so fake it ourselves
-     * in the same way
-     */
-    if (info->sockets == 0) {
-        int nr_cpus = sexpr_int(root, "node/nr_cpus");
-        int procs = info->nodes * info->cores * info->threads;
-        if (procs == 0) /* Sanity check in case of Xen bugs in futures..*/
-            return (-1);
-        info->sockets = nr_cpus / procs;
-        /* Should already be fine, but for further sanity make
-         * sure we have at least one socket
-         */
-        if (info->sockets == 0)
-            info->sockets = 1;
-    }
-    return (0);
-}
-
-
-/**
- * sexpr_to_xend_topology
- * @root: an S-Expression describing a node
- * @caps: capability info
- *
- * Internal routine populating capability info with
- * NUMA node mapping details
- *
- * Does nothing when the system doesn't support NUMA (not an error).
- *
- * Returns 0 in case of success, -1 in case of error
- */
-static int
-sexpr_to_xend_topology(virConnectPtr conn,
-                       const struct sexpr *root,
-                       virCapsPtr caps)
-{
-    const char *nodeToCpu;
-    const char *cur;
-    char *cpuset = NULL;
-    int *cpuNums = NULL;
-    int cell, cpu, nb_cpus;
-    int n = 0;
-    int numCpus;
-
-    nodeToCpu = sexpr_node(root, "node/node_to_cpu");
-    if (nodeToCpu == NULL)
-        return 0;               /* no NUMA support */
-
-    numCpus = sexpr_int(root, "node/nr_cpus");
-
-
-    if (VIR_ALLOC_N(cpuset, numCpus) < 0)
-        goto memory_error;
-    if (VIR_ALLOC_N(cpuNums, numCpus) < 0)
-        goto memory_error;
-
-    cur = nodeToCpu;
-    while (*cur != 0) {
-        /*
-         * Find the next NUMA cell described in the xend output
-         */
-        cur = strstr(cur, "node");
-        if (cur == NULL)
-            break;
-        cur += 4;
-        cell = virParseNumber(&cur);
-        if (cell < 0)
-            goto parse_error;
-        virSkipSpaces(&cur);
-        if (*cur != ':')
-            goto parse_error;
-        cur++;
-        virSkipSpaces(&cur);
-        if (STRPREFIX(cur, "no cpus")) {
-            nb_cpus = 0;
-            for (cpu = 0; cpu < numCpus; cpu++)
-                cpuset[cpu] = 0;
-        } else {
-            nb_cpus = virDomainCpuSetParse(conn, &cur, 'n', cpuset, numCpus);
-            if (nb_cpus < 0)
-                goto error;
-        }
-
-        for (n = 0, cpu = 0; cpu < numCpus; cpu++)
-            if (cpuset[cpu] == 1)
-                cpuNums[n++] = cpu;
-
-        if (virCapabilitiesAddHostNUMACell(caps,
-                                           cell,
-                                           nb_cpus,
-                                           cpuNums) < 0)
-            goto memory_error;
-    }
-    VIR_FREE(cpuNums);
-    VIR_FREE(cpuset);
-    return (0);
-
-  parse_error:
-    virXendError(conn, VIR_ERR_XEN_CALL, "%s", _("topology syntax error"));
-  error:
-    VIR_FREE(cpuNums);
-    VIR_FREE(cpuset);
-
-    return (-1);
-
-  memory_error:
-    VIR_FREE(cpuNums);
-    VIR_FREE(cpuset);
-    virReportOOMError(conn);
-    return (-1);
-}
-
-
-#ifndef PROXY
-/**
- * sexpr_to_domain:
- * @conn: an existing virtual connection block
- * @root: an S-Expression describing a domain
- *
- * Internal routine returning the associated virDomainPtr for this domain
- *
- * Returns the domain pointer or NULL in case of error.
- */
-static virDomainPtr
-sexpr_to_domain(virConnectPtr conn, const struct sexpr *root)
-{
-    virDomainPtr ret = NULL;
-    unsigned char uuid[VIR_UUID_BUFLEN];
-    const char *name;
-    const char *tmp;
-    xenUnifiedPrivatePtr priv;
-
-    if ((conn == NULL) || (root == NULL))
-        return(NULL);
-
-    priv = (xenUnifiedPrivatePtr) conn->privateData;
-
-    if (sexpr_uuid(uuid, root, "domain/uuid") < 0)
-        goto error;
-    name = sexpr_node(root, "domain/name");
-    if (name == NULL)
-        goto error;
-
-    ret = virGetDomain(conn, name, uuid);
-    if (ret == NULL) return NULL;
-
-    tmp = sexpr_node(root, "domain/domid");
-    /* New 3.0.4 XenD will not report a domid for inactive domains,
-     * so only error out for old XenD
-     */
-    if (!tmp && priv->xendConfigVersion < 3)
-        goto error;
-
-    if (tmp)
-        ret->id = sexpr_int(root, "domain/domid");
-    else
-        ret->id = -1; /* An inactive domain */
-
-    return (ret);
-
-error:
-    virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                 "%s", _("failed to parse Xend domain information"));
-    if (ret != NULL)
-        virUnrefDomain(ret);
-    return(NULL);
-}
-#endif /* !PROXY */
-
-/*****************************************************************
- ******
- ******
- ******
- ******
-             Refactored
- ******
- ******
- ******
- ******
- *****************************************************************/
-#ifndef PROXY
-/**
- * xenDaemonOpen:
- * @conn: an existing virtual connection block
- * @name: optional argument to select a connection type
- * @flags: combination of virDrvOpenFlag(s)
- *
- * Creates a localhost Xen Daemon connection
- *
- * Returns 0 in case of success, -1 in case of error.
- */
-virDrvOpenStatus
-xenDaemonOpen(virConnectPtr conn,
-              virConnectAuthPtr auth ATTRIBUTE_UNUSED,
-              int flags ATTRIBUTE_UNUSED)
-{
-    char *port = NULL;
-    int ret = VIR_DRV_OPEN_ERROR;
-
-    /* Switch on the scheme, which we expect to be NULL (file),
-     * "http" or "xen".
-     */
-    if (conn->uri->scheme == NULL) {
-        /* It should be a file access */
-        if (conn->uri->path == NULL) {
-            virXendError(NULL, VIR_ERR_NO_CONNECT, __FUNCTION__);
-            goto failed;
-        }
-        if (xenDaemonOpen_unix(conn, conn->uri->path) < 0 ||
-            xend_detect_config_version(conn) == -1)
-            goto failed;
-    }
-    else if (STRCASEEQ (conn->uri->scheme, "xen")) {
-        /*
-         * try first to open the unix socket
-         */
-        if (xenDaemonOpen_unix(conn, "/var/lib/xend/xend-socket") == 0 &&
-            xend_detect_config_version(conn) != -1)
-            goto done;
-
-        /*
-         * try though http on port 8000
-         */
-        if (xenDaemonOpen_tcp(conn, "localhost", "8000") < 0 ||
-            xend_detect_config_version(conn) == -1)
-            goto failed;
-    } else if (STRCASEEQ (conn->uri->scheme, "http")) {
-        if (conn->uri->port &&
-            virAsprintf(&port, "%d", conn->uri->port) == -1)
-            goto failed;
-
-        if (xenDaemonOpen_tcp(conn,
-                              conn->uri->server ? conn->uri->server : "localhost",
-                              port ? port : "8000") < 0 ||
-            xend_detect_config_version(conn) == -1)
-            goto failed;
-    } else {
-        virXendError(NULL, VIR_ERR_NO_CONNECT, __FUNCTION__);
-        goto failed;
-    }
-
- done:
-    ret = VIR_DRV_OPEN_SUCCESS;
-
-failed:
-    VIR_FREE(port);
-    return ret;
-}
-
-
-/**
- * xenDaemonClose:
- * @conn: an existing virtual connection block
- *
- * This method should be called when a connection to xend instance
- * initialized with xenDaemonOpen is no longer needed
- * to free the associated resources.
- *
- * Returns 0 in case of success, -1 in case of error
- */
-int
-xenDaemonClose(virConnectPtr conn ATTRIBUTE_UNUSED)
-{
-    return 0;
-}
-
-/**
- * xenDaemonDomainSuspend:
- * @domain: pointer to the Domain block
- *
- * Pause the domain, the domain is not scheduled anymore though its resources
- * are preserved. Use xenDaemonDomainResume() to resume execution.
- *
- * Returns 0 in case of success, -1 (with errno) in case of error.
- */
-int
-xenDaemonDomainSuspend(virDomainPtr domain)
-{
-    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
-        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                     __FUNCTION__);
-        return(-1);
-    }
-
-    if (domain->id < 0) {
-        virXendError(domain->conn, VIR_ERR_OPERATION_INVALID,
-                     _("Domain %s isn't running."), domain->name);
-        return(-1);
-    }
-
-    return xend_op(domain->conn, domain->name, "op", "pause", NULL);
-}
-
-/**
- * xenDaemonDomainResume:
- * @xend: pointer to the Xem Daemon block
- * @name: name for the domain
- *
- * Resume the domain after xenDaemonDomainSuspend() has been called
- *
- * Returns 0 in case of success, -1 (with errno) in case of error.
- */
-int
-xenDaemonDomainResume(virDomainPtr domain)
-{
-    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
-        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                     __FUNCTION__);
-        return(-1);
-    }
-
-    if (domain->id < 0) {
-        virXendError(domain->conn, VIR_ERR_OPERATION_INVALID,
-                     _("Domain %s isn't running."), domain->name);
-        return(-1);
-    }
-
-    return xend_op(domain->conn, domain->name, "op", "unpause", NULL);
-}
-
-/**
- * xenDaemonDomainShutdown:
- * @domain: pointer to the Domain block
- *
- * Shutdown the domain, the OS is requested to properly shutdown
- * and the domain may ignore it.  It will return immediately
- * after queuing the request.
- *
- * Returns 0 in case of success, -1 (with errno) in case of error.
- */
-int
-xenDaemonDomainShutdown(virDomainPtr domain)
-{
-    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
-        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                     __FUNCTION__);
-        return(-1);
-    }
-
-    if (domain->id < 0) {
-        virXendError(domain->conn, VIR_ERR_OPERATION_INVALID,
-                     _("Domain %s isn't running."), domain->name);
-        return(-1);
-    }
-
-    return xend_op(domain->conn, domain->name, "op", "shutdown", "reason", "poweroff", NULL);
-}
-
-/**
- * xenDaemonDomainReboot:
- * @domain: pointer to the Domain block
- * @flags: extra flags for the reboot operation, not used yet
- *
- * Reboot the domain, the OS is requested to properly shutdown
- * and restart but the domain may ignore it.  It will return immediately
- * after queuing the request.
- *
- * Returns 0 in case of success, -1 (with errno) in case of error.
- */
-int
-xenDaemonDomainReboot(virDomainPtr domain, unsigned int flags ATTRIBUTE_UNUSED)
-{
-    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
-        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                     __FUNCTION__);
-        return(-1);
-    }
-
-    if (domain->id < 0) {
-        virXendError(domain->conn, VIR_ERR_OPERATION_INVALID,
-                     _("Domain %s isn't running."), domain->name);
-        return(-1);
-    }
-
-    return xend_op(domain->conn, domain->name, "op", "shutdown", "reason", "reboot", NULL);
-}
-
-/**
- * xenDaemonDomainDestroy:
- * @domain: pointer to the Domain block
- *
- * Abruptly halt the domain, the OS is not properly shutdown and the
- * resources allocated for the domain are immediately freed, mounted
- * filesystems will be marked as uncleanly shutdown.
- * After calling this function, the domain's status will change to
- * dying and will go away completely once all of the resources have been
- * unmapped (usually from the backend devices).
- *
- * Returns 0 in case of success, -1 (with errno) in case of error.
- */
-int
-xenDaemonDomainDestroy(virDomainPtr domain)
-{
-    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
-        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                     __FUNCTION__);
-        return(-1);
-    }
-
-    if (domain->id < 0) {
-        virXendError(domain->conn, VIR_ERR_OPERATION_INVALID,
-                     _("Domain %s isn't running."), domain->name);
-        return(-1);
-    }
-
-    return xend_op(domain->conn, domain->name, "op", "destroy", NULL);
-}
-
-/**
- * xenDaemonDomainGetOSType:
- * @domain: a domain object
- *
- * Get the type of domain operation system.
- *
- * Returns the new string or NULL in case of error, the string must be
- *         freed by the caller.
- */
-static char *
-xenDaemonDomainGetOSType(virDomainPtr domain)
-{
-    char *type;
-    struct sexpr *root;
-    xenUnifiedPrivatePtr priv;
-
-    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
-        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                     __FUNCTION__);
-        return(NULL);
-    }
-
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-
-    if (domain->id < 0 && priv->xendConfigVersion < 3)
-        return(NULL);
-
-    /* can we ask for a subset ? worth it ? */
-    root = sexpr_get(domain->conn, "/xend/domain/%s?detail=1", domain->name);
-    if (root == NULL)
-        return(NULL);
-
-    if (sexpr_lookup(root, "domain/image/hvm")) {
-        type = strdup("hvm");
-    } else {
-        type = strdup("linux");
-    }
-
-    sexpr_free(root);
-
-    return(type);
-}
-
-/**
- * xenDaemonDomainSave:
- * @domain: pointer to the Domain block
- * @filename: path for the output file
- *
- * This method will suspend a domain and save its memory contents to
- * a file on disk.  Use xenDaemonDomainRestore() to restore a domain after
- * saving.
- * Note that for remote Xen Daemon the file path will be interpreted in
- * the remote host.
- *
- * Returns 0 in case of success, -1 (with errno) in case of error.
- */
-int
-xenDaemonDomainSave(virDomainPtr domain, const char *filename)
-{
-    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL) ||
-        (filename == NULL)) {
-        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                     __FUNCTION__);
-        return(-1);
-    }
-
-    if (domain->id < 0) {
-        virXendError(domain->conn, VIR_ERR_OPERATION_INVALID,
-                     _("Domain %s isn't running."), domain->name);
-        return(-1);
-    }
-
-    /* We can't save the state of Domain-0, that would mean stopping it too */
-    if (domain->id == 0) {
-        return(-1);
-    }
-
-    return xend_op(domain->conn, domain->name, "op", "save", "file", filename, NULL);
-}
-
-/**
- * xenDaemonDomainCoreDump:
- * @domain: pointer to the Domain block
- * @filename: path for the output file
- * @flags: extra flags, currently unused
- *
- * This method will dump the core of a domain on a given file for analysis.
- * Note that for remote Xen Daemon the file path will be interpreted in
- * the remote host.
- *
- * Returns 0 in case of success, -1 in case of error.
- */
-static int
-xenDaemonDomainCoreDump(virDomainPtr domain, const char *filename,
-                        int flags ATTRIBUTE_UNUSED)
-{
-    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL) ||
-        (filename == NULL)) {
-        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                     __FUNCTION__);
-        return(-1);
-    }
-
-    if (domain->id < 0) {
-        virXendError(domain->conn, VIR_ERR_OPERATION_INVALID,
-                     _("Domain %s isn't running."), domain->name);
-        return(-1);
-    }
-
-    return xend_op(domain->conn, domain->name, "op", "dump", "file", filename,
-                   "live", "0", "crash", "0", NULL);
-}
-
-/**
- * xenDaemonDomainRestore:
- * @conn: pointer to the Xem Daemon block
- * @filename: path for the output file
- *
- * This method will restore a domain saved to disk by xenDaemonDomainSave().
- * Note that for remote Xen Daemon the file path will be interpreted in
- * the remote host.
- *
- * Returns 0 in case of success, -1 (with errno) in case of error.
- */
-int
-xenDaemonDomainRestore(virConnectPtr conn, const char *filename)
-{
-    if ((conn == NULL) || (filename == NULL)) {
-        /* this should be caught at the interface but ... */
-        virXendError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
-    }
-    return xend_op(conn, "", "op", "restore", "file", filename, NULL);
-}
-#endif /* !PROXY */
-
-/**
- * xenDaemonDomainGetMaxMemory:
- * @domain: pointer to the domain block
- *
- * Ask the Xen Daemon for the maximum memory allowed for a domain
- *
- * Returns the memory size in kilobytes or 0 in case of error.
- */
-unsigned long
-xenDaemonDomainGetMaxMemory(virDomainPtr domain)
-{
-    unsigned long ret = 0;
-    struct sexpr *root;
-    xenUnifiedPrivatePtr priv;
-
-    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
-        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                     __FUNCTION__);
-        return(-1);
-    }
-
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-
-    if (domain->id < 0 && priv->xendConfigVersion < 3)
-        return(-1);
-
-    /* can we ask for a subset ? worth it ? */
-    root = sexpr_get(domain->conn, "/xend/domain/%s?detail=1", domain->name);
-    if (root == NULL)
-        return(0);
-
-    ret = (unsigned long) sexpr_u64(root, "domain/memory") << 10;
-    sexpr_free(root);
-
-    return(ret);
-}
-
-#ifndef PROXY
-/**
- * xenDaemonDomainSetMaxMemory:
- * @domain: pointer to the Domain block
- * @memory: The maximum memory in kilobytes
- *
- * This method will set the maximum amount of memory that can be allocated to
- * a domain.  Please note that a domain is able to allocate up to this amount
- * on its own.
- *
- * Returns 0 for success; -1 (with errno) on error
- */
-int
-xenDaemonDomainSetMaxMemory(virDomainPtr domain, unsigned long memory)
-{
-    char buf[1024];
-    xenUnifiedPrivatePtr priv;
-
-    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
-        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                     __FUNCTION__);
-        return(-1);
-    }
-
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-
-    if (domain->id < 0 && priv->xendConfigVersion < 3)
-        return(-1);
-
-    snprintf(buf, sizeof(buf), "%lu", memory >> 10);
-    return xend_op(domain->conn, domain->name, "op", "maxmem_set", "memory",
-                   buf, NULL);
-}
-
-/**
- * xenDaemonDomainSetMemory:
- * @domain: pointer to the Domain block
- * @memory: The target memory in kilobytes
- *
- * This method will set a target memory allocation for a given domain and
- * request that the guest meet this target.  The guest may or may not actually
- * achieve this target.  When this function returns, it does not signify that
- * the domain has actually reached that target.
- *
- * Memory for a domain can only be allocated up to the maximum memory setting.
- * There is no safe guard for allocations that are too small so be careful
- * when using this function to reduce a domain's memory usage.
- *
- * Returns 0 for success; -1 (with errno) on error
- */
-int
-xenDaemonDomainSetMemory(virDomainPtr domain, unsigned long memory)
-{
-    char buf[1024];
-    xenUnifiedPrivatePtr priv;
-
-    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
-        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                     __FUNCTION__);
-        return(-1);
-    }
-
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-
-    if (domain->id < 0 && priv->xendConfigVersion < 3)
-        return(-1);
-
-    snprintf(buf, sizeof(buf), "%lu", memory >> 10);
-    return xend_op(domain->conn, domain->name, "op", "mem_target_set",
-                   "target", buf, NULL);
-}
-
-#endif /* ! PROXY */
-
-virDomainDefPtr
-xenDaemonDomainFetch(virConnectPtr conn,
-                     int domid,
-                     const char *name,
-                     const char *cpus)
-{
-    struct sexpr *root;
-    xenUnifiedPrivatePtr priv;
-    virDomainDefPtr def;
-
-    if (name)
-        root = sexpr_get(conn, "/xend/domain/%s?detail=1", name);
-    else
-        root = sexpr_get(conn, "/xend/domain/%d?detail=1", domid);
-    if (root == NULL) {
-        virXendError (conn, VIR_ERR_XEN_CALL,
-                      "%s", _("xenDaemonDomainFetch failed to"
-                        " find this domain"));
-        return (NULL);
-    }
-
-    priv = (xenUnifiedPrivatePtr) conn->privateData;
-
-    if (!(def = xenDaemonParseSxpr(conn,
-                                   root,
-                                   priv->xendConfigVersion,
-                                   cpus)))
-        goto cleanup;
-
-cleanup:
-    sexpr_free(root);
-
-    return (def);
-}
-
-
-#ifndef PROXY
-/**
- * xenDaemonDomainDumpXML:
- * @domain: a domain object
- * @flags: potential dump flags
- * @cpus: list of cpu the domain is pinned to.
- *
- * Provide an XML description of the domain.
- *
- * Returns a 0 terminated UTF-8 encoded XML instance, or NULL in case of error.
- *         the caller must free() the returned value.
- */
-char *
-xenDaemonDomainDumpXML(virDomainPtr domain, int flags, const char *cpus)
-{
-    xenUnifiedPrivatePtr priv;
-    virDomainDefPtr def;
-    char *xml;
-
-    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
-        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                     __FUNCTION__);
-        return(NULL);
-    }
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-
-    if (domain->id < 0 && priv->xendConfigVersion < 3) {
-        // fall-through to the next driver to handle
-        return(NULL);
-    }
-
-    if (!(def = xenDaemonDomainFetch(domain->conn,
-                                     domain->id,
-                                     domain->name,
-                                     cpus)))
-        return(NULL);
-
-    xml = virDomainDefFormat(domain->conn, def, flags);
-
-    virDomainDefFree(def);
-
-    return xml;
-}
-#endif /* !PROXY */
-
-/**
- * xenDaemonDomainGetInfo:
- * @domain: a domain object
- * @info: pointer to a virDomainInfo structure allocated by the user
- *
- * This method looks up information about a domain and update the
- * information block provided.
- *
- * Returns 0 in case of success, -1 in case of error
- */
-int
-xenDaemonDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
-{
-    struct sexpr *root;
-    int ret;
-    xenUnifiedPrivatePtr priv;
-
-    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL) ||
-        (info == NULL)) {
-        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                     __FUNCTION__);
-        return(-1);
-    }
-
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-
-    if (domain->id < 0 && priv->xendConfigVersion < 3)
-        return(-1);
-
-    root = sexpr_get(domain->conn, "/xend/domain/%s?detail=1", domain->name);
-    if (root == NULL)
-        return (-1);
-
-    ret = sexpr_to_xend_domain_info(domain, root, info);
-    sexpr_free(root);
-    return (ret);
-}
-
-#ifndef PROXY
-/**
- * xenDaemonLookupByName:
- * @conn: A xend instance
- * @name: The name of the domain
- *
- * This method looks up information about a domain and returns
- * it in the form of a struct xend_domain.  This should be
- * free()'d when no longer needed.
- *
- * Returns domain info on success; NULL (with errno) on error
- */
-virDomainPtr
-xenDaemonLookupByName(virConnectPtr conn, const char *domname)
-{
-    struct sexpr *root;
-    virDomainPtr ret = NULL;
-
-    if ((conn == NULL) || (domname == NULL)) {
-        virXendError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return(NULL);
-    }
-
-    root = sexpr_get(conn, "/xend/domain/%s?detail=1", domname);
-    if (root == NULL)
-        goto error;
-
-    ret = sexpr_to_domain(conn, root);
-
-error:
-    sexpr_free(root);
-    return(ret);
-}
-#endif /* ! PROXY */
-
-/**
- * xenDaemonNodeGetInfo:
- * @conn: pointer to the Xen Daemon block
- * @info: pointer to a virNodeInfo structure allocated by the user
- *
- * Extract hardware information about the node.
- *
- * Returns 0 in case of success and -1 in case of failure.
- */
-int
-xenDaemonNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info) {
-    int ret = -1;
-    struct sexpr *root;
-
-    if (!VIR_IS_CONNECT(conn)) {
-        virXendError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return (-1);
-    }
-    if (info == NULL) {
-        virXendError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
-    }
-
-    root = sexpr_get(conn, "/xend/node/");
-    if (root == NULL)
-        return (-1);
-
-    ret = sexpr_to_xend_node_info(root, info);
-    sexpr_free(root);
-    return (ret);
-}
-
-/**
- * xenDaemonNodeGetTopology:
- * @conn: pointer to the Xen Daemon block
- * @caps: capabilities info
- *
- * This method retrieves a node's topology information.
- *
- * Returns -1 in case of error, 0 otherwise.
- */
-int
-xenDaemonNodeGetTopology(virConnectPtr conn,
-                         virCapsPtr caps) {
-    int ret = -1;
-    struct sexpr *root;
-
-    if (!VIR_IS_CONNECT(conn)) {
-        virXendError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return (-1);
-    }
-
-    if (caps == NULL) {
-        virXendError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
-    }
-
-    root = sexpr_get(conn, "/xend/node/");
-    if (root == NULL) {
-        return (-1);
-    }
-
-    ret = sexpr_to_xend_topology(conn, root, caps);
-    sexpr_free(root);
-    return (ret);
-}
-
-/**
- * xenDaemonGetVersion:
- * @conn: pointer to the Xen Daemon block
- * @hvVer: return value for the version of the running hypervisor (OUT)
- *
- * Get the version level of the Hypervisor running.
- *
- * Returns -1 in case of error, 0 otherwise. if the version can't be
- *    extracted by lack of capacities returns 0 and @hvVer is 0, otherwise
- *    @hvVer value is major * 1,000,000 + minor * 1,000 + release
- */
-int
-xenDaemonGetVersion(virConnectPtr conn, unsigned long *hvVer)
-{
-    struct sexpr *root;
-    int major, minor;
-    unsigned long version;
-
-    if (!VIR_IS_CONNECT(conn)) {
-        virXendError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return (-1);
-    }
-    if (hvVer == NULL) {
-        virXendError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
-    }
-    root = sexpr_get(conn, "/xend/node/");
-    if (root == NULL)
-        return(-1);
-
-    major = sexpr_int(root, "node/xen_major");
-    minor = sexpr_int(root, "node/xen_minor");
-    sexpr_free(root);
-    version = major * 1000000 + minor * 1000;
-    *hvVer = version;
-    return(0);
-}
-
-#ifndef PROXY
-/**
- * xenDaemonListDomains:
- * @conn: pointer to the hypervisor connection
- * @ids: array to collect the list of IDs of active domains
- * @maxids: size of @ids
- *
- * Collect the list of active domains, and store their ID in @maxids
- * TODO: this is quite expensive at the moment since there isn't one
- *       xend RPC providing both name and id for all domains.
- *
- * Returns the number of domain found or -1 in case of error
- */
-int
-xenDaemonListDomains(virConnectPtr conn, int *ids, int maxids)
-{
-    struct sexpr *root = NULL;
-    int ret = -1;
-    struct sexpr *_for_i, *node;
-    long id;
-
-    if (maxids == 0)
-        return(0);
-
-    if ((ids == NULL) || (maxids < 0))
-        goto error;
-    root = sexpr_get(conn, "/xend/domain");
-    if (root == NULL)
-        goto error;
-
-    ret = 0;
-
-    for (_for_i = root, node = root->u.s.car; _for_i->kind == SEXPR_CONS;
-         _for_i = _for_i->u.s.cdr, node = _for_i->u.s.car) {
-        if (node->kind != SEXPR_VALUE)
-            continue;
-        id = xenDaemonDomainLookupByName_ids(conn, node->u.value, NULL);
-        if (id >= 0)
-            ids[ret++] = (int) id;
-        if (ret >= maxids)
-            break;
-    }
-
-error:
-    sexpr_free(root);
-    return(ret);
-}
-
-/**
- * xenDaemonNumOfDomains:
- * @conn: pointer to the hypervisor connection
- *
- * Provides the number of active domains.
- *
- * Returns the number of domain found or -1 in case of error
- */
-static int
-xenDaemonNumOfDomains(virConnectPtr conn)
-{
-    struct sexpr *root = NULL;
-    int ret = -1;
-    struct sexpr *_for_i, *node;
-
-    root = sexpr_get(conn, "/xend/domain");
-    if (root == NULL)
-        goto error;
-
-    ret = 0;
-
-    for (_for_i = root, node = root->u.s.car; _for_i->kind == SEXPR_CONS;
-         _for_i = _for_i->u.s.cdr, node = _for_i->u.s.car) {
-        if (node->kind != SEXPR_VALUE)
-            continue;
-        ret++;
-    }
-
-error:
-    sexpr_free(root);
-    return(ret);
-}
-#endif /* ! PROXY */
-
-#ifndef PROXY
-/**
- * xenDaemonLookupByID:
- * @conn: pointer to the hypervisor connection
- * @id: the domain ID number
- *
- * Try to find a domain based on the hypervisor ID number
- *
- * Returns a new domain object or NULL in case of failure
- */
-virDomainPtr
-xenDaemonLookupByID(virConnectPtr conn, int id) {
-    char *name = NULL;
-    unsigned char uuid[VIR_UUID_BUFLEN];
-    virDomainPtr ret;
-
-    if (xenDaemonDomainLookupByID(conn, id, &name, uuid) < 0) {
-        goto error;
-    }
-
-    ret = virGetDomain(conn, name, uuid);
-    if (ret == NULL) goto error;
-
-    ret->id = id;
-    VIR_FREE(name);
-    return (ret);
-
- error:
-    VIR_FREE(name);
-    return (NULL);
-}
-
-/**
- * xenDaemonDomainSetVcpus:
- * @domain: pointer to domain object
- * @nvcpus: the new number of virtual CPUs for this domain
- *
- * Dynamically change the number of virtual CPUs used by the domain.
- *
- * Returns 0 for success; -1 (with errno) on error
- */
-int
-xenDaemonDomainSetVcpus(virDomainPtr domain, unsigned int vcpus)
-{
-    char buf[VIR_UUID_BUFLEN];
-    xenUnifiedPrivatePtr priv;
-
-    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)
-     || (vcpus < 1)) {
-        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                     __FUNCTION__);
-        return (-1);
-    }
-
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-
-    if (domain->id < 0 && priv->xendConfigVersion < 3)
-        return(-1);
-
-    snprintf(buf, sizeof(buf), "%d", vcpus);
-    return(xend_op(domain->conn, domain->name, "op", "set_vcpus", "vcpus",
-                   buf, NULL));
-}
-
-/**
- * xenDaemonDomainPinCpu:
- * @domain: pointer to domain object
- * @vcpu: virtual CPU number
- * @cpumap: pointer to a bit map of real CPUs (in 8-bit bytes)
- * @maplen: length of cpumap in bytes
- *
- * Dynamically change the real CPUs which can be allocated to a virtual CPU.
- * NOTE: The XenD cpu affinity map format changed from "[0,1,2]" to
- *       "0,1,2"
- *       the XenD cpu affinity works only after cset 19579.
- *       there is no fine grained xend version detection possible, so we
- *       use the old format for anything before version 3
- *
- * Returns 0 for success; -1 (with errno) on error
- */
-int
-xenDaemonDomainPinVcpu(virDomainPtr domain, unsigned int vcpu,
-                     unsigned char *cpumap, int maplen)
-{
-    char buf[VIR_UUID_BUFLEN], mapstr[sizeof(cpumap_t) * 64];
-    int i, j;
-    xenUnifiedPrivatePtr priv;
-
-    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)
-     || (cpumap == NULL) || (maplen < 1) || (maplen > (int)sizeof(cpumap_t))) {
-        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                     __FUNCTION__);
-        return (-1);
-    }
-
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-    if (priv->xendConfigVersion < 3) {
-        mapstr[0] = '[';
-        mapstr[1] = 0;
-    } else {
-        mapstr[0] = 0;
-    }
-
-    /* from bit map, build character string of mapped CPU numbers */
-    for (i = 0; i < maplen; i++) for (j = 0; j < 8; j++)
-     if (cpumap[i] & (1 << j)) {
-        snprintf(buf, sizeof(buf), "%d,", (8 * i) + j);
-        strcat(mapstr, buf);
-    }
-    if (priv->xendConfigVersion < 3)
-        mapstr[strlen(mapstr) - 1] = ']';
-    else
-        mapstr[strlen(mapstr) - 1] = 0;
-
-    snprintf(buf, sizeof(buf), "%d", vcpu);
-    return(xend_op(domain->conn, domain->name, "op", "pincpu", "vcpu", buf,
-                  "cpumap", mapstr, NULL));
-}
-
-/**
- * virDomainGetVcpus:
- * @domain: pointer to domain object, or NULL for Domain0
- * @info: pointer to an array of virVcpuInfo structures (OUT)
- * @maxinfo: number of structures in info array
- * @cpumaps: pointer to an bit map of real CPUs for all vcpus of this domain (in 8-bit bytes) (OUT)
- *     If cpumaps is NULL, then no cpumap information is returned by the API.
- *     It's assumed there is <maxinfo> cpumap in cpumaps array.
- *     The memory allocated to cpumaps must be (maxinfo * maplen) bytes
- *     (ie: calloc(maxinfo, maplen)).
- *     One cpumap inside cpumaps has the format described in virDomainPinVcpu() API.
- * @maplen: number of bytes in one cpumap, from 1 up to size of CPU map in
- *     underlying virtualization system (Xen...).
- *
- * Extract information about virtual CPUs of domain, store it in info array
- * and also in cpumaps if this pointer isn't NULL.
- *
- * Returns the number of info filled in case of success, -1 in case of failure.
- */
-int
-xenDaemonDomainGetVcpus(virDomainPtr domain, virVcpuInfoPtr info, int maxinfo,
-                        unsigned char *cpumaps, int maplen)
-{
-    struct sexpr *root, *s, *t;
-    virVcpuInfoPtr ipt = info;
-    int nbinfo = 0, oln;
-    unsigned char *cpumap;
-    int vcpu, cpu;
-
-    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)
-        || (info == NULL) || (maxinfo < 1)) {
-        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                     __FUNCTION__);
-        return (-1);
-    }
-    if (cpumaps != NULL && maplen < 1) {
-        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                     __FUNCTION__);
-        return (-1);
-    }
-
-    root = sexpr_get(domain->conn, "/xend/domain/%s?op=vcpuinfo", domain->name);
-    if (root == NULL)
-        return (-1);
-
-    if (cpumaps != NULL)
-        memset(cpumaps, 0, maxinfo * maplen);
-
-    /* scan the sexprs from "(vcpu (number x)...)" and get parameter values */
-    for (s = root; s->kind == SEXPR_CONS; s = s->u.s.cdr) {
-        if ((s->u.s.car->kind == SEXPR_CONS) &&
-            (s->u.s.car->u.s.car->kind == SEXPR_VALUE) &&
-            STREQ(s->u.s.car->u.s.car->u.value, "vcpu")) {
-            t = s->u.s.car;
-            vcpu = ipt->number = sexpr_int(t, "vcpu/number");
-            if ((oln = sexpr_int(t, "vcpu/online")) != 0) {
-                if (sexpr_int(t, "vcpu/running")) ipt->state = VIR_VCPU_RUNNING;
-                if (sexpr_int(t, "vcpu/blocked")) ipt->state = VIR_VCPU_BLOCKED;
-            }
-            else
-                ipt->state = VIR_VCPU_OFFLINE;
-            ipt->cpuTime = sexpr_float(t, "vcpu/cpu_time") * 1000000000;
-            ipt->cpu = oln ? sexpr_int(t, "vcpu/cpu") : -1;
-
-            if (cpumaps != NULL && vcpu >= 0 && vcpu < maxinfo) {
-                cpumap = (unsigned char *) VIR_GET_CPUMAP(cpumaps, maplen, vcpu);
-                /*
-                 * get sexpr from "(cpumap (x y z...))" and convert values
-                 * to bitmap
-                 */
-                for (t = t->u.s.cdr; t->kind == SEXPR_CONS; t = t->u.s.cdr)
-                    if ((t->u.s.car->kind == SEXPR_CONS) &&
-                        (t->u.s.car->u.s.car->kind == SEXPR_VALUE) &&
-                        STREQ(t->u.s.car->u.s.car->u.value, "cpumap") &&
-                        (t->u.s.car->u.s.cdr->kind == SEXPR_CONS)) {
-                        for (t = t->u.s.car->u.s.cdr->u.s.car; t->kind == SEXPR_CONS; t = t->u.s.cdr)
-                            if (t->u.s.car->kind == SEXPR_VALUE
-                                && virStrToLong_i(t->u.s.car->u.value, NULL, 10, &cpu) == 0
-                                && cpu >= 0
-                                && (VIR_CPU_MAPLEN(cpu+1) <= maplen)) {
-                                VIR_USE_CPU(cpumap, cpu);
-                            }
-                        break;
-                    }
-            }
-
-            if (++nbinfo == maxinfo) break;
-            ipt++;
-        }
-    }
-    sexpr_free(root);
-    return(nbinfo);
-}
-
-/**
- * xenDaemonLookupByUUID:
- * @conn: pointer to the hypervisor connection
- * @uuid: the raw UUID for the domain
- *
- * Try to lookup a domain on xend based on its UUID.
- *
- * Returns a new domain object or NULL in case of failure
- */
-virDomainPtr
-xenDaemonLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
-{
-    virDomainPtr ret;
-    char *name = NULL;
-    int id = -1;
-    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
-
-    /* Old approach for xen <= 3.0.3 */
-    if (priv->xendConfigVersion < 3) {
-        char **names, **tmp;
-        unsigned char ident[VIR_UUID_BUFLEN];
-        names = xenDaemonListDomainsOld(conn);
-        tmp = names;
-
-        if (names == NULL) {
-            return (NULL);
-        }
-        while (*tmp != NULL) {
-            id = xenDaemonDomainLookupByName_ids(conn, *tmp, &ident[0]);
-            if (id >= 0) {
-                if (!memcmp(uuid, ident, VIR_UUID_BUFLEN)) {
-                    name = strdup(*tmp);
-                    break;
-                }
-            }
-            tmp++;
-        }
-        VIR_FREE(names);
-    } else { /* New approach for xen >= 3.0.4 */
-        char *domname = NULL;
-        char uuidstr[VIR_UUID_STRING_BUFLEN];
-        struct sexpr *root = NULL;
-
-        virUUIDFormat(uuid, uuidstr);
-        root = sexpr_get(conn, "/xend/domain/%s?detail=1", uuidstr);
-        if (root == NULL)
-            return (NULL);
-        domname = (char*)sexpr_node(root, "domain/name");
-        if (sexpr_node(root, "domain/domid")) /* only active domains have domid */
-            id = sexpr_int(root, "domain/domid");
-        else
-            id = -1;
-        name = domname ? strdup(domname) : NULL;
-        sexpr_free(root);
-    }
-
-    if (name == NULL)
-        return (NULL);
-
-    ret = virGetDomain(conn, name, uuid);
-    if (ret == NULL) goto cleanup;
-
-    ret->id = id;
-
-  cleanup:
-    VIR_FREE(name);
-    return (ret);
-}
-
-/**
- * xenDaemonCreateXML:
- * @conn: pointer to the hypervisor connection
- * @xmlDesc: an XML description of the domain
- * @flags: an optional set of virDomainFlags
- *
- * Launch a new Linux guest domain, based on an XML description similar
- * to the one returned by virDomainGetXMLDesc()
- * This function may requires privileged access to the hypervisor.
- *
- * Returns a new domain object or NULL in case of failure
- */
-static virDomainPtr
-xenDaemonCreateXML(virConnectPtr conn, const char *xmlDesc,
-                     unsigned int flags ATTRIBUTE_UNUSED)
-{
-    int ret;
-    char *sexpr;
-    virDomainPtr dom = NULL;
-    xenUnifiedPrivatePtr priv;
-    virDomainDefPtr def;
-
-    priv = (xenUnifiedPrivatePtr) conn->privateData;
-
-    if (!(def = virDomainDefParseString(conn,
-                                        priv->caps,
-                                        xmlDesc,
-                                        VIR_DOMAIN_XML_INACTIVE)))
-        return (NULL);
-
-    if (!(sexpr = xenDaemonFormatSxpr(conn, def, priv->xendConfigVersion))) {
-        virDomainDefFree(def);
-        return (NULL);
-    }
-
-    ret = xenDaemonDomainCreateXML(conn, sexpr);
-    VIR_FREE(sexpr);
-    if (ret != 0) {
-        goto error;
-    }
-
-    /* This comes before wait_for_devices, to ensure that latter
-       cleanup will destroy the domain upon failure */
-    if (!(dom = virDomainLookupByName(conn, def->name)))
-        goto error;
-
-    if (xend_wait_for_devices(conn, def->name) < 0)
-        goto error;
-
-    if (xenDaemonDomainResume(dom) < 0)
-        goto error;
-
-    virDomainDefFree(def);
-    return (dom);
-
-  error:
-    /* Make sure we don't leave a still-born domain around */
-    if (dom != NULL) {
-        xenDaemonDomainDestroy(dom);
-        virUnrefDomain(dom);
-    }
-    virDomainDefFree(def);
-    return (NULL);
-}
-
-/**
- * xenDaemonAttachDevice:
- * @domain: pointer to domain object
- * @xml: pointer to XML description of device
- *
- * Create a virtual device attachment to backend.
- * XML description is translated into S-expression.
- *
- * Returns 0 in case of success, -1 in case of failure.
- */
-static int
-xenDaemonAttachDevice(virDomainPtr domain, const char *xml)
-{
-    xenUnifiedPrivatePtr priv;
-    char *sexpr = NULL;
-    int ret = -1;
-    virDomainDeviceDefPtr dev = NULL;
-    virDomainDefPtr def = NULL;
-    virBuffer buf = VIR_BUFFER_INITIALIZER;
-    char class[8], ref[80];
-
-    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
-        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                     __FUNCTION__);
-        return -1;
-    }
-
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-
-    /*
-     * on older Xen without the inactive guests management
-     * avoid doing this on inactive guests
-     */
-    if ((domain->id < 0) && (priv->xendConfigVersion < 3))
-        return -1;
-
-    if (!(def = xenDaemonDomainFetch(domain->conn,
-                                     domain->id,
-                                     domain->name,
-                                     NULL)))
-        goto cleanup;
-
-    if (!(dev = virDomainDeviceDefParse(domain->conn,
-                                        priv->caps,
-                                        def, xml, VIR_DOMAIN_XML_INACTIVE)))
-        goto cleanup;
-
-
-    switch (dev->type) {
-    case VIR_DOMAIN_DEVICE_DISK:
-        if (xenDaemonFormatSxprDisk(domain->conn,
-                                    dev->data.disk,
-                                    &buf,
-                                    STREQ(def->os.type, "hvm") ? 1 : 0,
-                                    priv->xendConfigVersion, 1) < 0)
-            goto cleanup;
-        break;
-
-    case VIR_DOMAIN_DEVICE_NET:
-        if (xenDaemonFormatSxprNet(domain->conn,
-                                   dev->data.net,
-                                   &buf,
-                                   STREQ(def->os.type, "hvm") ? 1 : 0,
-                                   priv->xendConfigVersion, 1) < 0)
-            goto cleanup;
-        break;
-
-    case VIR_DOMAIN_DEVICE_HOSTDEV:
-        if (dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
-            dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
-            if (xenDaemonFormatSxprOnePCI(domain->conn,
-                                          dev->data.hostdev,
-                                          &buf) < 0)
-                goto cleanup;
-        } else {
-            virXendError(domain->conn, VIR_ERR_NO_SUPPORT, "%s",
-                         _("unsupported device type"));
-            goto cleanup;
-        }
-        break;
-
-    default:
-        virXendError(domain->conn, VIR_ERR_NO_SUPPORT, "%s",
-                     _("unsupported device type"));
-        goto cleanup;
-    }
-
-    sexpr = virBufferContentAndReset(&buf);
-
-    if (virDomainXMLDevID(domain, dev, class, ref, sizeof(ref))) {
-        /* device doesn't exist, define it */
-        ret = xend_op(domain->conn, domain->name, "op", "device_create",
-                      "config", sexpr, NULL);
-    }
-    else {
-        /* device exists, attempt to modify it */
-        ret = xend_op(domain->conn, domain->name, "op", "device_configure",
-                      "config", sexpr, "dev", ref, NULL);
-    }
-
-cleanup:
-    VIR_FREE(sexpr);
-    virDomainDefFree(def);
-    virDomainDeviceDefFree(dev);
-    return ret;
-}
-
-/**
- * xenDaemonDetachDevice:
- * @domain: pointer to domain object
- * @xml: pointer to XML description of device
- *
- * Destroy a virtual device attachment to backend.
- *
- * Returns 0 in case of success, -1 in case of failure.
- */
-static int
-xenDaemonDetachDevice(virDomainPtr domain, const char *xml)
-{
-    xenUnifiedPrivatePtr priv;
-    char class[8], ref[80];
-    virDomainDeviceDefPtr dev = NULL;
-    virDomainDefPtr def = NULL;
-    int ret = -1;
-
-    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
-        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                     __FUNCTION__);
-        return (-1);
-    }
-
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-
-    /*
-     * on older Xen without the inactive guests management
-     * avoid doing this on inactive guests
-     */
-    if ((domain->id < 0) && (priv->xendConfigVersion < 3))
-        return -1;
-
-    if (!(def = xenDaemonDomainFetch(domain->conn,
-                                     domain->id,
-                                     domain->name,
-                                     NULL)))
-        goto cleanup;
-
-    if (!(dev = virDomainDeviceDefParse(domain->conn,
-                                        priv->caps,
-                                        def, xml, VIR_DOMAIN_XML_INACTIVE)))
-        goto cleanup;
-
-    if (virDomainXMLDevID(domain, dev, class, ref, sizeof(ref)))
-        goto cleanup;
-
-    ret = xend_op(domain->conn, domain->name, "op", "device_destroy",
-                  "type", class, "dev", ref, "force", "0", "rm_cfg", "1", NULL);
-
-cleanup:
-    virDomainDefFree(def);
-    virDomainDeviceDefFree(dev);
-
-    return ret;
-}
-
-int
-xenDaemonDomainGetAutostart(virDomainPtr domain,
-                            int *autostart)
-{
-    struct sexpr *root;
-    const char *tmp;
-    xenUnifiedPrivatePtr priv;
-
-    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
-        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                     __FUNCTION__);
-        return (-1);
-    }
-
-    /* xm_internal.c (the support for defined domains from /etc/xen
-     * config files used by old Xen) will handle this.
-     */
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-    if (priv->xendConfigVersion < 3)
-        return(-1);
-
-    root = sexpr_get(domain->conn, "/xend/domain/%s?detail=1", domain->name);
-    if (root == NULL) {
-        virXendError (domain->conn, VIR_ERR_XEN_CALL,
-                      "%s", _("xenDaemonGetAutostart failed to find this domain"));
-        return (-1);
-    }
-
-    *autostart = 0;
-
-    tmp = sexpr_node(root, "domain/on_xend_start");
-    if (tmp && STREQ(tmp, "start")) {
-        *autostart = 1;
-    }
-
-    sexpr_free(root);
-    return 0;
-}
-
-int
-xenDaemonDomainSetAutostart(virDomainPtr domain,
-                            int autostart)
-{
-    struct sexpr *root, *autonode;
-    const char *autostr;
-    char buf[4096];
-    int ret = -1;
-    xenUnifiedPrivatePtr priv;
-
-    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
-        virXendError((domain ? domain->conn : NULL), VIR_ERR_INTERNAL_ERROR,
-                     __FUNCTION__);
-        return (-1);
-    }
-
-    /* xm_internal.c (the support for defined domains from /etc/xen
-     * config files used by old Xen) will handle this.
-     */
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-    if (priv->xendConfigVersion < 3)
-        return(-1);
-
-    root = sexpr_get(domain->conn, "/xend/domain/%s?detail=1", domain->name);
-    if (root == NULL) {
-        virXendError (domain->conn, VIR_ERR_XEN_CALL,
-                      "%s", _("xenDaemonSetAutostart failed to find this domain"));
-        return (-1);
-    }
-
-    autostr = sexpr_node(root, "domain/on_xend_start");
-    if (autostr) {
-        if (!STREQ(autostr, "ignore") && !STREQ(autostr, "start")) {
-            virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR,
-                         "%s", _("unexpected value from on_xend_start"));
-            goto error;
-        }
-
-        // Change the autostart value in place, then define the new sexpr
-        autonode = sexpr_lookup(root, "domain/on_xend_start");
-        VIR_FREE(autonode->u.s.car->u.value);
-        autonode->u.s.car->u.value = (autostart ? strdup("start")
-                                                : strdup("ignore"));
-        if (!(autonode->u.s.car->u.value)) {
-            virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR,
-                         "%s", _("no memory"));
-            goto error;
-        }
-
-        if (sexpr2string(root, buf, sizeof(buf)) == 0) {
-            virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR,
-                         "%s", _("sexpr2string failed"));
-            goto error;
-        }
-        if (xend_op(domain->conn, "", "op", "new", "config", buf, NULL) != 0) {
-            virXendError(domain->conn, VIR_ERR_XEN_CALL,
-                         "%s", _("Failed to redefine sexpr"));
-            goto error;
-        }
-    } else {
-        virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR,
-                     "%s", _("on_xend_start not present in sexpr"));
-        goto error;
-    }
-
-    ret = 0;
-  error:
-    sexpr_free(root);
-    return ret;
-}
-
-int
-xenDaemonDomainMigratePrepare (virConnectPtr dconn,
-                               char **cookie ATTRIBUTE_UNUSED,
-                               int *cookielen ATTRIBUTE_UNUSED,
-                               const char *uri_in,
-                               char **uri_out,
-                               unsigned long flags ATTRIBUTE_UNUSED,
-                               const char *dname ATTRIBUTE_UNUSED,
-                               unsigned long resource ATTRIBUTE_UNUSED)
-{
-    int r;
-    char hostname [HOST_NAME_MAX+1];
-
-    /* If uri_in is NULL, get the current hostname as a best guess
-     * of how the source host should connect to us.  Note that caller
-     * deallocates this string.
-     */
-    if (uri_in == NULL) {
-        r = gethostname (hostname, HOST_NAME_MAX+1);
-        if (r == -1) {
-            virReportSystemError(dconn, errno,
-                                 _("unable to resolve name %s"), hostname);
-            return -1;
-        }
-        *uri_out = strdup (hostname);
-        if (*uri_out == NULL) {
-            virReportOOMError(dconn);
-            return -1;
-        }
-    }
-
-    return 0;
-}
-
-int
-xenDaemonDomainMigratePerform (virDomainPtr domain,
-                               const char *cookie ATTRIBUTE_UNUSED,
-                               int cookielen ATTRIBUTE_UNUSED,
-                               const char *uri,
-                               unsigned long flags,
-                               const char *dname,
-                               unsigned long bandwidth)
-{
-    /* Upper layers have already checked domain. */
-    virConnectPtr conn = domain->conn;
-    /* NB: Passing port=0 to xend means it ignores
-     * the port.  However this is somewhat specific to
-     * the internals of the xend Python code. (XXX).
-     */
-    char port[16] = "0";
-    char live[2] = "0";
-    int ret;
-    char *p, *hostname = NULL;
-
-    /* Xen doesn't support renaming domains during migration. */
-    if (dname) {
-        virXendError (conn, VIR_ERR_NO_SUPPORT,
-                      "%s", _("xenDaemonDomainMigrate: Xen does not support"
-                        " renaming domains during migration"));
-        return -1;
-    }
-
-    /* Xen (at least up to 3.1.0) takes a resource parameter but
-     * ignores it.
-     */
-    if (bandwidth) {
-        virXendError (conn, VIR_ERR_NO_SUPPORT,
-                      "%s", _("xenDaemonDomainMigrate: Xen does not support"
-                        " bandwidth limits during migration"));
-        return -1;
-    }
-
-    /* Check the flags. */
-    if ((flags & VIR_MIGRATE_LIVE)) {
-        strcpy (live, "1");
-        flags &= ~VIR_MIGRATE_LIVE;
-    }
-    if (flags != 0) {
-        virXendError (conn, VIR_ERR_NO_SUPPORT,
-                      "%s", _("xenDaemonDomainMigrate: unsupported flag"));
-        return -1;
-    }
-
-    /* Set hostname and port.
-     *
-     * URI is non-NULL (guaranteed by caller).  We expect either
-     * "hostname", "hostname:port" or "xenmigr://hostname[:port]/".
-     */
-    if (strstr (uri, "//")) {   /* Full URI. */
-        xmlURIPtr uriptr = xmlParseURI (uri);
-        if (!uriptr) {
-            virXendError (conn, VIR_ERR_INVALID_ARG,
-                          "%s", _("xenDaemonDomainMigrate: invalid URI"));
-            return -1;
-        }
-        if (uriptr->scheme && STRCASENEQ (uriptr->scheme, "xenmigr")) {
-            virXendError (conn, VIR_ERR_INVALID_ARG,
-                          "%s", _("xenDaemonDomainMigrate: only xenmigr://"
-                            " migrations are supported by Xen"));
-            xmlFreeURI (uriptr);
-            return -1;
-        }
-        if (!uriptr->server) {
-            virXendError (conn, VIR_ERR_INVALID_ARG,
-                          "%s", _("xenDaemonDomainMigrate: a hostname must be"
-                            " specified in the URI"));
-            xmlFreeURI (uriptr);
-            return -1;
-        }
-        hostname = strdup (uriptr->server);
-        if (!hostname) {
-            virReportOOMError (conn);
-            xmlFreeURI (uriptr);
-            return -1;
-        }
-        if (uriptr->port)
-            snprintf (port, sizeof port, "%d", uriptr->port);
-        xmlFreeURI (uriptr);
-    }
-    else if ((p = strrchr (uri, ':')) != NULL) { /* "hostname:port" */
-        int port_nr, n;
-
-        if (sscanf (p+1, "%d", &port_nr) != 1) {
-            virXendError (conn, VIR_ERR_INVALID_ARG,
-                          "%s", _("xenDaemonDomainMigrate: invalid port number"));
-            return -1;
-        }
-        snprintf (port, sizeof port, "%d", port_nr);
-
-        /* Get the hostname. */
-        n = p - uri; /* n = Length of hostname in bytes. */
-        hostname = strdup (uri);
-        if (!hostname) {
-            virReportOOMError (conn);
-            return -1;
-        }
-        hostname[n] = '\0';
-    }
-    else {                      /* "hostname" (or IP address) */
-        hostname = strdup (uri);
-        if (!hostname) {
-            virReportOOMError (conn);
-            return -1;
-        }
-    }
-
-    DEBUG("hostname = %s, port = %s", hostname, port);
-
-    /* Make the call. */
-    ret = xend_op (domain->conn, domain->name,
-                   "op", "migrate",
-                   "destination", hostname,
-                   "live", live,
-                   "port", port,
-                   "node", "-1",
-                   "ssl", "0",
-                   "resource", "0", /* required, xend ignores it */
-                   NULL);
-    VIR_FREE (hostname);
-
-    DEBUG0("migration done");
-
-    return ret;
-}
-
-virDomainPtr xenDaemonDomainDefineXML(virConnectPtr conn, const char *xmlDesc) {
-    int ret;
-    char *sexpr;
-    virDomainPtr dom;
-    xenUnifiedPrivatePtr priv;
-    virDomainDefPtr def;
-
-    priv = (xenUnifiedPrivatePtr) conn->privateData;
-
-    if (priv->xendConfigVersion < 3)
-        return(NULL);
-
-    if (!(def = virDomainDefParseString(conn, priv->caps, xmlDesc,
-                                        VIR_DOMAIN_XML_INACTIVE))) {
-        virXendError(conn, VIR_ERR_XML_ERROR,
-                     "%s", _("failed to parse domain description"));
-        return (NULL);
-    }
-
-    if (!(sexpr = xenDaemonFormatSxpr(conn, def, priv->xendConfigVersion))) {
-        virXendError(conn, VIR_ERR_XML_ERROR,
-                     "%s", _("failed to build sexpr"));
-        goto error;
-    }
-
-    DEBUG("Defining w/ sexpr: \n%s", sexpr);
-
-    ret = xend_op(conn, "", "op", "new", "config", sexpr, NULL);
-    VIR_FREE(sexpr);
-    if (ret != 0) {
-        virXendError(conn, VIR_ERR_XEN_CALL,
-                     _("Failed to create inactive domain %s\n"), def->name);
-        goto error;
-    }
-
-    dom = virDomainLookupByName(conn, def->name);
-    if (dom == NULL) {
-        goto error;
-    }
-    virDomainDefFree(def);
-    return (dom);
-
-  error:
-    virDomainDefFree(def);
-    return (NULL);
-}
-int xenDaemonDomainCreate(virDomainPtr domain)
-{
-    xenUnifiedPrivatePtr priv;
-    int ret;
-    virDomainPtr tmp;
-
-    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
-        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                     __FUNCTION__);
-        return(-1);
-    }
-
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-
-    if (priv->xendConfigVersion < 3)
-        return(-1);
-
-    ret = xend_op(domain->conn, domain->name, "op", "start", NULL);
-
-    if (ret != -1) {
-        /* Need to force a refresh of this object's ID */
-        tmp = virDomainLookupByName(domain->conn, domain->name);
-        if (tmp) {
-            domain->id = tmp->id;
-            virDomainFree(tmp);
-        }
-    }
-    return ret;
-}
-
-int xenDaemonDomainUndefine(virDomainPtr domain)
-{
-    xenUnifiedPrivatePtr priv;
-
-    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
-        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                     __FUNCTION__);
-        return(-1);
-    }
-
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-
-    if (priv->xendConfigVersion < 3)
-        return(-1);
-
-    return xend_op(domain->conn, domain->name, "op", "delete", NULL);
-}
-
-/**
- * xenDaemonNumOfDomains:
- * @conn: pointer to the hypervisor connection
- *
- * Provides the number of active domains.
- *
- * Returns the number of domain found or -1 in case of error
- */
-static int
-xenDaemonNumOfDefinedDomains(virConnectPtr conn)
-{
-    struct sexpr *root = NULL;
-    int ret = -1;
-    struct sexpr *_for_i, *node;
-    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
-
-    /* xm_internal.c (the support for defined domains from /etc/xen
-     * config files used by old Xen) will handle this.
-     */
-    if (priv->xendConfigVersion < 3)
-        return(-1);
-
-    root = sexpr_get(conn, "/xend/domain?state=halted");
-    if (root == NULL)
-        goto error;
-
-    ret = 0;
-
-    for (_for_i = root, node = root->u.s.car; _for_i->kind == SEXPR_CONS;
-         _for_i = _for_i->u.s.cdr, node = _for_i->u.s.car) {
-        if (node->kind != SEXPR_VALUE)
-            continue;
-        ret++;
-    }
-
-error:
-    sexpr_free(root);
-    return(ret);
-}
-
-static int
-xenDaemonListDefinedDomains(virConnectPtr conn, char **const names, int maxnames) {
-    struct sexpr *root = NULL;
-    int ret = -1;
-    struct sexpr *_for_i, *node;
-    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
-
-    if (priv->xendConfigVersion < 3)
-        return(-1);
-
-    if ((names == NULL) || (maxnames < 0))
-        goto error;
-    if (maxnames == 0)
-        return(0);
-
-    root = sexpr_get(conn, "/xend/domain?state=halted");
-    if (root == NULL)
-        goto error;
-
-    ret = 0;
-
-    for (_for_i = root, node = root->u.s.car; _for_i->kind == SEXPR_CONS;
-         _for_i = _for_i->u.s.cdr, node = _for_i->u.s.car) {
-        if (node->kind != SEXPR_VALUE)
-            continue;
-
-        names[ret++] = strdup(node->u.value);
-        if (ret >= maxnames)
-            break;
-    }
-
-error:
-    sexpr_free(root);
-    return(ret);
-}
-
-/**
- * xenDaemonGetSchedulerType:
- * @domain: pointer to the Domain block
- * @nparams: give a number of scheduler parameters
- *
- * Get the scheduler type of Xen
- *
- * Returns a scheduler name (credit or sedf) which must be freed by the
- * caller or NULL in case of failure
- */
-static char *
-xenDaemonGetSchedulerType(virDomainPtr domain, int *nparams)
-{
-    xenUnifiedPrivatePtr priv;
-    struct sexpr *root;
-    const char *ret = NULL;
-    char *schedulertype = NULL;
-
-    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)
-        || (nparams == NULL)) {
-        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                     __FUNCTION__);
-        return NULL;
-    }
-
-    /* Support only xendConfigVersion >=4 */
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-    if (priv->xendConfigVersion < 4) {
-        virXendError (domain->conn, VIR_ERR_NO_SUPPORT,
-                      "%s", _("unsupported in xendConfigVersion < 4"));
-        return NULL;
-    }
-
-    root = sexpr_get(domain->conn, "/xend/node/");
-    if (root == NULL)
-        return NULL;
-
-    /* get xen_scheduler from xend/node */
-    ret = sexpr_node(root, "node/xen_scheduler");
-    if (ret == NULL){
-        virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR,
-                     "%s", _("node information incomplete, missing scheduler name"));
-        goto error;
-    }
-    if (STREQ (ret, "credit")) {
-        schedulertype = strdup("credit");
-        if (schedulertype == NULL){
-            virXendError(domain->conn, VIR_ERR_SYSTEM_ERROR, "%s", _("strdup failed"));
-            goto error;
-        }
-        *nparams = XEN_SCHED_CRED_NPARAM;
-    } else if (STREQ (ret, "sedf")) {
-        schedulertype = strdup("sedf");
-        if (schedulertype == NULL){
-            virXendError(domain->conn, VIR_ERR_SYSTEM_ERROR, "%s", _("strdup failed"));
-            goto error;
-        }
-        *nparams = XEN_SCHED_SEDF_NPARAM;
-    } else {
-        virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR, "%s", _("Unknown scheduler"));
-        goto error;
-    }
-
-error:
-    sexpr_free(root);
-    return schedulertype;
-
-}
-
-static const char *str_weight = "weight";
-static const char *str_cap = "cap";
-
-/**
- * xenDaemonGetSchedulerParameters:
- * @domain: pointer to the Domain block
- * @params: pointer to scheduler parameters
- *          This memory area must be allocated by the caller
- * @nparams: a number of scheduler parameters which should be same as a
- *           given number from xenDaemonGetSchedulerType()
- *
- * Get the scheduler parameters
- *
- * Returns 0 or -1 in case of failure
- */
-static int
-xenDaemonGetSchedulerParameters(virDomainPtr domain,
-                                virSchedParameterPtr params, int *nparams)
-{
-    xenUnifiedPrivatePtr priv;
-    struct sexpr *root;
-    char *sched_type = NULL;
-    int sched_nparam = 0;
-    int ret = -1;
-
-    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)
-        || (params == NULL) || (nparams == NULL)) {
-        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                     __FUNCTION__);
-        return (-1);
-    }
-
-    /* Support only xendConfigVersion >=4 */
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-    if (priv->xendConfigVersion < 4) {
-        virXendError (domain->conn, VIR_ERR_NO_SUPPORT,
-                      "%s", _("unsupported in xendConfigVersion < 4"));
-        return (-1);
-    }
-
-    /* look up the information by domain name */
-    root = sexpr_get(domain->conn, "/xend/domain/%s?detail=1", domain->name);
-    if (root == NULL)
-        return (-1);
-
-    /* get the scheduler type */
-    sched_type = xenDaemonGetSchedulerType(domain, &sched_nparam);
-    if (sched_type == NULL) {
-        virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR,
-                     "%s", _("Failed to get a scheduler name"));
-        goto error;
-    }
-
-    switch (sched_nparam){
-        case XEN_SCHED_SEDF_NPARAM:
-            /* TODO: Implement for Xen/SEDF */
-            TODO
-            goto error;
-        case XEN_SCHED_CRED_NPARAM:
-            /* get cpu_weight/cpu_cap from xend/domain */
-            if (sexpr_node(root, "domain/cpu_weight") == NULL) {
-                virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR,
-                        "%s", _("domain information incomplete, missing cpu_weight"));
-                goto error;
-            }
-            if (sexpr_node(root, "domain/cpu_cap") == NULL) {
-                virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR,
-                        "%s", _("domain information incomplete, missing cpu_cap"));
-                goto error;
-            }
-
-            strncpy (params[0].field, str_weight, VIR_DOMAIN_SCHED_FIELD_LENGTH);
-            params[0].field[VIR_DOMAIN_SCHED_FIELD_LENGTH-1] = '\0';
-            params[0].type = VIR_DOMAIN_SCHED_FIELD_UINT;
-            params[0].value.ui = sexpr_int(root, "domain/cpu_weight");
-
-            strncpy (params[1].field, str_cap, VIR_DOMAIN_SCHED_FIELD_LENGTH);
-            params[1].field[VIR_DOMAIN_SCHED_FIELD_LENGTH-1] = '\0';
-            params[1].type = VIR_DOMAIN_SCHED_FIELD_UINT;
-            params[1].value.ui = sexpr_int(root, "domain/cpu_cap");
-            *nparams = XEN_SCHED_CRED_NPARAM;
-            ret = 0;
-            break;
-        default:
-            virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR, "%s", _("Unknown scheduler"));
-            goto error;
-    }
-
-error:
-    sexpr_free(root);
-    VIR_FREE(sched_type);
-    return (ret);
-}
-
-/**
- * xenDaemonSetSchedulerParameters:
- * @domain: pointer to the Domain block
- * @params: pointer to scheduler parameters
- * @nparams: a number of scheduler setting parameters
- *
- * Set the scheduler parameters
- *
- * Returns 0 or -1 in case of failure
- */
-static int
-xenDaemonSetSchedulerParameters(virDomainPtr domain,
-                                virSchedParameterPtr params, int nparams)
-{
-    xenUnifiedPrivatePtr priv;
-    struct sexpr *root;
-    char *sched_type = NULL;
-    int i;
-    int sched_nparam = 0;
-    int ret = -1;
-
-    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)
-        || (params == NULL)) {
-        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                     __FUNCTION__);
-        return (-1);
-    }
-
-    /* Support only xendConfigVersion >=4 and active domains */
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-    if (priv->xendConfigVersion < 4) {
-        virXendError (domain->conn, VIR_ERR_NO_SUPPORT,
-                      "%s", _("unsupported in xendConfigVersion < 4"));
-        return (-1);
-    }
-
-    /* look up the information by domain name */
-    root = sexpr_get(domain->conn, "/xend/domain/%s?detail=1", domain->name);
-    if (root == NULL)
-        return (-1);
-
-    /* get the scheduler type */
-    sched_type = xenDaemonGetSchedulerType(domain, &sched_nparam);
-    if (sched_type == NULL) {
-        virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR,
-                     "%s", _("Failed to get a scheduler name"));
-        goto error;
-    }
-
-    switch (sched_nparam){
-        case XEN_SCHED_SEDF_NPARAM:
-            /* TODO: Implement for Xen/SEDF */
-            TODO
-            goto error;
-        case XEN_SCHED_CRED_NPARAM: {
-            char buf_weight[VIR_UUID_BUFLEN];
-            char buf_cap[VIR_UUID_BUFLEN];
-            const char *weight = NULL;
-            const char *cap = NULL;
-
-            /* get the scheduler parameters */
-            memset(&buf_weight, 0, VIR_UUID_BUFLEN);
-            memset(&buf_cap, 0, VIR_UUID_BUFLEN);
-            for (i = 0; i < nparams; i++) {
-                if (STREQ (params[i].field, str_weight) &&
-                    params[i].type == VIR_DOMAIN_SCHED_FIELD_UINT) {
-                    snprintf(buf_weight, sizeof(buf_weight), "%u", params[i].value.ui);
-                } else if (STREQ (params[i].field, str_cap) &&
-                    params[i].type == VIR_DOMAIN_SCHED_FIELD_UINT) {
-                    snprintf(buf_cap, sizeof(buf_cap), "%u", params[i].value.ui);
-                } else {
-                    virXendError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-                    goto error;
-                }
-            }
-
-            /* if not get the scheduler parameter, set the current setting */
-            if (strlen(buf_weight) == 0) {
-                weight = sexpr_node(root, "domain/cpu_weight");
-                if (weight == NULL) {
-                    virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR,
-                                "%s", _("domain information incomplete, missing cpu_weight"));
-                    goto error;
-                }
-                snprintf(buf_weight, sizeof(buf_weight), "%s", weight);
-            }
-            if (strlen(buf_cap) == 0) {
-                cap = sexpr_node(root, "domain/cpu_cap");
-                if (cap == NULL) {
-                    virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR,
-                                "%s", _("domain information incomplete, missing cpu_cap"));
-                    goto error;
-                }
-                snprintf(buf_cap, sizeof(buf_cap), "%s", cap);
-            }
-
-            ret = xend_op(domain->conn, domain->name, "op",
-                          "domain_sched_credit_set", "weight", buf_weight,
-                          "cap", buf_cap, NULL);
-            break;
-        }
-        default:
-            virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR, "%s", _("Unknown scheduler"));
-            goto error;
-    }
-
-error:
-    sexpr_free(root);
-    VIR_FREE(sched_type);
-    return (ret);
-}
-
-/**
- * xenDaemonDomainBlockPeek:
- * @dom: domain object
- * @path: path to the file or device
- * @offset: offset
- * @size: size
- * @buffer: return buffer
- *
- * Returns 0 if successful, -1 if error, -2 if declined.
- */
-int
-xenDaemonDomainBlockPeek (virDomainPtr domain, const char *path,
-                          unsigned long long offset, size_t size,
-                          void *buffer)
-{
-    xenUnifiedPrivatePtr priv;
-    struct sexpr *root = NULL;
-    int fd = -1, ret = -1;
-    int found = 0, i;
-    virDomainDefPtr def;
-
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-
-    if (domain->id < 0 && priv->xendConfigVersion < 3)
-        return -2;              /* Decline, allow XM to handle it. */
-
-    /* Security check: The path must correspond to a block device. */
-    if (domain->id > 0)
-        root = sexpr_get (domain->conn, "/xend/domain/%d?detail=1",
-                          domain->id);
-    else if (domain->id < 0)
-        root = sexpr_get (domain->conn, "/xend/domain/%s?detail=1",
-                          domain->name);
-    else {
-        /* This call always fails for dom0. */
-        virXendError (domain->conn, VIR_ERR_NO_SUPPORT,
-                      "%s", _("domainBlockPeek is not supported for dom0"));
-        return -1;
-    }
-
-    if (!root) {
-        virXendError (domain->conn, VIR_ERR_XEN_CALL, __FUNCTION__);
-        return -1;
-    }
-
-    if (!(def = xenDaemonParseSxpr(domain->conn, root, priv->xendConfigVersion, NULL)))
-        goto cleanup;
-
-    for (i = 0 ; i < def->ndisks ; i++) {
-        if (def->disks[i]->src &&
-            STREQ(def->disks[i]->src, path)) {
-            found = 1;
-            break;
-        }
-    }
-    if (!found) {
-        virXendError (domain->conn, VIR_ERR_INVALID_ARG,
-                      _("%s: invalid path"), path);
-        goto cleanup;
-    }
-
-    /* The path is correct, now try to open it and get its size. */
-    fd = open (path, O_RDONLY);
-    if (fd == -1) {
-        virReportSystemError(domain->conn, errno,
-                             _("failed to open for reading: %s"),
-                             path);
-        goto cleanup;
-    }
-
-    /* Seek and read. */
-    /* NB. Because we configure with AC_SYS_LARGEFILE, off_t should
-     * be 64 bits on all platforms.
-     */
-    if (lseek (fd, offset, SEEK_SET) == (off_t) -1 ||
-        saferead (fd, buffer, size) == (ssize_t) -1) {
-        virReportSystemError(domain->conn, errno,
-                             _("failed to lseek or read from file: %s"),
-                             path);
-        goto cleanup;
-    }
-
-    ret = 0;
- cleanup:
-    if (fd >= 0) close (fd);
-    sexpr_free(root);
-    virDomainDefFree(def);
-    return ret;
-}
-
-struct xenUnifiedDriver xenDaemonDriver = {
-    xenDaemonOpen,               /* open */
-    xenDaemonClose,              /* close */
-    xenDaemonGetVersion,         /* version */
-    NULL,                        /* hostname */
-    xenDaemonNodeGetInfo,        /* nodeGetInfo */
-    NULL,                        /* getCapabilities */
-    xenDaemonListDomains,        /* listDomains */
-    xenDaemonNumOfDomains,       /* numOfDomains */
-    xenDaemonCreateXML,          /* domainCreateXML */
-    xenDaemonDomainSuspend,      /* domainSuspend */
-    xenDaemonDomainResume,       /* domainResume */
-    xenDaemonDomainShutdown,     /* domainShutdown */
-    xenDaemonDomainReboot,       /* domainReboot */
-    xenDaemonDomainDestroy,      /* domainDestroy */
-    xenDaemonDomainGetOSType,    /* domainGetOSType */
-    xenDaemonDomainGetMaxMemory, /* domainGetMaxMemory */
-    xenDaemonDomainSetMaxMemory, /* domainSetMaxMemory */
-    xenDaemonDomainSetMemory,    /* domainMaxMemory */
-    xenDaemonDomainGetInfo,      /* domainGetInfo */
-    xenDaemonDomainSave,         /* domainSave */
-    xenDaemonDomainRestore,      /* domainRestore */
-    xenDaemonDomainCoreDump,     /* domainCoreDump */
-    xenDaemonDomainSetVcpus,     /* domainSetVcpus */
-    xenDaemonDomainPinVcpu,      /* domainPinVcpu */
-    xenDaemonDomainGetVcpus,     /* domainGetVcpus */
-    NULL,                        /* domainGetMaxVcpus */
-    xenDaemonListDefinedDomains, /* listDefinedDomains */
-    xenDaemonNumOfDefinedDomains,/* numOfDefinedDomains */
-    xenDaemonDomainCreate,       /* domainCreate */
-    xenDaemonDomainDefineXML,    /* domainDefineXML */
-    xenDaemonDomainUndefine,     /* domainUndefine */
-    xenDaemonAttachDevice,       /* domainAttachDevice */
-    xenDaemonDetachDevice,       /* domainDetachDevice */
-    xenDaemonDomainGetAutostart, /* domainGetAutostart */
-    xenDaemonDomainSetAutostart, /* domainSetAutostart */
-    xenDaemonGetSchedulerType,   /* domainGetSchedulerType */
-    xenDaemonGetSchedulerParameters, /* domainGetSchedulerParameters */
-    xenDaemonSetSchedulerParameters, /* domainSetSchedulerParameters */
-};
-
-/************************************************************************
- *                                                                     *
- * Converter functions to go from the XML tree to an S-Expr for Xen    *
- *                                                                     *
- ************************************************************************/
-
-
-/**
- * virtDomainParseXMLGraphicsDescVFB:
- * @conn: pointer to the hypervisor connection
- * @node: node containing graphics description
- * @buf: a buffer for the result S-Expr
- *
- * Parse the graphics part of the XML description and add it to the S-Expr
- * in buf.  This is a temporary interface as the S-Expr interface will be
- * replaced by XML-RPC in the future. However the XML format should stay
- * valid over time.
- *
- * Returns 0 in case of success, -1 in case of error
- */
-static int
-xenDaemonFormatSxprGraphicsNew(virConnectPtr conn,
-                               virDomainGraphicsDefPtr def,
-                               virBufferPtr buf)
-{
-    if (def->type != VIR_DOMAIN_GRAPHICS_TYPE_SDL &&
-        def->type != VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
-        virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                     _("unexpected graphics type %d"),
-                     def->type);
-        return -1;
-    }
-
-    virBufferAddLit(buf, "(device (vkbd))");
-    virBufferAddLit(buf, "(device (vfb ");
-
-    if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
-        virBufferAddLit(buf, "(type sdl)");
-        if (def->data.sdl.display)
-            virBufferVSprintf(buf, "(display '%s')", def->data.sdl.display);
-        if (def->data.sdl.xauth)
-            virBufferVSprintf(buf, "(xauthority '%s')", def->data.sdl.xauth);
-    } else if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
-        virBufferAddLit(buf, "(type vnc)");
-        if (def->data.vnc.autoport) {
-            virBufferAddLit(buf, "(vncunused 1)");
-        } else {
-            virBufferAddLit(buf, "(vncunused 0)");
-            virBufferVSprintf(buf, "(vncdisplay %d)", def->data.vnc.port-5900);
-        }
-
-        if (def->data.vnc.listenAddr)
-            virBufferVSprintf(buf, "(vnclisten '%s')", def->data.vnc.listenAddr);
-        if (def->data.vnc.passwd)
-            virBufferVSprintf(buf, "(vncpasswd '%s')", def->data.vnc.passwd);
-        if (def->data.vnc.keymap)
-            virBufferVSprintf(buf, "(keymap '%s')", def->data.vnc.keymap);
-    }
-
-    virBufferAddLit(buf, "))");
-
-    return 0;
-}
-
-
-static int
-xenDaemonFormatSxprGraphicsOld(virConnectPtr conn,
-                               virDomainGraphicsDefPtr def,
-                               virBufferPtr buf,
-                               int xendConfigVersion)
-{
-    if (def->type != VIR_DOMAIN_GRAPHICS_TYPE_SDL &&
-        def->type != VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
-        virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                     _("unexpected graphics type %d"),
-                     def->type);
-        return -1;
-    }
-
-    if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
-        virBufferAddLit(buf, "(sdl 1)");
-        if (def->data.sdl.display)
-            virBufferVSprintf(buf, "(display '%s')", def->data.sdl.display);
-        if (def->data.sdl.xauth)
-            virBufferVSprintf(buf, "(xauthority '%s')", def->data.sdl.xauth);
-    } else if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
-        virBufferAddLit(buf, "(vnc 1)");
-        if (xendConfigVersion >= 2) {
-            if (def->data.vnc.autoport) {
-                virBufferAddLit(buf, "(vncunused 1)");
-            } else {
-                virBufferAddLit(buf, "(vncunused 0)");
-                virBufferVSprintf(buf, "(vncdisplay %d)", def->data.vnc.port-5900);
-            }
-
-            if (def->data.vnc.listenAddr)
-                virBufferVSprintf(buf, "(vnclisten '%s')", def->data.vnc.listenAddr);
-            if (def->data.vnc.passwd)
-                virBufferVSprintf(buf, "(vncpasswd '%s')", def->data.vnc.passwd);
-            if (def->data.vnc.keymap)
-                virBufferVSprintf(buf, "(keymap '%s')", def->data.vnc.keymap);
-
-        }
-    }
-
-    return 0;
-}
-
-int
-xenDaemonFormatSxprChr(virConnectPtr conn,
-                       virDomainChrDefPtr def,
-                       virBufferPtr buf)
-{
-    const char *type = virDomainChrTypeToString(def->type);
-
-    if (!type) {
-        virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                     "%s", _("unexpected chr device type"));
-        return -1;
-    }
-
-    switch (def->type) {
-    case VIR_DOMAIN_CHR_TYPE_NULL:
-    case VIR_DOMAIN_CHR_TYPE_STDIO:
-    case VIR_DOMAIN_CHR_TYPE_VC:
-    case VIR_DOMAIN_CHR_TYPE_PTY:
-        virBufferVSprintf(buf, "%s", type);
-        break;
-
-    case VIR_DOMAIN_CHR_TYPE_FILE:
-    case VIR_DOMAIN_CHR_TYPE_PIPE:
-        virBufferVSprintf(buf, "%s:%s", type, def->data.file.path);
-        break;
-
-    case VIR_DOMAIN_CHR_TYPE_DEV:
-        virBufferVSprintf(buf, "%s", def->data.file.path);
-        break;
-
-    case VIR_DOMAIN_CHR_TYPE_TCP:
-        virBufferVSprintf(buf, "%s:%s:%s%s",
-                          (def->data.tcp.protocol == VIR_DOMAIN_CHR_TCP_PROTOCOL_RAW ?
-                           "tcp" : "telnet"),
-                          (def->data.tcp.host ? def->data.tcp.host : ""),
-                          (def->data.tcp.service ? def->data.tcp.service : ""),
-                          (def->data.tcp.listen ? ",listen" : ""));
-        break;
-
-    case VIR_DOMAIN_CHR_TYPE_UDP:
-        virBufferVSprintf(buf, "%s:%s:%s@%s:%s", type,
-                          (def->data.udp.connectHost ? def->data.udp.connectHost : ""),
-                          (def->data.udp.connectService ? def->data.udp.connectService : ""),
-                          (def->data.udp.bindHost ? def->data.udp.bindHost : ""),
-                          (def->data.udp.bindService ? def->data.udp.bindService : ""));
-        break;
-
-    case VIR_DOMAIN_CHR_TYPE_UNIX:
-        virBufferVSprintf(buf, "%s:%s%s", type,
-                          def->data.nix.path,
-                          def->data.nix.listen ? ",listen" : "");
-        break;
-    }
-
-    if (virBufferError(buf))
-        return -1;
-
-    return 0;
-}
-
-
-/**
- * virDomainParseXMLDiskDesc:
- * @node: node containing disk description
- * @conn: pointer to the hypervisor connection
- * @buf: a buffer for the result S-Expr
- * @xendConfigVersion: xend configuration file format
- *
- * Parse the one disk in the XML description and add it to the S-Expr in buf
- * This is a temporary interface as the S-Expr interface
- * will be replaced by XML-RPC in the future. However the XML format should
- * stay valid over time.
- *
- * Returns 0 in case of success, -1 in case of error.
- */
-static int
-xenDaemonFormatSxprDisk(virConnectPtr conn ATTRIBUTE_UNUSED,
-                        virDomainDiskDefPtr def,
-                        virBufferPtr buf,
-                        int hvm,
-                        int xendConfigVersion,
-                        int isAttach)
-{
-    /* Xend (all versions) put the floppy device config
-     * under the hvm (image (os)) block
-     */
-    if (hvm &&
-        def->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
-        if (isAttach) {
-            virXendError(conn, VIR_ERR_INVALID_ARG,
-                     _("Cannot directly attach floppy %s"), def->src);
-            return -1;
-        }
-        return 0;
-    }
-
-    /* Xend <= 3.0.2 doesn't include cdrom config here */
-    if (hvm &&
-        def->device == VIR_DOMAIN_DISK_DEVICE_CDROM &&
-        xendConfigVersion == 1) {
-        if (isAttach) {
-            virXendError(conn, VIR_ERR_INVALID_ARG,
-                     _("Cannot directly attach CDROM %s"), def->src);
-            return -1;
-        }
-        return 0;
-    }
-
-    if (!isAttach)
-        virBufferAddLit(buf, "(device ");
-
-    /* Normally disks are in a (device (vbd ...)) block
-     * but blktap disks ended up in a differently named
-     * (device (tap ....)) block.... */
-    if (def->driverName &&
-        STREQ(def->driverName, "tap")) {
-        virBufferAddLit(buf, "(tap ");
-    } else {
-        virBufferAddLit(buf, "(vbd ");
-    }
-
-    if (hvm) {
-        /* Xend <= 3.0.2 wants a ioemu: prefix on devices for HVM */
-        if (xendConfigVersion == 1)
-            virBufferVSprintf(buf, "(dev 'ioemu:%s')", def->dst);
-        else                    /* But newer does not */
-            virBufferVSprintf(buf, "(dev '%s:%s')", def->dst,
-                              def->device == VIR_DOMAIN_DISK_DEVICE_CDROM ?
-                              "cdrom" : "disk");
-    } else if (def->device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
-        virBufferVSprintf(buf, "(dev '%s:cdrom')", def->dst);
-    } else {
-        virBufferVSprintf(buf, "(dev '%s')", def->dst);
-    }
-
-    if (def->src) {
-        if (def->driverName) {
-            if (STREQ(def->driverName, "tap")) {
-                virBufferVSprintf(buf, "(uname '%s:%s:%s')",
-                                  def->driverName,
-                                  def->driverType ? def->driverType : "aio",
-                                  def->src);
-            } else {
-                virBufferVSprintf(buf, "(uname '%s:%s')",
-                                  def->driverName,
-                                  def->src);
-            }
-        } else {
-            if (def->type == VIR_DOMAIN_DISK_TYPE_FILE) {
-                virBufferVSprintf(buf, "(uname 'file:%s')", def->src);
-            } else {
-                if (def->src[0] == '/')
-                    virBufferVSprintf(buf, "(uname 'phy:%s')", def->src);
-                else
-                    virBufferVSprintf(buf, "(uname 'phy:/dev/%s')", def->src);
-            }
-        }
-    }
-
-    if (def->readonly)
-        virBufferAddLit(buf, "(mode 'r')");
-    else if (def->shared)
-        virBufferAddLit(buf, "(mode 'w!')");
-    else
-        virBufferAddLit(buf, "(mode 'w')");
-
-    if (!isAttach)
-        virBufferAddLit(buf, ")");
-
-    virBufferAddLit(buf, ")");
-
-    return 0;
-}
-
-/**
- * xenDaemonFormatSxprNet
- * @conn: pointer to the hypervisor connection
- * @node: node containing the interface description
- * @buf: a buffer for the result S-Expr
- * @xendConfigVersion: xend configuration file format
- *
- * Parse the one interface the XML description and add it to the S-Expr in buf
- * This is a temporary interface as the S-Expr interface
- * will be replaced by XML-RPC in the future. However the XML format should
- * stay valid over time.
- *
- * Returns 0 in case of success, -1 in case of error.
- */
-static int
-xenDaemonFormatSxprNet(virConnectPtr conn,
-                       virDomainNetDefPtr def,
-                       virBufferPtr buf,
-                       int hvm,
-                       int xendConfigVersion,
-                       int isAttach)
-{
-    const char *script = DEFAULT_VIF_SCRIPT;
-
-    if (def->type != VIR_DOMAIN_NET_TYPE_BRIDGE &&
-        def->type != VIR_DOMAIN_NET_TYPE_NETWORK &&
-        def->type != VIR_DOMAIN_NET_TYPE_ETHERNET) {
-        virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                     _("unsupported network type %d"), def->type);
-        return -1;
-    }
-
-    if (!isAttach)
-        virBufferAddLit(buf, "(device ");
-
-    virBufferAddLit(buf, "(vif ");
-
-    virBufferVSprintf(buf,
-                      "(mac '%02x:%02x:%02x:%02x:%02x:%02x')",
-                      def->mac[0], def->mac[1], def->mac[2],
-                      def->mac[3], def->mac[4], def->mac[5]);
-
-    switch (def->type) {
-    case VIR_DOMAIN_NET_TYPE_BRIDGE:
-        virBufferVSprintf(buf, "(bridge '%s')", def->data.bridge.brname);
-        if (def->data.bridge.script)
-            script = def->data.bridge.script;
-
-        virBufferVSprintf(buf, "(script '%s')", script);
-        if (def->data.bridge.ipaddr != NULL)
-            virBufferVSprintf(buf, "(ip '%s')", def->data.bridge.ipaddr);
-        break;
-
-    case VIR_DOMAIN_NET_TYPE_NETWORK:
-    {
-        virNetworkPtr network =
-            virNetworkLookupByName(conn, def->data.network.name);
-        char *bridge;
-
-        if (!network) {
-            virXendError(conn, VIR_ERR_NO_NETWORK, "%s",
-                         def->data.network.name);
-            return -1;
-        }
-
-        bridge = virNetworkGetBridgeName(network);
-        virNetworkFree(network);
-        if (!bridge) {
-            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                         _("network %s is not active"),
-                         def->data.network.name);
-            return -1;
-        }
-        virBufferVSprintf(buf, "(bridge '%s')", bridge);
-        virBufferVSprintf(buf, "(script '%s')", script);
-        VIR_FREE(bridge);
-    }
-    break;
-
-    case VIR_DOMAIN_NET_TYPE_ETHERNET:
-        if (def->data.ethernet.script)
-            virBufferVSprintf(buf, "(script '%s')", def->data.ethernet.script);
-        if (def->data.ethernet.ipaddr != NULL)
-            virBufferVSprintf(buf, "(ip '%s')", def->data.ethernet.ipaddr);
-        break;
-    }
-
-    if (def->ifname != NULL &&
-        !STRPREFIX(def->ifname, "vif"))
-        virBufferVSprintf(buf, "(vifname '%s')", def->ifname);
-
-    if (def->model != NULL)
-        virBufferVSprintf(buf, "(model '%s')", def->model);
-
-    /*
-     * apparently (type ioemu) breaks paravirt drivers on HVM so skip this
-     * from Xen 3.1.0
-     */
-    if (hvm && xendConfigVersion <= XEND_CONFIG_MAX_VERS_NET_TYPE_IOEMU)
-        virBufferAddLit(buf, "(type ioemu)");
-
-    if (!isAttach)
-        virBufferAddLit(buf, ")");
-
-    virBufferAddLit(buf, ")");
-
-    return 0;
-}
-
-
-static void
-xenDaemonFormatSxprPCI(virDomainHostdevDefPtr def,
-                       virBufferPtr buf)
-{
-    virBufferVSprintf(buf, "(dev (domain 0x%04x)(bus 0x%02x)(slot 0x%02x)(func 0x%x))",
-                      def->source.subsys.u.pci.domain,
-                      def->source.subsys.u.pci.bus,
-                      def->source.subsys.u.pci.slot,
-                      def->source.subsys.u.pci.function);
-}
-
-static int
-xenDaemonFormatSxprOnePCI(virConnectPtr conn,
-                          virDomainHostdevDefPtr def,
-                          virBufferPtr buf)
-{
-    if (def->managed) {
-        virXendError(conn, VIR_ERR_NO_SUPPORT, "%s",
-                     _("managed PCI devices not supported with XenD"));
-        return -1;
-    }
-
-    virBufferAddLit(buf, "(pci ");
-    xenDaemonFormatSxprPCI(def, buf);
-    virBufferAddLit(buf, ")");
-
-    return 0;
-}
-
-static int
-xenDaemonFormatSxprAllPCI(virConnectPtr conn,
-                          virDomainDefPtr def,
-                          virBufferPtr buf)
-{
-    int hasPCI = 0;
-    int i;
-
-    for (i = 0 ; i < def->nhostdevs ; i++)
-        if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
-            def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
-            hasPCI = 1;
-
-    if (!hasPCI)
-        return 0;
-
-    /*
-     * With the (domain ...) block we have the following odd setup
-     *
-     * (device
-     *    (pci
-     *       (dev (domain 0x0000) (bus 0x00) (slot 0x1b) (func 0x0))
-     *       (dev (domain 0x0000) (bus 0x00) (slot 0x13) (func 0x0))
-     *    )
-     * )
-     *
-     * Normally there is one (device ...) block per device, but in
-     * wierd world of Xen PCI, once (device ...) covers multiple
-     * devices.
-     */
-
-    virBufferAddLit(buf, "(device (pci ");
-    for (i = 0 ; i < def->nhostdevs ; i++) {
-        if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
-            def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
-            if (def->hostdevs[i]->managed) {
-                virXendError(conn, VIR_ERR_NO_SUPPORT, "%s",
-                             _("managed PCI devices not supported with XenD"));
-                return -1;
-            }
-
-            xenDaemonFormatSxprPCI(def->hostdevs[i], buf);
-        }
-    }
-    virBufferAddLit(buf, "))");
-
-    return 0;
-}
-
-int
-xenDaemonFormatSxprSound(virConnectPtr conn,
-                         virDomainDefPtr def,
-                         virBufferPtr buf)
-{
-    const char *str;
-    int i;
-
-    for (i = 0 ; i < def->nsounds ; i++) {
-        if (!(str = virDomainSoundModelTypeToString(def->sounds[i]->model))) {
-            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                         _("unexpected sound model %d"),
-                         def->sounds[i]->model);
-            return -1;
-        }
-        virBufferVSprintf(buf, "%s%s", i ? "," : "", str);
-    }
-
-    if (virBufferError(buf))
-        return -1;
-
-    return 0;
-}
-
-
-static int
-xenDaemonFormatSxprInput(virConnectPtr conn,
-                         virDomainInputDefPtr input,
-                         virBufferPtr buf)
-{
-    if (input->bus != VIR_DOMAIN_INPUT_BUS_USB)
-        return 0;
-
-    if (input->type != VIR_DOMAIN_INPUT_TYPE_MOUSE &&
-        input->type != VIR_DOMAIN_INPUT_TYPE_TABLET) {
-        virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                     _("unexpected input type %d"), input->type);
-        return -1;
-    }
-
-    virBufferVSprintf(buf, "(usbdevice %s)",
-                      input->type == VIR_DOMAIN_INPUT_TYPE_MOUSE ?
-                      "mouse" : "tablet");
-
-    return 0;
-}
-
-
-/**
- * xenDaemonFormatSxpr:
- * @conn: pointer to the hypervisor connection
- * @def: domain config definition
- * @xendConfigVersion: xend configuration file format
- *
- * Generate an SEXPR representing the domain configuration.
- *
- * Returns the 0 terminatedi S-Expr string or NULL in case of error.
- *         the caller must free() the returned value.
- */
-char *
-xenDaemonFormatSxpr(virConnectPtr conn,
-                    virDomainDefPtr def,
-                    int xendConfigVersion)
-{
-    virBuffer buf = VIR_BUFFER_INITIALIZER;
-    char uuidstr[VIR_UUID_STRING_BUFLEN];
-    const char *tmp;
-    int hvm = 0, i;
-
-    virBufferAddLit(&buf, "(vm ");
-    virBufferVSprintf(&buf, "(name '%s')", def->name);
-    virBufferVSprintf(&buf, "(memory %lu)(maxmem %lu)",
-                      def->memory/1024, def->maxmem/1024);
-    virBufferVSprintf(&buf, "(vcpus %lu)", def->vcpus);
-
-    if (def->cpumask) {
-        char *ranges = virDomainCpuSetFormat(conn, def->cpumask, def->cpumasklen);
-        if (ranges == NULL)
-            goto error;
-        virBufferVSprintf(&buf, "(cpus '%s')", ranges);
-        VIR_FREE(ranges);
-    }
-
-    virUUIDFormat(def->uuid, uuidstr);
-    virBufferVSprintf(&buf, "(uuid '%s')", uuidstr);
-
-    if (def->os.bootloader) {
-        if (def->os.bootloader[0])
-            virBufferVSprintf(&buf, "(bootloader '%s')", def->os.bootloader);
-        else
-            virBufferAddLit(&buf, "(bootloader)");
-
-        if (def->os.bootloaderArgs)
-            virBufferVSprintf(&buf, "(bootloader_args '%s')", def->os.bootloaderArgs);
-    }
-
-    if (!(tmp = virDomainLifecycleTypeToString(def->onPoweroff))) {
-        virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                     _("unexpected lifecycle value %d"), def->onPoweroff);
-        goto error;
-    }
-    virBufferVSprintf(&buf, "(on_poweroff '%s')", tmp);
-
-    if (!(tmp = virDomainLifecycleTypeToString(def->onReboot))) {
-        virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                     _("unexpected lifecycle value %d"), def->onReboot);
-        goto error;
-    }
-    virBufferVSprintf(&buf, "(on_reboot '%s')", tmp);
-
-    if (!(tmp = virDomainLifecycleTypeToString(def->onCrash))) {
-        virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                     _("unexpected lifecycle value %d"), def->onCrash);
-        goto error;
-    }
-    virBufferVSprintf(&buf, "(on_crash '%s')", tmp);
-
-    /* Set localtime here for current XenD (both PV & HVM) */
-    if (def->localtime)
-        virBufferAddLit(&buf, "(localtime 1)");
-
-    if (!def->os.bootloader) {
-        if (STREQ(def->os.type, "hvm"))
-            hvm = 1;
-
-        if (hvm)
-            virBufferAddLit(&buf, "(image (hvm ");
-        else
-            virBufferAddLit(&buf, "(image (linux ");
-
-        if (hvm &&
-            def->os.loader == NULL) {
-            virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                         "%s",_("no HVM domain loader"));
-            goto error;
-        }
-
-        if (def->os.kernel)
-            virBufferVSprintf(&buf, "(kernel '%s')", def->os.kernel);
-        if (def->os.initrd)
-            virBufferVSprintf(&buf, "(ramdisk '%s')", def->os.initrd);
-        if (def->os.root)
-            virBufferVSprintf(&buf, "(root '%s')", def->os.root);
-        if (def->os.cmdline)
-            virBufferVSprintf(&buf, "(args '%s')", def->os.cmdline);
-
-        if (hvm) {
-            char bootorder[VIR_DOMAIN_BOOT_LAST+1];
-            if (def->os.kernel)
-                virBufferVSprintf(&buf, "(loader '%s')", def->os.loader);
-            else
-                virBufferVSprintf(&buf, "(kernel '%s')", def->os.loader);
-
-            virBufferVSprintf(&buf, "(vcpus %lu)", def->vcpus);
-
-            for (i = 0 ; i < def->os.nBootDevs ; i++) {
-                switch (def->os.bootDevs[i]) {
-                case VIR_DOMAIN_BOOT_FLOPPY:
-                    bootorder[i] = 'a';
-                    break;
-                default:
-                case VIR_DOMAIN_BOOT_DISK:
-                    bootorder[i] = 'c';
-                    break;
-                case VIR_DOMAIN_BOOT_CDROM:
-                    bootorder[i] = 'd';
-                    break;
-                case VIR_DOMAIN_BOOT_NET:
-                    bootorder[i] = 'n';
-                    break;
-                }
-            }
-            if (def->os.nBootDevs == 0) {
-                bootorder[0] = 'c';
-                bootorder[1] = '\0';
-            } else {
-                bootorder[def->os.nBootDevs] = '\0';
-            }
-            virBufferVSprintf(&buf, "(boot %s)", bootorder);
-
-            /* some disk devices are defined here */
-            for (i = 0 ; i < def->ndisks ; i++) {
-                switch (def->disks[i]->device) {
-                case VIR_DOMAIN_DISK_DEVICE_CDROM:
-                    /* Only xend <= 3.0.2 wants cdrom config here */
-                    if (xendConfigVersion != 1)
-                        break;
-                    if (!STREQ(def->disks[i]->dst, "hdc") ||
-                        def->disks[i]->src == NULL)
-                        break;
-
-                    virBufferVSprintf(&buf, "(cdrom '%s')",
-                                      def->disks[i]->src);
-                    break;
-
-                case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
-                    /* all xend versions define floppies here */
-                    virBufferVSprintf(&buf, "(%s '%s')", def->disks[i]->dst,
-                        def->disks[i]->src);
-                    break;
-
-                default:
-                    break;
-                }
-            }
-
-            if (def->features & (1 << VIR_DOMAIN_FEATURE_ACPI))
-                virBufferAddLit(&buf, "(acpi 1)");
-            if (def->features & (1 << VIR_DOMAIN_FEATURE_APIC))
-                virBufferAddLit(&buf, "(apic 1)");
-            if (def->features & (1 << VIR_DOMAIN_FEATURE_PAE))
-                virBufferAddLit(&buf, "(pae 1)");
-
-            virBufferAddLit(&buf, "(usb 1)");
-
-            for (i = 0 ; i < def->ninputs ; i++)
-                if (xenDaemonFormatSxprInput(conn, def->inputs[i], &buf) < 0)
-                    goto error;
-
-            if (def->parallels) {
-                virBufferAddLit(&buf, "(parallel ");
-                if (xenDaemonFormatSxprChr(conn, def->parallels[0], &buf) < 0)
-                    goto error;
-                virBufferAddLit(&buf, ")");
-            } else {
-                virBufferAddLit(&buf, "(parallel none)");
-            }
-            if (def->serials) {
-                virBufferAddLit(&buf, "(serial ");
-                if (xenDaemonFormatSxprChr(conn, def->serials[0], &buf) < 0)
-                    goto error;
-                virBufferAddLit(&buf, ")");
-            } else {
-                virBufferAddLit(&buf, "(serial none)");
-            }
-
-            /* Set localtime here to keep old XenD happy for HVM */
-            if (def->localtime)
-                virBufferAddLit(&buf, "(localtime 1)");
-
-            if (def->sounds) {
-                virBufferAddLit(&buf, "(soundhw '");
-                if (xenDaemonFormatSxprSound(conn, def, &buf) < 0)
-                    goto error;
-                virBufferAddLit(&buf, "')");
-            }
-        }
-
-        /* get the device emulation model */
-        if (def->emulator && (hvm || xendConfigVersion >= 3))
-            virBufferVSprintf(&buf, "(device_model '%s')", def->emulator);
-
-
-        /* PV graphics for xen <= 3.0.4, or HVM graphics for xen <= 3.1.0 */
-        if ((!hvm && xendConfigVersion < XEND_CONFIG_MIN_VERS_PVFB_NEWCONF) ||
-            (hvm && xendConfigVersion < 4)) {
-            if ((def->ngraphics == 1) &&
-                xenDaemonFormatSxprGraphicsOld(conn, def->graphics[0],
-                                               &buf, xendConfigVersion) < 0)
-                goto error;
-        }
-
-        virBufferAddLit(&buf, "))");
-    }
-
-    for (i = 0 ; i < def->ndisks ; i++)
-        if (xenDaemonFormatSxprDisk(conn, def->disks[i],
-                                    &buf, hvm, xendConfigVersion, 0) < 0)
-            goto error;
-
-    for (i = 0 ; i < def->nnets ; i++)
-        if (xenDaemonFormatSxprNet(conn, def->nets[i],
-                                   &buf, hvm, xendConfigVersion, 0) < 0)
-            goto error;
-
-    if (xenDaemonFormatSxprAllPCI(conn, def, &buf) < 0)
-        goto error;
-
-    /* New style PV graphics config xen >= 3.0.4,
-     * or HVM graphics config xen >= 3.0.5 */
-    if ((xendConfigVersion >= XEND_CONFIG_MIN_VERS_PVFB_NEWCONF && !hvm) ||
-        (xendConfigVersion >= 4 && hvm)) {
-        if ((def->ngraphics == 1) &&
-            xenDaemonFormatSxprGraphicsNew(conn, def->graphics[0], &buf) < 0)
-            goto error;
-    }
-
-    virBufferAddLit(&buf, ")"); /* closes (vm */
-
-    if (virBufferError(&buf)) {
-        virReportOOMError(conn);
-        return NULL;
-    }
-
-    return virBufferContentAndReset(&buf);
-
-error:
-    tmp = virBufferContentAndReset(&buf);
-    VIR_FREE(tmp);
-    return NULL;
-}
-
-
-/**
- * virDomainXMLDevID:
- * @domain: pointer to domain object
- * @dev: pointer to device config object
- * @class: Xen device class "vbd" or "vif" (OUT)
- * @ref: Xen device reference (OUT)
- *
- * Set class according to XML root, and:
- *  - if disk, copy in ref the target name from description
- *  - if network, get MAC address from description, scan XenStore and
- *    copy in ref the corresponding vif number.
- *
- * Returns 0 in case of success, -1 in case of failure.
- */
-static int
-virDomainXMLDevID(virDomainPtr domain,
-                  virDomainDeviceDefPtr dev,
-                  char *class,
-                  char *ref,
-                  int ref_len)
-{
-    xenUnifiedPrivatePtr priv = domain->conn->privateData;
-    char *xref;
-
-    if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
-        if (dev->data.disk->driverName &&
-            STREQ(dev->data.disk->driverName, "tap"))
-            strcpy(class, "tap");
-        else
-            strcpy(class, "vbd");
-
-        if (dev->data.disk->dst == NULL)
-            return -1;
-        xenUnifiedLock(priv);
-        xref = xenStoreDomainGetDiskID(domain->conn, domain->id,
-                                       dev->data.disk->dst);
-        xenUnifiedUnlock(priv);
-        if (xref == NULL)
-            return -1;
-
-        strncpy(ref, xref, ref_len);
-        free(xref);
-        ref[ref_len - 1] = '\0';
-    } else if (dev->type == VIR_DOMAIN_DEVICE_NET) {
-        char mac[30];
-        virDomainNetDefPtr def = dev->data.net;
-        snprintf(mac, sizeof(mac), "%02x:%02x:%02x:%02x:%02x:%02x",
-                 def->mac[0], def->mac[1], def->mac[2],
-                 def->mac[3], def->mac[4], def->mac[5]);
-
-        strcpy(class, "vif");
-
-        xenUnifiedLock(priv);
-        xref = xenStoreDomainGetNetworkID(domain->conn, domain->id,
-                                          mac);
-        xenUnifiedUnlock(priv);
-        if (xref == NULL)
-            return -1;
-
-        strncpy(ref, xref, ref_len);
-        free(xref);
-        ref[ref_len - 1] = '\0';
-    } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV &&
-               dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
-               dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
-    } else {
-        virXendError(NULL, VIR_ERR_NO_SUPPORT,
-                     "%s", _("hotplug of device type not supported"));
-        return -1;
-    }
-
-    return 0;
-}
-
-#endif /* ! PROXY */
diff --git a/src/xend_internal.h b/src/xend_internal.h
deleted file mode 100644 (file)
index 9d2571b..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * xend_internal.h
- *
- * Copyright (C) 2005,2006
- *
- *      Anthony Liguori <aliguori@us.ibm.com>
- *     Daniel Veillard <veillard@redhat.com>
- *
- * Copyright 2006-2008 Red Hat
- *
- *  This file is subject to the terms and conditions of the GNU Lesser General
- *  Public License. See the file COPYING in the main directory of this archive
- *  for more details.
- */
-
-#ifndef __XEND_INTERNAL_H_
-#define __XEND_INTERNAL_H_
-
-#include <sys/types.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <libxml/uri.h>
-
-#include "internal.h"
-#include "capabilities.h"
-#include "domain_conf.h"
-#include "driver.h"
-#include "buf.h"
-
-#ifdef __sun
-#define DEFAULT_VIF_SCRIPT "vif-vnic"
-#else
-#define DEFAULT_VIF_SCRIPT "vif-bridge"
-#endif
-
-int
-xenDaemonOpen_unix(virConnectPtr conn, const char *path);
-
-/**
- * \brief Blocks until a domain's devices are initialized
- * \param xend A xend instance
- * \param name The domain's name
- * \return 0 for success; -1 (with errno) on error
- *
- * xen_create() returns after a domain has been allocated including
- * its memory.  This does not guarentee, though, that the devices
- * have come up properly.  For instance, if you create a VBD with an
- * invalid filename, the error won't occur until after this function
- * returns.
- */
-    int xend_wait_for_devices(virConnectPtr xend, const char *name);
-
-
-/**
- * \brief Create a new domain
- * \param xend A xend instance
- * \param sexpr An S-Expr defining the domain
- * \return 0 for success; -1 (with errno) on error
- *
- * This method will create a domain based the passed in description.  The
- * domain will be paused after creation and must be unpaused with
- * xenDaemonResumeDomain() to begin execution.
- */
-int xenDaemonDomainCreateXML(virConnectPtr xend, const char *sexpr);
-
-/**
- * \brief Lookup the id of a domain
- * \param xend A xend instance
- * \param name The name of the domain
- * \param uuid pointer to store a copy of the uuid
- * \return the id number on success; -1 (with errno) on error
- *
- * This method looks up the ids of a domain
- */
-int xenDaemonDomainLookupByName_ids(virConnectPtr xend,
-                            const char *name, unsigned char *uuid);
-
-
-/**
- * \brief Lookup the name of a domain
- * \param xend A xend instance
- * \param id The id of the domain
- * \param name pointer to store a copy of the name
- * \param uuid pointer to store a copy of the uuid
- *
- * This method looks up the name/uuid of a domain
- */
-int xenDaemonDomainLookupByID(virConnectPtr xend,
-                              int id,
-                              char **name, unsigned char *uuid);
-
-
-virDomainDefPtr
-xenDaemonDomainFetch(virConnectPtr xend,
-                     int domid,
-                     const char *name,
-                     const char *cpus);
-
-    int xend_parse_sexp_desc_char(virConnectPtr conn,
-                                  virBufferPtr buf,
-                                  const char *devtype,
-                                  int portNum,
-                                  const char *value,
-                                  const char *tty);
-
-virDomainDefPtr
-xenDaemonParseSxprString(virConnectPtr conn,
-                         const char *sexpr,
-                         int xendConfigVersion);
-
-int
-xenDaemonParseSxprSound(virConnectPtr conn,
-                        virDomainDefPtr def,
-                        const char *str);
-virDomainChrDefPtr
-xenDaemonParseSxprChar(virConnectPtr conn,
-                       const char *value,
-                       const char *tty);
-
-int
-xenDaemonFormatSxprChr(virConnectPtr conn,
-                       virDomainChrDefPtr def,
-                       virBufferPtr buf);
-int
-xenDaemonFormatSxprSound(virConnectPtr conn,
-                         virDomainDefPtr def,
-                         virBufferPtr buf);
-
-char *
-xenDaemonFormatSxpr(virConnectPtr conn,
-                    virDomainDefPtr def,
-                    int xendConfigVersion);
-
-  int is_sound_model_valid(const char *model);
-  int is_sound_model_conflict(const char *model, const char *soundstr);
-
-
-/* refactored ones */
-virDrvOpenStatus xenDaemonOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags);
-int xenDaemonClose(virConnectPtr conn);
-int xenDaemonGetVersion(virConnectPtr conn, unsigned long *hvVer);
-int xenDaemonNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info);
-int xenDaemonNodeGetTopology(virConnectPtr conn, virCapsPtr caps);
-int xenDaemonDomainSuspend(virDomainPtr domain);
-int xenDaemonDomainResume(virDomainPtr domain);
-int xenDaemonDomainShutdown(virDomainPtr domain);
-int xenDaemonDomainReboot(virDomainPtr domain, unsigned int flags);
-int xenDaemonDomainDestroy(virDomainPtr domain);
-int xenDaemonDomainSave(virDomainPtr domain, const char *filename);
-int xenDaemonDomainRestore(virConnectPtr conn, const char *filename);
-int xenDaemonDomainSetMemory(virDomainPtr domain, unsigned long memory);
-int xenDaemonDomainSetMaxMemory(virDomainPtr domain, unsigned long memory);
-int xenDaemonDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info);
-char *xenDaemonDomainDumpXML(virDomainPtr domain, int flags, const char *cpus);
-unsigned long xenDaemonDomainGetMaxMemory(virDomainPtr domain);
-char **xenDaemonListDomainsOld(virConnectPtr xend);
-
-virDomainPtr xenDaemonDomainDefineXML(virConnectPtr xend, const char *sexpr);
-int xenDaemonDomainCreate(virDomainPtr domain);
-int xenDaemonDomainUndefine(virDomainPtr domain);
-
-int    xenDaemonDomainSetVcpus         (virDomainPtr domain,
-                                         unsigned int vcpus);
-int    xenDaemonDomainPinVcpu          (virDomainPtr domain,
-                                         unsigned int vcpu,
-                                         unsigned char *cpumap,
-                                         int maplen);
-int    xenDaemonDomainGetVcpus         (virDomainPtr domain,
-                                         virVcpuInfoPtr info,
-                                         int maxinfo,
-                                         unsigned char *cpumaps,
-                                         int maplen);
-int xenDaemonDomainGetAutostart          (virDomainPtr dom,
-                                          int *autostart);
-int xenDaemonDomainSetAutostart          (virDomainPtr domain,
-                                          int autostart);
-
-/* xen_unified calls through here. */
-extern struct xenUnifiedDriver xenDaemonDriver;
-int xenDaemonInit (void);
-
-virDomainPtr xenDaemonLookupByID(virConnectPtr conn, int id);
-virDomainPtr xenDaemonLookupByUUID(virConnectPtr conn, const unsigned char *uuid);
-virDomainPtr xenDaemonLookupByName(virConnectPtr conn, const char *domname);
-int xenDaemonDomainMigratePrepare (virConnectPtr dconn, char **cookie, int *cookielen, const char *uri_in, char **uri_out, unsigned long flags, const char *dname, unsigned long resource);
-int xenDaemonDomainMigratePerform (virDomainPtr domain, const char *cookie, int cookielen, const char *uri, unsigned long flags, const char *dname, unsigned long resource);
-
-int xenDaemonDomainBlockPeek (virDomainPtr domain, const char *path, unsigned long long offset, size_t size, void *buffer);
-int xenDaemonListDomains(virConnectPtr conn, int *ids, int maxids);
-
-#endif /* __XEND_INTERNAL_H_ */
diff --git a/src/xm_internal.c b/src/xm_internal.c
deleted file mode 100644 (file)
index de3aca9..0000000
+++ /dev/null
@@ -1,3066 +0,0 @@
-/*
- * xm_internal.h: helper routines for dealing with inactive domains
- *
- * Copyright (C) 2006-2007, 2009 Red Hat
- * Copyright (C) 2006 Daniel P. Berrange
- *
- * 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: Daniel P. Berrange <berrange@redhat.com>
- *
- */
-
-#include <config.h>
-
-#include <dirent.h>
-#include <time.h>
-#include <sys/stat.h>
-#include <limits.h>
-#include <string.h>
-#include <errno.h>
-
-#include <unistd.h>
-#include <stdint.h>
-#include <xen/dom0_ops.h>
-
-#include "virterror_internal.h"
-#include "datatypes.h"
-#include "xm_internal.h"
-#include "xen_unified.h"
-#include "xend_internal.h"
-#include "hash.h"
-#include "buf.h"
-#include "uuid.h"
-#include "util.h"
-#include "memory.h"
-#include "logging.h"
-
-#define VIR_FROM_THIS VIR_FROM_XENXM
-
-#ifdef WITH_RHEL5_API
-#define XEND_CONFIG_MAX_VERS_NET_TYPE_IOEMU 0
-#define XEND_CONFIG_MIN_VERS_PVFB_NEWCONF 2
-#else
-#define XEND_CONFIG_MAX_VERS_NET_TYPE_IOEMU 3
-#define XEND_CONFIG_MIN_VERS_PVFB_NEWCONF 3
-#endif
-
-/* The true Xen limit varies but so far is always way
-   less than 1024, which is the Linux kernel limit according
-   to sched.h, so we'll match that for now */
-#define XEN_MAX_PHYSICAL_CPU 1024
-
-static int xenXMConfigSetString(virConfPtr conf, const char *setting,
-                                const char *str);
-char * xenXMAutoAssignMac(void);
-static int xenXMDomainAttachDevice(virDomainPtr domain, const char *xml);
-static int xenXMDomainDetachDevice(virDomainPtr domain, const char *xml);
-
-#define XM_REFRESH_INTERVAL 10
-
-#define XM_CONFIG_DIR "/etc/xen"
-#define XM_EXAMPLE_PREFIX "xmexample"
-#define XEND_CONFIG_FILE "xend-config.sxp"
-#define XEND_PCI_CONFIG_PREFIX "xend-pci-"
-#define QEMU_IF_SCRIPT "qemu-ifup"
-#define XM_XML_ERROR "Invalid xml"
-
-struct xenUnifiedDriver xenXMDriver = {
-    xenXMOpen, /* open */
-    xenXMClose, /* close */
-    NULL, /* version */
-    NULL, /* hostname */
-    NULL, /* nodeGetInfo */
-    NULL, /* getCapabilities */
-    NULL, /* listDomains */
-    NULL, /* numOfDomains */
-    NULL, /* domainCreateXML */
-    NULL, /* domainSuspend */
-    NULL, /* domainResume */
-    NULL, /* domainShutdown */
-    NULL, /* domainReboot */
-    NULL, /* domainDestroy */
-    NULL, /* domainGetOSType */
-    xenXMDomainGetMaxMemory, /* domainGetMaxMemory */
-    xenXMDomainSetMaxMemory, /* domainSetMaxMemory */
-    xenXMDomainSetMemory, /* domainMaxMemory */
-    xenXMDomainGetInfo, /* domainGetInfo */
-    NULL, /* domainSave */
-    NULL, /* domainRestore */
-    NULL, /* domainCoreDump */
-    xenXMDomainSetVcpus, /* domainSetVcpus */
-    xenXMDomainPinVcpu, /* domainPinVcpu */
-    NULL, /* domainGetVcpus */
-    NULL, /* domainGetMaxVcpus */
-    xenXMListDefinedDomains, /* listDefinedDomains */
-    xenXMNumOfDefinedDomains, /* numOfDefinedDomains */
-    xenXMDomainCreate, /* domainCreate */
-    xenXMDomainDefineXML, /* domainDefineXML */
-    xenXMDomainUndefine, /* domainUndefine */
-    xenXMDomainAttachDevice, /* domainAttachDevice */
-    xenXMDomainDetachDevice, /* domainDetachDevice */
-    NULL, /* domainGetAutostart */
-    NULL, /* domainSetAutostart */
-    NULL, /* domainGetSchedulerType */
-    NULL, /* domainGetSchedulerParameters */
-    NULL, /* domainSetSchedulerParameters */
-};
-
-#define xenXMError(conn, code, fmt...)                                       \
-        virReportErrorHelper(conn, VIR_FROM_XENXM, code, __FILE__,         \
-                               __FUNCTION__, __LINE__, fmt)
-
-#ifndef WITH_XEN_INOTIFY
-static int xenInotifyActive(virConnectPtr conn ATTRIBUTE_UNUSED)
-{
-   return 0;
-}
-#else
-static int xenInotifyActive(virConnectPtr conn)
-{
-   xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
-   return priv->inotifyWatch > 0;
-}
-#endif
-
-/* Convenience method to grab a int from the config file object */
-static int xenXMConfigGetBool(virConnectPtr conn,
-                              virConfPtr conf,
-                              const char *name,
-                              int *value,
-                              int def) {
-    virConfValuePtr val;
-
-    *value = 0;
-    if (!(val = virConfGetValue(conf, name))) {
-        *value = def;
-        return 0;
-    }
-
-    if (val->type == VIR_CONF_LONG) {
-        *value = val->l ? 1 : 0;
-    } else if (val->type == VIR_CONF_STRING) {
-        if (!val->str) {
-            *value = def;
-        }
-        *value = STREQ(val->str, "1") ? 1 : 0;
-    } else {
-        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
-                   _("config value %s was malformed"), name);
-        return -1;
-    }
-    return 0;
-}
-
-
-/* Convenience method to grab a int from the config file object */
-static int xenXMConfigGetULong(virConnectPtr conn,
-                               virConfPtr conf,
-                               const char *name,
-                               unsigned long *value,
-                               int def) {
-    virConfValuePtr val;
-
-    *value = 0;
-    if (!(val = virConfGetValue(conf, name))) {
-        *value = def;
-        return 0;
-    }
-
-    if (val->type == VIR_CONF_LONG) {
-        *value = val->l;
-    } else if (val->type == VIR_CONF_STRING) {
-        char *ret;
-        if (!val->str) {
-            *value = def;
-        }
-        *value = strtol(val->str, &ret, 10);
-        if (ret == val->str) {
-            xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
-                       _("config value %s was malformed"), name);
-            return -1;
-        }
-    } else {
-        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
-                   _("config value %s was malformed"), name);
-        return -1;
-    }
-    return 0;
-}
-
-
-/* Convenience method to grab a string from the config file object */
-static int xenXMConfigGetString(virConnectPtr conn,
-                                virConfPtr conf,
-                                const char *name,
-                                const char **value,
-                                const char *def) {
-    virConfValuePtr val;
-
-    *value = NULL;
-    if (!(val = virConfGetValue(conf, name))) {
-        *value = def;
-        return 0;
-    }
-
-    if (val->type != VIR_CONF_STRING) {
-        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
-                   _("config value %s was malformed"), name);
-        return -1;
-    }
-    if (!val->str)
-        *value = def;
-    else
-        *value = val->str;
-    return 0;
-}
-
-static int xenXMConfigCopyStringInternal(virConnectPtr conn,
-                                         virConfPtr conf,
-                                         const char *name,
-                                         char **value,
-                                         int allowMissing) {
-    virConfValuePtr val;
-
-    *value = NULL;
-    if (!(val = virConfGetValue(conf, name))) {
-        if (allowMissing)
-            return 0;
-        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
-                   _("config value %s was missing"), name);
-        return -1;
-    }
-
-    if (val->type != VIR_CONF_STRING) {
-        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
-                   _("config value %s was not a string"), name);
-        return -1;
-    }
-    if (!val->str) {
-        if (allowMissing)
-            return 0;
-        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
-                   _("config value %s was missing"), name);
-        return -1;
-    }
-
-    if (!(*value = strdup(val->str))) {
-        virReportOOMError(conn);
-        return -1;
-    }
-
-    return 0;
-}
-
-
-static int xenXMConfigCopyString(virConnectPtr conn,
-                                 virConfPtr conf,
-                                 const char *name,
-                                 char **value) {
-    return xenXMConfigCopyStringInternal(conn, conf, name, value, 0);
-}
-
-static int xenXMConfigCopyStringOpt(virConnectPtr conn,
-                                    virConfPtr conf,
-                                    const char *name,
-                                    char **value) {
-    return xenXMConfigCopyStringInternal(conn, conf, name, value, 1);
-}
-
-
-/* Convenience method to grab a string UUID from the config file object */
-static int xenXMConfigGetUUID(virConfPtr conf, const char *name, unsigned char *uuid) {
-    virConfValuePtr val;
-    if (!uuid || !name || !conf)
-        return (-1);
-    if (!(val = virConfGetValue(conf, name))) {
-        return (-1);
-    }
-
-    if (val->type != VIR_CONF_STRING)
-        return (-1);
-    if (!val->str)
-        return (-1);
-
-    if (virUUIDParse(val->str, uuid) < 0)
-        return (-1);
-
-    return (0);
-}
-
-
-/* Release memory associated with a cached config object */
-static void xenXMConfigFree(void *payload, const char *key ATTRIBUTE_UNUSED) {
-    xenXMConfCachePtr entry = (xenXMConfCachePtr)payload;
-    virDomainDefFree(entry->def);
-    VIR_FREE(entry);
-}
-
-struct xenXMConfigReaperData {
-    xenUnifiedPrivatePtr priv;
-    time_t now;
-};
-
-/* Remove any configs which were not refreshed recently */
-static int xenXMConfigReaper(const void *payload, const char *key ATTRIBUTE_UNUSED, const void *data) {
-    const struct xenXMConfigReaperData *args = data;
-    xenXMConfCachePtr entry = (xenXMConfCachePtr)payload;
-
-    /* We're going to purge this config file, so check if it
-       is currently mapped as owner of a named domain. */
-    if (entry->refreshedAt != args->now) {
-        const char *olddomname = entry->def->name;
-        char *nameowner = (char *)virHashLookup(args->priv->nameConfigMap, olddomname);
-        if (nameowner && STREQ(nameowner, key)) {
-            virHashRemoveEntry(args->priv->nameConfigMap, olddomname, NULL);
-        }
-        return (1);
-    }
-    return (0);
-}
-
-
-static virDomainDefPtr
-xenXMConfigReadFile(virConnectPtr conn, const char *filename) {
-    virConfPtr conf;
-    virDomainDefPtr def;
-
-    if (!(conf = virConfReadFile(filename, 0)))
-        return NULL;
-
-    def = xenXMDomainConfigParse(conn, conf);
-    virConfFree(conf);
-
-    return def;
-}
-
-static int
-xenXMConfigSaveFile(virConnectPtr conn, const char *filename, virDomainDefPtr def) {
-    virConfPtr conf;
-    int ret;
-
-    if (!(conf = xenXMDomainConfigFormat(conn, def)))
-        return -1;
-
-    ret = virConfWriteFile(filename, conf);
-    virConfFree(conf);
-    return ret;
-}
-
-
-/*
- * Caller must hold the lock on 'conn->privateData' before
- * calling this funtion
- */
-int
-xenXMConfigCacheRemoveFile(virConnectPtr conn,
-                           const char *filename)
-{
-    xenUnifiedPrivatePtr priv = conn->privateData;
-    xenXMConfCachePtr entry;
-
-    entry = virHashLookup(priv->configCache, filename);
-    if (!entry) {
-        DEBUG("No config entry for %s", filename);
-        return 0;
-    }
-
-    virHashRemoveEntry(priv->nameConfigMap, entry->def->name, NULL);
-    virHashRemoveEntry(priv->configCache, filename, xenXMConfigFree);
-    DEBUG("Removed %s %s", entry->def->name, filename);
-    return 0;
-}
-
-
-/*
- * Caller must hold the lock on 'conn->privateData' before
- * calling this funtion
- */
-int
-xenXMConfigCacheAddFile(virConnectPtr conn, const char *filename)
-{
-    xenUnifiedPrivatePtr priv = conn->privateData;
-    xenXMConfCachePtr entry;
-    struct stat st;
-    int newborn = 0;
-    time_t now = time(NULL);
-
-    DEBUG("Adding file %s", filename);
-
-    /* Get modified time */
-    if ((stat(filename, &st) < 0)) {
-        virReportSystemError(conn, errno,
-                             _("cannot stat: %s"),
-                             filename);
-        return -1;
-    }
-
-    /* Ignore zero length files, because inotify fires before
-       any content has actually been created */
-    if (st.st_size == 0) {
-        DEBUG("Ignoring zero length file %s", filename);
-        return -1;
-    }
-
-    /* If we already have a matching entry and it is not
-    modified, then carry on to next one*/
-    if ((entry = virHashLookup(priv->configCache, filename))) {
-        char *nameowner;
-
-        if (entry->refreshedAt >= st.st_mtime) {
-            entry->refreshedAt = now;
-            /* return success if up-to-date */
-            return 0;
-        }
-
-        /* If we currently own the name, then release it and
-            re-acquire it later - just in case it was renamed */
-        nameowner = (char *)virHashLookup(priv->nameConfigMap, entry->def->name);
-        if (nameowner && STREQ(nameowner, filename)) {
-            virHashRemoveEntry(priv->nameConfigMap, entry->def->name, NULL);
-        }
-
-        /* Clear existing config entry which needs refresh */
-        virDomainDefFree(entry->def);
-        entry->def = NULL;
-    } else { /* Completely new entry */
-        newborn = 1;
-        if (VIR_ALLOC(entry) < 0) {
-            virReportOOMError(conn);
-            return -1;
-        }
-        memcpy(entry->filename, filename, PATH_MAX);
-    }
-    entry->refreshedAt = now;
-
-    if (!(entry->def = xenXMConfigReadFile(conn, entry->filename))) {
-        DEBUG("Failed to read %s", entry->filename);
-        if (!newborn)
-            virHashRemoveEntry(priv->configCache, filename, NULL);
-        VIR_FREE(entry);
-        return -1;
-    }
-
-    /* If its a completely new entry, it must be stuck into
-        the cache (refresh'd entries are already registered) */
-    if (newborn) {
-        if (virHashAddEntry(priv->configCache, entry->filename, entry) < 0) {
-            virDomainDefFree(entry->def);
-            VIR_FREE(entry);
-            xenXMError (conn, VIR_ERR_INTERNAL_ERROR,
-                        "%s", _("xenXMConfigCacheRefresh: virHashAddEntry"));
-            return -1;
-        }
-    }
-
-    /* See if we need to map this config file in as the primary owner
-        * of the domain in question
-        */
-    if (!virHashLookup(priv->nameConfigMap, entry->def->name)) {
-        if (virHashAddEntry(priv->nameConfigMap, entry->def->name, entry->filename) < 0) {
-            virHashRemoveEntry(priv->configCache, filename, NULL);
-            virDomainDefFree(entry->def);
-            VIR_FREE(entry);
-        }
-    }
-    DEBUG("Added config %s %s", entry->def->name, filename);
-
-    return 0;
-}
-
-/* This method is called by various methods to scan /etc/xen
- * (or whatever directory was set by  LIBVIRT_XM_CONFIG_DIR
- * environment variable) and process any domain configs. It
- * has rate-limited so never rescans more frequently than
- * once every X seconds
- *
- * Caller must hold the lock on 'conn->privateData' before
- * calling this funtion
- */
-int xenXMConfigCacheRefresh (virConnectPtr conn) {
-    xenUnifiedPrivatePtr priv = conn->privateData;
-    DIR *dh;
-    struct dirent *ent;
-    time_t now = time(NULL);
-    int ret = -1;
-    struct xenXMConfigReaperData args;
-
-    if (now == ((time_t)-1)) {
-        virReportSystemError(conn, errno,
-                             "%s", _("cannot get time of day"));
-        return (-1);
-    }
-
-    /* Rate limit re-scans */
-    if ((now - priv->lastRefresh) < XM_REFRESH_INTERVAL)
-        return (0);
-
-    priv->lastRefresh = now;
-
-    /* Process the files in the config dir */
-    if (!(dh = opendir(priv->configDir))) {
-        virReportSystemError(conn, errno,
-                             _("cannot read directory %s"),
-                             priv->configDir);
-        return (-1);
-    }
-
-    while ((ent = readdir(dh))) {
-        struct stat st;
-        char path[PATH_MAX];
-
-        /*
-         * Skip a bunch of crufty files that clearly aren't config files
-         */
-
-        /* Like 'dot' files... */
-        if (STRPREFIX(ent->d_name, "."))
-            continue;
-        /* ...and the XenD server config file */
-        if (STRPREFIX(ent->d_name, XEND_CONFIG_FILE))
-            continue;
-        /* ...and random PCI config cruft */
-        if (STRPREFIX(ent->d_name, XEND_PCI_CONFIG_PREFIX))
-            continue;
-        /* ...and the example domain configs */
-        if (STRPREFIX(ent->d_name, XM_EXAMPLE_PREFIX))
-            continue;
-        /* ...and the QEMU networking script */
-        if (STRPREFIX(ent->d_name, QEMU_IF_SCRIPT))
-            continue;
-
-        /* ...and editor backups */
-        if (ent->d_name[0] == '#')
-            continue;
-        if (ent->d_name[strlen(ent->d_name)-1] == '~')
-            continue;
-
-        /* Build the full file path */
-        if ((strlen(priv->configDir) + 1 + strlen(ent->d_name) + 1) > PATH_MAX)
-            continue;
-        strcpy(path, priv->configDir);
-        strcat(path, "/");
-        strcat(path, ent->d_name);
-
-        /* Skip anything which isn't a file (takes care of scripts/ subdir */
-        if ((stat(path, &st) < 0) ||
-            (!S_ISREG(st.st_mode))) {
-            continue;
-        }
-
-        /* If we already have a matching entry and it is not
-           modified, then carry on to next one*/
-        if (xenXMConfigCacheAddFile(conn, path) < 0) {
-            /* Ignoring errors, since alot of stuff goes wrong in /etc/xen */
-        }
-    }
-
-    /* Reap all entries which were not changed, by comparing
-       their refresh timestamp - the timestamp should match
-       'now' if they were refreshed. If timestamp doesn't match
-       then the config is no longer on disk */
-    args.now = now;
-    args.priv = priv;
-    virHashRemoveSet(priv->configCache, xenXMConfigReaper, xenXMConfigFree, &args);
-    ret = 0;
-
-    if (dh)
-        closedir(dh);
-
-    return (ret);
-}
-
-
-/*
- * The XM driver keeps a cache of config files as virDomainDefPtr
- * objects in the xenUnifiedPrivatePtr. Optionally inotify lets
- * us watch for changes (see separate driver), otherwise we poll
- * every few seconds
- */
-virDrvOpenStatus
-xenXMOpen (virConnectPtr conn,
-           virConnectAuthPtr auth ATTRIBUTE_UNUSED,
-           int flags ATTRIBUTE_UNUSED)
-{
-    xenUnifiedPrivatePtr priv = conn->privateData;
-
-    priv->configDir = XM_CONFIG_DIR;
-
-    priv->configCache = virHashCreate(50);
-    if (!priv->configCache)
-        return (-1);
-    priv->nameConfigMap = virHashCreate(50);
-    if (!priv->nameConfigMap) {
-        virHashFree(priv->configCache, NULL);
-        priv->configCache = NULL;
-        return (-1);
-    }
-    /* Force the cache to be reloaded next time that
-     * xenXMConfigCacheRefresh is called.
-     */
-    priv->lastRefresh = 0;
-
-    return (0);
-}
-
-/*
- * Free the cached config files associated with this
- * connection
- */
-int xenXMClose(virConnectPtr conn) {
-    xenUnifiedPrivatePtr priv = conn->privateData;
-
-    virHashFree(priv->nameConfigMap, NULL);
-    virHashFree(priv->configCache, xenXMConfigFree);
-
-    return (0);
-}
-
-/*
- * Since these are all offline domains, we only return info about
- * VCPUs and memory.
- */
-int xenXMDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info) {
-    xenUnifiedPrivatePtr priv;
-    const char *filename;
-    xenXMConfCachePtr entry;
-    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
-        xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                   __FUNCTION__);
-        return(-1);
-    }
-
-    if (domain->id != -1)
-        return (-1);
-
-    priv = domain->conn->privateData;
-    xenUnifiedLock(priv);
-
-    if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
-        goto error;
-
-    if (!(entry = virHashLookup(priv->configCache, filename)))
-        goto error;
-
-    memset(info, 0, sizeof(virDomainInfo));
-    info->maxMem = entry->def->maxmem;
-    info->memory = entry->def->memory;
-    info->nrVirtCpu = entry->def->vcpus;
-    info->state = VIR_DOMAIN_SHUTOFF;
-    info->cpuTime = 0;
-
-    xenUnifiedUnlock(priv);
-    return (0);
-
-error:
-    xenUnifiedUnlock(priv);
-    return -1;
-}
-
-#define MAX_VFB 1024
-/*
- * Turn a config record into a lump of XML describing the
- * domain, suitable for later feeding for virDomainCreateXML
- */
-virDomainDefPtr
-xenXMDomainConfigParse(virConnectPtr conn, virConfPtr conf) {
-    const char *str;
-    int hvm = 0;
-    int val;
-    virConfValuePtr list;
-    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
-    virDomainDefPtr def = NULL;
-    virDomainDiskDefPtr disk = NULL;
-    virDomainNetDefPtr net = NULL;
-    virDomainGraphicsDefPtr graphics = NULL;
-    virDomainHostdevDefPtr hostdev = NULL;
-    int i;
-    const char *defaultArch, *defaultMachine;
-
-    if (VIR_ALLOC(def) < 0)
-        return NULL;
-
-    def->virtType = VIR_DOMAIN_VIRT_XEN;
-    def->id = -1;
-
-    if (xenXMConfigCopyString(conn, conf, "name", &def->name) < 0)
-        goto cleanup;
-    if (xenXMConfigGetUUID(conf, "uuid", def->uuid) < 0)
-        goto cleanup;
-
-
-    if ((xenXMConfigGetString(conn, conf, "builder", &str, "linux") == 0) &&
-        STREQ(str, "hvm"))
-        hvm = 1;
-
-    if (!(def->os.type = strdup(hvm ? "hvm" : "xen")))
-        goto no_memory;
-
-    defaultArch = virCapabilitiesDefaultGuestArch(priv->caps, def->os.type, virDomainVirtTypeToString(def->virtType));
-    if (defaultArch == NULL) {
-        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
-                   _("no supported architecture for os type '%s'"),
-                   def->os.type);
-        goto cleanup;
-    }
-    if (!(def->os.arch = strdup(defaultArch)))
-        goto no_memory;
-
-    defaultMachine = virCapabilitiesDefaultGuestMachine(priv->caps,
-                                                        def->os.type,
-                                                        def->os.arch);
-    if (defaultMachine != NULL) {
-        if (!(def->os.machine = strdup(defaultMachine)))
-            goto no_memory;
-    }
-
-    if (hvm) {
-        const char *boot;
-        if (xenXMConfigCopyString(conn, conf, "kernel", &def->os.loader) < 0)
-            goto cleanup;
-
-        if (xenXMConfigGetString(conn, conf, "boot", &boot, "c") < 0)
-            goto cleanup;
-
-        for (i = 0 ; i < VIR_DOMAIN_BOOT_LAST && boot[i] ; i++) {
-            switch (*boot) {
-            case 'a':
-                def->os.bootDevs[i] = VIR_DOMAIN_BOOT_FLOPPY;
-                break;
-            case 'd':
-                def->os.bootDevs[i] = VIR_DOMAIN_BOOT_CDROM;
-                break;
-            case 'n':
-                def->os.bootDevs[i] = VIR_DOMAIN_BOOT_NET;
-                break;
-            case 'c':
-            default:
-                def->os.bootDevs[i] = VIR_DOMAIN_BOOT_DISK;
-                break;
-            }
-            def->os.nBootDevs++;
-        }
-    } else {
-        if (xenXMConfigCopyStringOpt(conn, conf, "bootloader", &def->os.bootloader) < 0)
-            goto cleanup;
-        if (xenXMConfigCopyStringOpt(conn, conf, "bootargs", &def->os.bootloaderArgs) < 0)
-            goto cleanup;
-
-        if (xenXMConfigCopyStringOpt(conn, conf, "kernel", &def->os.kernel) < 0)
-            goto cleanup;
-        if (xenXMConfigCopyStringOpt(conn, conf, "ramdisk", &def->os.initrd) < 0)
-            goto cleanup;
-        if (xenXMConfigCopyStringOpt(conn, conf, "extra", &def->os.cmdline) < 0)
-            goto cleanup;
-    }
-
-    if (xenXMConfigGetULong(conn, conf, "memory", &def->memory, MIN_XEN_GUEST_SIZE * 2) < 0)
-        goto cleanup;
-
-    if (xenXMConfigGetULong(conn, conf, "maxmem", &def->maxmem, def->memory) < 0)
-        goto cleanup;
-
-    def->memory *= 1024;
-    def->maxmem *= 1024;
-
-
-    if (xenXMConfigGetULong(conn, conf, "vcpus", &def->vcpus, 1) < 0)
-        goto cleanup;
-
-    if (xenXMConfigGetString(conn, conf, "cpus", &str, NULL) < 0)
-        goto cleanup;
-    if (str) {
-        def->cpumasklen = 4096;
-        if (VIR_ALLOC_N(def->cpumask, def->cpumasklen) < 0)
-            goto no_memory;
-
-        if (virDomainCpuSetParse(conn, &str, 0,
-                                 def->cpumask, def->cpumasklen) < 0)
-            goto cleanup;
-    }
-
-
-    if (xenXMConfigGetString(conn, conf, "on_poweroff", &str, "destroy") < 0)
-        goto cleanup;
-    if ((def->onPoweroff = virDomainLifecycleTypeFromString(str)) < 0) {
-        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
-                   _("unexpected value %s for on_poweroff"), str);
-        goto cleanup;
-    }
-
-    if (xenXMConfigGetString(conn, conf, "on_reboot", &str, "restart") < 0)
-        goto cleanup;
-    if ((def->onReboot = virDomainLifecycleTypeFromString(str)) < 0) {
-        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
-                   _("unexpected value %s for on_reboot"), str);
-        goto cleanup;
-    }
-
-    if (xenXMConfigGetString(conn, conf, "on_crash", &str, "restart") < 0)
-        goto cleanup;
-    if ((def->onCrash = virDomainLifecycleTypeFromString(str)) < 0) {
-        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
-                   _("unexpected value %s for on_crash"), str);
-        goto cleanup;
-    }
-
-
-
-    if (hvm) {
-        if (xenXMConfigGetBool(conn, conf, "pae", &val, 0) < 0)
-            goto cleanup;
-        else if (val)
-            def->features |= (1 << VIR_DOMAIN_FEATURE_PAE);
-        if (xenXMConfigGetBool(conn, conf, "acpi", &val, 0) < 0)
-            goto cleanup;
-        else if (val)
-            def->features |= (1 << VIR_DOMAIN_FEATURE_ACPI);
-        if (xenXMConfigGetBool(conn, conf, "apic", &val, 0) < 0)
-            goto cleanup;
-        else if (val)
-            def->features |= (1 << VIR_DOMAIN_FEATURE_APIC);
-    }
-    if (xenXMConfigGetBool(conn, conf, "localtime", &def->localtime, 0) < 0)
-        goto cleanup;
-
-    if (xenXMConfigCopyStringOpt(conn, conf, "device_model", &def->emulator) < 0)
-        goto cleanup;
-
-    list = virConfGetValue(conf, "disk");
-    if (list && list->type == VIR_CONF_LIST) {
-        list = list->list;
-        while (list) {
-            char *head;
-            char *offset;
-            char *tmp;
-
-            if ((list->type != VIR_CONF_STRING) || (list->str == NULL))
-                goto skipdisk;
-            head = list->str;
-
-            if (VIR_ALLOC(disk) < 0)
-                goto no_memory;
-
-            /*
-             * Disks have 3 components, SOURCE,DEST-DEVICE,MODE
-             * eg, phy:/dev/HostVG/XenGuest1,xvda,w
-             * The SOURCE is usually prefixed with a driver type,
-             * and optionally driver sub-type
-             * The DEST-DEVICE is optionally post-fixed with disk type
-             */
-
-            /* Extract the source file path*/
-            if (!(offset = strchr(head, ',')))
-                goto skipdisk;
-            if ((offset - head) >= (PATH_MAX-1))
-                goto skipdisk;
-
-            if (offset == head) {
-                disk->src = NULL; /* No source file given, eg CDROM with no media */
-            } else {
-                if (VIR_ALLOC_N(disk->src, (offset - head) + 1) < 0)
-                    goto no_memory;
-                strncpy(disk->src, head, (offset - head));
-                disk->src[(offset-head)] = '\0';
-            }
-            head = offset + 1;
-
-            /* Remove legacy ioemu: junk */
-            if (STRPREFIX(head, "ioemu:"))
-                head = head + 6;
-
-            /* Extract the dest device name */
-            if (!(offset = strchr(head, ',')))
-                goto skipdisk;
-            if (VIR_ALLOC_N(disk->dst, (offset - head) + 1) < 0)
-                goto no_memory;
-            strncpy(disk->dst, head, (offset - head));
-            disk->dst[(offset-head)] = '\0';
-            head = offset + 1;
-
-
-            /* Extract source driver type */
-            if (disk->src) {
-                /* The main type  phy:, file:, tap: ... */
-                if ((tmp = strchr(disk->src, ':')) != NULL) {
-                    if (VIR_ALLOC_N(disk->driverName, (tmp - disk->src) + 1) < 0)
-                        goto no_memory;
-                    strncpy(disk->driverName, disk->src, (tmp - disk->src));
-                    disk->driverName[tmp - disk->src] = '\0';
-
-                    /* Strip the prefix we found off the source file name */
-                    memmove(disk->src, disk->src+(tmp-disk->src)+1,
-                            strlen(disk->src)-(tmp-disk->src));
-                }
-
-                /* And the sub-type for tap:XXX: type */
-                if (disk->driverName &&
-                    STREQ(disk->driverName, "tap")) {
-                    if (!(tmp = strchr(disk->src, ':')))
-                        goto skipdisk;
-                    if (VIR_ALLOC_N(disk->driverType, (tmp - disk->src) + 1) < 0)
-                        goto no_memory;
-                    strncpy(disk->driverType, disk->src, (tmp - disk->src));
-                    disk->driverType[tmp - disk->src] = '\0';
-
-                    /* Strip the prefix we found off the source file name */
-                    memmove(disk->src, disk->src+(tmp-disk->src)+1,
-                            strlen(disk->src)-(tmp-disk->src));
-                }
-            }
-
-            /* No source, or driver name, so fix to phy: */
-            if (!disk->driverName &&
-                !(disk->driverName = strdup("phy")))
-                goto no_memory;
-
-
-            /* phy: type indicates a block device */
-            disk->type = STREQ(disk->driverName, "phy") ?
-                VIR_DOMAIN_DISK_TYPE_BLOCK : VIR_DOMAIN_DISK_TYPE_FILE;
-
-            /* Check for a :cdrom/:disk postfix */
-            disk->device = VIR_DOMAIN_DISK_DEVICE_DISK;
-            if ((tmp = strchr(disk->dst, ':')) != NULL) {
-                if (STREQ(tmp, ":cdrom"))
-                    disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
-                tmp[0] = '\0';
-            }
-
-            if (STRPREFIX(disk->dst, "xvd") || !hvm) {
-                disk->bus = VIR_DOMAIN_DISK_BUS_XEN;
-            } else if (STRPREFIX(disk->dst, "sd")) {
-                disk->bus = VIR_DOMAIN_DISK_BUS_SCSI;
-            } else {
-                disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
-            }
-
-            if (STREQ(head, "r") ||
-                STREQ(head, "ro"))
-                disk->readonly = 1;
-            else if ((STREQ(head, "w!")) ||
-                     (STREQ(head, "!")))
-                disk->shared = 1;
-
-            /* Maintain list in sorted order according to target device name */
-            if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0)
-                goto no_memory;
-            def->disks[def->ndisks++] = disk;
-            disk = NULL;
-
-            skipdisk:
-            list = list->next;
-            virDomainDiskDefFree(disk);
-        }
-    }
-
-    if (hvm && priv->xendConfigVersion == 1) {
-        if (xenXMConfigGetString(conn, conf, "cdrom", &str, NULL) < 0)
-            goto cleanup;
-        if (str) {
-            if (VIR_ALLOC(disk) < 0)
-                goto no_memory;
-
-            disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
-            disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
-            if (!(disk->driverName = strdup("file")))
-                goto no_memory;
-            if (!(disk->src = strdup(str)))
-                goto no_memory;
-            if (!(disk->dst = strdup("hdc")))
-                goto no_memory;
-            disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
-            disk->readonly = 1;
-
-            if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0)
-                goto no_memory;
-            def->disks[def->ndisks++] = disk;
-            disk = NULL;
-        }
-    }
-
-    list = virConfGetValue(conf, "vif");
-    if (list && list->type == VIR_CONF_LIST) {
-        list = list->list;
-        while (list) {
-            char script[PATH_MAX];
-            char model[10];
-            char ip[16];
-            char mac[18];
-            char bridge[50];
-            char vifname[50];
-            char *key;
-
-            bridge[0] = '\0';
-            mac[0] = '\0';
-            script[0] = '\0';
-            ip[0] = '\0';
-            model[0] = '\0';
-            vifname[0] = '\0';
-
-            if ((list->type != VIR_CONF_STRING) || (list->str == NULL))
-                goto skipnic;
-
-            key = list->str;
-            while (key) {
-                char *data;
-                char *nextkey = strchr(key, ',');
-
-                if (!(data = strchr(key, '=')))
-                    goto skipnic;
-                data++;
-
-                if (STRPREFIX(key, "mac=")) {
-                    int len = nextkey ? (nextkey - data) : 17;
-                    if (len > 17)
-                        len = 17;
-                    strncpy(mac, data, len);
-                    mac[len] = '\0';
-                } else if (STRPREFIX(key, "bridge=")) {
-                    int len = nextkey ? (nextkey - data) : sizeof(bridge)-1;
-                    if (len > (sizeof(bridge)-1))
-                        len = sizeof(bridge)-1;
-                    strncpy(bridge, data, len);
-                    bridge[len] = '\0';
-                } else if (STRPREFIX(key, "script=")) {
-                    int len = nextkey ? (nextkey - data) : PATH_MAX-1;
-                    if (len > (PATH_MAX-1))
-                        len = PATH_MAX-1;
-                    strncpy(script, data, len);
-                    script[len] = '\0';
-                } else if (STRPREFIX(key, "model=")) {
-                    int len = nextkey ? (nextkey - data) : sizeof(model)-1;
-                    if (len > (sizeof(model)-1))
-                        len = sizeof(model)-1;
-                    strncpy(model, data, len);
-                    model[len] = '\0';
-                } else if (STRPREFIX(key, "vifname=")) {
-                    int len = nextkey ? (nextkey - data) : sizeof(vifname)-1;
-                    if (len > (sizeof(vifname)-1))
-                        len = sizeof(vifname)-1;
-                    strncpy(vifname, data, len);
-                    vifname[len] = '\0';
-                } else if (STRPREFIX(key, "ip=")) {
-                    int len = nextkey ? (nextkey - data) : 15;
-                    if (len > 15)
-                        len = 15;
-                    strncpy(ip, data, len);
-                    ip[len] = '\0';
-                }
-
-                while (nextkey && (nextkey[0] == ',' ||
-                                   nextkey[0] == ' ' ||
-                                   nextkey[0] == '\t'))
-                    nextkey++;
-                key = nextkey;
-            }
-
-            if (VIR_ALLOC(net) < 0)
-                goto cleanup;
-
-            if (mac[0]) {
-                unsigned int rawmac[6];
-                sscanf(mac, "%02x:%02x:%02x:%02x:%02x:%02x",
-                       (unsigned int*)&rawmac[0],
-                       (unsigned int*)&rawmac[1],
-                       (unsigned int*)&rawmac[2],
-                       (unsigned int*)&rawmac[3],
-                       (unsigned int*)&rawmac[4],
-                       (unsigned int*)&rawmac[5]);
-                net->mac[0] = rawmac[0];
-                net->mac[1] = rawmac[1];
-                net->mac[2] = rawmac[2];
-                net->mac[3] = rawmac[3];
-                net->mac[4] = rawmac[4];
-                net->mac[5] = rawmac[5];
-            }
-
-            if (bridge[0] || STREQ(script, "vif-bridge") ||
-                STREQ(script, "vif-vnic")) {
-                net->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
-            } else {
-                net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
-            }
-
-            if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
-                if (bridge[0] &&
-                    !(net->data.bridge.brname = strdup(bridge)))
-                    goto no_memory;
-                if (script[0] &&
-                    !(net->data.bridge.script = strdup(script)))
-                    goto no_memory;
-                if (ip[0] &&
-                    !(net->data.bridge.ipaddr = strdup(ip)))
-                    goto no_memory;
-            } else {
-                if (script[0] &&
-                    !(net->data.ethernet.script = strdup(script)))
-                    goto no_memory;
-                if (ip[0] &&
-                    !(net->data.ethernet.ipaddr = strdup(ip)))
-                    goto no_memory;
-            }
-            if (model[0] &&
-                !(net->model = strdup(model)))
-                goto no_memory;
-
-            if (vifname[0] &&
-                !(net->ifname = strdup(vifname)))
-                goto no_memory;
-
-            if (VIR_REALLOC_N(def->nets, def->nnets+1) < 0)
-                goto no_memory;
-            def->nets[def->nnets++] = net;
-            net = NULL;
-
-        skipnic:
-            list = list->next;
-            virDomainNetDefFree(net);
-        }
-    }
-
-    list = virConfGetValue(conf, "pci");
-    if (list && list->type == VIR_CONF_LIST) {
-        list = list->list;
-        while (list) {
-            char domain[5];
-            char bus[3];
-            char slot[3];
-            char func[2];
-            char *key, *nextkey;
-            int domainID;
-            int busID;
-            int slotID;
-            int funcID;
-
-            domain[0] = bus[0] = slot[0] = func[0] = '\0';
-
-            if ((list->type != VIR_CONF_STRING) || (list->str == NULL))
-                goto skippci;
-
-            /* pci=['0000:00:1b.0','0000:00:13.0'] */
-            if (!(key = list->str))
-                goto skippci;
-            if (!(nextkey = strchr(key, ':')))
-                goto skippci;
-
-            if ((nextkey - key) > (sizeof(domain)-1))
-                goto skippci;
-
-            strncpy(domain, key, sizeof(domain));
-            domain[sizeof(domain)-1] = '\0';
-
-            key = nextkey + 1;
-            if (!(nextkey = strchr(key, ':')))
-                goto skippci;
-
-            strncpy(bus, key, sizeof(bus));
-            bus[sizeof(bus)-1] = '\0';
-
-            key = nextkey + 1;
-            if (!(nextkey = strchr(key, '.')))
-                goto skippci;
-
-            strncpy(slot, key, sizeof(slot));
-            slot[sizeof(slot)-1] = '\0';
-
-            key = nextkey + 1;
-            if (strlen(key) != 1)
-                goto skippci;
-
-            strncpy(func, key, sizeof(func));
-            func[sizeof(func)-1] = '\0';
-
-            if (virStrToLong_i(domain, NULL, 16, &domainID) < 0)
-                goto skippci;
-            if (virStrToLong_i(bus, NULL, 16, &busID) < 0)
-                goto skippci;
-            if (virStrToLong_i(slot, NULL, 16, &slotID) < 0)
-                goto skippci;
-            if (virStrToLong_i(func, NULL, 16, &funcID) < 0)
-                goto skippci;
-
-            if (VIR_ALLOC(hostdev) < 0)
-                goto cleanup;
-
-            hostdev->managed = 0;
-            hostdev->source.subsys.type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI;
-            hostdev->source.subsys.u.pci.domain = domainID;
-            hostdev->source.subsys.u.pci.bus = busID;
-            hostdev->source.subsys.u.pci.slot = slotID;
-            hostdev->source.subsys.u.pci.function = funcID;
-
-            if (VIR_REALLOC_N(def->hostdevs, def->nhostdevs+1) < 0)
-                goto no_memory;
-            def->hostdevs[def->nhostdevs++] = hostdev;
-            hostdev = NULL;
-
-        skippci:
-            list = list->next;
-        }
-    }
-
-    if (hvm) {
-        if (xenXMConfigGetString(conn, conf, "usbdevice", &str, NULL) < 0)
-            goto cleanup;
-        if (str &&
-            (STREQ(str, "tablet") ||
-             STREQ(str, "mouse"))) {
-            virDomainInputDefPtr input;
-            if (VIR_ALLOC(input) < 0)
-                goto no_memory;
-            input->bus = VIR_DOMAIN_INPUT_BUS_USB;
-            input->type = STREQ(str, "tablet") ?
-                VIR_DOMAIN_INPUT_TYPE_TABLET :
-                VIR_DOMAIN_INPUT_TYPE_MOUSE;
-            if (VIR_ALLOC_N(def->inputs, 1) < 0) {
-                virDomainInputDefFree(input);
-                goto no_memory;
-            }
-            def->inputs[0] = input;
-            def->ninputs = 1;
-        }
-    }
-
-    /* HVM guests, or old PV guests use this config format */
-    if (hvm || priv->xendConfigVersion < 3) {
-        if (xenXMConfigGetBool(conn, conf, "vnc", &val, 0) < 0)
-            goto cleanup;
-
-        if (val) {
-            if (VIR_ALLOC(graphics) < 0)
-                goto no_memory;
-            graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_VNC;
-            if (xenXMConfigGetBool(conn, conf, "vncunused", &val, 1) < 0)
-                goto cleanup;
-            graphics->data.vnc.autoport = val ? 1 : 0;
-
-            if (!graphics->data.vnc.autoport) {
-                unsigned long vncdisplay;
-                if (xenXMConfigGetULong(conn, conf, "vncdisplay", &vncdisplay, 0) < 0)
-                    goto cleanup;
-                graphics->data.vnc.port = (int)vncdisplay + 5900;
-            }
-            if (xenXMConfigCopyStringOpt(conn, conf, "vnclisten", &graphics->data.vnc.listenAddr) < 0)
-                goto cleanup;
-            if (xenXMConfigCopyStringOpt(conn, conf, "vncpasswd", &graphics->data.vnc.passwd) < 0)
-                goto cleanup;
-            if (xenXMConfigCopyStringOpt(conn, conf, "keymap", &graphics->data.vnc.keymap) < 0)
-                goto cleanup;
-
-            if (VIR_ALLOC_N(def->graphics, 1) < 0)
-                goto no_memory;
-            def->graphics[0] = graphics;
-            def->ngraphics = 1;
-            graphics = NULL;
-        } else {
-            if (xenXMConfigGetBool(conn, conf, "sdl", &val, 0) < 0)
-                goto cleanup;
-            if (val) {
-                if (VIR_ALLOC(graphics) < 0)
-                    goto no_memory;
-                graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_SDL;
-                if (xenXMConfigCopyStringOpt(conn, conf, "display", &graphics->data.sdl.display) < 0)
-                    goto cleanup;
-                if (xenXMConfigCopyStringOpt(conn, conf, "xauthority", &graphics->data.sdl.xauth) < 0)
-                    goto cleanup;
-                if (VIR_ALLOC_N(def->graphics, 1) < 0)
-                    goto no_memory;
-                def->graphics[0] = graphics;
-                def->ngraphics = 1;
-                graphics = NULL;
-            }
-        }
-    }
-
-    if (!hvm && def->graphics == NULL) { /* New PV guests use this format */
-        list = virConfGetValue(conf, "vfb");
-        if (list && list->type == VIR_CONF_LIST &&
-            list->list && list->list->type == VIR_CONF_STRING &&
-            list->list->str) {
-            char vfb[MAX_VFB];
-            char *key = vfb;
-            strncpy(vfb, list->list->str, MAX_VFB-1);
-            vfb[MAX_VFB-1] = '\0';
-
-            if (VIR_ALLOC(graphics) < 0)
-                goto no_memory;
-
-            if (strstr(key, "type=sdl"))
-                graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_SDL;
-            else
-                graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_VNC;
-
-            while (key) {
-                char *data;
-                char *nextkey = strchr(key, ',');
-                char *end = nextkey;
-                if (nextkey) {
-                    *end = '\0';
-                    nextkey++;
-                }
-
-                if (!(data = strchr(key, '=')))
-                    break;
-
-                if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
-                    if (STRPREFIX(key, "vncunused=")) {
-                        if (STREQ(key + 10, "1"))
-                            graphics->data.vnc.autoport = 1;
-                    } else if (STRPREFIX(key, "vnclisten=")) {
-                        if (!(graphics->data.vnc.listenAddr = strdup(key + 10)))
-                            goto no_memory;
-                    } else if (STRPREFIX(key, "vncpasswd=")) {
-                        if (!(graphics->data.vnc.passwd = strdup(key + 10)))
-                            goto no_memory;
-                    } else if (STRPREFIX(key, "keymap=")) {
-                        if (!(graphics->data.vnc.keymap = strdup(key + 7)))
-                            goto no_memory;
-                    } else if (STRPREFIX(key, "vncdisplay=")) {
-                        graphics->data.vnc.port = strtol(key+11, NULL, 10) + 5900;
-                    }
-                } else {
-                    if (STRPREFIX(key, "display=")) {
-                        if (!(graphics->data.sdl.display = strdup(key + 8)))
-                            goto no_memory;
-                    } else if (STRPREFIX(key, "xauthority=")) {
-                        if (!(graphics->data.sdl.xauth = strdup(key + 11)))
-                            goto no_memory;
-                    }
-                }
-
-                while (nextkey && (nextkey[0] == ',' ||
-                                   nextkey[0] == ' ' ||
-                                   nextkey[0] == '\t'))
-                    nextkey++;
-                key = nextkey;
-            }
-            if (VIR_ALLOC_N(def->graphics, 1) < 0)
-                goto no_memory;
-            def->graphics[0] = graphics;
-            def->ngraphics = 1;
-            graphics = NULL;
-        }
-    }
-
-    if (hvm) {
-        virDomainChrDefPtr chr = NULL;
-
-        if (xenXMConfigGetString(conn, conf, "parallel", &str, NULL) < 0)
-            goto cleanup;
-        if (str && STRNEQ(str, "none") &&
-            !(chr = xenDaemonParseSxprChar(conn, str, NULL)))
-            goto cleanup;
-
-        if (chr) {
-            if (VIR_ALLOC_N(def->parallels, 1) < 0) {
-                virDomainChrDefFree(chr);
-                goto no_memory;
-            }
-            def->parallels[0] = chr;
-            def->nparallels++;
-            chr = NULL;
-        }
-
-        if (xenXMConfigGetString(conn, conf, "serial", &str, NULL) < 0)
-            goto cleanup;
-        if (str && STRNEQ(str, "none") &&
-            !(chr = xenDaemonParseSxprChar(conn, str, NULL)))
-            goto cleanup;
-
-        if (chr) {
-            if (VIR_ALLOC_N(def->serials, 1) < 0) {
-                virDomainChrDefFree(chr);
-                goto no_memory;
-            }
-            def->serials[0] = chr;
-            def->nserials++;
-        }
-    } else {
-        if (!(def->console = xenDaemonParseSxprChar(conn, "pty", NULL)))
-            goto cleanup;
-    }
-
-    if (hvm) {
-        if (xenXMConfigGetString(conn, conf, "soundhw", &str, NULL) < 0)
-            goto cleanup;
-
-        if (str &&
-            xenDaemonParseSxprSound(conn, def, str) < 0)
-            goto cleanup;
-    }
-
-    return def;
-
-no_memory:
-    virReportOOMError(conn);
-    /* fallthrough */
-cleanup:
-    virDomainGraphicsDefFree(graphics);
-    virDomainNetDefFree(net);
-    virDomainDiskDefFree(disk);
-    virDomainDefFree(def);
-    return NULL;
-}
-
-
-/*
- * Turn a config record into a lump of XML describing the
- * domain, suitable for later feeding for virDomainCreateXML
- */
-char *xenXMDomainDumpXML(virDomainPtr domain, int flags) {
-    xenUnifiedPrivatePtr priv;
-    const char *filename;
-    xenXMConfCachePtr entry;
-    char *ret = NULL;
-
-    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
-        xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                   __FUNCTION__);
-        return(NULL);
-    }
-    if (domain->id != -1)
-        return (NULL);
-
-    priv = domain->conn->privateData;
-    xenUnifiedLock(priv);
-
-    if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
-        goto cleanup;
-
-    if (!(entry = virHashLookup(priv->configCache, filename)))
-        goto cleanup;
-
-    ret = virDomainDefFormat(domain->conn, entry->def, flags);
-
-cleanup:
-    xenUnifiedUnlock(priv);
-    return ret;
-}
-
-
-/*
- * Update amount of memory in the config file
- */
-int xenXMDomainSetMemory(virDomainPtr domain, unsigned long memory) {
-    xenUnifiedPrivatePtr priv;
-    const char *filename;
-    xenXMConfCachePtr entry;
-    int ret = -1;
-
-    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
-        xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                   __FUNCTION__);
-        return (-1);
-    }
-    if (domain->conn->flags & VIR_CONNECT_RO)
-        return (-1);
-    if (domain->id != -1)
-        return (-1);
-    if (memory < 1024 * MIN_XEN_GUEST_SIZE)
-        return (-1);
-
-    priv = domain->conn->privateData;
-    xenUnifiedLock(priv);
-
-    if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
-        goto cleanup;
-
-    if (!(entry = virHashLookup(priv->configCache, filename)))
-        goto cleanup;
-
-    entry->def->memory = memory;
-    if (entry->def->memory > entry->def->maxmem)
-        entry->def->memory = entry->def->maxmem;
-
-    /* If this fails, should we try to undo our changes to the
-     * in-memory representation of the config file. I say not!
-     */
-    if (xenXMConfigSaveFile(domain->conn, entry->filename, entry->def) < 0)
-        goto cleanup;
-    ret = 0;
-
-cleanup:
-    xenUnifiedUnlock(priv);
-    return ret;
-}
-
-/*
- * Update maximum memory limit in config
- */
-int xenXMDomainSetMaxMemory(virDomainPtr domain, unsigned long memory) {
-    xenUnifiedPrivatePtr priv;
-    const char *filename;
-    xenXMConfCachePtr entry;
-    int ret = -1;
-
-    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
-        xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                   __FUNCTION__);
-        return (-1);
-    }
-    if (domain->conn->flags & VIR_CONNECT_RO)
-        return (-1);
-    if (domain->id != -1)
-        return (-1);
-
-    priv = domain->conn->privateData;
-    xenUnifiedLock(priv);
-
-    if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
-        goto cleanup;
-
-    if (!(entry = virHashLookup(priv->configCache, filename)))
-        goto cleanup;
-
-    entry->def->maxmem = memory;
-    if (entry->def->memory > entry->def->maxmem)
-        entry->def->memory = entry->def->maxmem;
-
-    /* If this fails, should we try to undo our changes to the
-     * in-memory representation of the config file. I say not!
-     */
-    if (xenXMConfigSaveFile(domain->conn, entry->filename, entry->def) < 0)
-        goto cleanup;
-    ret = 0;
-
-cleanup:
-    xenUnifiedUnlock(priv);
-    return ret;
-}
-
-/*
- * Get max memory limit from config
- */
-unsigned long xenXMDomainGetMaxMemory(virDomainPtr domain) {
-    xenUnifiedPrivatePtr priv;
-    const char *filename;
-    xenXMConfCachePtr entry;
-    unsigned long ret = 0;
-
-    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
-        xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                   __FUNCTION__);
-        return (0);
-    }
-    if (domain->id != -1)
-        return (0);
-
-    priv = domain->conn->privateData;
-    xenUnifiedLock(priv);
-
-    if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
-        goto cleanup;
-
-    if (!(entry = virHashLookup(priv->configCache, filename)))
-        goto cleanup;
-
-    ret = entry->def->maxmem;
-
-cleanup:
-    xenUnifiedUnlock(priv);
-    return ret;
-}
-
-/*
- * Set the VCPU count in config
- */
-int xenXMDomainSetVcpus(virDomainPtr domain, unsigned int vcpus) {
-    xenUnifiedPrivatePtr priv;
-    const char *filename;
-    xenXMConfCachePtr entry;
-    int ret = -1;
-
-    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
-        xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                   __FUNCTION__);
-        return (-1);
-    }
-    if (domain->conn->flags & VIR_CONNECT_RO)
-        return (-1);
-    if (domain->id != -1)
-        return (-1);
-
-    priv = domain->conn->privateData;
-    xenUnifiedLock(priv);
-
-    if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
-        goto cleanup;
-
-    if (!(entry = virHashLookup(priv->configCache, filename)))
-        goto cleanup;
-
-    entry->def->vcpus = vcpus;
-
-    /* If this fails, should we try to undo our changes to the
-     * in-memory representation of the config file. I say not!
-     */
-    if (xenXMConfigSaveFile(domain->conn, entry->filename, entry->def) < 0)
-        goto cleanup;
-    ret = 0;
-
-cleanup:
-    xenUnifiedUnlock(priv);
-    return ret;
-}
-
-/**
- * xenXMDomainPinVcpu:
- * @domain: pointer to domain object
- * @vcpu: virtual CPU number (reserved)
- * @cpumap: pointer to a bit map of real CPUs (in 8-bit bytes)
- * @maplen: length of cpumap in bytes
- *
- * Set the vcpu affinity in config
- *
- * Returns 0 for success; -1 (with errno) on error
- */
-int xenXMDomainPinVcpu(virDomainPtr domain,
-                       unsigned int vcpu ATTRIBUTE_UNUSED,
-                       unsigned char *cpumap, int maplen)
-{
-    xenUnifiedPrivatePtr priv;
-    const char *filename;
-    xenXMConfCachePtr entry;
-    virBuffer mapbuf = VIR_BUFFER_INITIALIZER;
-    char *mapstr = NULL, *mapsave = NULL;
-    int i, j, n, comma = 0;
-    int ret = -1;
-    char *cpuset = NULL;
-    int maxcpu = XEN_MAX_PHYSICAL_CPU;
-
-    if (domain == NULL || domain->conn == NULL || domain->name == NULL
-        || cpumap == NULL || maplen < 1 || maplen > (int)sizeof(cpumap_t)) {
-        xenXMError(domain ? domain->conn : NULL, VIR_ERR_INVALID_ARG,
-                   __FUNCTION__);
-        return -1;
-    }
-    if (domain->conn->flags & VIR_CONNECT_RO) {
-        xenXMError (domain->conn, VIR_ERR_INVALID_ARG,
-                    "%s", _("read only connection"));
-        return -1;
-    }
-    if (domain->id != -1) {
-        xenXMError (domain->conn, VIR_ERR_INVALID_ARG,
-                    "%s", _("not inactive domain"));
-        return -1;
-    }
-
-    priv = domain->conn->privateData;
-    xenUnifiedLock(priv);
-
-    if (!(filename = virHashLookup(priv->nameConfigMap, domain->name))) {
-        xenXMError (domain->conn, VIR_ERR_INTERNAL_ERROR, "%s", _("virHashLookup"));
-        goto cleanup;
-    }
-    if (!(entry = virHashLookup(priv->configCache, filename))) {
-        xenXMError (domain->conn, VIR_ERR_INTERNAL_ERROR,
-                    "%s", _("can't retrieve config file for domain"));
-        goto cleanup;
-    }
-
-    /* from bit map, build character string of mapped CPU numbers */
-    for (i = 0; i < maplen; i++)
-        for (j = 0; j < 8; j++)
-            if ((cpumap[i] & (1 << j))) {
-                n = i*8 + j;
-
-                if (comma)
-                    virBufferAddLit (&mapbuf, ",");
-                comma = 1;
-
-                virBufferVSprintf (&mapbuf, "%d", n);
-            }
-
-    if (virBufferError(&mapbuf)) {
-        virReportOOMError(domain->conn);
-        goto cleanup;
-    }
-
-    mapstr = virBufferContentAndReset(&mapbuf);
-    mapsave = mapstr;
-
-    if (VIR_ALLOC_N(cpuset, maxcpu) < 0) {
-        virReportOOMError(domain->conn);
-        goto cleanup;
-    }
-    if (virDomainCpuSetParse(domain->conn,
-                             (const char **)&mapstr, 0,
-                             cpuset, maxcpu) < 0)
-        goto cleanup;
-
-    VIR_FREE(entry->def->cpumask);
-    entry->def->cpumask = cpuset;
-    entry->def->cpumasklen = maxcpu;
-    cpuset = NULL;
-
-    if (xenXMConfigSaveFile(domain->conn, entry->filename, entry->def) < 0)
-        goto cleanup;
-
-    ret = 0;
-
- cleanup:
-    VIR_FREE(mapsave);
-    VIR_FREE(cpuset);
-    xenUnifiedUnlock(priv);
-    return (ret);
-}
-
-/*
- * Find an inactive domain based on its name
- */
-virDomainPtr xenXMDomainLookupByName(virConnectPtr conn, const char *domname) {
-    xenUnifiedPrivatePtr priv;
-    const char *filename;
-    xenXMConfCachePtr entry;
-    virDomainPtr ret = NULL;
-
-    if (!VIR_IS_CONNECT(conn)) {
-        xenXMError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return (NULL);
-    }
-    if (domname == NULL) {
-        xenXMError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (NULL);
-    }
-
-    priv = conn->privateData;
-    xenUnifiedLock(priv);
-
-    if (!xenInotifyActive(conn) && xenXMConfigCacheRefresh (conn) < 0)
-        goto cleanup;
-
-    if (!(filename = virHashLookup(priv->nameConfigMap, domname)))
-        goto cleanup;
-
-    if (!(entry = virHashLookup(priv->configCache, filename)))
-        goto cleanup;
-
-    if (!(ret = virGetDomain(conn, domname, entry->def->uuid)))
-        goto cleanup;
-
-    /* Ensure its marked inactive, because may be cached
-       handle to a previously active domain */
-    ret->id = -1;
-
-cleanup:
-    xenUnifiedUnlock(priv);
-    return (ret);
-}
-
-
-/*
- * Hash table iterator to search for a domain based on UUID
- */
-static int xenXMDomainSearchForUUID(const void *payload, const char *name ATTRIBUTE_UNUSED, const void *data) {
-    const unsigned char *wantuuid = (const unsigned char *)data;
-    const xenXMConfCachePtr entry = (const xenXMConfCachePtr)payload;
-
-    if (!memcmp(entry->def->uuid, wantuuid, VIR_UUID_BUFLEN))
-        return (1);
-
-    return (0);
-}
-
-/*
- * Find an inactive domain based on its UUID
- */
-virDomainPtr xenXMDomainLookupByUUID(virConnectPtr conn,
-                                     const unsigned char *uuid) {
-    xenUnifiedPrivatePtr priv;
-    xenXMConfCachePtr entry;
-    virDomainPtr ret = NULL;
-
-    if (!VIR_IS_CONNECT(conn)) {
-        xenXMError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return (NULL);
-    }
-    if (uuid == NULL) {
-        xenXMError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (NULL);
-    }
-
-    priv = conn->privateData;
-    xenUnifiedLock(priv);
-
-    if (!xenInotifyActive(conn) && xenXMConfigCacheRefresh (conn) < 0)
-        goto cleanup;
-
-    if (!(entry = virHashSearch(priv->configCache, xenXMDomainSearchForUUID, (const void *)uuid)))
-        goto cleanup;
-
-    if (!(ret = virGetDomain(conn, entry->def->name, uuid)))
-        goto cleanup;
-
-    /* Ensure its marked inactive, because may be cached
-       handle to a previously active domain */
-    ret->id = -1;
-
-cleanup:
-    xenUnifiedUnlock(priv);
-    return (ret);
-}
-
-
-/*
- * Start a domain from an existing defined config file
- */
-int xenXMDomainCreate(virDomainPtr domain) {
-    char *sexpr;
-    int ret = -1;
-    xenUnifiedPrivatePtr priv;
-    const char *filename;
-    xenXMConfCachePtr entry;
-
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-
-    if (domain->id != -1)
-        return (-1);
-
-    xenUnifiedLock(priv);
-
-    if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
-        goto error;
-
-    if (!(entry = virHashLookup(priv->configCache, filename)))
-        goto error;
-
-    if (!(sexpr = xenDaemonFormatSxpr(domain->conn, entry->def, priv->xendConfigVersion)))
-        goto error;
-
-    ret = xenDaemonDomainCreateXML(domain->conn, sexpr);
-    VIR_FREE(sexpr);
-    if (ret != 0)
-        goto error;
-
-    if ((ret = xenDaemonDomainLookupByName_ids(domain->conn, domain->name,
-                                               entry->def->uuid)) < 0)
-        goto error;
-    domain->id = ret;
-
-    if (xend_wait_for_devices(domain->conn, domain->name) < 0)
-        goto error;
-
-    if (xenDaemonDomainResume(domain) < 0)
-        goto error;
-
-    xenUnifiedUnlock(priv);
-    return (0);
-
- error:
-    if (domain->id != -1) {
-        xenDaemonDomainDestroy(domain);
-        domain->id = -1;
-    }
-    xenUnifiedUnlock(priv);
-    return (-1);
-}
-
-
-static
-int xenXMConfigSetInt(virConfPtr conf, const char *setting, long l) {
-    virConfValuePtr value = NULL;
-
-    if (VIR_ALLOC(value) < 0)
-        return -1;
-
-    value->type = VIR_CONF_LONG;
-    value->next = NULL;
-    value->l = l;
-
-    return virConfSetValue(conf, setting, value);
-}
-
-
-static
-int xenXMConfigSetString(virConfPtr conf, const char *setting, const char *str) {
-    virConfValuePtr value = NULL;
-
-    if (VIR_ALLOC(value) < 0)
-        return -1;
-
-    value->type = VIR_CONF_STRING;
-    value->next = NULL;
-    if (!(value->str = strdup(str))) {
-        VIR_FREE(value);
-        return -1;
-    }
-
-    return virConfSetValue(conf, setting, value);
-}
-
-
-static int xenXMDomainConfigFormatDisk(virConnectPtr conn,
-                                       virConfValuePtr list,
-                                       virDomainDiskDefPtr disk,
-                                       int hvm,
-                                       int xendConfigVersion)
-{
-    virBuffer buf = VIR_BUFFER_INITIALIZER;
-    virConfValuePtr val, tmp;
-    char *str;
-
-    if(disk->src) {
-        if (disk->driverName) {
-            virBufferVSprintf(&buf, "%s:", disk->driverName);
-            if (STREQ(disk->driverName, "tap"))
-                virBufferVSprintf(&buf, "%s:", disk->driverType ? disk->driverType : "aio");
-        } else {
-            virBufferVSprintf(&buf, "%s:",
-                              disk->type == VIR_DOMAIN_DISK_TYPE_FILE ?
-                              "file" : "phy");
-        }
-        virBufferVSprintf(&buf, "%s", disk->src);
-    }
-    virBufferAddLit(&buf, ",");
-    if (hvm && xendConfigVersion == 1)
-        virBufferAddLit(&buf, "ioemu:");
-
-    virBufferVSprintf(&buf, "%s", disk->dst);
-    if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM)
-        virBufferAddLit(&buf, ":cdrom");
-
-    if (disk->readonly)
-        virBufferAddLit(&buf, ",r");
-    else if (disk->shared)
-        virBufferAddLit(&buf, ",!");
-    else
-        virBufferAddLit(&buf, ",w");
-
-    if (virBufferError(&buf)) {
-        virReportOOMError(conn);
-        return -1;
-    }
-
-    if (VIR_ALLOC(val) < 0) {
-        virReportOOMError(conn);
-        goto cleanup;
-    }
-
-    val->type = VIR_CONF_STRING;
-    val->str = virBufferContentAndReset(&buf);
-    tmp = list->list;
-    while (tmp && tmp->next)
-        tmp = tmp->next;
-    if (tmp)
-        tmp->next = val;
-    else
-        list->list = val;
-
-    return 0;
-
-cleanup:
-    str = virBufferContentAndReset(&buf);
-    VIR_FREE(str);
-    return -1;
-}
-
-static int xenXMDomainConfigFormatNet(virConnectPtr conn,
-                                      virConfValuePtr list,
-                                      virDomainNetDefPtr net,
-                                      int hvm)
-{
-    virBuffer buf = VIR_BUFFER_INITIALIZER;
-    virConfValuePtr val, tmp;
-    char *str;
-    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
-
-    virBufferVSprintf(&buf, "mac=%02x:%02x:%02x:%02x:%02x:%02x",
-                      net->mac[0], net->mac[1],
-                      net->mac[2], net->mac[3],
-                      net->mac[4], net->mac[5]);
-
-    switch (net->type) {
-    case VIR_DOMAIN_NET_TYPE_BRIDGE:
-        virBufferVSprintf(&buf, ",bridge=%s", net->data.bridge.brname);
-        if (net->data.bridge.ipaddr)
-            virBufferVSprintf(&buf, ",ip=%s", net->data.bridge.ipaddr);
-        virBufferVSprintf(&buf, ",script=%s", DEFAULT_VIF_SCRIPT);
-        break;
-
-    case VIR_DOMAIN_NET_TYPE_ETHERNET:
-        if (net->data.ethernet.script)
-            virBufferVSprintf(&buf, ",script=%s", net->data.ethernet.script);
-        if (net->data.ethernet.ipaddr)
-            virBufferVSprintf(&buf, ",ip=%s", net->data.ethernet.ipaddr);
-        break;
-
-    case VIR_DOMAIN_NET_TYPE_NETWORK:
-    {
-        virNetworkPtr network = virNetworkLookupByName(conn, net->data.network.name);
-        char *bridge;
-        if (!network) {
-            xenXMError(conn, VIR_ERR_NO_NETWORK, "%s",
-                       net->data.network.name);
-            return -1;
-        }
-        bridge = virNetworkGetBridgeName(network);
-        virNetworkFree(network);
-        if (!bridge) {
-            xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
-                       _("network %s is not active"),
-                       net->data.network.name);
-            return -1;
-        }
-
-        virBufferVSprintf(&buf, ",bridge=%s", bridge);
-        virBufferVSprintf(&buf, ",script=%s", DEFAULT_VIF_SCRIPT);
-    }
-    break;
-
-    default:
-        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
-                   _("unsupported network type %d"),
-                   net->type);
-        goto cleanup;
-    }
-
-    if (hvm && priv->xendConfigVersion <= XEND_CONFIG_MAX_VERS_NET_TYPE_IOEMU)
-        virBufferAddLit(&buf, ",type=ioemu");
-
-    if (net->model)
-        virBufferVSprintf(&buf, ",model=%s",
-                          net->model);
-
-    if (net->ifname)
-        virBufferVSprintf(&buf, ",vifname=%s",
-                          net->ifname);
-
-    if (virBufferError(&buf))
-        goto cleanup;
-
-    if (VIR_ALLOC(val) < 0) {
-        virReportOOMError(conn);
-        goto cleanup;
-    }
-
-    val->type = VIR_CONF_STRING;
-    val->str = virBufferContentAndReset(&buf);
-    tmp = list->list;
-    while (tmp && tmp->next)
-        tmp = tmp->next;
-    if (tmp)
-        tmp->next = val;
-    else
-        list->list = val;
-
-    return 0;
-
-cleanup:
-    str = virBufferContentAndReset(&buf);
-    VIR_FREE(str);
-    return -1;
-}
-
-
-
-static int
-xenXMDomainConfigFormatPCI(virConnectPtr conn,
-                           virConfPtr conf,
-                           virDomainDefPtr def)
-{
-
-    virConfValuePtr pciVal = NULL;
-    int hasPCI = 0;
-    int i;
-
-    for (i = 0 ; i < def->nhostdevs ; i++)
-        if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
-            def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
-            hasPCI = 1;
-
-    if (!hasPCI)
-        return 0;
-
-    if (VIR_ALLOC(pciVal) < 0)
-        return -1;
-
-    pciVal->type = VIR_CONF_LIST;
-    pciVal->list = NULL;
-
-    for (i = 0 ; i < def->nhostdevs ; i++) {
-        if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
-            def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
-            virConfValuePtr val, tmp;
-            char *buf;
-
-            if (virAsprintf(&buf, "%04x:%02x:%02x.%x",
-                            def->hostdevs[i]->source.subsys.u.pci.domain,
-                            def->hostdevs[i]->source.subsys.u.pci.bus,
-                            def->hostdevs[i]->source.subsys.u.pci.slot,
-                            def->hostdevs[i]->source.subsys.u.pci.function) < 0)
-                goto error;
-
-            if (VIR_ALLOC(val) < 0) {
-                VIR_FREE(buf);
-                virReportOOMError(conn);
-                goto error;
-            }
-            val->type = VIR_CONF_STRING;
-            val->str = buf;
-            tmp = pciVal->list;
-            while (tmp && tmp->next)
-                tmp = tmp->next;
-            if (tmp)
-                tmp->next = val;
-            else
-                pciVal->list = val;
-        }
-    }
-
-    if (pciVal->list != NULL) {
-        int ret = virConfSetValue(conf, "pci", pciVal);
-        pciVal = NULL;
-        if (ret < 0)
-            return -1;
-    }
-    VIR_FREE(pciVal);
-
-    return 0;
-
-error:
-    virConfFreeValue(pciVal);
-    return -1;
-}
-
-
-virConfPtr xenXMDomainConfigFormat(virConnectPtr conn,
-                                   virDomainDefPtr def) {
-    virConfPtr conf = NULL;
-    int hvm = 0, i;
-    xenUnifiedPrivatePtr priv;
-    char *cpus = NULL;
-    const char *lifecycle;
-    char uuid[VIR_UUID_STRING_BUFLEN];
-    virConfValuePtr diskVal = NULL;
-    virConfValuePtr netVal = NULL;
-
-    priv = (xenUnifiedPrivatePtr) conn->privateData;
-
-    if (!(conf = virConfNew()))
-        goto cleanup;
-
-
-    if (xenXMConfigSetString(conf, "name", def->name) < 0)
-        goto no_memory;
-
-    virUUIDFormat(def->uuid, uuid);
-    if (xenXMConfigSetString(conf, "uuid", uuid) < 0)
-        goto no_memory;
-
-    if (xenXMConfigSetInt(conf, "maxmem", def->maxmem / 1024) < 0)
-        goto no_memory;
-
-    if (xenXMConfigSetInt(conf, "memory", def->memory / 1024) < 0)
-        goto no_memory;
-
-    if (xenXMConfigSetInt(conf, "vcpus", def->vcpus) < 0)
-        goto no_memory;
-
-    if (def->cpumask &&
-        !(cpus = virDomainCpuSetFormat(conn, def->cpumask, def->cpumasklen)) < 0)
-        goto cleanup;
-
-    if (cpus &&
-        xenXMConfigSetString(conf, "cpus", cpus) < 0)
-        goto no_memory;
-    VIR_FREE(cpus);
-
-    hvm = STREQ(def->os.type, "hvm") ? 1 : 0;
-
-    if (hvm) {
-        char boot[VIR_DOMAIN_BOOT_LAST+1];
-        if (xenXMConfigSetString(conf, "builder", "hvm") < 0)
-            goto no_memory;
-
-        if (def->os.loader &&
-            xenXMConfigSetString(conf, "kernel", def->os.loader) < 0)
-            goto no_memory;
-
-        for (i = 0 ; i < def->os.nBootDevs ; i++) {
-            switch (def->os.bootDevs[i]) {
-            case VIR_DOMAIN_BOOT_FLOPPY:
-                boot[i] = 'a';
-                break;
-            case VIR_DOMAIN_BOOT_CDROM:
-                boot[i] = 'd';
-                break;
-            case VIR_DOMAIN_BOOT_NET:
-                boot[i] = 'n';
-                break;
-            case VIR_DOMAIN_BOOT_DISK:
-            default:
-                boot[i] = 'c';
-                break;
-            }
-        }
-        if (!def->os.nBootDevs) {
-            boot[0] = 'c';
-            boot[1] = '\0';
-        } else {
-            boot[def->os.nBootDevs] = '\0';
-        }
-
-        if (xenXMConfigSetString(conf, "boot", boot) < 0)
-            goto no_memory;
-
-        if (xenXMConfigSetInt(conf, "pae",
-                              (def->features &
-                               (1 << VIR_DOMAIN_FEATURE_PAE)) ? 1 : 0) < 0)
-            goto no_memory;
-
-        if (xenXMConfigSetInt(conf, "acpi",
-                              (def->features &
-                               (1 << VIR_DOMAIN_FEATURE_ACPI)) ? 1 : 0) < 0)
-            goto no_memory;
-
-        if (xenXMConfigSetInt(conf, "apic",
-                              (def->features &
-                               (1 << VIR_DOMAIN_FEATURE_APIC)) ? 1 : 0) < 0)
-            goto no_memory;
-
-
-        if (xenXMConfigSetInt(conf, "localtime", def->localtime ? 1 : 0) < 0)
-            goto no_memory;
-
-        if (priv->xendConfigVersion == 1) {
-            for (i = 0 ; i < def->ndisks ; i++) {
-                if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_CDROM &&
-                    def->disks[i]->dst &&
-                    STREQ(def->disks[i]->dst, "hdc") &&
-                    def->disks[i]->src) {
-                    if (xenXMConfigSetString(conf, "cdrom",
-                                             def->disks[i]->src) < 0)
-                        goto no_memory;
-                    break;
-                }
-            }
-        }
-
-        /* XXX floppy disks */
-    } else {
-        if (def->os.bootloader &&
-            xenXMConfigSetString(conf, "bootloader", def->os.bootloader) < 0)
-            goto no_memory;
-        if (def->os.bootloaderArgs &&
-            xenXMConfigSetString(conf, "bootloader_args", def->os.bootloaderArgs) < 0)
-            goto no_memory;
-        if (def->os.kernel &&
-            xenXMConfigSetString(conf, "kernel", def->os.kernel) < 0)
-            goto no_memory;
-        if (def->os.initrd &&
-            xenXMConfigSetString(conf, "ramdisk", def->os.initrd) < 0)
-            goto no_memory;
-        if (def->os.cmdline &&
-            xenXMConfigSetString(conf, "extra", def->os.cmdline) < 0)
-            goto no_memory;
-
-    }
-
-    if (!(lifecycle = virDomainLifecycleTypeToString(def->onPoweroff))) {
-        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
-                   _("unexpected lifecycle action %d"), def->onPoweroff);
-        goto cleanup;
-    }
-    if (xenXMConfigSetString(conf, "on_poweroff", lifecycle) < 0)
-        goto no_memory;
-
-
-    if (!(lifecycle = virDomainLifecycleTypeToString(def->onReboot))) {
-        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
-                   _("unexpected lifecycle action %d"), def->onReboot);
-        goto cleanup;
-    }
-    if (xenXMConfigSetString(conf, "on_reboot", lifecycle) < 0)
-        goto no_memory;
-
-
-    if (!(lifecycle = virDomainLifecycleTypeToString(def->onCrash))) {
-        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
-                   _("unexpected lifecycle action %d"), def->onCrash);
-        goto cleanup;
-    }
-    if (xenXMConfigSetString(conf, "on_crash", lifecycle) < 0)
-        goto no_memory;
-
-
-
-    if (hvm) {
-        if (def->emulator &&
-            xenXMConfigSetString(conf, "device_model", def->emulator) < 0)
-            goto no_memory;
-
-        for (i = 0 ; i < def->ninputs ; i++) {
-            if (def->inputs[i]->bus == VIR_DOMAIN_INPUT_BUS_USB) {
-                if (xenXMConfigSetInt(conf, "usb", 1) < 0)
-                    goto no_memory;
-                if (xenXMConfigSetString(conf, "usbdevice",
-                                         def->inputs[i]->type == VIR_DOMAIN_INPUT_TYPE_MOUSE ?
-                                         "mouse" : "tablet") < 0)
-                    goto no_memory;
-                break;
-            }
-        }
-    }
-
-    if (def->ngraphics == 1) {
-        if (priv->xendConfigVersion < (hvm ? 4 : XEND_CONFIG_MIN_VERS_PVFB_NEWCONF)) {
-            if (def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
-                if (xenXMConfigSetInt(conf, "sdl", 1) < 0)
-                    goto no_memory;
-                if (xenXMConfigSetInt(conf, "vnc", 0) < 0)
-                    goto no_memory;
-                if (def->graphics[0]->data.sdl.display &&
-                    xenXMConfigSetString(conf, "display",
-                                     def->graphics[0]->data.sdl.display) < 0)
-                    goto no_memory;
-                if (def->graphics[0]->data.sdl.xauth &&
-                    xenXMConfigSetString(conf, "xauthority",
-                                         def->graphics[0]->data.sdl.xauth) < 0)
-                    goto no_memory;
-            } else {
-                if (xenXMConfigSetInt(conf, "sdl", 0) < 0)
-                    goto no_memory;
-                if (xenXMConfigSetInt(conf, "vnc", 1) < 0)
-                    goto no_memory;
-                if (xenXMConfigSetInt(conf, "vncunused",
-                              def->graphics[0]->data.vnc.autoport ? 1 : 0) < 0)
-                    goto no_memory;
-                if (!def->graphics[0]->data.vnc.autoport &&
-                    xenXMConfigSetInt(conf, "vncdisplay",
-                                  def->graphics[0]->data.vnc.port - 5900) < 0)
-                    goto no_memory;
-                if (def->graphics[0]->data.vnc.listenAddr &&
-                    xenXMConfigSetString(conf, "vnclisten",
-                                    def->graphics[0]->data.vnc.listenAddr) < 0)
-                    goto no_memory;
-                if (def->graphics[0]->data.vnc.passwd &&
-                    xenXMConfigSetString(conf, "vncpasswd",
-                                        def->graphics[0]->data.vnc.passwd) < 0)
-                    goto no_memory;
-                if (def->graphics[0]->data.vnc.keymap &&
-                    xenXMConfigSetString(conf, "keymap",
-                                        def->graphics[0]->data.vnc.keymap) < 0)
-                    goto no_memory;
-            }
-        } else {
-            virConfValuePtr vfb, disp;
-            char *vfbstr = NULL;
-            virBuffer buf = VIR_BUFFER_INITIALIZER;
-            if (def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
-                virBufferAddLit(&buf, "type=sdl");
-                if (def->graphics[0]->data.sdl.display)
-                    virBufferVSprintf(&buf, ",display=%s",
-                                      def->graphics[0]->data.sdl.display);
-                if (def->graphics[0]->data.sdl.xauth)
-                    virBufferVSprintf(&buf, ",xauthority=%s",
-                                      def->graphics[0]->data.sdl.xauth);
-            } else {
-                virBufferAddLit(&buf, "type=vnc");
-                virBufferVSprintf(&buf, ",vncunused=%d",
-                                  def->graphics[0]->data.vnc.autoport ? 1 : 0);
-                if (!def->graphics[0]->data.vnc.autoport)
-                    virBufferVSprintf(&buf, ",vncdisplay=%d",
-                                      def->graphics[0]->data.vnc.port - 5900);
-                if (def->graphics[0]->data.vnc.listenAddr)
-                    virBufferVSprintf(&buf, ",vnclisten=%s",
-                                      def->graphics[0]->data.vnc.listenAddr);
-                if (def->graphics[0]->data.vnc.passwd)
-                    virBufferVSprintf(&buf, ",vncpasswd=%s",
-                                      def->graphics[0]->data.vnc.passwd);
-                if (def->graphics[0]->data.vnc.keymap)
-                    virBufferVSprintf(&buf, ",keymap=%s",
-                                      def->graphics[0]->data.vnc.keymap);
-            }
-            if (virBufferError(&buf))
-                goto no_memory;
-
-            vfbstr = virBufferContentAndReset(&buf);
-
-            if (VIR_ALLOC(vfb) < 0) {
-                VIR_FREE(vfbstr);
-                goto no_memory;
-            }
-
-            if (VIR_ALLOC(disp) < 0) {
-                VIR_FREE(vfb);
-                VIR_FREE(vfbstr);
-                goto no_memory;
-            }
-
-            vfb->type = VIR_CONF_LIST;
-            vfb->list = disp;
-            disp->type = VIR_CONF_STRING;
-            disp->str = vfbstr;
-
-            if (virConfSetValue(conf, "vfb", vfb) < 0)
-                goto no_memory;
-        }
-    }
-
-    /* analyze of the devices */
-    if (VIR_ALLOC(diskVal) < 0)
-        goto no_memory;
-    diskVal->type = VIR_CONF_LIST;
-    diskVal->list = NULL;
-
-    for (i = 0 ; i < def->ndisks ; i++) {
-        if (priv->xendConfigVersion == 1 &&
-            def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_CDROM &&
-            def->disks[i]->dst &&
-            STREQ(def->disks[i]->dst, "hdc")) {
-            continue;
-        }
-        if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY)
-            continue;
-
-        if (xenXMDomainConfigFormatDisk(conn, diskVal, def->disks[i],
-                                        hvm, priv->xendConfigVersion) < 0)
-            goto cleanup;
-    }
-    if (diskVal->list != NULL) {
-        int ret = virConfSetValue(conf, "disk", diskVal);
-        diskVal = NULL;
-        if (ret < 0)
-            goto no_memory;
-    }
-    VIR_FREE(diskVal);
-
-    if (VIR_ALLOC(netVal) < 0)
-        goto no_memory;
-    netVal->type = VIR_CONF_LIST;
-    netVal->list = NULL;
-
-    for (i = 0 ; i < def->nnets ; i++) {
-        if (xenXMDomainConfigFormatNet(conn, netVal,
-                                       def->nets[i],
-                                       hvm) < 0)
-            goto cleanup;
-    }
-    if (netVal->list != NULL) {
-        int ret = virConfSetValue(conf, "vif", netVal);
-        netVal = NULL;
-        if (ret < 0)
-            goto no_memory;
-    }
-    VIR_FREE(netVal);
-
-    if (xenXMDomainConfigFormatPCI(conn, conf, def) < 0)
-        goto cleanup;
-
-    if (hvm) {
-        if (def->nparallels) {
-            virBuffer buf = VIR_BUFFER_INITIALIZER;
-            char *str;
-            int ret;
-
-            ret = xenDaemonFormatSxprChr(conn, def->parallels[0], &buf);
-            str = virBufferContentAndReset(&buf);
-            if (ret == 0)
-                ret = xenXMConfigSetString(conf, "parallel", str);
-            VIR_FREE(str);
-            if (ret < 0)
-                goto no_memory;
-        } else {
-            if (xenXMConfigSetString(conf, "parallel", "none") < 0)
-                goto no_memory;
-        }
-
-        if (def->nserials) {
-            virBuffer buf = VIR_BUFFER_INITIALIZER;
-            char *str;
-            int ret;
-
-            ret = xenDaemonFormatSxprChr(conn, def->serials[0], &buf);
-            str = virBufferContentAndReset(&buf);
-            if (ret == 0)
-                ret = xenXMConfigSetString(conf, "serial", str);
-            VIR_FREE(str);
-            if (ret < 0)
-                goto no_memory;
-        } else {
-            if (xenXMConfigSetString(conf, "serial", "none") < 0)
-                goto no_memory;
-        }
-
-
-        if (def->sounds) {
-            virBuffer buf = VIR_BUFFER_INITIALIZER;
-            char *str = NULL;
-            int ret = xenDaemonFormatSxprSound(conn,
-                                               def,
-                                               &buf);
-            str = virBufferContentAndReset(&buf);
-            if (ret == 0)
-                ret = xenXMConfigSetString(conf, "soundhw", str);
-
-            VIR_FREE(str);
-            if (ret < 0)
-                goto no_memory;
-        }
-    }
-
-    return conf;
-
-no_memory:
-    virReportOOMError(conn);
-
-cleanup:
-    virConfFreeValue(diskVal);
-    virConfFreeValue(netVal);
-    VIR_FREE(cpus);
-    if (conf)
-        virConfFree(conf);
-    return (NULL);
-}
-
-/*
- * Create a config file for a domain, based on an XML
- * document describing its config
- */
-virDomainPtr xenXMDomainDefineXML(virConnectPtr conn, const char *xml) {
-    virDomainPtr ret;
-    virDomainPtr olddomain;
-    char filename[PATH_MAX];
-    const char * oldfilename;
-    virDomainDefPtr def = NULL;
-    xenXMConfCachePtr entry = NULL;
-    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
-
-    if (!VIR_IS_CONNECT(conn)) {
-        xenXMError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return (NULL);
-    }
-    if (xml == NULL) {
-        xenXMError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (NULL);
-    }
-    if (conn->flags & VIR_CONNECT_RO)
-        return (NULL);
-
-    xenUnifiedLock(priv);
-
-    if (!xenInotifyActive(conn) && xenXMConfigCacheRefresh (conn) < 0) {
-        xenUnifiedUnlock(priv);
-        return (NULL);
-    }
-
-    if (!(def = virDomainDefParseString(conn, priv->caps, xml,
-                                        VIR_DOMAIN_XML_INACTIVE))) {
-        xenUnifiedUnlock(priv);
-        return (NULL);
-    }
-
-    if (virHashLookup(priv->nameConfigMap, def->name)) {
-        /* domain exists, we will overwrite it */
-
-        if (!(oldfilename = (char *)virHashLookup(priv->nameConfigMap, def->name))) {
-            xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
-                       "%s", _("can't retrieve config filename for domain to overwrite"));
-            goto error;
-        }
-
-        if (!(entry = virHashLookup(priv->configCache, oldfilename))) {
-            xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
-                       "%s", _("can't retrieve config entry for domain to overwrite"));
-            goto error;
-        }
-
-        /* XXX wtf.com is this line for - it appears to be amemory leak */
-        if (!(olddomain = virGetDomain(conn, def->name, entry->def->uuid)))
-            goto error;
-
-        /* Remove the name -> filename mapping */
-        if (virHashRemoveEntry(priv->nameConfigMap, def->name, NULL) < 0) {
-            xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
-                       "%s", _("failed to remove old domain from config map"));
-            goto error;
-        }
-
-        /* Remove the config record itself */
-        if (virHashRemoveEntry(priv->configCache, oldfilename, xenXMConfigFree) < 0) {
-            xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
-                       "%s", _("failed to remove old domain from config map"));
-            goto error;
-        }
-
-        entry = NULL;
-    }
-
-    if ((strlen(priv->configDir) + 1 + strlen(def->name) + 1) > PATH_MAX) {
-        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
-                   "%s", _("config file name is too long"));
-        goto error;
-    }
-
-    strcpy(filename, priv->configDir);
-    strcat(filename, "/");
-    strcat(filename, def->name);
-
-    if (xenXMConfigSaveFile(conn, filename, def) < 0)
-        goto error;
-
-    if (VIR_ALLOC(entry) < 0) {
-        virReportOOMError(conn);
-        goto error;
-    }
-
-    if ((entry->refreshedAt = time(NULL)) == ((time_t)-1)) {
-        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
-                   "%s", _("unable to get current time"));
-        goto error;
-    }
-
-    memmove(entry->filename, filename, PATH_MAX);
-    entry->def = def;
-
-    if (virHashAddEntry(priv->configCache, filename, entry) < 0) {
-        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
-                   "%s", _("unable to store config file handle"));
-        goto error;
-    }
-
-    if (virHashAddEntry(priv->nameConfigMap, def->name, entry->filename) < 0) {
-        virHashRemoveEntry(priv->configCache, filename, NULL);
-        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
-                   "%s", _("unable to store config file handle"));
-        goto error;
-    }
-
-    ret = virGetDomain(conn, def->name, def->uuid);
-    xenUnifiedUnlock(priv);
-    return (ret);
-
- error:
-    VIR_FREE(entry);
-    virDomainDefFree(def);
-    xenUnifiedUnlock(priv);
-    return (NULL);
-}
-
-/*
- * Delete a domain from disk
- */
-int xenXMDomainUndefine(virDomainPtr domain) {
-    xenUnifiedPrivatePtr priv;
-    const char *filename;
-    xenXMConfCachePtr entry;
-    int ret = -1;
-
-    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
-        xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                   __FUNCTION__);
-        return (-1);
-    }
-
-    if (domain->id != -1)
-        return (-1);
-    if (domain->conn->flags & VIR_CONNECT_RO)
-        return (-1);
-
-    priv = domain->conn->privateData;
-    xenUnifiedLock(priv);
-
-    if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
-        goto cleanup;
-
-    if (!(entry = virHashLookup(priv->configCache, filename)))
-        goto cleanup;
-
-    if (unlink(entry->filename) < 0)
-        goto cleanup;
-
-    /* Remove the name -> filename mapping */
-    if (virHashRemoveEntry(priv->nameConfigMap, domain->name, NULL) < 0)
-        goto cleanup;
-
-    /* Remove the config record itself */
-    if (virHashRemoveEntry(priv->configCache, entry->filename, xenXMConfigFree) < 0)
-        goto cleanup;
-
-    ret = 0;
-
-cleanup:
-    xenUnifiedUnlock(priv);
-    return ret;
-}
-
-struct xenXMListIteratorContext {
-    virConnectPtr conn;
-    int max;
-    int count;
-    char ** names;
-};
-
-static void xenXMListIterator(const void *payload ATTRIBUTE_UNUSED, const char *name, const void *data) {
-    struct xenXMListIteratorContext *ctx = (struct xenXMListIteratorContext *)data;
-    virDomainPtr dom = NULL;
-
-    if (ctx->count == ctx->max)
-        return;
-
-    dom = xenDaemonLookupByName(ctx->conn, name);
-    if (!dom) {
-        ctx->names[ctx->count] = strdup(name);
-        ctx->count++;
-    } else {
-        virDomainFree(dom);
-    }
-}
-
-
-/*
- * List all defined domains, filtered to remove any which
- * are currently running
- */
-int xenXMListDefinedDomains(virConnectPtr conn, char **const names, int maxnames) {
-    xenUnifiedPrivatePtr priv;
-    struct xenXMListIteratorContext ctx;
-    int ret = -1;
-
-    if (!VIR_IS_CONNECT(conn)) {
-        xenXMError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return (-1);
-    }
-
-    priv = conn->privateData;
-    xenUnifiedLock(priv);
-
-    if (!xenInotifyActive(conn) && xenXMConfigCacheRefresh (conn) < 0)
-        goto cleanup;
-
-    if (maxnames > virHashSize(priv->configCache))
-        maxnames = virHashSize(priv->configCache);
-
-    ctx.conn = conn;
-    ctx.count = 0;
-    ctx.max = maxnames;
-    ctx.names = names;
-
-    virHashForEach(priv->nameConfigMap, xenXMListIterator, &ctx);
-    ret = ctx.count;
-
-cleanup:
-    xenUnifiedUnlock(priv);
-    return ret;
-}
-
-/*
- * Return the maximum number of defined domains - not filtered
- * based on number running
- */
-int xenXMNumOfDefinedDomains(virConnectPtr conn) {
-    xenUnifiedPrivatePtr priv;
-    int ret = -1;
-
-    if (!VIR_IS_CONNECT(conn)) {
-        xenXMError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return (-1);
-    }
-
-    priv = conn->privateData;
-    xenUnifiedLock(priv);
-
-    if (!xenInotifyActive(conn) && xenXMConfigCacheRefresh (conn) < 0)
-        goto cleanup;
-
-    ret = virHashSize(priv->nameConfigMap);
-
-cleanup:
-    xenUnifiedUnlock(priv);
-    return ret;
-}
-
-
-/**
- * xenXMDomainAttachDevice:
- * @domain: pointer to domain object
- * @xml: pointer to XML description of device
- *
- * Create a virtual device attachment to backend.
- * XML description is translated into config file.
- *
- * Returns 0 in case of success, -1 in case of failure.
- */
-static int
-xenXMDomainAttachDevice(virDomainPtr domain, const char *xml) {
-    const char *filename = NULL;
-    xenXMConfCachePtr entry = NULL;
-    int ret = -1;
-    virDomainDeviceDefPtr dev = NULL;
-    virDomainDefPtr def;
-    xenUnifiedPrivatePtr priv;
-
-    if ((!domain) || (!domain->conn) || (!domain->name) || (!xml)) {
-        xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                   __FUNCTION__);
-        return -1;
-    }
-
-    if (domain->conn->flags & VIR_CONNECT_RO)
-        return -1;
-    if (domain->id != -1)
-        return -1;
-
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-    xenUnifiedLock(priv);
-
-    if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
-        goto cleanup;
-    if (!(entry = virHashLookup(priv->configCache, filename)))
-        goto cleanup;
-    def = entry->def;
-
-    if (!(dev = virDomainDeviceDefParse(domain->conn,
-                                        priv->caps,
-                                        entry->def,
-                                        xml, VIR_DOMAIN_XML_INACTIVE)))
-        goto cleanup;
-
-    switch (dev->type) {
-    case VIR_DOMAIN_DEVICE_DISK:
-    {
-        if (virDomainDiskInsert(def, dev->data.disk) < 0) {
-            virReportOOMError(domain->conn);
-            goto cleanup;
-        }
-        dev->data.disk = NULL;
-    }
-    break;
-
-    case VIR_DOMAIN_DEVICE_NET:
-    {
-        if (VIR_REALLOC_N(def->nets, def->nnets+1) < 0) {
-            virReportOOMError(domain->conn);
-            goto cleanup;
-        }
-        def->nets[def->nnets++] = dev->data.net;
-        dev->data.net = NULL;
-        break;
-    }
-
-    default:
-        xenXMError(domain->conn, VIR_ERR_XML_ERROR,
-                   "%s", _("unknown device"));
-        goto cleanup;
-    }
-
-    /* If this fails, should we try to undo our changes to the
-     * in-memory representation of the config file. I say not!
-     */
-    if (xenXMConfigSaveFile(domain->conn, entry->filename, entry->def) < 0)
-        goto cleanup;
-
-    ret = 0;
-
- cleanup:
-    virDomainDeviceDefFree(dev);
-    xenUnifiedUnlock(priv);
-    return ret;
-}
-
-
-/**
- * xenXMDomainDetachDevice:
- * @domain: pointer to domain object
- * @xml: pointer to XML description of device
- *
- * Destroy a virtual device attachment to backend.
- *
- * Returns 0 in case of success, -1 in case of failure.
- */
-static int
-xenXMDomainDetachDevice(virDomainPtr domain, const char *xml) {
-    const char *filename = NULL;
-    xenXMConfCachePtr entry = NULL;
-    virDomainDeviceDefPtr dev = NULL;
-    virDomainDefPtr def;
-    int ret = -1;
-    int i;
-    xenUnifiedPrivatePtr priv;
-
-    if ((!domain) || (!domain->conn) || (!domain->name) || (!xml)) {
-        xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                   __FUNCTION__);
-        return -1;
-    }
-
-
-    if (domain->conn->flags & VIR_CONNECT_RO)
-        return -1;
-    if (domain->id != -1)
-        return -1;
-
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-    xenUnifiedLock(priv);
-
-    if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
-        goto cleanup;
-    if (!(entry = virHashLookup(priv->configCache, filename)))
-        goto cleanup;
-    def = entry->def;
-
-    if (!(dev = virDomainDeviceDefParse(domain->conn,
-                                        priv->caps,
-                                        entry->def,
-                                        xml, VIR_DOMAIN_XML_INACTIVE)))
-        goto cleanup;
-
-    switch (dev->type) {
-    case VIR_DOMAIN_DEVICE_DISK:
-    {
-        for (i = 0 ; i < def->ndisks ; i++) {
-            if (def->disks[i]->dst &&
-                dev->data.disk->dst &&
-                STREQ(def->disks[i]->dst, dev->data.disk->dst)) {
-                virDomainDiskDefFree(def->disks[i]);
-                if (i < (def->ndisks - 1))
-                    memmove(def->disks + i,
-                            def->disks + i + 1,
-                            sizeof(*def->disks) *
-                            (def->ndisks - (i + 1)));
-                break;
-            }
-        }
-        break;
-    }
-
-    case VIR_DOMAIN_DEVICE_NET:
-    {
-        for (i = 0 ; i < def->nnets ; i++) {
-            if (!memcmp(def->nets[i]->mac,
-                        dev->data.net->mac,
-                        sizeof(def->nets[i]->mac))) {
-                virDomainNetDefFree(def->nets[i]);
-                if (i < (def->nnets - 1))
-                    memmove(def->nets + i,
-                            def->nets + i + 1,
-                            sizeof(*def->nets) *
-                            (def->nnets - (i + 1)));
-                break;
-            }
-        }
-        break;
-    }
-    default:
-        xenXMError(domain->conn, VIR_ERR_XML_ERROR,
-                   "%s", _("unknown device"));
-        goto cleanup;
-    }
-
-    /* If this fails, should we try to undo our changes to the
-     * in-memory representation of the config file. I say not!
-     */
-    if (xenXMConfigSaveFile(domain->conn, entry->filename, entry->def) < 0)
-        goto cleanup;
-
-    ret = 0;
-
- cleanup:
-    virDomainDeviceDefFree(dev);
-    xenUnifiedUnlock(priv);
-    return (ret);
-}
-
-int
-xenXMDomainBlockPeek (virDomainPtr dom,
-                      const char *path ATTRIBUTE_UNUSED,
-                      unsigned long long offset ATTRIBUTE_UNUSED,
-                      size_t size ATTRIBUTE_UNUSED,
-                      void *buffer ATTRIBUTE_UNUSED)
-{
-    xenXMError (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
-    return -1;
-}
-
-
-static char *xenXMAutostartLinkName(virDomainPtr dom)
-{
-    char *ret;
-    virAsprintf(&ret, "/etc/xen/auto/%s", dom->name);
-    return ret;
-}
-
-static char *xenXMDomainConfigName(virDomainPtr dom)
-{
-    char *ret;
-    virAsprintf(&ret, "/etc/xen/%s", dom->name);
-    return ret;
-}
-
-int xenXMDomainGetAutostart(virDomainPtr dom, int *autostart)
-{
-    char *linkname = xenXMAutostartLinkName(dom);
-    char *config = xenXMDomainConfigName(dom);
-    int ret = -1;
-
-    if (!linkname || !config) {
-        virReportOOMError(dom->conn);
-        goto cleanup;
-    }
-
-    *autostart = virFileLinkPointsTo(linkname, config);
-    if (*autostart < 0) {
-        virReportSystemError(dom->conn, errno,
-                             _("cannot check link %s points to config %s"),
-                             linkname, config);
-        goto cleanup;
-    }
-
-    ret = 0;
-
-cleanup:
-    VIR_FREE(linkname);
-    VIR_FREE(config);
-    return ret;
-}
-
-
-int xenXMDomainSetAutostart(virDomainPtr dom, int autostart)
-{
-    char *linkname = xenXMAutostartLinkName(dom);
-    char *config = xenXMDomainConfigName(dom);
-    int ret = -1;
-
-    if (!linkname || !config) {
-        virReportOOMError(dom->conn);
-        goto cleanup;
-    }
-
-    if (autostart) {
-        if (symlink(config, linkname) < 0 &&
-            errno != EEXIST) {
-            virReportSystemError(dom->conn, errno,
-                                 _("failed to create link %s to %s"),
-                                 config, linkname);
-            goto cleanup;
-        }
-    } else {
-        if (unlink(linkname)  < 0 &&
-            errno != ENOENT) {
-            virReportSystemError(dom->conn, errno,
-                                 _("failed to remove link %s"),
-                                 linkname);
-            goto cleanup;
-        }
-    }
-    ret = 0;
-
-cleanup:
-    VIR_FREE(linkname);
-    VIR_FREE(config);
-
-    return ret;
-}
diff --git a/src/xm_internal.h b/src/xm_internal.h
deleted file mode 100644 (file)
index 7d52ac8..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * xm_internal.h: helper routines for dealing with inactive domains
- *
- * Copyright (C) 2006-2007 Red Hat
- * Copyright (C) 2006 Daniel P. Berrange
- *
- * 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: Daniel P. Berrange <berrange@redhat.com>
- *
- */
-
-#ifndef _LIBVIRT_XM_INTERNAL_H_
-#define _LIBVIRT_XM_INTERNAL_H_
-
-#include "internal.h"
-#include "driver.h"
-#include "conf.h"
-#include "domain_conf.h"
-
-extern struct xenUnifiedDriver xenXMDriver;
-
-int xenXMConfigCacheRefresh (virConnectPtr conn);
-int xenXMConfigCacheAddFile(virConnectPtr conn, const char *filename);
-int xenXMConfigCacheRemoveFile(virConnectPtr conn, const char *filename);
-
-virDrvOpenStatus xenXMOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags);
-int xenXMClose(virConnectPtr conn);
-const char *xenXMGetType(virConnectPtr conn);
-int xenXMDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info);
-char *xenXMDomainDumpXML(virDomainPtr domain, int flags);
-int xenXMDomainSetMemory(virDomainPtr domain, unsigned long memory);
-int xenXMDomainSetMaxMemory(virDomainPtr domain, unsigned long memory);
-unsigned long xenXMDomainGetMaxMemory(virDomainPtr domain);
-int xenXMDomainSetVcpus(virDomainPtr domain, unsigned int vcpus);
-int xenXMDomainPinVcpu(virDomainPtr domain, unsigned int vcpu,
-                       unsigned char *cpumap, int maplen);
-virDomainPtr xenXMDomainLookupByName(virConnectPtr conn, const char *domname);
-virDomainPtr xenXMDomainLookupByUUID(virConnectPtr conn,
-                                     const unsigned char *uuid);
-
-int xenXMListDefinedDomains(virConnectPtr conn, char ** const names, int maxnames);
-int xenXMNumOfDefinedDomains(virConnectPtr conn);
-
-int xenXMDomainCreate(virDomainPtr domain);
-virDomainPtr xenXMDomainDefineXML(virConnectPtr con, const char *xml);
-int xenXMDomainUndefine(virDomainPtr domain);
-
-virConfPtr xenXMDomainConfigFormat(virConnectPtr conn, virDomainDefPtr def);
-virDomainDefPtr xenXMDomainConfigParse(virConnectPtr conn, virConfPtr conf);
-
-int xenXMDomainBlockPeek (virDomainPtr dom, const char *path, unsigned long long offset, size_t size, void *buffer);
-
-int xenXMDomainGetAutostart(virDomainPtr dom, int *autostart);
-int xenXMDomainSetAutostart(virDomainPtr dom, int autostart);
-
-#endif
diff --git a/src/xs_internal.c b/src/xs_internal.c
deleted file mode 100644 (file)
index 1f54b1f..0000000
+++ /dev/null
@@ -1,1407 +0,0 @@
-/*
- * xs_internal.c: access to Xen Store
- *
- * Copyright (C) 2006, 2009 Red Hat, Inc.
- *
- * See COPYING.LIB for the License of this software
- *
- * Daniel Veillard <veillard@redhat.com>
- */
-
-#include <config.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <sys/ioctl.h>
-
-#include <stdint.h>
-
-#include <xen/dom0_ops.h>
-#include <xen/version.h>
-#include <xen/xen.h>
-
-#include <xs.h>
-
-#include "virterror_internal.h"
-#include "datatypes.h"
-#include "driver.h"
-#include "memory.h"
-#include "event.h"
-#include "logging.h"
-#include "uuid.h"
-#include "xen_unified.h"
-#include "xs_internal.h"
-#include "xen_internal.h"
-
-#define VIR_FROM_THIS VIR_FROM_XEN
-
-#ifndef PROXY
-static char *xenStoreDomainGetOSType(virDomainPtr domain);
-static void xenStoreWatchEvent(int watch, int fd, int events, void *data);
-static void xenStoreWatchListFree(xenStoreWatchListPtr list);
-
-struct xenUnifiedDriver xenStoreDriver = {
-    xenStoreOpen, /* open */
-    xenStoreClose, /* close */
-    NULL, /* version */
-    NULL, /* hostname */
-    NULL, /* nodeGetInfo */
-    NULL, /* getCapabilities */
-    xenStoreListDomains, /* listDomains */
-    NULL, /* numOfDomains */
-    NULL, /* domainCreateXML */
-    NULL, /* domainSuspend */
-    NULL, /* domainResume */
-    xenStoreDomainShutdown, /* domainShutdown */
-    xenStoreDomainReboot, /* domainReboot */
-    NULL, /* domainDestroy */
-    xenStoreDomainGetOSType, /* domainGetOSType */
-    xenStoreDomainGetMaxMemory, /* domainGetMaxMemory */
-    NULL, /* domainSetMaxMemory */
-    xenStoreDomainSetMemory, /* domainSetMemory */
-    xenStoreGetDomainInfo, /* domainGetInfo */
-    NULL, /* domainSave */
-    NULL, /* domainRestore */
-    NULL, /* domainCoreDump */
-    NULL, /* domainSetVcpus */
-    NULL, /* domainPinVcpu */
-    NULL, /* domainGetVcpus */
-    NULL, /* domainGetMaxVcpus */
-    NULL, /* listDefinedDomains */
-    NULL, /* numOfDefinedDomains */
-    NULL, /* domainCreate */
-    NULL, /* domainDefineXML */
-    NULL, /* domainUndefine */
-    NULL, /* domainAttachDevice */
-    NULL, /* domainDetachDevice */
-    NULL, /* domainGetAutostart */
-    NULL, /* domainSetAutostart */
-    NULL, /* domainGetSchedulerType */
-    NULL, /* domainGetSchedulerParameters */
-    NULL, /* domainSetSchedulerParameters */
-};
-
-#endif /* ! PROXY */
-
-#define virXenStoreError(conn, code, fmt...)                                 \
-        virReportErrorHelper(NULL, VIR_FROM_XENSTORE, code, __FILE__,      \
-                               __FUNCTION__, __LINE__, fmt)
-
-/************************************************************************
- *                                                                     *
- *             Helper internal APIs                                    *
- *                                                                     *
- ************************************************************************/
-#ifndef PROXY
-/**
- * virConnectDoStoreList:
- * @conn: pointer to the hypervisor connection
- * @path: the absolute path of the directory in the store to list
- * @nb: OUT pointer to the number of items found
- *
- * Internal API querying the Xenstore for a list
- *
- * Returns a string which must be freed by the caller or NULL in case of error
- */
-static char **
-virConnectDoStoreList(virConnectPtr conn, const char *path,
-                      unsigned int *nb)
-{
-    xenUnifiedPrivatePtr priv;
-
-    if (conn == NULL)
-        return NULL;
-
-    priv = (xenUnifiedPrivatePtr) conn->privateData;
-    if (priv->xshandle == NULL || path == NULL || nb == NULL)
-        return (NULL);
-
-    return xs_directory (priv->xshandle, 0, path, nb);
-}
-#endif /* ! PROXY */
-
-/**
- * virDomainDoStoreQuery:
- * @conn: pointer to the hypervisor connection
- * @domid: id of the domain
- * @path: the relative path of the data in the store to retrieve
- *
- * Internal API querying the Xenstore for a string value.
- *
- * Returns a string which must be freed by the caller or NULL in case of error
- */
-static char *
-virDomainDoStoreQuery(virConnectPtr conn, int domid, const char *path)
-{
-    char s[256];
-    unsigned int len = 0;
-    xenUnifiedPrivatePtr priv;
-
-    if (!conn)
-        return NULL;
-
-    priv = (xenUnifiedPrivatePtr) conn->privateData;
-    if (priv->xshandle == NULL)
-        return (NULL);
-
-    snprintf(s, 255, "/local/domain/%d/%s", domid, path);
-    s[255] = 0;
-
-    return xs_read(priv->xshandle, 0, &s[0], &len);
-}
-
-#ifndef PROXY
-/**
- * virDomainDoStoreWrite:
- * @domain: a domain object
- * @path: the relative path of the data in the store to retrieve
- *
- * Internal API setting up a string value in the Xenstore
- * Requires write access to the XenStore
- *
- * Returns 0 in case of success, -1 in case of failure
- */
-static int
-virDomainDoStoreWrite(virDomainPtr domain, const char *path,
-                      const char *value)
-{
-    char s[256];
-    xenUnifiedPrivatePtr priv;
-    int ret = -1;
-
-    if (!VIR_IS_CONNECTED_DOMAIN(domain))
-        return (-1);
-
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-    if (priv->xshandle == NULL)
-        return (-1);
-    if (domain->conn->flags & VIR_CONNECT_RO)
-        return (-1);
-
-    snprintf(s, 255, "/local/domain/%d/%s", domain->id, path);
-    s[255] = 0;
-
-    if (xs_write(priv->xshandle, 0, &s[0], value, strlen(value)))
-        ret = 0;
-
-    return (ret);
-}
-
-/**
- * virDomainGetVM:
- * @domain: a domain object
- *
- * Internal API extracting a xenstore vm path.
- *
- * Returns the new string or NULL in case of error
- */
-static char *
-virDomainGetVM(virDomainPtr domain)
-{
-    char *vm;
-    char query[200];
-    unsigned int len;
-    xenUnifiedPrivatePtr priv;
-
-    if (!VIR_IS_CONNECTED_DOMAIN(domain))
-        return (NULL);
-
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-    if (priv->xshandle == NULL)
-        return (NULL);
-
-    snprintf(query, 199, "/local/domain/%d/vm", virDomainGetID(domain));
-    query[199] = 0;
-
-    vm = xs_read(priv->xshandle, 0, &query[0], &len);
-
-    return (vm);
-}
-
-/**
- * virDomainGetVMInfo:
- * @domain: a domain object
- * @vm: the xenstore vm path
- * @name: the value's path
- *
- * Internal API extracting one information the device used
- * by the domain from xensttore
- *
- * Returns the new string or NULL in case of error
- */
-static char *
-virDomainGetVMInfo(virDomainPtr domain, const char *vm, const char *name)
-{
-    char s[256];
-    char *ret = NULL;
-    unsigned int len = 0;
-    xenUnifiedPrivatePtr priv;
-
-    if (!VIR_IS_CONNECTED_DOMAIN(domain))
-        return (NULL);
-
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-    if (priv->xshandle == NULL)
-        return (NULL);
-
-    snprintf(s, 255, "%s/%s", vm, name);
-    s[255] = 0;
-
-    ret = xs_read(priv->xshandle, 0, &s[0], &len);
-
-    return (ret);
-}
-
-#endif /* ! PROXY */
-
-/************************************************************************
- *                                                                     *
- *             Canonical internal APIs                                 *
- *                                                                     *
- ************************************************************************/
-/**
- * xenStoreOpen:
- * @conn: pointer to the connection block
- * @name: URL for the target, NULL for local
- * @flags: combination of virDrvOpenFlag(s)
- *
- * Connects to the Xen hypervisor.
- *
- * Returns 0 or -1 in case of error.
- */
-virDrvOpenStatus
-xenStoreOpen(virConnectPtr conn,
-             virConnectAuthPtr auth ATTRIBUTE_UNUSED,
-             int flags ATTRIBUTE_UNUSED)
-{
-    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
-
-#ifdef PROXY
-    priv->xshandle = xs_daemon_open_readonly();
-#else
-    if (flags & VIR_CONNECT_RO)
-        priv->xshandle = xs_daemon_open_readonly();
-    else
-        priv->xshandle = xs_daemon_open();
-#endif /* ! PROXY */
-
-    if (priv->xshandle == NULL) {
-        /*
-         * not being able to connect via the socket as an unprivileged
-         * user is rather normal, this should fallback to the proxy (or
-         * remote) mechanism.
-         */
-        if (xenHavePrivilege()) {
-            virXenStoreError(NULL, VIR_ERR_NO_XEN,
-                                 "%s", _("failed to connect to Xen Store"));
-        }
-        return (-1);
-    }
-
-#ifndef PROXY
-    /* Init activeDomainList */
-    if (VIR_ALLOC(priv->activeDomainList) < 0) {
-        virXenStoreError(NULL, VIR_ERR_INTERNAL_ERROR,
-                                 "%s", _("failed to allocate activeDomainList"));
-        return -1;
-    }
-
-    /* Init watch list before filling in domInfoList,
-       so we can know if it is the first time through
-       when the callback fires */
-    if ( VIR_ALLOC(priv->xsWatchList) < 0 ) {
-        virXenStoreError(NULL, VIR_ERR_INTERNAL_ERROR,
-                                 "%s", _("failed to allocate xsWatchList"));
-        return -1;
-    }
-
-    /* This will get called once at start */
-    if ( xenStoreAddWatch(conn, "@releaseDomain",
-                     "releaseDomain", xenStoreDomainReleased, priv) < 0 )
-    {
-        virXenStoreError(NULL, VIR_ERR_INTERNAL_ERROR,
-                                 "%s", _("adding watch @releaseDomain"));
-        return -1;
-    }
-
-    /* The initial call of this will fill domInfoList */
-    if( xenStoreAddWatch(conn, "@introduceDomain",
-                     "introduceDomain", xenStoreDomainIntroduced, priv) < 0 )
-    {
-        virXenStoreError(NULL, VIR_ERR_INTERNAL_ERROR,
-                                 "%s", _("adding watch @introduceDomain"));
-        return -1;
-    }
-
-    /* Add an event handle */
-    if ((priv->xsWatch = virEventAddHandle(xs_fileno(priv->xshandle),
-                                           VIR_EVENT_HANDLE_READABLE,
-                                           xenStoreWatchEvent,
-                                           conn,
-                                           NULL)) < 0)
-        DEBUG0("Failed to add event handle, disabling events\n");
-
-#endif //PROXY
-    return 0;
-}
-
-/**
- * xenStoreClose:
- * @conn: pointer to the connection block
- *
- * Close the connection to the Xen hypervisor.
- *
- * Returns 0 in case of success or -1 in case of error.
- */
-int
-xenStoreClose(virConnectPtr conn)
-{
-    xenUnifiedPrivatePtr priv;
-
-    if (conn == NULL) {
-        virXenStoreError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return(-1);
-    }
-
-    priv = (xenUnifiedPrivatePtr) conn->privateData;
-
-#ifndef PROXY
-    if (xenStoreRemoveWatch(conn, "@introduceDomain", "introduceDomain") < 0) {
-        DEBUG0("Warning, could not remove @introduceDomain watch");
-        /* not fatal */
-    }
-
-    if (xenStoreRemoveWatch(conn, "@releaseDomain", "releaseDomain") < 0) {
-        DEBUG0("Warning, could not remove @releaseDomain watch");
-        /* not fatal */
-    }
-
-    xenStoreWatchListFree(priv->xsWatchList);
-    priv->xsWatchList = NULL;
-    xenUnifiedDomainInfoListFree(priv->activeDomainList);
-    priv->activeDomainList = NULL;
-#endif
-    if (priv->xshandle == NULL)
-        return(-1);
-
-    if (priv->xsWatch != -1)
-        virEventRemoveHandle(priv->xsWatch);
-    xs_daemon_close(priv->xshandle);
-    priv->xshandle = NULL;
-
-    return (0);
-}
-
-#ifndef PROXY
-/**
- * xenStoreGetDomainInfo:
- * @domain: pointer to the domain block
- * @info: the place where information should be stored
- *
- * Do an hypervisor call to get the related set of domain information.
- *
- * Returns 0 in case of success, -1 in case of error.
- */
-int
-xenStoreGetDomainInfo(virDomainPtr domain, virDomainInfoPtr info)
-{
-    char *tmp, **tmp2;
-    unsigned int nb_vcpus;
-    char request[200];
-    xenUnifiedPrivatePtr priv;
-
-    if (!VIR_IS_CONNECTED_DOMAIN(domain))
-        return (-1);
-
-    if ((domain == NULL) || (domain->conn == NULL) || (info == NULL)) {
-        virXenStoreError(domain ? domain->conn : NULL, VIR_ERR_INVALID_ARG,
-                         __FUNCTION__);
-        return(-1);
-    }
-
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-    if (priv->xshandle == NULL)
-        return(-1);
-
-    if (domain->id == -1)
-        return(-1);
-
-    tmp = virDomainDoStoreQuery(domain->conn, domain->id, "running");
-    if (tmp != NULL) {
-        if (tmp[0] == '1')
-            info->state = VIR_DOMAIN_RUNNING;
-        free(tmp);
-    } else {
-        info->state = VIR_DOMAIN_NOSTATE;
-    }
-    tmp = virDomainDoStoreQuery(domain->conn, domain->id, "memory/target");
-    if (tmp != NULL) {
-        info->memory = atol(tmp);
-        info->maxMem = atol(tmp);
-        free(tmp);
-    } else {
-        info->memory = 0;
-        info->maxMem = 0;
-    }
-#if 0
-    /* doesn't seems to work */
-    tmp = virDomainDoStoreQuery(domain->conn, domain->id, "cpu_time");
-    if (tmp != NULL) {
-        info->cpuTime = atol(tmp);
-        free(tmp);
-    } else {
-        info->cpuTime = 0;
-    }
-#endif
-    snprintf(request, 199, "/local/domain/%d/cpu", domain->id);
-    request[199] = 0;
-    tmp2 = virConnectDoStoreList(domain->conn, request, &nb_vcpus);
-    if (tmp2 != NULL) {
-        info->nrVirtCpu = nb_vcpus;
-        free(tmp2);
-    }
-    return (0);
-}
-
-/**
- * xenStoreDomainSetMemory:
- * @domain: pointer to the domain block
- * @memory: the max memory size in kilobytes.
- *
- * Change the maximum amount of memory allowed in the xen store
- *
- * Returns 0 in case of success, -1 in case of error.
- */
-int
-xenStoreDomainSetMemory(virDomainPtr domain, unsigned long memory)
-{
-    int ret;
-    char value[20];
-
-    if ((domain == NULL) || (domain->conn == NULL) ||
-        (memory < 1024 * MIN_XEN_GUEST_SIZE)) {
-        virXenStoreError(domain ? domain->conn : NULL, VIR_ERR_INVALID_ARG,
-                         __FUNCTION__);
-        return(-1);
-    }
-    if (domain->id == -1)
-        return(-1);
-    if ((domain->id == 0) && (memory < (2 * MIN_XEN_GUEST_SIZE * 1024)))
-        return(-1);
-    snprintf(value, 19, "%lu", memory);
-    value[19] = 0;
-    ret = virDomainDoStoreWrite(domain, "memory/target", &value[0]);
-    if (ret < 0)
-        return (-1);
-    return (0);
-}
-
-/**
- * xenStoreDomainGetMaxMemory:
- * @domain: pointer to the domain block
- *
- * Ask the xenstore for the maximum memory allowed for a domain
- *
- * Returns the memory size in kilobytes or 0 in case of error.
- */
-unsigned long
-xenStoreDomainGetMaxMemory(virDomainPtr domain)
-{
-    char *tmp;
-    unsigned long ret = 0;
-    xenUnifiedPrivatePtr priv;
-
-    if (!VIR_IS_CONNECTED_DOMAIN(domain))
-        return (ret);
-    if (domain->id == -1)
-        return(-1);
-
-    priv = domain->conn->privateData;
-    xenUnifiedLock(priv);
-    tmp = virDomainDoStoreQuery(domain->conn, domain->id, "memory/target");
-    if (tmp != NULL) {
-        ret = (unsigned long) atol(tmp);
-        VIR_FREE(tmp);
-    }
-    xenUnifiedUnlock(priv);
-    return(ret);
-}
-
-/**
- * xenStoreNumOfDomains:
- * @conn: pointer to the hypervisor connection
- *
- * Provides the number of active domains.
- *
- * Returns the number of domain found or -1 in case of error
- */
-int
-xenStoreNumOfDomains(virConnectPtr conn)
-{
-    unsigned int num;
-    char **idlist;
-    int ret = -1;
-    xenUnifiedPrivatePtr priv;
-
-    if (conn == NULL) {
-        virXenStoreError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return -1;
-    }
-
-    priv = (xenUnifiedPrivatePtr) conn->privateData;
-    if (priv->xshandle == NULL) {
-        virXenStoreError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return(-1);
-    }
-    idlist = xs_directory(priv->xshandle, 0, "/local/domain", &num);
-    if (idlist) {
-        free(idlist);
-        ret = num;
-    }
-    return(ret);
-}
-
-/**
- * xenStoreDoListDomains:
- * @conn: pointer to the hypervisor connection
- * @ids: array to collect the list of IDs of active domains
- * @maxids: size of @ids
- *
- * Internal API: collect the list of active domains, and store
- * their ID in @maxids. The driver lock must be held.
- *
- * Returns the number of domain found or -1 in case of error
- */
-static int
-xenStoreDoListDomains(xenUnifiedPrivatePtr priv, int *ids, int maxids)
-{
-    char **idlist = NULL, *endptr;
-    unsigned int num, i;
-    int ret = -1;
-    long id;
-
-    if (priv->xshandle == NULL)
-        goto out;
-
-    idlist = xs_directory (priv->xshandle, 0, "/local/domain", &num);
-    if (idlist == NULL)
-        goto out;
-
-    for (ret = 0, i = 0; (i < num) && (ret < maxids); i++) {
-        id = strtol(idlist[i], &endptr, 10);
-        if ((endptr == idlist[i]) || (*endptr != 0))
-            goto out;
-        ids[ret++] = (int) id;
-    }
-
-out:
-    VIR_FREE (idlist);
-    return ret;
-}
-
-/**
- * xenStoreListDomains:
- * @conn: pointer to the hypervisor connection
- * @ids: array to collect the list of IDs of active domains
- * @maxids: size of @ids
- *
- * Collect the list of active domains, and store their ID in @maxids
- *
- * Returns the number of domain found or -1 in case of error
- */
-int
-xenStoreListDomains(virConnectPtr conn, int *ids, int maxids)
-{
-    xenUnifiedPrivatePtr priv;
-    int ret;
-
-    if ((conn == NULL) || (ids == NULL)) {
-        virXenStoreError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return(-1);
-    }
-
-    priv = (xenUnifiedPrivatePtr) conn->privateData;
-
-    xenUnifiedLock(priv);
-    ret = xenStoreDoListDomains(priv, ids, maxids);
-    xenUnifiedUnlock(priv);
-
-    return(ret);
-}
-
-/**
- * xenStoreLookupByName:
- * @conn: A xend instance
- * @name: The name of the domain
- *
- * Try to lookup a domain on the Xen Store based on its name.
- *
- * Returns a new domain object or NULL in case of failure
- */
-virDomainPtr
-xenStoreLookupByName(virConnectPtr conn, const char *name)
-{
-    virDomainPtr ret = NULL;
-    unsigned int num, i, len;
-    long id = -1;
-    char **idlist = NULL, *endptr;
-    char prop[200], *tmp;
-    int found = 0;
-    struct xend_domain *xenddomain = NULL;
-    xenUnifiedPrivatePtr priv;
-
-    if ((conn == NULL) || (name == NULL)) {
-        virXenStoreError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return(NULL);
-    }
-
-    priv = (xenUnifiedPrivatePtr) conn->privateData;
-    if (priv->xshandle == NULL)
-        return(NULL);
-
-    idlist = xs_directory(priv->xshandle, 0, "/local/domain", &num);
-    if (idlist == NULL)
-        goto done;
-
-    for (i = 0; i < num; i++) {
-        id = strtol(idlist[i], &endptr, 10);
-        if ((endptr == idlist[i]) || (*endptr != 0)) {
-            goto done;
-        }
-#if 0
-        if (virConnectCheckStoreID(conn, (int) id) < 0)
-            continue;
-#endif
-        snprintf(prop, 199, "/local/domain/%s/name", idlist[i]);
-        prop[199] = 0;
-        tmp = xs_read(priv->xshandle, 0, prop, &len);
-        if (tmp != NULL) {
-            found = STREQ (name, tmp);
-            free(tmp);
-            if (found)
-                break;
-        }
-    }
-    if (!found)
-        goto done;
-
-    ret = virGetDomain(conn, name, NULL);
-    if (ret == NULL)
-        goto done;
-
-    ret->id = id;
-
-done:
-        free(xenddomain);
-        free(idlist);
-
-    return(ret);
-}
-
-/**
- * xenStoreDomainShutdown:
- * @domain: pointer to the Domain block
- *
- * Shutdown the domain, the OS is requested to properly shutdown
- * and the domain may ignore it.  It will return immediately
- * after queuing the request.
- *
- * Returns 0 in case of success, -1 in case of error.
- */
-int
-xenStoreDomainShutdown(virDomainPtr domain)
-{
-    int ret;
-    xenUnifiedPrivatePtr priv;
-
-    if ((domain == NULL) || (domain->conn == NULL)) {
-        virXenStoreError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                         __FUNCTION__);
-        return(-1);
-    }
-    if (domain->id == -1 || domain->id == 0)
-        return(-1);
-    /*
-     * this is very hackish, the domU kernel probes for a special
-     * node in the xenstore and launch the shutdown command if found.
-     */
-    priv = domain->conn->privateData;
-    xenUnifiedLock(priv);
-    ret = virDomainDoStoreWrite(domain, "control/shutdown", "poweroff");
-    xenUnifiedUnlock(priv);
-    return ret;
-}
-
-/**
- * xenStoreDomainReboot:
- * @domain: pointer to the Domain block
- * @flags: extra flags for the reboot operation, not used yet
- *
- * Reboot the domain, the OS is requested to properly shutdown
- * and reboot but the domain may ignore it.  It will return immediately
- * after queuing the request.
- *
- * Returns 0 in case of success, -1 in case of error.
- */
-int
-xenStoreDomainReboot(virDomainPtr domain, unsigned int flags ATTRIBUTE_UNUSED)
-{
-    int ret;
-    xenUnifiedPrivatePtr priv;
-
-    if ((domain == NULL) || (domain->conn == NULL)) {
-        virXenStoreError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                         __FUNCTION__);
-        return(-1);
-    }
-    if (domain->id == -1 || domain->id == 0)
-        return(-1);
-    /*
-     * this is very hackish, the domU kernel probes for a special
-     * node in the xenstore and launch the shutdown command if found.
-     */
-    priv = domain->conn->privateData;
-    xenUnifiedLock(priv);
-    ret = virDomainDoStoreWrite(domain, "control/shutdown", "reboot");
-    xenUnifiedUnlock(priv);
-    return ret;
-}
-
-/*
- * xenStoreDomainGetOSType:
- * @domain: a domain object
- *
- * Get the type of domain operation system.
- *
- * Returns the new string or NULL in case of error, the string must be
- *         freed by the caller.
- */
-static char *
-xenStoreDomainGetOSType(virDomainPtr domain) {
-    char *vm, *str = NULL;
-
-    if ((domain == NULL) || (domain->conn == NULL)) {
-        virXenStoreError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
-                         __FUNCTION__);
-        return(NULL);
-    }
-
-    vm = virDomainGetVM(domain);
-    if (vm) {
-        xenUnifiedPrivatePtr priv = domain->conn->privateData;
-        xenUnifiedLock(priv);
-        str = virDomainGetVMInfo(domain, vm, "image/ostype");
-        xenUnifiedUnlock(priv);
-        VIR_FREE(vm);
-    }
-
-    return (str);
-}
-#endif /* ! PROXY */
-
-/**
- * xenStoreDomainGetVNCPort:
- * @conn: the hypervisor connection
- * @domid: id of the domain
- *
- * Return the port number on which the domain is listening for VNC
- * connections.
- *
- * The caller must hold the lock on the privateData
- * associated with the 'conn' parameter.
- *
- * Returns the port number, -1 in case of error
- */
-int             xenStoreDomainGetVNCPort(virConnectPtr conn, int domid) {
-    char *tmp;
-    int ret = -1;
-
-    tmp = virDomainDoStoreQuery(conn, domid, "console/vnc-port");
-    if (tmp != NULL) {
-        char *end;
-        ret = strtol(tmp, &end, 10);
-        if (ret == 0 && end == tmp)
-            ret = -1;
-        free(tmp);
-    }
-    return(ret);
-}
-
-/**
- * xenStoreDomainGetConsolePath:
- * @conn: the hypervisor connection
- * @domid: id of the domain
- *
- * Return the path to the psuedo TTY on which the guest domain's
- * serial console is attached.
- *
- * Returns the path to the serial console. It is the callers
- * responsibilty to free() the return string. Returns NULL
- * on error
- *
- * The caller must hold the lock on the privateData
- * associated with the 'conn' parameter.
- */
-char *          xenStoreDomainGetConsolePath(virConnectPtr conn, int domid) {
-  return virDomainDoStoreQuery(conn, domid, "console/tty");
-}
-
-#ifdef PROXY
-/*
- * xenStoreDomainGetOSTypeID:
- * @conn: pointer to the connection.
- * @id: the domain id
- *
- * Get the type of domain operation system.
- *
- * The caller must hold the lock on the privateData
- * associated with the 'conn' parameter.
- *
- * Returns the new string or NULL in case of error, the string must be
- *         freed by the caller.
- */
-char *
-xenStoreDomainGetOSTypeID(virConnectPtr conn, int id) {
-    char *vm, *str = NULL;
-    char query[200];
-    unsigned int len;
-    xenUnifiedPrivatePtr priv;
-
-    if (id < 0)
-        return(NULL);
-
-    priv = (xenUnifiedPrivatePtr) conn->privateData;
-    if (priv->xshandle == NULL)
-        return (NULL);
-
-    snprintf(query, 199, "/local/domain/%d/vm", id);
-    query[199] = 0;
-
-    vm = xs_read(priv->xshandle, 0, &query[0], &len);
-
-    if (vm) {
-        snprintf(query, 199, "%s/image/ostype", vm);
-        str = xs_read(priv->xshandle, 0, &query[0], &len);
-        free(vm);
-    }
-    if (str == NULL)
-        str = strdup("linux");
-
-
-    return (str);
-}
-#endif /* PROXY */
-
-/*
- * xenStoreDomainGetNetworkID:
- * @conn: pointer to the connection.
- * @id: the domain id
- * @mac: the mac address
- *
- * Get the reference (i.e. the string number) for the device on that domain
- * which uses the given mac address
- *
- * The caller must hold the lock on the privateData
- * associated with the 'conn' parameter.
- *
- * Returns the new string or NULL in case of error, the string must be
- *         freed by the caller.
- */
-char *
-xenStoreDomainGetNetworkID(virConnectPtr conn, int id, const char *mac) {
-    char dir[80], path[128], **list = NULL, *val = NULL;
-    unsigned int len, i, num;
-    char *ret = NULL;
-    xenUnifiedPrivatePtr priv;
-
-    if (id < 0)
-        return(NULL);
-
-    priv = (xenUnifiedPrivatePtr) conn->privateData;
-    if (priv->xshandle == NULL)
-        return (NULL);
-    if (mac == NULL)
-        return (NULL);
-
-    snprintf(dir, sizeof(dir), "/local/domain/0/backend/vif/%d", id);
-    list = xs_directory(priv->xshandle, 0, dir, &num);
-    if (list == NULL)
-        return(NULL);
-    for (i = 0; i < num; i++) {
-        snprintf(path, sizeof(path), "%s/%s/%s", dir, list[i], "mac");
-        if ((val = xs_read(priv->xshandle, 0, path, &len)) == NULL)
-            break;
-
-        bool match = (virMacAddrCompare(val, mac) == 0);
-
-        VIR_FREE(val);
-
-        if (match) {
-            ret = strdup(list[i]);
-            break;
-        }
-    }
-
-    VIR_FREE(list);
-    return(ret);
-}
-
-/*
- * xenStoreDomainGetDiskID:
- * @conn: pointer to the connection.
- * @id: the domain id
- * @dev: the virtual block device name
- *
- * Get the reference (i.e. the string number) for the device on that domain
- * which uses the given virtual block device name
- *
- * The caller must hold the lock on the privateData
- * associated with the 'conn' parameter.
- *
- * Returns the new string or NULL in case of error, the string must be
- *         freed by the caller.
- */
-char *
-xenStoreDomainGetDiskID(virConnectPtr conn, int id, const char *dev) {
-    char dir[80], path[128], **list = NULL, *val = NULL;
-    unsigned int devlen, len, i, num;
-    char *ret = NULL;
-    xenUnifiedPrivatePtr priv;
-
-    if (id < 0)
-        return(NULL);
-
-    priv = (xenUnifiedPrivatePtr) conn->privateData;
-    if (priv->xshandle == NULL)
-        return (NULL);
-    if (dev == NULL)
-        return (NULL);
-    devlen = strlen(dev);
-    if (devlen <= 0)
-        return (NULL);
-
-    snprintf(dir, sizeof(dir), "/local/domain/0/backend/vbd/%d", id);
-    list = xs_directory(priv->xshandle, 0, dir, &num);
-    if (list != NULL) {
-        for (i = 0; i < num; i++) {
-            snprintf(path, sizeof(path), "%s/%s/%s", dir, list[i], "dev");
-            val = xs_read(priv->xshandle, 0, path, &len);
-            if (val == NULL)
-                break;
-            if ((devlen != len) || memcmp(val, dev, len)) {
-                free (val);
-            } else {
-                ret = strdup(list[i]);
-                free (val);
-                free (list);
-                return (ret);
-            }
-        }
-        free (list);
-    }
-    snprintf(dir, sizeof(dir), "/local/domain/0/backend/tap/%d", id);
-    list = xs_directory(priv->xshandle, 0, dir, &num);
-    if (list != NULL) {
-        for (i = 0; i < num; i++) {
-            snprintf(path, sizeof(path), "%s/%s/%s", dir, list[i], "dev");
-            val = xs_read(priv->xshandle, 0, path, &len);
-            if (val == NULL)
-                break;
-            if ((devlen != len) || memcmp(val, dev, len)) {
-                free (val);
-            } else {
-                ret = strdup(list[i]);
-                free (val);
-                free (list);
-                return (ret);
-            }
-        }
-        free (list);
-    }
-    return (NULL);
-}
-
-/*
- * The caller must hold the lock on the privateData
- * associated with the 'conn' parameter.
- */
-char *xenStoreDomainGetName(virConnectPtr conn,
-                            int id) {
-    char prop[200];
-    xenUnifiedPrivatePtr priv;
-    unsigned int len;
-
-    priv = (xenUnifiedPrivatePtr) conn->privateData;
-    if (priv->xshandle == NULL)
-        return(NULL);
-
-    snprintf(prop, 199, "/local/domain/%d/name", id);
-    prop[199] = 0;
-    return xs_read(priv->xshandle, 0, prop, &len);
-}
-
-#ifndef PROXY
-/*
- * The caller must hold the lock on the privateData
- * associated with the 'conn' parameter.
- */
-int xenStoreDomainGetUUID(virConnectPtr conn,
-                          int id,
-                          unsigned char *uuid) {
-    char prop[200];
-    xenUnifiedPrivatePtr priv;
-    unsigned int len;
-    char *uuidstr;
-    int ret = 0;
-
-    priv = (xenUnifiedPrivatePtr) conn->privateData;
-    if (priv->xshandle == NULL)
-        return -1;
-
-    snprintf(prop, 199, "/local/domain/%d/vm", id);
-    prop[199] = 0;
-    // This will return something like
-    // /vm/00000000-0000-0000-0000-000000000000
-    uuidstr = xs_read(priv->xshandle, 0, prop, &len);
-
-    // remove "/vm/"
-    ret = virUUIDParse(uuidstr + 4, uuid);
-
-    VIR_FREE(uuidstr);
-
-    return ret;
-}
-
-static void
-xenStoreWatchListFree(xenStoreWatchListPtr list)
-{
-    int i;
-    for (i=0; i<list->count; i++) {
-        VIR_FREE(list->watches[i]->path);
-        VIR_FREE(list->watches[i]->token);
-        VIR_FREE(list->watches[i]);
-    }
-    VIR_FREE(list);
-}
-
-/*
- * The caller must hold the lock on the privateData
- * associated with the 'conn' parameter.
- */
-int xenStoreAddWatch(virConnectPtr conn,
-                     const char *path,
-                     const char *token,
-                     xenStoreWatchCallback cb,
-                     void *opaque)
-{
-    xenStoreWatchPtr watch;
-    int n;
-    xenStoreWatchListPtr list;
-    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
-
-    if (priv->xshandle == NULL)
-        return -1;
-
-    list = priv->xsWatchList;
-    if(!list)
-        return -1;
-
-    /* check if we already have this callback on our list */
-    for (n=0; n < list->count; n++) {
-        if( STREQ(list->watches[n]->path, path) &&
-            STREQ(list->watches[n]->token, token)) {
-            virXenStoreError(NULL, VIR_ERR_INTERNAL_ERROR,
-                                 "%s", _("watch already tracked"));
-            return -1;
-        }
-    }
-
-    if (VIR_ALLOC(watch) < 0)
-        return -1;
-    watch->path   = strdup(path);
-    watch->token  = strdup(token);
-    watch->cb     = cb;
-    watch->opaque = opaque;
-
-    /* Make space on list */
-    n = list->count;
-    if (VIR_REALLOC_N(list->watches, n + 1) < 0) {
-        virXenStoreError(NULL, VIR_ERR_INTERNAL_ERROR,
-                                 "%s", _("reallocating list"));
-        VIR_FREE(watch);
-        return -1;
-    }
-
-    list->watches[n] = watch;
-    list->count++;
-
-    conn->refs++;
-
-    return xs_watch(priv->xshandle, watch->path, watch->token);
-}
-
-/*
- * The caller must hold the lock on the privateData
- * associated with the 'conn' parameter.
- */
-int xenStoreRemoveWatch(virConnectPtr conn,
-                        const char *path,
-                        const char *token)
-{
-    int i;
-    xenStoreWatchListPtr list;
-    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
-
-    if (priv->xshandle == NULL)
-        return -1;
-
-    list = priv->xsWatchList;
-    if(!list)
-        return -1;
-
-    for (i = 0 ; i < list->count ; i++) {
-        if( STREQ(list->watches[i]->path, path) &&
-            STREQ(list->watches[i]->token, token)) {
-
-            if (!xs_unwatch(priv->xshandle,
-                       list->watches[i]->path,
-                       list->watches[i]->token))
-            {
-                DEBUG0("WARNING: Could not remove watch");
-                /* Not fatal, continue */
-            }
-
-            VIR_FREE(list->watches[i]->path);
-            VIR_FREE(list->watches[i]->token);
-            VIR_FREE(list->watches[i]);
-
-            if (i < (list->count - 1))
-                memmove(list->watches + i,
-                        list->watches + i + 1,
-                        sizeof(*(list->watches)) *
-                                (list->count - (i + 1)));
-
-            if (VIR_REALLOC_N(list->watches,
-                              list->count - 1) < 0) {
-                ; /* Failure to reduce memory allocation isn't fatal */
-            }
-            list->count--;
-            virUnrefConnect(conn);
-            return 0;
-        }
-    }
-    return -1;
-}
-
-static xenStoreWatchPtr
-xenStoreFindWatch(xenStoreWatchListPtr list,
-                  const char *path,
-                  const char *token)
-{
-    int i;
-    for (i = 0 ; i < list->count ; i++)
-        if( STREQ(path, list->watches[i]->path) &&
-            STREQ(token, list->watches[i]->token) )
-            return list->watches[i];
-
-    return NULL;
-}
-
-static void
-xenStoreWatchEvent(int watch ATTRIBUTE_UNUSED,
-                   int fd ATTRIBUTE_UNUSED,
-                   int events,
-                   void *data)
-{
-    char                **event;
-    char                *path;
-    char                *token;
-    unsigned int        stringCount;
-    xenStoreWatchPtr     sw;
-
-    virConnectPtr        conn = data;
-    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
-
-    if(!priv) return;
-
-    /* only set a watch on read and write events */
-    if (events & (VIR_EVENT_HANDLE_ERROR | VIR_EVENT_HANDLE_HANGUP)) return;
-
-    xenUnifiedLock(priv);
-
-    if(!priv->xshandle)
-        goto cleanup;
-
-    event = xs_read_watch(priv->xshandle, &stringCount);
-    if (!event)
-        goto cleanup;
-
-    path  = event[XS_WATCH_PATH];
-    token = event[XS_WATCH_TOKEN];
-
-    sw = xenStoreFindWatch(priv->xsWatchList, path, token);
-    if( sw )
-        sw->cb(conn, path, token, sw->opaque);
-    VIR_FREE(event);
-
-cleanup:
-    xenUnifiedUnlock(priv);
-}
-
-
-/*
- * The domain callback for the @introduceDomain watch
- *
- * The lock on 'priv' is held when calling this
- */
-int xenStoreDomainIntroduced(virConnectPtr conn,
-                             const char *path ATTRIBUTE_UNUSED,
-                             const char *token ATTRIBUTE_UNUSED,
-                             void *opaque)
-{
-    int i, j, found, missing = 0, retries = 20;
-    int new_domain_cnt;
-    int *new_domids;
-    int nread;
-
-    xenUnifiedPrivatePtr priv = opaque;
-
-retry:
-    new_domain_cnt = xenStoreNumOfDomains(conn);
-    if( VIR_ALLOC_N(new_domids,new_domain_cnt) < 0 ) {
-        virReportOOMError(NULL);
-        return -1;
-    }
-    nread = xenStoreDoListDomains(priv, new_domids, new_domain_cnt);
-    if (nread != new_domain_cnt) {
-        // mismatch. retry this read
-        VIR_FREE(new_domids);
-        goto retry;
-    }
-
-    missing = 0;
-    for (i=0 ; i < new_domain_cnt ; i++) {
-        found = 0;
-        for (j = 0 ; j < priv->activeDomainList->count ; j++) {
-            if (priv->activeDomainList->doms[j]->id == new_domids[i]) {
-                found = 1;
-                break;
-            }
-        }
-
-        if (!found) {
-            virDomainEventPtr event;
-            char *name;
-            unsigned char uuid[VIR_UUID_BUFLEN];
-
-            if (!(name = xenStoreDomainGetName(conn, new_domids[i]))) {
-                missing = 1;
-                continue;
-            }
-            if (xenStoreDomainGetUUID(conn, new_domids[i], uuid) < 0) {
-                missing = 1;
-                VIR_FREE(name);
-                continue;
-            }
-
-            event = virDomainEventNew(new_domids[i], name, uuid,
-                                      VIR_DOMAIN_EVENT_STARTED,
-                                      VIR_DOMAIN_EVENT_STARTED_BOOTED);
-            if (event)
-                xenUnifiedDomainEventDispatch(priv, event);
-
-            /* Add to the list */
-            xenUnifiedAddDomainInfo(priv->activeDomainList,
-                                    new_domids[i], name, uuid);
-
-            VIR_FREE(name);
-        }
-    }
-    VIR_FREE(new_domids);
-
-    if (missing && retries--) {
-        DEBUG0("Some domains were missing, trying again");
-        usleep(100 * 1000);
-        goto retry;
-    }
-    return 0;
-}
-
-/*
- * The domain callback for the @destroyDomain watch
- *
- * The lock on 'priv' is held when calling this
- */
-int xenStoreDomainReleased(virConnectPtr conn,
-                            const char *path  ATTRIBUTE_UNUSED,
-                            const char *token ATTRIBUTE_UNUSED,
-                            void *opaque)
-{
-    int i, j, found, removed, retries = 20;
-    int new_domain_cnt;
-    int *new_domids;
-    int nread;
-
-    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) opaque;
-
-    if(!priv->activeDomainList->count) return 0;
-
-retry:
-    new_domain_cnt = xenStoreNumOfDomains(conn);
-
-    if( VIR_ALLOC_N(new_domids,new_domain_cnt) < 0 ) {
-        virReportOOMError(NULL);
-        return -1;
-    }
-    nread = xenStoreDoListDomains(priv, new_domids, new_domain_cnt);
-    if (nread != new_domain_cnt) {
-        // mismatch. retry this read
-        VIR_FREE(new_domids);
-        goto retry;
-    }
-
-    removed = 0;
-    for (j=0 ; j < priv->activeDomainList->count ; j++) {
-        found = 0;
-        for (i=0 ; i < new_domain_cnt ; i++) {
-            if (priv->activeDomainList->doms[j]->id == new_domids[i]) {
-                found = 1;
-                break;
-            }
-        }
-
-        if (!found) {
-            virDomainEventPtr event =
-                virDomainEventNew(-1,
-                                  priv->activeDomainList->doms[j]->name,
-                                  priv->activeDomainList->doms[j]->uuid,
-                                  VIR_DOMAIN_EVENT_STOPPED,
-                                  VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
-            if (event)
-                xenUnifiedDomainEventDispatch(priv, event);
-
-            /* Remove from the list */
-            xenUnifiedRemoveDomainInfo(priv->activeDomainList,
-                                       priv->activeDomainList->doms[j]->id,
-                                       priv->activeDomainList->doms[j]->name,
-                                       priv->activeDomainList->doms[j]->uuid);
-
-            removed = 1;
-        }
-    }
-
-    VIR_FREE(new_domids);
-
-    if (!removed && retries--) {
-        DEBUG0("No domains removed, retrying");
-        usleep(100 * 1000);
-        goto retry;
-    }
-    return 0;
-}
-
-#endif //PROXY
diff --git a/src/xs_internal.h b/src/xs_internal.h
deleted file mode 100644 (file)
index 29e680f..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * xs_internal.h: internal API for access to XenStore
- *
- * Copyright (C) 2006 Red Hat, Inc.
- *
- * See COPYING.LIB for the License of this software
- *
- * Daniel Veillard <veillard@redhat.com>
- */
-
-#ifndef __VIR_XS_INTERNAL_H__
-#define __VIR_XS_INTERNAL_H__
-
-#include "internal.h"
-#include "driver.h"
-
-extern struct xenUnifiedDriver xenStoreDriver;
-int xenStoreInit (void);
-
-virDrvOpenStatus       xenStoreOpen    (virConnectPtr conn,
-                                         virConnectAuthPtr auth,
-                                         int flags);
-int            xenStoreClose           (virConnectPtr conn);
-int            xenStoreGetDomainInfo   (virDomainPtr domain,
-                                         virDomainInfoPtr info);
-int            xenStoreNumOfDomains    (virConnectPtr conn);
-int            xenStoreListDomains     (virConnectPtr conn,
-                                         int *ids,
-                                         int maxids);
-virDomainPtr   xenStoreLookupByName(virConnectPtr conn,
-                                         const char *name);
-unsigned long  xenStoreGetMaxMemory    (virDomainPtr domain);
-int            xenStoreDomainSetMemory (virDomainPtr domain,
-                                         unsigned long memory);
-unsigned long  xenStoreDomainGetMaxMemory(virDomainPtr domain);
-int            xenStoreDomainShutdown  (virDomainPtr domain);
-int            xenStoreDomainReboot    (virDomainPtr domain,
-                                         unsigned int flags);
-
-/* those are entry point for the proxy */
-int             xenStoreDomainGetVNCPort(virConnectPtr conn,
-                                         int domid);
-char *          xenStoreDomainGetConsolePath(virConnectPtr conn,
-                                         int domid);
-char *         xenStoreDomainGetOSTypeID(virConnectPtr conn,
-                                         int id);
-char *         xenStoreDomainGetNetworkID(virConnectPtr conn,
-                                         int id,
-                                         const char *mac);
-char *         xenStoreDomainGetDiskID(virConnectPtr conn,
-                                         int id,
-                                         const char *dev);
-char *          xenStoreDomainGetName(virConnectPtr conn,
-                                      int id);
-int             xenStoreDomainGetUUID(virConnectPtr conn,
-                                      int id,
-                                      unsigned char *uuid);
-
-typedef int (*xenStoreWatchCallback)(virConnectPtr conn,
-                                     const char *path,
-                                     const char *token,
-                                     void *opaque);
-
-struct _xenStoreWatch {
-    char *path;
-    char *token;
-    xenStoreWatchCallback cb;
-    void *opaque;
-};
-typedef struct _xenStoreWatch xenStoreWatch;
-typedef xenStoreWatch *xenStoreWatchPtr;
-
-struct _xenStoreWatchList {
-    unsigned int count;
-    xenStoreWatchPtr *watches;
-};
-typedef struct _xenStoreWatchList xenStoreWatchList;
-typedef xenStoreWatchList *xenStoreWatchListPtr;
-
-
-int             xenStoreAddWatch(virConnectPtr conn,
-                                 const char *path,
-                                 const char *token,
-                                 xenStoreWatchCallback cb,
-                                 void *opaque);
-int             xenStoreRemoveWatch(virConnectPtr conn,
-                                    const char *path,
-                                    const char *token);
-
-/* domain events */
-int xenStoreDomainIntroduced(virConnectPtr conn,
-                             const char *path,
-                             const char *token,
-                             void *opaque);
-int xenStoreDomainReleased(virConnectPtr conn,
-                            const char *path,
-                            const char *token,
-                            void *opaque);
-
-int xenStoreDomainEventEmitted(virDomainEventType evt);
-#endif /* __VIR_XS_INTERNAL_H__ */
index 7b834a92002712a8f956380886741397e01aa47b..1196e234686dcff4a3cfd3d1817b41dd45620eb6 100644 (file)
@@ -7,8 +7,8 @@
 #include "internal.h"
 #include "xml.h"
 #include "datatypes.h"
-#include "xen_unified.h"
-#include "xend_internal.h"
+#include "xen/xen_driver.h"
+#include "xen/xend_internal.h"
 #include "testutils.h"
 #include "testutilsxen.h"
 
index 5b7d35a58c0cd1b6885feb5c9996ddbbea76542b..82c0daa3951ebabd6485b5d38720cc4123f6857a 100644 (file)
@@ -6,7 +6,7 @@
 
 #include "stats_linux.h"
 #include "internal.h"
-
+#include "xen/block_stats.h"
 #include "testutils.h"
 
 #if WITH_XEN
index c01efc0544b495cbc05db7b9b5c1decd6241fd56..8f3fb3eb6523ea424ef54b169e09c383cca37831 100644 (file)
@@ -8,7 +8,7 @@
 #include "internal.h"
 #include "xml.h"
 #include "testutils.h"
-#include "xen_internal.h"
+#include "xen/xen_hypervisor.h"
 
 static char *progname;
 static char *abs_srcdir;
index 2255984248f696aa41915cdfaee7f37abb6e0e51..f6aea5a433d73d962c2740f336b4e5b43b54a487 100644 (file)
@@ -29,8 +29,8 @@
 
 #include "internal.h"
 #include "datatypes.h"
-#include "xen_unified.h"
-#include "xm_internal.h"
+#include "xen/xen_driver.h"
+#include "xen/xm_internal.h"
 #include "testutils.h"
 #include "testutilsxen.h"
 #include "memory.h"
index b4ee4e0b2368e4fa37273f10a459638de4b703be..d83b37cc815432d54152b83de8eac5e4c11db81e 100644 (file)
@@ -9,7 +9,7 @@
 #include <unistd.h>
 
 #include "internal.h"
-#include "xend_internal.h"
+#include "xen/xend_internal.h"
 #include "testutils.h"
 #include "testutilsxen.h"