WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH 1 of 2] introducing libxenlight

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH 1 of 2] introducing libxenlight
From: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
Date: Mon, 9 Nov 2009 14:04:51 +0000
Delivery-date: Mon, 09 Nov 2009 06:04:40 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Alpine 2.00 (DEB 1167 2008-08-23)
This patch adds the initial libxenlight implementation under tools/libxl


Signed-off-by: Vincent Hanquez <Vincent.Hanquez@xxxxxxxxxxxxx>
Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>

---

diff -r 37829fd7c1e3 tools/libxl/Makefile
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/Makefile      Mon Nov 09 13:44:46 2009 +0000
@@ -0,0 +1,81 @@
+#
+# tools/libxl/Makefile
+#
+# This file is subject to the terms and conditions of the GNU General
+# Public License.  See the file "COPYING" in the main directory of
+# this archive for more details.
+#
+# Copyright (C) 2009 by Stefano Stabellini
+#
+
+XEN_ROOT       = ../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+MAJOR = 1.0
+MINOR = 0
+
+#CFLAGS += -Werror
+CFLAGS += -I. -fPIC
+CFLAGS += $(CFLAGS_libxenctrl) $(CFLAGS_libxenguest) $(CFLAGS_libxenstore)
+
+LDFLAGS = $(LDFLAGS_libxenctrl) $(LDFLAGS_libxenguest) $(LDFLAGS_libxenstore) 
-luuid
+
+LIBCONFIG_URL ?= http://www.hyperrealm.com/libconfig
+LIBCONFIG_SOURCE = libconfig-1.3.2
+LIBCONFIG_OUTPUT = $(LIBCONFIG_SOURCE)/.libs
+WGET=wget -c
+
+LIBXL_OBJS = flexarray.o libxl.o libxl_dom.o libxl_exec.o libxl_xshelp.o 
libxl_device.o libxl_internal.o xenguest.o osdeps.o libxl_utils.o
+
+CLIENTS = xl
+
+.PHONY: all
+all: $(CLIENTS) libxenlight.so libxenlight.a
+
+libxenlight.so: libxenlight.so.$(MAJOR)
+       ln -sf $< $@
+
+libxenlight.so.$(MAJOR): libxenlight.so.$(MAJOR).$(MINOR)
+       ln -sf $< $@
+
+libxenlight.so.$(MAJOR).$(MINOR): $(LIBXL_OBJS)
+       $(CC) $(CFLAGS) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) 
-Wl,libxenlight.so.$(MAJOR) $(SHLIB_CFLAGS) -o $@ $^
+
+libxenlight.a: $(LIBXL_OBJS)
+       $(AR) rcs libxenlight.a $^
+
+$(LIBCONFIG_SOURCE).tar.gz:
+       $(WGET) $(LIBCONFIG_URL)/$@
+
+$(LIBCONFIG_SOURCE): $(LIBCONFIG_SOURCE).tar.gz
+       tar xzf $<
+
+$(LIBCONFIG_OUTPUT)/libconfig.so: $(LIBCONFIG_SOURCE)
+       cd $(LIBCONFIG_SOURCE) && ./configure --prefix=$(DESTDIR)$(PREFIX) && 
$(MAKE)
+
+xl.o: $(LIBCONFIG_SOURCE)
+       $(CC) $(CFLAGS) -I$(LIBCONFIG_SOURCE) -c xl.c
+
+$(CLIENTS): xl.o libxenlight.so $(LIBCONFIG_OUTPUT)/libconfig.so
+       $(CC) $(LDFLAGS) -o $@ $< -L . -lxenlight -L$(LIBCONFIG_OUTPUT) -lconfig
+
+.PHONY: install
+install: all
+       $(INSTALL_PROG) xl $(DESTDIR)$(SBINDIR)
+       $(INSTALL_PROG) libxenlight.so.$(MAJOR).$(MINOR) $(DESTDIR)$(LIBDIR)
+       ln -sf libxenlight.so.$(MAJOR).$(MINOR) 
$(DESTDIR)$(LIBDIR)/libxenlight.so.$(MAJOR)
+       ln -sf libxenlight.so.$(MAJOR) $(DESTDIR)$(LIBDIR)/libxenlight.so
+       $(INSTALL_DATA) libxenlight.a $(DESTDIR)$(LIBDIR)
+       cd $(LIBCONFIG_SOURCE) && DESTDIR= $(MAKE) install
+
+.PHONY: clean
+clean:
+       $(RM) *.o
+       rm -f *.so*
+       rm -f *.a
+       rm -f $(CLIENTS)
+       rm -rf $(LIBCONFIG_SOURCE)
+
+distclean: clean
+       rm $(LIBCONFIG_SOURCE).tar.gz
+
diff -r 37829fd7c1e3 tools/libxl/flexarray.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/flexarray.c   Mon Nov 09 13:44:46 2009 +0000
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2009      Citrix Ltd.
+ * Author Vincent Hanquez <vincent.hanquez@xxxxxxxxxxxxx>
+ *
+ * This program 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; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program 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.
+ */
+
+#include <stdlib.h>
+#include "flexarray.h"
+
+flexarray_t *flexarray_make(int size, int autogrow)
+{
+    flexarray_t *array = malloc(sizeof(struct flexarray));
+    if (array) {
+        array->size = size;
+        array->autogrow = autogrow;
+        array->data = calloc(size, sizeof(void *));
+    }
+    return array;
+}
+
+void flexarray_free(flexarray_t *array)
+{
+    free(array->data);
+    free(array);
+}
+
+int flexarray_grow(flexarray_t *array, int extents)
+{
+    void **data;
+    int newsize;
+
+    newsize = array->size + extents;
+    data = realloc(array->data, sizeof(void *) * newsize);
+    if (!data)
+        return 1;
+    array->size += extents;
+    array->data = data;
+    return 0;
+}
+
+int flexarray_set(flexarray_t *array, unsigned int index, void *ptr)
+{
+    if (index >= array->size) {
+        int newsize;
+        if (!array->autogrow)
+            return 1;
+        newsize = (array->size * 2 < index) ? index + 1 : array->size * 2;
+        if (flexarray_grow(array, newsize - array->size))
+            return 2;
+    }
+    array->data[index] = ptr;
+    return 0;
+}
+
+int flexarray_get(flexarray_t *array, int index, void **ptr)
+{
+    if (index >= array->size)
+        return 1;
+    *ptr = array->data[index];
+    return 0;
+}
+
+void **flexarray_contents(flexarray_t *array)
+{
+    void **data;
+    data = array->data;
+    free(array);
+    return data;
+}
diff -r 37829fd7c1e3 tools/libxl/flexarray.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/flexarray.h   Mon Nov 09 13:44:46 2009 +0000
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2009      Citrix Ltd.
+ * Author Vincent Hanquez <vincent.hanquez@xxxxxxxxxxxxx>
+ *
+ * This program 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; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program 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.
+ */
+
+#ifndef FLEXARRAY_H
+#define FLEXARRAY_H
+
+typedef struct flexarray {
+    int size;
+    int autogrow;
+    void **data; /* array of pointer */
+} flexarray_t;
+
+flexarray_t *flexarray_make(int size, int autogrow);
+void flexarray_free(flexarray_t *array);
+int flexarray_grow(flexarray_t *array, int extents);
+int flexarray_set(flexarray_t *array, unsigned int index, void *ptr);
+int flexarray_get(flexarray_t *array, int index, void **ptr);
+
+void **flexarray_contents(flexarray_t *array);
+
+#endif
diff -r 37829fd7c1e3 tools/libxl/libxl.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/libxl.c       Mon Nov 09 13:44:46 2009 +0000
@@ -0,0 +1,742 @@
+/*
+ * Copyright (C) 2009      Citrix Ltd.
+ * Author Vincent Hanquez <vincent.hanquez@xxxxxxxxxxxxx>
+ * Author Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
+ *
+ * This program 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; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program 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.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/select.h>
+#include <signal.h>
+#include "libxl.h"
+#include "libxl_utils.h"
+#include "libxl_internal.h"
+#include "flexarray.h"
+
+int libxl_ctx_init(struct libxl_ctx *ctx)
+{
+    memset(ctx, 0, sizeof(struct libxl_ctx));
+    ctx->alloc_maxsize = 256;
+    ctx->alloc_ptrs = calloc(ctx->alloc_maxsize, sizeof(void *));
+    if (!ctx->alloc_ptrs)
+        return ERROR_NOMEM;
+
+    ctx->xch = xc_interface_open();
+    ctx->xsh = xs_daemon_open();
+    return 0;
+}
+
+int libxl_ctx_free(struct libxl_ctx *ctx)
+{
+    libxl_free_all(ctx);
+    free(ctx->alloc_ptrs);
+    ctx->alloc_ptrs = NULL;
+    xc_interface_close(ctx->xch);
+    xs_daemon_close(ctx->xsh);
+    return 0;
+}
+
+int libxl_ctx_set_log(struct libxl_ctx *ctx, libxl_log_callback log_callback, 
void *log_data)
+{
+    ctx->log_callback = log_callback;
+    ctx->log_userdata = log_data;
+    return 0;
+}
+
+/******************************************************************************/
+
+int libxl_domain_make(struct libxl_ctx *ctx, libxl_domain_create_info *info,
+                       uint32_t *domid)
+{
+    int flags, ret, i;
+        char *uuid_string;
+    char *rw_paths[] = { "device" };
+    char *ro_paths[] = { "cpu", "memory", "device", "error", "drivers",
+                         "control", "attr", "data", "messages" };
+    char *dom_path, *vm_path, *vss_path;
+    struct xs_permissions roperm[2];
+    struct xs_permissions rwperm[1];
+    xs_transaction_t t;
+
+    uuid_string = uuid_to_string(ctx, info->uuid);
+    if (!uuid_string) {
+        XL_LOG(ctx, XL_LOG_ERROR, "missing uuid");
+        return ERROR_FAIL;
+    }
+
+    flags = info->hvm ? XEN_DOMCTL_CDF_hvm_guest : 0;
+    flags |= info->hap ? XEN_DOMCTL_CDF_hap : 0;
+    *domid = 0;
+
+    ret = xc_domain_create(ctx->xch, info->ssidref, info->uuid, flags, domid);
+    if (ret < 0) {
+        XL_LOG(ctx, XL_LOG_ERROR, "domain creation fail: %d", ret);
+        return ERROR_FAIL;
+    }
+
+    dom_path = libxl_xs_get_dompath(ctx, *domid);
+    vm_path = libxl_sprintf(ctx, "/vm/%s", uuid_string);
+    vss_path = libxl_sprintf(ctx, "/vss/%s", uuid_string);
+    if (!dom_path || !vm_path || !vss_path) {
+        XL_LOG(ctx, XL_LOG_ERROR, "cannot allocate create paths");
+        return ERROR_FAIL;
+    }
+
+    roperm[0].id = 0;
+    roperm[0].perms = XS_PERM_NONE;
+    roperm[1].id = *domid;
+    roperm[1].perms = XS_PERM_READ;
+    rwperm[0].id = *domid;
+    rwperm[0].perms = XS_PERM_NONE;
+
+retry_transaction:
+    t = xs_transaction_start(ctx->xsh);
+    xs_rm(ctx->xsh, t, dom_path);
+    xs_mkdir(ctx->xsh, t, dom_path);
+    xs_set_permissions(ctx->xsh, t, dom_path, roperm, ARRAY_SIZE(roperm));
+
+    xs_rm(ctx->xsh, t, vm_path);
+    xs_mkdir(ctx->xsh, t, vm_path);
+    xs_set_permissions(ctx->xsh, t, vm_path, roperm, ARRAY_SIZE(roperm));
+
+    xs_rm(ctx->xsh, t, vss_path);
+    xs_mkdir(ctx->xsh, t, vss_path);
+    xs_set_permissions(ctx->xsh, t, vss_path, rwperm, ARRAY_SIZE(rwperm));
+
+    xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/vm", dom_path), vm_path, 
strlen(vm_path));
+    xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/vss", dom_path), vss_path, 
strlen(vss_path));
+    xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/name", dom_path), info->name, 
strlen(info->name));
+
+    for (i = 0; i < ARRAY_SIZE(rw_paths); i++) {
+        char *path = libxl_sprintf(ctx, "%s/%s", dom_path, rw_paths[i]);
+        xs_mkdir(ctx->xsh, t, path);
+        xs_set_permissions(ctx->xsh, t, path, rwperm, ARRAY_SIZE(rwperm));
+        libxl_free(ctx, path);
+    }
+    for (i = 0; i < ARRAY_SIZE(ro_paths); i++) {
+        char *path = libxl_sprintf(ctx, "%s/%s", dom_path, ro_paths[i]);
+        xs_mkdir(ctx->xsh, t, path);
+        xs_set_permissions(ctx->xsh, t, path, roperm, ARRAY_SIZE(roperm));
+        libxl_free(ctx, path);
+    }
+
+    xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/uuid", vm_path), uuid_string, 
strlen(uuid_string));
+    xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/name", vm_path), info->name, 
strlen(info->name));
+
+    libxl_xs_writev(ctx, t, dom_path, info->xsdata);
+    libxl_xs_writev(ctx, t, libxl_sprintf(ctx, "%s/platform", dom_path), 
info->platformdata);
+
+    xs_write(ctx->xsh, t, libxl_sprintf(ctx, 
"%s/control/platform-feature-multiprocessor-suspend", dom_path), "1", 1);
+
+    if (!xs_transaction_end(ctx->xsh, t, 0))
+        if (errno == EAGAIN)
+            goto retry_transaction;
+    return 0;
+}
+
+int libxl_domain_build(struct libxl_ctx *ctx, libxl_domain_build_info *info, 
uint32_t domid)
+{
+    libxl_domain_build_state state;
+    char **vments = NULL, **localents = NULL;
+
+    memset(&state, '\0', sizeof(state));
+
+    build_pre(ctx, domid, info, &state);
+    if (info->hvm) {
+        build_hvm(ctx, domid, info, &state);
+        vments = libxl_calloc(ctx, 4, sizeof(char *));
+        vments[0] = libxl_sprintf(ctx, "rtc/timeoffset");
+        vments[1] = libxl_sprintf(ctx, "%s", (info->u.hvm.timeoffset) ? 
info->u.hvm.timeoffset : "");
+    } else {
+        build_pv(ctx, domid, info, &state);
+    }
+    build_post(ctx, domid, info, &state, vments, localents);
+    return 0;
+}
+
+int libxl_domain_restore(struct libxl_ctx *ctx, libxl_domain_build_info *info,
+                          uint32_t domid, int fd)
+{
+    libxl_domain_build_state state;
+    char **vments = NULL, **localents = NULL;
+
+    memset(&state, '\0', sizeof(state));
+
+    build_pre(ctx, domid, info, &state);
+    restore_common(ctx, domid, info, &state, fd);
+    if (info->hvm) {
+        vments = libxl_calloc(ctx, 4, sizeof(char *));
+        vments[0] = libxl_sprintf(ctx, "rtc/timeoffset");
+        vments[1] = libxl_sprintf(ctx, "%s", (info->u.hvm.timeoffset) ? 
info->u.hvm.timeoffset : "");
+    } else {
+        localents = libxl_calloc(ctx, 4 * 2, sizeof(char *));
+        localents[0] = libxl_sprintf(ctx, "serial/0/limit");
+        localents[1] = libxl_sprintf(ctx, "%d", 65536);
+        localents[2] = libxl_sprintf(ctx, "console/port");
+        localents[3] = libxl_sprintf(ctx, "%d", state.console_port);
+        localents[4] = libxl_sprintf(ctx, "console/ring-ref");
+        localents[5] = libxl_sprintf(ctx, "%ld", state.console_mfn);
+    }
+    build_post(ctx, domid, info, &state, vments, localents);
+    return 0;
+}
+
+struct libxl_dominfo * libxl_domain_list(struct libxl_ctx *ctx, int *nb_domain)
+{
+    struct libxl_dominfo *ptr;
+    int index, i, ret, first_domain;
+    xc_domaininfo_t info[16];
+    int size = 16;
+
+    first_domain = 1;
+    index = 0;
+    ptr = libxl_calloc(ctx, size, sizeof(struct libxl_dominfo));
+    if (!ptr)
+        return NULL;
+redo:
+    ret = xc_domain_getinfolist(ctx->xch, first_domain, 16, info);
+    for (i = 0; i < ret; i++) {
+        if (index == size) {
+            struct libxl_dominfo *ptr2;
+
+            ptr2 = libxl_calloc(ctx, size * 2, sizeof(struct libxl_dominfo));
+            if (!ptr2) {
+                libxl_free(ctx, ptr);
+                return NULL;
+            }
+            memcpy(ptr2, ptr, sizeof(struct libxl_dominfo) * size);
+            libxl_free(ctx, ptr);
+            ptr = ptr2;
+            size *= 2;
+        }
+        memcpy(ptr[index].uuid, info[i].handle, 16 * sizeof(uint8_t));
+        ptr[index].domid = info[i].domain;
+        first_domain = info[i].domain + 1;
+        index++;
+    }
+    if (ret == 16)
+        goto redo;
+    *nb_domain = index;
+    return ptr;
+}
+
+xc_dominfo_t * libxl_domain_infolist(struct libxl_ctx *ctx, int *nb_domain)
+{
+    int index, first_domain;
+    xc_dominfo_t *info;
+    int size = 1024;
+
+    first_domain = 0;
+    index = 0;
+    info = (xc_dominfo_t *) libxl_calloc(ctx, size, sizeof(xc_dominfo_t));
+    if (!info) {
+        *nb_domain = 0;
+        return NULL;
+    }
+    *nb_domain = xc_domain_getinfo(ctx->xch, first_domain, 1024, info);
+    return info;
+}
+
+int libxl_domain_suspend(struct libxl_ctx *ctx, libxl_domain_suspend_info 
*info,
+                         uint32_t domid, int fd)
+{
+    int hvm = 1;
+    int live = 0;
+    int debug = 0;
+    char savesig[] = "XenSavedDomain\n";
+
+    write(fd, savesig, strlen(savesig));
+
+    core_suspend(ctx, domid, fd, hvm, live, debug);
+
+    return 0;
+}
+
+int libxl_domain_pause(struct libxl_ctx *ctx, uint32_t domid)
+{
+    xc_domain_pause(ctx->xch, domid);
+    return 0;
+}
+
+int libxl_domain_unpause(struct libxl_ctx *ctx, uint32_t domid)
+{
+    xc_domain_unpause(ctx->xch, domid);
+    return 0;
+}
+
+static char *req_table[] = {
+    [0] = "poweroff",
+    [1] = "reboot",
+    [2] = "suspend",
+    [3] = "crash",
+    [4] = "halt",
+};
+
+int libxl_domain_shutdown(struct libxl_ctx *ctx, uint32_t domid, int req)
+{
+    char *shutdown_path;
+    char *dom_path;
+
+    if (req > ARRAY_SIZE(req_table))
+        return ERROR_INVAL;
+
+    dom_path = libxl_xs_get_dompath(ctx, domid);
+    shutdown_path = libxl_sprintf(ctx, "%s/control/shutdown", dom_path);
+
+    xs_write(ctx->xsh, XBT_NULL, shutdown_path, req_table[req], 
strlen(req_table[req]));
+    if (/* hvm */ 0) {
+        unsigned long acpi_s_state = 0;
+        unsigned long pvdriver = 0;
+        xc_get_hvm_param(ctx->xch, domid, HVM_PARAM_ACPI_S_STATE, 
&acpi_s_state);
+        xc_get_hvm_param(ctx->xch, domid, HVM_PARAM_CALLBACK_IRQ, &pvdriver);
+        if (!pvdriver && acpi_s_state != 0)
+            xc_domain_shutdown(ctx->xch, domid, req);
+    }
+    return 0;
+}
+
+static int libxl_destroy_device_model(struct libxl_ctx *ctx, uint32_t domid)
+{
+    char *pid;
+    int ret;
+
+    pid = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"/local/domain/%d/image/device-model-pid", domid));
+    if (!pid) {
+        XL_LOG(ctx, XL_LOG_ERROR, "Couldn't find device model's pid\n");
+        return -1;
+    }
+    xs_rm(ctx->xsh, XBT_NULL, libxl_sprintf(ctx, 
"/local/domain/0/device-model/%d", domid));
+ 
+    ret = kill(atoi(pid), SIGHUP);
+    if (ret < 0 && errno == ESRCH) {
+        XL_LOG(ctx, XL_LOG_DEBUG, "Device Model already exited\n");
+        ret = 0;
+    } else if (ret == 0) {
+        XL_LOG(ctx, XL_LOG_DEBUG, "Device Model signaled\n");
+        ret = 0;
+    } else {
+        XL_LOG(ctx, XL_LOG_ERROR, "kill %d returned %d errno=%d\n", atoi(pid), 
ret, errno);
+    }
+    return ret;
+}
+
+int libxl_domain_destroy(struct libxl_ctx *ctx, uint32_t domid, int force)
+{
+    char *dom_path, vm_path[41];
+    uint8_t *uuid;
+
+    dom_path = libxl_xs_get_dompath(ctx, domid);
+    if (!dom_path) {
+        XL_LOG(ctx, XL_LOG_ERROR, "dompath doesn't exist for %d\n", domid);
+        return -1;
+    }
+    if (libxl_domid_to_uuid(ctx, &uuid, domid) < 0) {
+        XL_LOG(ctx, XL_LOG_ERROR, "failed ot get uuid for %d\n", domid);
+        return -1;
+    }
+    xs_write(ctx->xsh, XBT_NULL,
+             libxl_sprintf(ctx, "/local/domain/0/device-model/%d/command", 
domid),
+             "shutdown", strlen("shutdown"));
+    if (xc_domain_pause(ctx->xch, domid) < 0) {
+        XL_LOG(ctx, XL_LOG_ERROR, "xc_domain_pause failed for %d\n", domid);
+        return -1;
+    }
+    /* do_FLR */
+    if (xc_domain_destroy(ctx->xch, domid) < 0) {
+        XL_LOG(ctx, XL_LOG_ERROR, "xc_domain_destroy failed for %d\n", domid);
+        return -1;
+    }
+    if (libxl_devices_destroy(ctx, domid, force) < 0)
+        XL_LOG(ctx, XL_LOG_ERROR, "libxl_destroy_devices failed for %d\n", 
domid);
+    if (libxl_destroy_device_model(ctx, domid) < 0)
+        XL_LOG(ctx, XL_LOG_ERROR, "libxl_destroy_device_model failed for 
%d\n", domid);
+    if (!xs_rm(ctx->xsh, XBT_NULL, dom_path))
+        XL_LOG(ctx, XL_LOG_ERROR, "xs_rm failed for %s\n", dom_path);
+    snprintf(vm_path, sizeof(vm_path), "/vm/%s", uuid_to_string(ctx, uuid)); 
+    if (!xs_rm(ctx->xsh, XBT_NULL, vm_path))
+        XL_LOG(ctx, XL_LOG_ERROR, "xs_rm failed for %s\n", vm_path);
+    return 0;
+}
+
+static char ** libxl_build_device_model_args(struct libxl_ctx *ctx,
+                                             libxl_device_model_info *info,
+                                             libxl_device_nic *vifs,
+                                             int num_vifs)
+{
+    int num = 0, i;
+    flexarray_t *dm_args;
+    dm_args = flexarray_make(16, 1);
+    if (!dm_args)
+        return NULL;
+
+    flexarray_set(dm_args, num++, libxl_sprintf(ctx, "qemu-dm"));
+    flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-d"));
+
+    flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%d", info->domid));
+
+    if (info->dom_name) {
+        flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-domain-name"));
+        flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s", 
info->dom_name));
+    }
+    if (info->videoram) {
+        flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-videoram"));
+        flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%d", 
info->videoram));
+    }
+    if (info->stdvga) {
+        flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-std-vga"));
+    }
+    if (info->vnc || info->vncdisplay || info->vnclisten || info->vncunused) {
+        flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-vnc"));
+        if (info->vncdisplay) {
+            if (info->vnclisten && strchr(info->vnclisten, ':') == NULL) {
+                flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s:%d", 
info->vnclisten, info->vncdisplay));
+            } else {
+                flexarray_set(dm_args, num++, libxl_sprintf(ctx, 
"127.0.0.1:%d", info->vncdisplay));
+            }
+        } else if (info->vnclisten) {
+            if (strchr(info->vnclisten, ':') != NULL) {
+                flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s", 
info->vnclisten));
+            } else {
+                flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s:0", 
info->vnclisten));
+            }
+        } else {
+            flexarray_set(dm_args, num++, libxl_sprintf(ctx, "127.0.0.1:0"));
+        }
+        if (info->vncunused) {
+            flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-vncunused"));
+        }
+    }
+    if (info->sdl || info->opengl) {
+        flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-sdl"));
+        if (info->opengl) {
+            flexarray_set(dm_args, num++, libxl_sprintf(ctx, 
"-disable-opengl"));
+        }
+    }
+    if (info->keymap) {
+        flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-k"));
+        flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s", info->keymap));
+    }
+    if (info->nographic && (!info->sdl && !info->vnc)) {
+        flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-nographic"));
+    }
+    if (info->serial) {
+        flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-serial"));
+        flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s", info->serial));
+    }
+    if (info->boot) {
+        flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-boot"));
+        flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s", info->boot));
+    }
+    if (info->usb) {
+        flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-usb"));
+        if (info->usbdevice) {
+            flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-usbdevice"));
+            flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s", 
info->usbdevice));
+        }
+    }
+    if (info->apic) {
+        flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-acpi"));
+    }
+    if (info->extra) {
+        int i = 0;
+        while (info->extra[i] != NULL) {
+            flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s", 
info->extra[i]));
+        }
+    }
+    for (i = 0; i < num_vifs; i++) {
+        if (vifs[i].nictype == NICTYPE_IOEMU) {
+            flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-net"));
+            flexarray_set(dm_args, num++, libxl_sprintf(ctx, 
"nic,vlan=%d,macaddr=%s,model=%s",
+                                                        vifs[i].devid, 
vifs[i].smac, vifs[i].model));
+            flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-net"));
+            flexarray_set(dm_args, num++, libxl_sprintf(ctx, 
"tap,vlan=%d,ifname=%s,bridge=%s",
+                                                        vifs[i].devid, 
vifs[i].ifname, vifs[i].bridge));
+        }
+    }
+    flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-M"));
+    flexarray_set(dm_args, num++, libxl_sprintf(ctx, "xenfv"));
+    flexarray_set(dm_args, num++, NULL);
+
+    return (char **) flexarray_contents(dm_args);
+}
+
+int libxl_create_device_model(struct libxl_ctx *ctx,
+                              libxl_device_model_info *info,
+                              libxl_device_nic *vifs, int num_vifs)
+{
+    char *dom_path, *path, *logfile, *logfile_new;
+    char *kvs[3];
+    struct stat stat_buf;
+    int logfile_w, null, pid;
+    int i;
+    char **args;
+
+    args = libxl_build_device_model_args(ctx, info, vifs, num_vifs);
+    if (!args)
+        return ERROR_FAIL;
+
+    dom_path = libxl_xs_get_dompath(ctx, info->domid);
+
+    path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d", info->domid);
+    xs_mkdir(ctx->xsh, XBT_NULL, path);
+
+    logfile = libxl_sprintf(ctx, "/var/log/xen/qemu-dm-%s.log", 
info->dom_name);
+    if (stat(logfile, &stat_buf) == 0) {
+        /* file exists, rotate */
+        logfile = libxl_sprintf(ctx, "/var/log/xen/qemu-dm-%s.log.10", 
info->dom_name);
+        unlink(logfile);
+        for (i = 9; i > 0; i--) {
+            logfile = libxl_sprintf(ctx, "/var/log/xen/qemu-dm-%s.log.%d", 
info->dom_name, i);
+            logfile_new = libxl_sprintf(ctx, "/var/log/xen/qemu-dm-%s.log.%d", 
info->dom_name, i + 1);
+            rename(logfile, logfile_new);
+        }
+        logfile = libxl_sprintf(ctx, "/var/log/xen/qemu-dm-%s.log", 
info->dom_name);
+        logfile_new = libxl_sprintf(ctx, "/var/log/xen/qemu-dm-%s.log.1", 
info->dom_name);
+        rename(logfile, logfile_new);
+    }
+    logfile = libxl_sprintf(ctx, "/var/log/xen/qemu-dm-%s.log", 
info->dom_name);
+    logfile_w = open(logfile, O_WRONLY|O_CREAT);
+    null = open("/dev/null", O_RDONLY);
+    pid = libxl_exec(ctx, null, logfile_w, logfile_w, info->device_model, 
args);
+    close(null);
+    close(logfile_w);
+
+    kvs[0] = libxl_sprintf(ctx, "image/device-model-pid");
+    kvs[1] = libxl_sprintf(ctx, "%d", pid);
+    kvs[2] = NULL;
+    libxl_xs_writev(ctx, XBT_NULL, dom_path, kvs);
+
+    return 0;
+}
+
+/******************************************************************************/
+int libxl_device_disk_add(struct libxl_ctx *ctx, uint32_t domid, 
libxl_device_disk *disk)
+{
+    flexarray_t *front;
+    flexarray_t *back;
+    char *backend_type;
+    unsigned int boffset = 0;
+    unsigned int foffset = 0;
+    int devid;
+    libxl_device device;
+
+    front = flexarray_make(16, 1);
+    if (!front)
+        return ERROR_NOMEM;
+    back = flexarray_make(16, 1);
+    if (!back) /* leaks front if error */
+        return ERROR_NOMEM;
+
+    backend_type = device_disk_backend_type_of_phystype(disk->phystype);
+    devid = device_disk_dev_number(disk->virtpath);
+
+    device.backend_devid = devid;
+    device.backend_domid = disk->backend_domid;
+    device.devid = devid;
+    device.domid = disk->domid;
+    device.kind = DEVICE_VBD;
+
+    switch (disk->phystype) {
+        case PHYSTYPE_FILE:
+            return ERROR_NI; /* FIXME */
+            break;
+        case PHYSTYPE_PHY: {
+            int major, minor;
+
+            device_disk_major_minor(disk->virtpath, &major, &minor);
+            flexarray_set(back, boffset++, libxl_sprintf(ctx, 
"physical-device"));
+            flexarray_set(back, boffset++, libxl_sprintf(ctx, "%x:%x", major, 
minor));
+
+            flexarray_set(back, boffset++, libxl_sprintf(ctx, "params"));
+            flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s", 
disk->physpath));
+
+            device.backend_kind = DEVICE_VBD;
+            break;
+        }
+        case PHYSTYPE_AIO: case PHYSTYPE_QCOW: case PHYSTYPE_QCOW2: case 
PHYSTYPE_VHD:
+            flexarray_set(back, boffset++, libxl_sprintf(ctx, "params"));
+            flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s:%s",
+                          device_disk_string_of_phystype(disk->phystype), 
disk->physpath));
+
+            device.backend_kind = DEVICE_TAP;
+            break;
+    }
+
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "frontend-id"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", disk->domid));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "online"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "1"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "removable"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 
(disk->unpluggable) ? 1 : 0));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "state"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "dev"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s", disk->virtpath));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "type"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s", backend_type));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "mode"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s", (disk->readwrite) 
? "w" : "r"));
+
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "backend-id"));
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 
disk->backend_domid));
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "state"));
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "virtual-device"));
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", devid));
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "device-type"));
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%s", (disk->is_cdrom) 
? "cdrom" : "disk"));
+
+    if (0 /* protocol != native*/) {
+        flexarray_set(front, foffset++, libxl_sprintf(ctx, "protocol"));
+        flexarray_set(front, foffset++, libxl_sprintf(ctx, "x86_32-abi")); /* 
hardcoded ! */
+    }
+
+    libxl_device_generic_add(ctx, &device,
+                             libxl_xs_kvs_of_flexarray(ctx, back, boffset),
+                             libxl_xs_kvs_of_flexarray(ctx, front, foffset));
+    /* leaks both flexarray here */
+    return 0;
+}
+
+int libxl_device_disk_clean_shutdown(struct libxl_ctx *ctx, uint32_t domid)
+{
+    return ERROR_NI;
+}
+
+int libxl_device_disk_hard_shutdown(struct libxl_ctx *ctx, uint32_t domid)
+{
+    return ERROR_NI;
+}
+
+/******************************************************************************/
+int libxl_device_nic_add(struct libxl_ctx *ctx, uint32_t domid, 
libxl_device_nic *nic)
+{
+    flexarray_t *front;
+    flexarray_t *back;
+    unsigned int boffset = 0;
+    unsigned int foffset = 0;
+    libxl_device device;
+
+    front = flexarray_make(16, 1);
+    if (!front)
+        return ERROR_NOMEM;
+    back = flexarray_make(16, 1);
+    if (!back)
+        return ERROR_NOMEM;
+
+    device.backend_devid = nic->devid;
+    device.backend_domid = nic->backend_domid;
+    device.backend_kind = DEVICE_VIF;
+    device.devid = nic->devid;
+    device.domid = nic->domid;
+    device.kind = DEVICE_VIF;
+
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "frontend-id"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", nic->domid));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "online"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "1"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "state"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "script"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s", nic->script));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "mac"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, 
"%02x:%02x:%02x:%02x:%02x:%02x",
+                                                 nic->mac[0], nic->mac[1], 
nic->mac[2],
+                                                 nic->mac[3], nic->mac[4], 
nic->mac[5]));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "handle"));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", nic->devid));
+
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "backend-id"));
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 
nic->backend_domid));
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "state"));
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "handle"));
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", nic->devid));
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "mac"));
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, 
"%02x:%02x:%02x:%02x:%02x:%02x",
+                                                  nic->mac[0], nic->mac[1], 
nic->mac[2],
+                                                  nic->mac[3], nic->mac[4], 
nic->mac[5]));
+    if (0 /* protocol != native*/) {
+        flexarray_set(front, foffset++, libxl_sprintf(ctx, "protocol"));
+        flexarray_set(front, foffset++, libxl_sprintf(ctx, "x86_32-abi")); /* 
hardcoded ! */
+    }
+
+    libxl_device_generic_add(ctx, &device,
+                             libxl_xs_kvs_of_flexarray(ctx, back, boffset),
+                             libxl_xs_kvs_of_flexarray(ctx, front, foffset));
+
+    /* FIXME: wait for plug */
+    return 0;
+}
+
+int libxl_device_nic_clean_shutdown(struct libxl_ctx *ctx, uint32_t domid)
+{
+    return ERROR_NI;
+}
+
+int libxl_device_nic_hard_shutdown(struct libxl_ctx *ctx, uint32_t domid)
+{
+    return ERROR_NI;
+}
+
+/******************************************************************************/
+int libxl_device_vkb_add(struct libxl_ctx *ctx, uint32_t domid)
+{
+    return ERROR_NI;
+}
+
+int libxl_device_vkb_clean_shutdown(struct libxl_ctx *ctx, uint32_t domid)
+{
+    return ERROR_NI;
+}
+
+int libxl_device_vkb_hard_shutdown(struct libxl_ctx *ctx, uint32_t domid)
+{
+    return ERROR_NI;
+}
+
+/******************************************************************************/
+int libxl_device_vfb_add(struct libxl_ctx *ctx, uint32_t domid)
+{
+    return ERROR_NI;
+}
+
+int libxl_device_vfb_clean_shutdown(struct libxl_ctx *ctx, uint32_t domid)
+{
+    return ERROR_NI;
+}
+
+int libxl_device_vfb_hard_shutdown(struct libxl_ctx *ctx, uint32_t domid)
+{
+    return ERROR_NI;
+}
+
+/******************************************************************************/
+int libxl_device_pci_add(struct libxl_ctx *ctx, uint32_t domid)
+{
+    return ERROR_NI;
+}
+
+int libxl_device_pci_clean_shutdown(struct libxl_ctx *ctx, uint32_t domid)
+{
+    return ERROR_NI;
+}
+
+int libxl_device_pci_hard_shutdown(struct libxl_ctx *ctx, uint32_t domid)
+{
+    return ERROR_NI;
+}
diff -r 37829fd7c1e3 tools/libxl/libxl.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/libxl.h       Mon Nov 09 13:44:46 2009 +0000
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2009      Citrix Ltd.
+ * Author Vincent Hanquez <vincent.hanquez@xxxxxxxxxxxxx>
+ *
+ * This program 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; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program 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.
+ */
+#ifndef LIBXL_H
+#define LIBXL_H
+
+#include "osdeps.h"
+#include <stdint.h>
+#include <stdarg.h>
+#include <netinet/in.h>
+#include <xenctrl.h>
+
+typedef int bool;
+
+typedef void (*libxl_log_callback)(void *userdata, int loglevel, const char 
*file,
+                                   int line, const char *func, char *s);
+
+struct libxl_dominfo {
+    uint8_t uuid[16];
+    uint32_t domid;
+};
+
+struct libxl_ctx {
+    int xch;
+    struct xs_handle *xsh;
+    /* errors/debug buf */
+    void *log_userdata;
+    libxl_log_callback log_callback;
+    
+    /* mini-GC */
+    int alloc_maxsize;
+    void **alloc_ptrs;
+};
+
+typedef struct {
+    bool hvm;
+    bool hap;
+    int ssidref;
+    char *name;
+    uint8_t *uuid;
+    char **xsdata;
+    char **platformdata;
+} libxl_domain_create_info;
+
+typedef struct {
+    int timer_mode;
+    int hpet;
+    int vpt_align;
+    int max_vcpus;
+    uint32_t max_memkb;
+    uint32_t video_memkb;
+    uint32_t shadow_memkb;
+    const char *kernel;
+    int hvm;
+    union {
+        struct {
+            bool pae;
+            bool apic;
+            bool acpi;
+            bool nx;
+            bool viridian;
+            char *timeoffset;
+        } hvm;
+        struct {
+            const char *cmdline;
+            const char *ramdisk;
+        } pv;
+    } u;
+} libxl_domain_build_info;
+
+typedef struct {
+    int flags;
+    int (*suspend_callback)(void *, int);
+} libxl_domain_suspend_info;
+
+typedef struct {
+    int domid;
+    char *dom_name;
+    char *device_model;
+    int videoram; /* size of the videoram in MB */
+    bool stdvga; /* stdvga enabled or disabled */
+    bool vnc; /* vnc enabled or disabled */
+    char *vnclisten; /* address:port that should be listened on for the VNC 
server if vnc is set */
+    int vncdisplay; /* set VNC display number */
+    bool vncunused; /* try to find an unused port for the VNC server */
+    char *keymap; /* set keyboard layout, default is en-us keyboard */
+    bool sdl; /* sdl enabled or disabled */
+    bool opengl; /* opengl enabled or disabled (if enabled requires sdl 
enabled) */
+    bool nographic; /* no graphics, use serial port */
+    char *serial; /* serial port re-direct to pty deivce */
+    char *boot; /* boot order, for example dca */
+    bool usb; /* usb support enabled or disabled */
+    char *usbdevice; /* enable usb mouse: tablet for absolute mouse, mouse for 
PS/2 protocol relative mouse */
+    bool apic; /* apic enabled or disabled */
+    char **extra; /* extra parameters pass directly to qemu, NULL terminated */
+    /* Network is missing */
+} libxl_device_model_info;
+
+typedef enum {
+    PHYSTYPE_QCOW,
+    PHYSTYPE_QCOW2,
+    PHYSTYPE_VHD,
+    PHYSTYPE_AIO,
+    PHYSTYPE_FILE,
+    PHYSTYPE_PHY,
+} libxl_disk_phystype;
+
+typedef struct {
+    uint32_t backend_domid;
+    uint32_t domid;
+    char *physpath;
+    libxl_disk_phystype phystype;
+    char *virtpath;
+    int unpluggable;
+    int readwrite;
+    int is_cdrom;
+} libxl_device_disk;
+
+typedef enum {
+    NICTYPE_IOEMU,
+    NICTYPE_VIF,
+} libxl_nic_type;
+
+typedef struct {
+    uint32_t backend_domid;
+    uint32_t domid;
+    int devid;
+    int mtu;
+    char *model;
+    uint8_t mac[6];
+    char *smac;
+    struct in_addr ip;
+    char *bridge;
+    char *ifname;
+    char *script;
+    libxl_nic_type nictype;
+} libxl_device_nic;
+
+#define ERROR_FAIL (-2)
+#define ERROR_NI (-101)
+#define ERROR_NOMEM (-1032)
+#define ERROR_INVAL (-1245)
+
+/* context functions */
+int libxl_ctx_init(struct libxl_ctx *ctx);
+int libxl_ctx_free(struct libxl_ctx *ctx);
+int libxl_ctx_set_log(struct libxl_ctx *ctx, libxl_log_callback log_callback, 
void *log_data);
+
+/* domain related functions */
+int libxl_domain_make(struct libxl_ctx *ctx, libxl_domain_create_info *info, 
uint32_t *domid);
+int libxl_domain_build(struct libxl_ctx *ctx, libxl_domain_build_info *info, 
uint32_t domid);
+int libxl_domain_restore(struct libxl_ctx *ctx, libxl_domain_build_info *info,
+                          uint32_t domid, int fd);
+int libxl_domain_suspend(struct libxl_ctx *ctx, libxl_domain_suspend_info 
*info,
+                          uint32_t domid, int fd);
+int libxl_domain_shutdown(struct libxl_ctx *ctx, uint32_t domid, int req);
+int libxl_domain_destroy(struct libxl_ctx *ctx, uint32_t domid, int force);
+
+int libxl_domain_pause(struct libxl_ctx *ctx, uint32_t domid);
+int libxl_domain_unpause(struct libxl_ctx *ctx, uint32_t domid);
+
+struct libxl_dominfo * libxl_domain_list(struct libxl_ctx *ctx, int 
*nb_domain);
+xc_dominfo_t * libxl_domain_infolist(struct libxl_ctx *ctx, int *nb_domain);
+
+int libxl_create_device_model(struct libxl_ctx *ctx,
+                              libxl_device_model_info *info,
+                              libxl_device_nic *vifs, int num_vifs);
+
+int libxl_device_disk_add(struct libxl_ctx *ctx, uint32_t domid, 
libxl_device_disk *disk);
+int libxl_device_disk_clean_shutdown(struct libxl_ctx *ctx, uint32_t domid);
+int libxl_device_disk_hard_shutdown(struct libxl_ctx *ctx, uint32_t domid);
+
+int libxl_device_nic_add(struct libxl_ctx *ctx, uint32_t domid, 
libxl_device_nic *nic);
+int libxl_device_nic_clean_shutdown(struct libxl_ctx *ctx, uint32_t domid);
+int libxl_device_nic_hard_shutdown(struct libxl_ctx *ctx, uint32_t domid);
+
+int libxl_device_vkb_add(struct libxl_ctx *ctx, uint32_t domid);
+int libxl_device_vkb_clean_shutdown(struct libxl_ctx *ctx, uint32_t domid);
+int libxl_device_vkb_hard_shutdown(struct libxl_ctx *ctx, uint32_t domid);
+
+int libxl_device_vfb_add(struct libxl_ctx *ctx, uint32_t domid);
+int libxl_device_vfb_clean_shutdown(struct libxl_ctx *ctx, uint32_t domid);
+int libxl_device_vfb_hard_shutdown(struct libxl_ctx *ctx, uint32_t domid);
+
+int libxl_device_pci_add(struct libxl_ctx *ctx, uint32_t domid);
+int libxl_device_pci_clean_shutdown(struct libxl_ctx *ctx, uint32_t domid);
+int libxl_device_pci_hard_shutdown(struct libxl_ctx *ctx, uint32_t domid);
+
+#endif
diff -r 37829fd7c1e3 tools/libxl/libxl_device.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/libxl_device.c        Mon Nov 09 13:44:46 2009 +0000
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2009      Citrix Ltd.
+ * Author Vincent Hanquez <vincent.hanquez@xxxxxxxxxxxxx>
+ * Author Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
+ *
+ * This program 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; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program 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.
+ */
+
+#include <string.h>
+#include "libxl.h"
+#include "libxl_internal.h"
+
+char *string_of_kinds[] = {
+    [DEVICE_VIF] = "vif",
+    [DEVICE_VBD] = "vbd",
+    [DEVICE_TAP] = "tap",
+    [DEVICE_PCI] = "pci",
+    [DEVICE_VFB] = "vfb",
+    [DEVICE_VKBD] = "vkbd",
+};
+
+int libxl_device_generic_add(struct libxl_ctx *ctx, libxl_device *device,
+                             char **bents, char **fents)
+{
+    char *dom_path_backend, *dom_path, *frontend_path, *backend_path, 
*hotplug_path;
+    xs_transaction_t t;
+    struct xs_permissions frontend_perms[2];
+    struct xs_permissions backend_perms[2];
+    struct xs_permissions hotplug_perms[1];
+
+    dom_path_backend = xs_get_domain_path(ctx->xsh, device->backend_domid);
+    dom_path = xs_get_domain_path(ctx->xsh, device->domid);
+
+    frontend_path = libxl_sprintf(ctx, "%s/device/%s/%d",
+                                  dom_path, string_of_kinds[device->kind], 
device->devid);
+    backend_path = libxl_sprintf(ctx, "%s/backend/%s/%u/%d",
+                                 dom_path_backend, 
string_of_kinds[device->backend_kind], device->domid, device->devid);
+    hotplug_path = libxl_sprintf(ctx, "/xapi/%d/hotplug/%s/%d",
+                                  device->domid, 
string_of_kinds[device->kind], device->devid);
+
+    frontend_perms[0].id = device->domid;
+    frontend_perms[0].perms = XS_PERM_NONE;
+    frontend_perms[1].id = device->backend_domid;
+    frontend_perms[1].perms = XS_PERM_READ;
+
+    backend_perms[0].id = device->backend_domid;
+    backend_perms[0].perms = XS_PERM_NONE;
+    backend_perms[1].id = device->domid;
+    backend_perms[1].perms = XS_PERM_READ;
+
+    hotplug_perms[0].id = device->backend_domid;
+    hotplug_perms[0].perms = XS_PERM_NONE;
+
+retry_transaction:
+    t = xs_transaction_start(ctx->xsh);
+    /* FIXME: read frontend_path and check state before removing stuff */
+
+    xs_rm(ctx->xsh, t, frontend_path);
+    xs_rm(ctx->xsh, t, backend_path);
+
+    xs_mkdir(ctx->xsh, t, frontend_path);
+    xs_set_permissions(ctx->xsh, t, frontend_path, frontend_perms, 
ARRAY_SIZE(frontend_perms));
+
+    xs_mkdir(ctx->xsh, t, backend_path);
+    xs_set_permissions(ctx->xsh, t, backend_path, backend_perms, 
ARRAY_SIZE(backend_perms));
+
+    xs_mkdir(ctx->xsh, t, hotplug_path);
+    xs_set_permissions(ctx->xsh, t, hotplug_path, hotplug_perms, 
ARRAY_SIZE(hotplug_perms));
+
+    xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/backend", frontend_path), 
backend_path, strlen(backend_path));
+    xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/frontend", backend_path), 
frontend_path, strlen(frontend_path));
+
+    /* and write frontend kvs and backend kvs */
+    libxl_xs_writev(ctx, t, backend_path, bents);
+    libxl_xs_writev(ctx, t, frontend_path, fents);
+
+    if (!xs_transaction_end(ctx->xsh, t, 0))
+        if (errno == EAGAIN)
+            goto retry_transaction;
+    return 0;
+}
+
+char *device_disk_string_of_phystype(libxl_disk_phystype phystype)
+{
+    switch (phystype) {
+        case PHYSTYPE_QCOW: return "qcow";
+        case PHYSTYPE_QCOW2: return "qcow2";
+        case PHYSTYPE_VHD: return "vhd";
+        case PHYSTYPE_AIO: return "aio";
+        case PHYSTYPE_FILE: return "file";
+        case PHYSTYPE_PHY: return "phy";
+        default: return NULL;
+    }
+}
+
+char *device_disk_backend_type_of_phystype(libxl_disk_phystype phystype)
+{
+    switch (phystype) {
+        case PHYSTYPE_QCOW: return "tap";
+        case PHYSTYPE_VHD: return "tap";
+        case PHYSTYPE_AIO: return "tap";
+        case PHYSTYPE_FILE: return "file";
+        case PHYSTYPE_PHY: return "phy";
+        default: return NULL;
+    }
+}
+
+int device_disk_major_minor(char *virtpath, int *major, int *minor)
+{
+    if (strstr(virtpath, "sd") == virtpath) {
+        return -1;
+    } else if (strstr(virtpath, "xvd") == virtpath) {
+        return -1;
+    } else if (strstr(virtpath, "hd") == virtpath) {
+        char letter, letter2;
+
+        *major = 0; *minor = 0;
+        letter = virtpath[2];
+        if (letter < 'a' || letter > 't')
+            return -1;
+        letter2 = virtpath[3];
+
+        *major = letter - 'a';
+        *minor = atoi(virtpath + 3);
+        return 0;
+    } else {
+        return -1;
+    }
+}
+
+int device_disk_dev_number(char *virtpath)
+{
+    int majors_table[] = { 3, 22, 33, 34, 56, 57, 88, 89, 90, 91 };
+    int major, minor;
+
+    if (device_disk_major_minor(virtpath, &major, &minor))
+        return -1;
+    return majors_table[major / 2] * 256 + (64 * (major % 2)) + minor;
+}
+
+int libxl_device_destroy(struct libxl_ctx *ctx, char *be_path, int force)
+{
+    xs_transaction_t t;
+    char *state_path = libxl_sprintf(ctx, "%s/state", be_path);
+    char *state = libxl_xs_read(ctx, XBT_NULL, state_path);
+    if (!state)
+        return 0;
+    if (atoi(state) <= 3) {
+        xs_rm(ctx->xsh, XBT_NULL, be_path);
+        return 0;
+    }
+
+retry_transaction:
+    t = xs_transaction_start(ctx->xsh);
+    xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/online", be_path), "0", 
strlen("0"));
+    xs_write(ctx->xsh, t, state_path, "5", strlen("5"));
+    if (!xs_transaction_end(ctx->xsh, t, 0)) {
+        if (errno == EAGAIN)
+            goto retry_transaction;
+        else
+            return -1;
+    }
+    if (!force) {
+        xs_watch(ctx->xsh, state_path, be_path);
+        return 1;
+    } else
+        return 0;
+}
+
+int libxl_devices_destroy(struct libxl_ctx *ctx, uint32_t domid, int force)
+{
+    char *path, *be_path, *fe_path;
+    unsigned int num1, num2;
+    char **l1 = NULL, **l2 = NULL;
+    int i, j, nfds, n = 0, n_watches = 0;
+    fd_set rfds;
+    struct timeval tv;
+    flexarray_t *toremove;
+
+    toremove = flexarray_make(16, 1);
+    path = libxl_sprintf(ctx, "/local/domain/%d/device", domid);
+    l1 = libxl_xs_directory(ctx, XBT_NULL, path, &num1);
+    if (!l1) {
+        XL_LOG(ctx, XL_LOG_ERROR, "%s is empty\n", path);
+        return -1;
+    }
+    for (i = 0; i < num1; i++) {
+        path = libxl_sprintf(ctx, "/local/domain/%d/device/%s", domid, l1[i]);
+        l2 = libxl_xs_directory(ctx, XBT_NULL, path, &num2);
+        if (!l2)
+            continue;
+        for (j = 0; j < num2; j++) {
+            fe_path = libxl_sprintf(ctx, "/local/domain/%d/device/%s/%s", 
domid, l1[i], l2[j]);
+            be_path = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/backend", fe_path));
+            if (be_path != NULL) {
+                if (libxl_device_destroy(ctx, be_path, force) > 0)
+                    n_watches++;
+                flexarray_set(toremove, n++, libxl_dirname(ctx, be_path));
+            } else {
+                xs_rm(ctx->xsh, XBT_NULL, path);
+            }
+        }
+    }
+    if (!force) {
+        nfds = xs_fileno(ctx->xsh) + 1;
+        /* Linux-ism */
+        tv.tv_sec = LIBXL_DESTROY_TIMEOUT;
+        tv.tv_usec = 0;
+        while (n_watches > 0 && tv.tv_sec > 0) {
+            FD_ZERO(&rfds);
+            FD_SET(xs_fileno(ctx->xsh), &rfds);
+            if (select(nfds, &rfds, NULL, NULL, &tv) > 0) {
+                l1 = xs_read_watch(ctx->xsh, &num1);
+                if (l1 != NULL) {
+                    char *state = libxl_xs_read(ctx, XBT_NULL, l1[0]);
+                    if (!state || atoi(state) == 6) {
+                        xs_unwatch(ctx->xsh, l1[0], l1[1]);
+                        xs_rm(ctx->xsh, XBT_NULL, l1[1]);
+                        XL_LOG(ctx, XL_LOG_DEBUG, "Destroyed device backend at 
%s\n", l1[1]);
+                        n_watches--;
+                    }
+                }
+            } else
+                break;
+        }
+    }
+    for (i = 0; i < n; i++) {
+        flexarray_get(toremove, i, (void**) &path);
+        xs_rm(ctx->xsh, XBT_NULL, path);
+    }
+    flexarray_free(toremove);
+    return 0;
+}
diff -r 37829fd7c1e3 tools/libxl/libxl_dom.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/libxl_dom.c   Mon Nov 09 13:44:46 2009 +0000
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2009      Citrix Ltd.
+ * Author Vincent Hanquez <vincent.hanquez@xxxxxxxxxxxxx>
+ *
+ * This program 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; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program 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.
+ */
+
+#include "libxl.h"
+#include "libxl_internal.h"
+#include <inttypes.h>
+#include <xenguest.h>
+#include <string.h>
+
+int is_hvm(struct libxl_ctx *ctx, uint32_t domid)
+{
+    xc_domaininfo_t info;
+    int ret;
+
+    ret = xc_domain_getinfolist(ctx->xch, domid, 1, &info);
+    if (ret != 1)
+        return -1;
+    if (info.domain != domid)
+        return -1;
+    return !!(info.flags & XEN_DOMINF_hvm_guest);
+}
+
+int build_pre(struct libxl_ctx *ctx, uint32_t domid,
+              libxl_domain_build_info *info, libxl_domain_build_state *state)
+{
+    unsigned long shadow;
+    if (info->timer_mode != -1)
+        xc_set_hvm_param(ctx->xch, domid, HVM_PARAM_TIMER_MODE,
+                (unsigned long) info->timer_mode);
+    if (info->hpet != -1)
+        xc_set_hvm_param(ctx->xch, domid, HVM_PARAM_HPET_ENABLED, (unsigned 
long) info->hpet);
+    if (info->vpt_align != -1)
+        xc_set_hvm_param(ctx->xch, domid, HVM_PARAM_VPT_ALIGN, (unsigned long) 
info->vpt_align);
+    xc_domain_max_vcpus(ctx->xch, domid, info->max_vcpus);
+    xc_domain_setmaxmem(ctx->xch, domid, info->max_memkb + info->video_memkb);
+    xc_domain_set_memmap_limit(ctx->xch, domid, info->max_memkb);
+    shadow = (info->shadow_memkb + 1023) / 1024;
+    xc_shadow_control(ctx->xch, domid, XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION, 
NULL, 0, &shadow, 0, NULL);
+
+    state->store_port = xc_evtchn_alloc_unbound(ctx->xch, domid, 0);
+    state->console_port = xc_evtchn_alloc_unbound(ctx->xch, domid, 0);
+    return 0;
+}
+
+int build_post(struct libxl_ctx *ctx, uint32_t domid,
+               libxl_domain_build_info *info, libxl_domain_build_state *state,
+               char **vms_ents, char **local_ents)
+{
+    char *dom_path, *vm_path;
+    xs_transaction_t t;
+    char **ents;
+
+    ents = libxl_calloc(ctx, 6 * 2, sizeof(char *));
+    ents[0] = libxl_sprintf(ctx, "memory/static-max");
+    ents[1] = libxl_sprintf(ctx, "%d", info->max_memkb);
+    ents[2] = libxl_sprintf(ctx, "memory/target");
+    ents[3] = libxl_sprintf(ctx, "%d", info->max_memkb); /* PROBABLY WRONG */
+    ents[4] = libxl_sprintf(ctx, "domid");
+    ents[5] = libxl_sprintf(ctx, "%d", domid);
+    ents[6] = libxl_sprintf(ctx, "store/port");
+    ents[7] = libxl_sprintf(ctx, "%"PRIu32, state->store_port);
+    ents[8] = libxl_sprintf(ctx, "store/ring-ref");
+    ents[9] = libxl_sprintf(ctx, "%lu", state->store_mfn);
+
+    dom_path = libxl_xs_get_dompath(ctx, domid);
+    vm_path = xs_read(ctx->xsh, XBT_NULL, libxl_sprintf(ctx, "%s/vm", 
dom_path), NULL);
+retry_transaction:
+    t = xs_transaction_start(ctx->xsh);
+
+    libxl_xs_writev(ctx, t, dom_path, ents);
+    libxl_xs_writev(ctx, t, dom_path, local_ents);
+    libxl_xs_writev(ctx, t, vm_path, vms_ents);
+
+    if (!xs_transaction_end(ctx->xsh, t, 0))
+        if (errno == EAGAIN)
+            goto retry_transaction;
+    xs_introduce_domain(ctx->xsh, domid, state->store_mfn, state->store_port);
+    return 0;
+}
+
+int build_pv(struct libxl_ctx *ctx, uint32_t domid,
+             libxl_domain_build_info *info, libxl_domain_build_state *state)
+{
+    int mem_target_kib = info->max_memkb;
+    char *domid_str = libxl_sprintf(ctx, "%d", domid);
+    char *memsize_str = libxl_sprintf(ctx, "%d", mem_target_kib / 1024);
+    char *store_port_str = libxl_sprintf(ctx, "%d", state->store_port);
+    char *console_port_str = libxl_sprintf(ctx, "%d", state->console_port);
+    return ERROR_NI;
+}
+
+int build_hvm(struct libxl_ctx *ctx, uint32_t domid,
+              libxl_domain_build_info *info, libxl_domain_build_state *state)
+{
+    int ret;
+
+    ret = xc_hvm_build(ctx->xch, domid, info->max_memkb / 1024, info->kernel);
+    if (ret) {
+        XL_LOG(ctx, XL_LOG_ERROR, "hvm building failed: %d", ret);
+        return ERROR_FAIL;
+    }
+    ret = hvm_build_set_params(ctx->xch, domid, info->u.hvm.apic, 
info->u.hvm.acpi,
+                               info->u.hvm.pae, info->u.hvm.nx, 
info->u.hvm.viridian,
+                               info->max_vcpus,
+                               state->store_port, &state->store_mfn);
+    if (ret) {
+        XL_LOG(ctx, XL_LOG_ERROR, "hvm build set params failed: %d", ret);
+        return ERROR_FAIL;
+    }
+    xc_cpuid_apply_policy(ctx->xch, domid);
+    return 0;
+}
+
+int restore_common(struct libxl_ctx *ctx, uint32_t domid,
+                   libxl_domain_build_info *info, libxl_domain_build_state 
*state,
+                   int fd)
+{
+    /* read signature */
+    xc_domain_restore(ctx->xch, fd, domid,
+                      state->store_port, &state->store_mfn,
+                      state->console_port, &state->console_mfn,
+                      info->hvm, info->u.hvm.pae, 0);
+    return 0;
+}
+
+/* the following code is extremely ugly and racy without forking.
+   we intend to fix the re-entrancy of the underlying code instead of forking 
*/
+static struct libxl_ctx *global_suspend_ctx = NULL;
+static struct suspendinfo {
+    int xch;
+    int xce; /* event channel handle */
+    int suspend_eventchn;
+    int domid;
+    int hvm;
+    unsigned int flags;
+} si;
+
+void core_suspend_switch_qemu_logdirty(int domid, unsigned int enable)
+{
+    struct xs_handle *xs;
+    char *path, *ret_path, *cmd_path, *ret_str, *cmd_str, **watch;
+    unsigned int len;
+    struct timeval tv;
+    fd_set fdset;
+    struct libxl_ctx *ctx = global_suspend_ctx;
+
+    xs = xs_daemon_open();
+    if (!xs)
+        return;
+    path = libxl_sprintf(ctx, "/local/domain/0/device-model/%i/logdirty", 
domid);
+    if (!path)
+        return;
+    ret_path = libxl_sprintf(ctx, "%s/ret", path);
+    if (!ret_path)
+        return;
+    cmd_path = libxl_sprintf(ctx, "%s/cmd", path);
+    if (!ret_path)
+        return;
+
+    /* Watch for qemu's return value */
+    if (!xs_watch(xs, ret_path, "qemu-logdirty-ret"))
+        return;
+
+    cmd_str = (enable == 0) ? "disable" : "enable";
+
+    /* Tell qemu that we want it to start logging dirty page to Xen */
+    if (!xs_write(xs, XBT_NULL, cmd_path, cmd_str, strlen(cmd_str)))
+        return;
+
+    /* Wait a while for qemu to signal that it has service logdirty command */
+read_again:
+    tv.tv_sec = 5;
+    tv.tv_usec = 0;
+    FD_ZERO(&fdset);
+    FD_SET(xs_fileno(xs), &fdset);
+
+    if ((select(xs_fileno(xs) + 1, &fdset, NULL, NULL, &tv)) != 1)
+        return;
+
+    watch = xs_read_watch(xs, &len);
+    free(watch);
+
+    ret_str = xs_read(xs, XBT_NULL, ret_path, &len);
+    if (ret_str == NULL || strcmp(ret_str, cmd_str))
+        /* Watch fired but value is not yet right */
+        goto read_again;
+    free(ret_str);
+}
+
+static int core_suspend_callback(void)
+{
+    unsigned long s_state = 0;
+    int ret;
+
+    if (si.hvm)
+        xc_get_hvm_param(si.xch, si.domid, HVM_PARAM_ACPI_S_STATE, &s_state);
+    if ((s_state == 0) && (si.suspend_eventchn >= 0)) {
+        ret = xc_evtchn_notify(si.xch, si.suspend_eventchn);
+        if (ret < 0) {
+            return 0;
+        }
+        ret = xc_await_suspend(si.xch, si.suspend_eventchn);
+        if (ret < 0) {
+            return 0;
+        }
+        return 1;
+    }
+    /* need to shutdown (to suspend) the domain here */
+    return 0;
+}
+
+int core_suspend(struct libxl_ctx *ctx, uint32_t domid, int fd, int hvm, int 
live, int debug)
+{
+    int flags;
+    int port;
+
+    flags = (live) ? XCFLAGS_LIVE : 0
+          | (debug) ? XCFLAGS_DEBUG : 0;
+
+    /* crappy global lock until we make everything clean */
+    while (global_suspend_ctx) {
+        sleep(1);
+    }
+    global_suspend_ctx = ctx;
+
+    si.domid = domid;
+    si.flags = flags;
+    si.hvm = hvm;
+    si.suspend_eventchn = si.xce = -1;
+    si.xch = ctx->xch;
+
+    si.xce = xc_evtchn_open();
+    if (si.xce < 0)
+        return -1;
+
+    if (si.xce > 0) {
+        port = xs_suspend_evtchn_port(si.domid);
+
+        if (port < 0) {
+        } else {
+            si.suspend_eventchn = xc_suspend_evtchn_init(si.xch, si.xce, 
si.domid, port);
+
+            if (si.suspend_eventchn < 0) {
+            }
+        }
+    }
+
+    xc_domain_save(ctx->xch, fd, domid, 0, 0, flags,
+                   core_suspend_callback, hvm,
+                   core_suspend_switch_qemu_logdirty);
+
+    if (si.suspend_eventchn > 0)
+        xc_suspend_evtchn_release(si.xce, si.suspend_eventchn);
+    if (si.xce > 0)
+        xc_evtchn_close(si.xce);
+
+    global_suspend_ctx = NULL;
+    return 0;
+}
diff -r 37829fd7c1e3 tools/libxl/libxl_exec.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/libxl_exec.c  Mon Nov 09 13:44:46 2009 +0000
@@ -0,0 +1,48 @@
+
+/*
+ * Copyright (C) 2009      Citrix Ltd.
+ * Author Vincent Hanquez <vincent.hanquez@xxxxxxxxxxxxx>
+ * Author Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
+ *
+ * This program 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; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program 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.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "libxl.h"
+#include "libxl_internal.h"
+
+int libxl_exec(struct libxl_ctx *ctx, int stdinfd, int stdoutfd, int stderrfd,
+               char *arg0, char **args)
+{
+    int pid, i;
+
+    pid = fork();
+    if (pid == -1) {
+        XL_LOG(ctx, XL_LOG_ERROR, "fork failed");
+        return -1;
+    }
+    if (pid == 0) {
+        /* child */
+        if (stdinfd != -1)
+            dup2(stdinfd, STDIN_FILENO);
+        if (stdoutfd != -1)
+            dup2(stdoutfd, STDOUT_FILENO);
+        if (stderrfd != -1)
+            dup2(stderrfd, STDERR_FILENO);
+        for (i = 4; i < 256; i++)
+            close(i);
+        execv(arg0, args);
+        exit(256);
+    }
+    return pid;
+}
diff -r 37829fd7c1e3 tools/libxl/libxl_internal.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/libxl_internal.c      Mon Nov 09 13:44:46 2009 +0000
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2009      Citrix Ltd.
+ * Author Vincent Hanquez <vincent.hanquez@xxxxxxxxxxxxx>
+ *
+ * This program 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; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program 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.
+ */
+#include "libxl.h"
+#include "libxl_internal.h"
+#include "libxl_utils.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+int libxl_error_set(struct libxl_ctx *ctx, int code)
+{
+    return 0;
+}
+
+int libxl_ptr_add(struct libxl_ctx *ctx, void *ptr)
+{
+    int i;
+    void **re;
+
+    if (!ptr)
+        return 0;
+
+    /* fast case: we have space in the array for storing the pointer */
+    for (i = 0; i < ctx->alloc_maxsize; i++) {
+        if (!ctx->alloc_ptrs[i]) {
+            ctx->alloc_ptrs[i] = ptr;
+            return 0;
+        }
+    }
+    /* realloc alloc_ptrs manually with calloc/free/replace */
+    re = calloc(ctx->alloc_maxsize + 25, sizeof(void *));
+    if (!re)
+        return -1;
+    for (i = 0; i < ctx->alloc_maxsize; i++)
+        re[i] = ctx->alloc_ptrs[i];
+    /* assign the next pointer */
+    re[i] = ptr;
+
+    /* replace the old alloc_ptr */
+    free(ctx->alloc_ptrs);
+    ctx->alloc_ptrs = re;
+    ctx->alloc_maxsize += 25;
+    return 0;
+}
+
+int libxl_free(struct libxl_ctx *ctx, void *ptr)
+{
+    int i;
+
+    if (!ptr)
+        return 0;
+
+    /* remove the pointer from the tracked ptrs */
+    for (i = 0; i < ctx->alloc_maxsize; i++) {
+        if (ctx->alloc_ptrs[i] == ptr) {
+            ctx->alloc_ptrs[i] = NULL;
+            free(ptr);
+            return 0;
+        }
+    }
+    /* haven't find the pointer, really bad */
+    return -1;
+}
+
+int libxl_free_all(struct libxl_ctx *ctx)
+{
+    void *ptr;
+    int i;
+
+    for (i = 0; i < ctx->alloc_maxsize; i++) {
+        ptr = ctx->alloc_ptrs[i];
+        ctx->alloc_ptrs[i] = NULL;
+        free(ptr);
+    }
+    return 0;
+}
+
+void *libxl_zalloc(struct libxl_ctx *ctx, int bytes)
+{
+    void *ptr = calloc(bytes, 1);
+    if (!ptr) {
+        libxl_error_set(ctx, ENOMEM);
+        return NULL;
+    }
+
+    libxl_ptr_add(ctx, ptr);
+    return ptr;
+}
+
+void *libxl_calloc(struct libxl_ctx *ctx, size_t nmemb, size_t size)
+{
+    void *ptr = calloc(nmemb, size);
+    if (!ptr) {
+        libxl_error_set(ctx, ENOMEM);
+        return NULL;
+    }
+
+    libxl_ptr_add(ctx, ptr);
+    return ptr;
+}
+
+char *libxl_sprintf(struct libxl_ctx *ctx, const char *fmt, ...)
+{
+    char *s;
+    va_list ap;
+    int ret;
+    
+    va_start(ap, fmt);
+    ret = vsnprintf(NULL, 0, fmt, ap);
+    va_end(ap);
+
+    if (ret < 0) {
+        return NULL;
+    }
+
+    s = libxl_zalloc(ctx, ret + 1);
+    if (s) {
+        va_start(ap, fmt);
+        ret = vsnprintf(s, ret + 1, fmt, ap);
+        va_end(ap);
+    }
+    return s;
+}
+
+char *libxl_dirname(struct libxl_ctx *ctx, const char *s)
+{
+    char *c;
+    char *ptr = libxl_sprintf(ctx, "%s", s);
+
+    c = strrchr(ptr, '/');
+    if (!c)
+        return NULL;
+    *c = '\0';
+    return ptr;
+}
+
+void xl_log(struct libxl_ctx *ctx, int loglevel, const char *file, int line, 
const char *func, char *fmt, ...)
+{
+    va_list ap;
+    char *s;
+    va_start(ap, fmt);
+    vasprintf(&s, fmt, ap);
+    va_end(ap);
+
+    ctx->log_callback(ctx->log_userdata, loglevel, file, line, func, s);
+    free(s);
+}
diff -r 37829fd7c1e3 tools/libxl/libxl_internal.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/libxl_internal.h      Mon Nov 09 13:44:46 2009 +0000
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2009      Citrix Ltd.
+ * Author Vincent Hanquez <vincent.hanquez@xxxxxxxxxxxxx>
+ * Author Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
+ *
+ * This program 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; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program 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.
+ */
+
+#ifndef LIBXL_INTERNAL_H
+# define LIBXL_INTERNAL_H
+
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+#include <xs.h>
+#include <xenctrl.h>
+
+#include "flexarray.h"
+#include "libxl_utils.h"
+
+#define LIBXL_DESTROY_TIMEOUT 10
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+
+
+#define XL_LOGGING_ENABLED
+
+#ifdef XL_LOGGING_ENABLED
+#define XL_LOG(ctx, loglevel, _f, _a...)   xl_log(ctx, loglevel, __FILE__, 
__LINE__, __func__, _f, ##_a)
+#else
+#define XL_LOG(ctx, loglevel, _f, _a...)
+#endif
+
+#define XL_LOG_DEBUG 3
+#define XL_LOG_INFO 2
+#define XL_LOG_WARNING 1
+#define XL_LOG_ERROR 0
+
+void xl_log(struct libxl_ctx *ctx, int loglevel, const char *file, int line, 
const char *func, char *fmt, ...);
+
+typedef struct {
+    uint32_t store_port;
+    unsigned long store_mfn;
+    uint32_t console_port;
+    unsigned long console_mfn;
+} libxl_domain_build_state;
+
+typedef enum {
+    DEVICE_VIF,
+    DEVICE_VBD,
+    DEVICE_TAP,
+    DEVICE_PCI,
+    DEVICE_VFB,
+    DEVICE_VKBD,
+} libxl_device_kinds;
+
+typedef struct {
+    uint32_t backend_devid;
+    uint32_t backend_domid;
+    uint32_t devid;
+    uint32_t domid;
+    libxl_device_kinds backend_kind;
+    libxl_device_kinds kind;
+} libxl_device;
+
+#define PRINTF_ATTRIBUTE(x, y) __attribute__((format(printf, x, y)))
+
+/* memory allocation tracking/helpers */
+int libxl_ptr_add(struct libxl_ctx *ctx, void *ptr);
+int libxl_free(struct libxl_ctx *ctx, void *ptr);
+int libxl_free_all(struct libxl_ctx *ctx);
+void *libxl_zalloc(struct libxl_ctx *ctx, int bytes);
+void *libxl_calloc(struct libxl_ctx *ctx, size_t nmemb, size_t size);
+char *libxl_sprintf(struct libxl_ctx *ctx, const char *fmt, ...) 
PRINTF_ATTRIBUTE(2, 3);
+char *libxl_dirname(struct libxl_ctx *ctx, const char *s);
+char *uuid_to_string(struct libxl_ctx *ctx, uint8_t *uuid);
+
+char **libxl_xs_kvs_of_flexarray(struct libxl_ctx *ctx, flexarray_t *array, 
int length);
+int libxl_xs_writev(struct libxl_ctx *ctx, xs_transaction_t t,
+                    char *dir, char **kvs);
+int libxl_xs_write(struct libxl_ctx *ctx, xs_transaction_t t,
+                   char *path, char *fmt, ...);
+char *libxl_xs_get_dompath(struct libxl_ctx *ctx, uint32_t domid);
+char *libxl_xs_read(struct libxl_ctx *ctx, xs_transaction_t t, char *path);
+char **libxl_xs_directory(struct libxl_ctx *ctx, xs_transaction_t t, char 
*path, unsigned int *nb);
+
+/* from xd_dom */
+int is_hvm(struct libxl_ctx *ctx, uint32_t domid);
+int build_pre(struct libxl_ctx *ctx, uint32_t domid,
+              libxl_domain_build_info *info, libxl_domain_build_state *state);
+int build_post(struct libxl_ctx *ctx, uint32_t domid,
+               libxl_domain_build_info *info, libxl_domain_build_state *state,
+               char **vms_ents, char **local_ents);
+
+int build_pv(struct libxl_ctx *ctx, uint32_t domid,
+             libxl_domain_build_info *info, libxl_domain_build_state *state);
+int build_hvm(struct libxl_ctx *ctx, uint32_t domid,
+              libxl_domain_build_info *info, libxl_domain_build_state *state);
+
+int restore_common(struct libxl_ctx *ctx, uint32_t domid,
+                   libxl_domain_build_info *info, libxl_domain_build_state 
*state, int fd);
+int core_suspend(struct libxl_ctx *ctx, uint32_t domid, int fd, int hvm, int 
live, int debug);
+
+/* from xd_device */
+char *device_disk_backend_type_of_phystype(libxl_disk_phystype phystype);
+char *device_disk_string_of_phystype(libxl_disk_phystype phystype);
+
+int device_disk_major_minor(char *virtpath, int *major, int *minor);
+int device_disk_dev_number(char *virtpath);
+
+int libxl_device_generic_add(struct libxl_ctx *ctx, libxl_device *device,
+                             char **bents, char **fents);
+int libxl_device_destroy(struct libxl_ctx *ctx, char *be_path, int force);
+int libxl_devices_destroy(struct libxl_ctx *ctx, uint32_t domid, int force);
+
+/* from xenguest (helper */
+int hvm_build_set_params(int handle, uint32_t domid,
+                         int apic, int acpi, int pae, int nx, int viridian,
+                         int vcpus, int store_evtchn, unsigned long 
*store_mfn);
+
+/* xd_exec */
+int libxl_exec(struct libxl_ctx *ctx, int stdinfd, int stdoutfd, int stderrfd,
+               char *arg0, char **args);
+
+#endif
+
diff -r 37829fd7c1e3 tools/libxl/libxl_utils.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/libxl_utils.c Mon Nov 09 13:44:46 2009 +0000
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2009      Citrix Ltd.
+ * Author Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
+ *
+ * This program 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; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program 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.
+ */
+
+#include "libxl_utils.h"
+#include "libxl_internal.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <xs.h>
+#include <xenctrl.h>
+#include <ctype.h>
+#include <errno.h>
+
+
+
+unsigned long libxl_get_required_shadow_memory(unsigned long maxmem_kb, 
unsigned int smp_cpus)
+{
+    /* 256 pages (1MB) per vcpu,
+       plus 1 page per MiB of RAM for the P2M map,
+       plus 1 page per MiB of RAM to shadow the resident processes.  
+       This is higher than the minimum that Xen would allocate if no value 
+       were given (but the Xen minimum is for safety, not performance).
+     */
+    return 4 * (256 * smp_cpus + 2 * (maxmem_kb / 1024));
+}
+
+char *libxl_domid_to_name(struct libxl_ctx *ctx, uint32_t domid)
+{
+    unsigned int len;
+    char path[strlen("/local/domain") + 12];
+    char *s;
+
+    snprintf(path, sizeof(path), "/local/domain/%d/name", domid);
+    s = xs_read(ctx->xsh, XBT_NULL, path, &len);
+    libxl_ptr_add(ctx, s);
+    return s;
+}
+
+int libxl_name_to_domid(struct libxl_ctx *ctx, char *name, uint32_t *domid)
+{
+    unsigned int num, len;
+    char path[strlen("/local/domain") + 12];
+    int i;
+    char *domname, **l;
+
+    l = xs_directory(ctx->xsh, XBT_NULL, "/local/domain", &num);
+    for (i = 0; i < num; i++) {
+        snprintf(path, sizeof(path), "/local/domain/%s/name", l[i]);
+        domname = xs_read(ctx->xsh, XBT_NULL, path, &len);
+        if (domname != NULL && !strncmp(domname, name, len)) {
+            *domid = atoi(l[i]);
+            free(l);
+            free(domname);
+            return 0;
+        }
+        free(domname);
+    }
+    free(l);
+    return -1;
+}
+
+int libxl_uuid_to_domid(struct libxl_ctx *ctx, uint8_t *uuid, uint32_t *domid)
+{
+    int nb_domain, i;
+    struct libxl_dominfo *info = libxl_domain_list(ctx, &nb_domain);
+    for (i = 0; i < nb_domain; i++) {
+        if (!memcmp(info[i].uuid, uuid, 16)) {
+            *domid = info[i].domid;
+            return 0;
+        }
+    }
+    return -1;
+}
+
+int libxl_domid_to_uuid(struct libxl_ctx *ctx, uint8_t **uuid, uint32_t domid)
+{
+    int nb_domain, i;
+    struct libxl_dominfo *info = libxl_domain_list(ctx, &nb_domain);
+    for (i = 0; i < nb_domain; i++) {
+        if (domid == info[i].domid) {
+            *uuid = libxl_zalloc(ctx, 16);
+            memcpy(*uuid, info[i].uuid, 16);
+            return 0;
+        }
+    }
+    return -1;
+}
+
+int libxl_is_uuid(char *s)
+{
+    int i;
+    if (!s || strlen(s) != 36)
+        return 0;
+    for (i = 0; i < 36; i++) {
+        if (i == 8 || i == 13 || i == 18 || i == 23) {
+            if (s[i] != '-')
+                return 0;
+        } else {
+            if (!isxdigit(s[i]))
+                return 0;
+        }
+    }
+    return 1;
+}
+
+uint8_t *string_to_uuid(struct libxl_ctx *ctx, char *s)
+{
+    uint8_t *buf;
+    if (!s || !ctx)
+        return NULL;
+    
+    buf = libxl_zalloc(ctx, 16);
+    sscanf(s, UUID_FMT, &buf[0], &buf[1], &buf[2], &buf[3], &buf[4], &buf[5],
+           &buf[6], &buf[7], &buf[8], &buf[9], &buf[10], &buf[11], &buf[12],
+           &buf[13], &buf[14], &buf[15]);
+    return buf;
+}
+
+char *uuid_to_string(struct libxl_ctx *ctx, uint8_t *uuid)
+{
+    if (!uuid)
+        return NULL;
+    return libxl_sprintf(ctx, UUID_FMT,
+                         uuid[0], uuid[1], uuid[2], uuid[3],
+                         uuid[4], uuid[5], uuid[6], uuid[7],
+                         uuid[8], uuid[9], uuid[10], uuid[11],
+                         uuid[12], uuid[13], uuid[14], uuid[15]);
+}
+
+int libxl_param_to_domid(struct libxl_ctx *ctx, char *p, uint32_t *domid)
+{
+    uint8_t *uuid;
+    uint32_t d;
+
+    if (libxl_is_uuid(p)) {
+        uuid = string_to_uuid(ctx, p);
+        return libxl_uuid_to_domid(ctx, uuid, domid);
+    }
+    errno = 0;
+    d = strtol(p, (char **) NULL, 10);
+    if (!errno && d != 0 && d != LONG_MAX && d != LONG_MIN) {
+        *domid = d;
+        return 0;
+    }
+    return libxl_name_to_domid(ctx, p, domid);
+}
diff -r 37829fd7c1e3 tools/libxl/libxl_utils.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/libxl_utils.h Mon Nov 09 13:44:46 2009 +0000
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2009      Citrix Ltd.
+ * Author Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
+ *
+ * This program 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; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program 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.
+ */
+
+#ifndef LIBXL_UTILS_H
+#define LIBXL_UTILS_H
+
+#include "libxl.h"
+
+#define UUID_FMT 
"%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
+
+unsigned long libxl_get_required_shadow_memory(unsigned long maxmem_kb, 
unsigned int smp_cpus);
+int libxl_name_to_domid(struct libxl_ctx *ctx, char *name, uint32_t *domid);
+char *libxl_domid_to_name(struct libxl_ctx *ctx, uint32_t domid);
+int libxl_uuid_to_domid(struct libxl_ctx *ctx, uint8_t *uuid, uint32_t *domid);
+int libxl_domid_to_uuid(struct libxl_ctx *ctx, uint8_t **uuid, uint32_t domid);
+int libxl_is_uuid(char *s);
+uint8_t *string_to_uuid(struct libxl_ctx *ctx, char *s);
+char *uuid_to_string(struct libxl_ctx *ctx, uint8_t *uuid);
+int libxl_param_to_domid(struct libxl_ctx *ctx, char *p, uint32_t *domid);
+
+#endif
+
diff -r 37829fd7c1e3 tools/libxl/libxl_xshelp.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/libxl_xshelp.c        Mon Nov 09 13:44:46 2009 +0000
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2009      Citrix Ltd.
+ * Author Vincent Hanquez <vincent.hanquez@xxxxxxxxxxxxx>
+ *
+ * This program 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; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program 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.
+ */
+
+#include <string.h>
+#include <stddef.h>
+#include "libxl.h"
+#include "libxl_internal.h"
+#include <stdio.h>
+#include <stdarg.h>
+
+char **libxl_xs_kvs_of_flexarray(struct libxl_ctx *ctx, flexarray_t *array, 
int length)
+{
+    char **kvs;
+    int i;
+
+    kvs = libxl_calloc(ctx, length + 2, sizeof(char *));
+    if (kvs) {
+        for (i = 0; i < length; i += 2) {
+            void *ptr;
+
+            flexarray_get(array, i, &ptr);
+            kvs[i] = (char *) ptr;
+            flexarray_get(array, i + 1, &ptr);
+            kvs[i + 1] = (char *) ptr;
+        }
+        kvs[i] = NULL;
+        kvs[i + 1] = NULL;
+    }
+    return kvs;
+}
+
+int libxl_xs_writev(struct libxl_ctx *ctx, xs_transaction_t t,
+                    char *dir, char *kvs[])
+{
+    char *path;
+    int i;
+
+    if (!kvs)
+        return 0;
+
+    for (i = 0; kvs[i] != NULL; i += 2) {
+        path = libxl_sprintf(ctx, "%s/%s", dir, kvs[i]);
+        if (path) {
+            int length = strlen(kvs[i + 1]);
+            xs_write(ctx->xsh, t, path, kvs[i + 1], length);
+        }
+        libxl_free(ctx, path);
+    }
+    return 0;
+}
+
+int libxl_xs_write(struct libxl_ctx *ctx, xs_transaction_t t,
+                   char *path, char *fmt, ...)
+{
+    char *s;
+    va_list ap;
+    int ret;
+    va_start(ap, fmt);
+    ret = vasprintf(&s, fmt, ap);
+    va_end(ap);
+
+    if (ret == -1) {
+        return -1;
+    }
+    xs_write(ctx->xsh, t, path, s, ret);
+    free(s);
+    return 0;
+}
+
+char * libxl_xs_read(struct libxl_ctx *ctx, xs_transaction_t t, char *path)
+{
+    unsigned int len;
+    char *ptr;
+    
+    ptr = xs_read(ctx->xsh, t, path, &len);
+    if (ptr != NULL) {
+        libxl_ptr_add(ctx, ptr);
+        return ptr;
+    }
+    return 0;
+}
+
+char *libxl_xs_get_dompath(struct libxl_ctx *ctx, uint32_t domid)
+{
+    char *s = xs_get_domain_path(ctx->xsh, domid);
+    libxl_ptr_add(ctx, s);
+    return s;
+}
+
+char **libxl_xs_directory(struct libxl_ctx *ctx, xs_transaction_t t, char 
*path, unsigned int *nb)
+{
+    char **ret = NULL;
+    ret = xs_directory(ctx->xsh, XBT_NULL, path, nb);
+    libxl_ptr_add(ctx, ret);
+    return ret;
+}
diff -r 37829fd7c1e3 tools/libxl/osdeps.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/osdeps.c      Mon Nov 09 13:44:46 2009 +0000
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2009      Citrix Ltd.
+ * Author Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
+ *
+ * This program 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; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program 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.
+ */
+
+#include <unistd.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <stdlib.h>
+
+int vasprintf(char **buffer, const char *fmt, va_list ap)
+{
+    int size = 0;
+    int nchars;
+
+    *buffer = 0;
+
+    nchars = vsnprintf(*buffer, 0, fmt, ap);
+
+    if (nchars >= size)
+    {
+        char *tmpbuff;
+        /* Reallocate buffer now that we know how much space is needed. */
+        size = nchars+1;
+        tmpbuff = (char*)realloc(*buffer, size);
+
+
+        if (tmpbuff == NULL) { /* we need to free it*/
+            free(*buffer);
+            return -1;
+        }
+
+        *buffer=tmpbuff;
+        /* Try again. */
+        nchars = vsnprintf(*buffer, size, fmt, ap);
+    }
+
+    if (nchars < 0) return nchars;
+    return size;
+}
+
+int asprintf(char **buffer, char *fmt, ...)
+{
+    int status;
+    va_list ap;
+
+    va_start (ap, fmt);
+    status = vasprintf (buffer, fmt, ap);
+    va_end (ap);
+    return status;
+}
diff -r 37829fd7c1e3 tools/libxl/osdeps.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/osdeps.h      Mon Nov 09 13:44:46 2009 +0000
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2009      Citrix Ltd.
+ * Author Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
+ *
+ * This program 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; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program 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.
+ */
+
+#ifndef LIBXL_OSDEP
+#define LIBXL_OSDEP
+
+#include <stdarg.h>
+
+int asprintf(char **buffer, char *fmt, ...);
+int vasprintf(char **buffer, const char *fmt, va_list ap);
+
+#endif
diff -r 37829fd7c1e3 tools/libxl/xenguest.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/xenguest.c    Mon Nov 09 13:44:46 2009 +0000
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2009      Citrix Ltd.
+ * Author Vincent Hanquez <vincent.hanquez@xxxxxxxxxxxxx>
+ *
+ * This program 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; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program 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.
+ */
+
+#include <xenctrl.h>
+#include <xenguest.h>
+#include <sys/mman.h>
+#include <xen/hvm/hvm_info_table.h>
+
+int hvm_build_set_params(int handle, uint32_t domid,
+                         int apic, int acpi, int pae, int nx, int viridian,
+                         int vcpus, int store_evtchn, unsigned long *store_mfn)
+{
+    struct hvm_info_table *va_hvm;
+    uint8_t *va_map, sum;
+    int i;
+
+    va_map = xc_map_foreign_range(handle, domid,
+                                  XC_PAGE_SIZE, PROT_READ | PROT_WRITE,
+                                  HVM_INFO_PFN);
+    if (va_map == NULL)
+        return -1;
+
+    va_hvm = (struct hvm_info_table *)(va_map + HVM_INFO_OFFSET);
+    va_hvm->acpi_enabled = acpi;
+    va_hvm->apic_mode = apic;
+    va_hvm->nr_vcpus = vcpus;
+    for (i = 0, sum = 0; i < va_hvm->length; i++)
+        sum += ((uint8_t *) va_hvm)[i];
+    va_hvm->checksum -= sum;
+    munmap(va_map, XC_PAGE_SIZE);
+
+    xc_get_hvm_param(handle, domid, HVM_PARAM_STORE_PFN, store_mfn);
+    xc_set_hvm_param(handle, domid, HVM_PARAM_PAE_ENABLED, pae);
+    xc_set_hvm_param(handle, domid, HVM_PARAM_VIRIDIAN, viridian);
+    xc_set_hvm_param(handle, domid, HVM_PARAM_STORE_EVTCHN, store_evtchn);
+    return 0;
+}
diff -r 37829fd7c1e3 tools/libxl/xl.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/xl.c  Mon Nov 09 13:44:46 2009 +0000
@@ -0,0 +1,727 @@
+/*
+ * Copyright (C) 2009      Citrix Ltd.
+ * Author Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
+ * Author Vincent Hanquez <vincent.hanquez@xxxxxxxxxxxxx>
+ *
+ * This program 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; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program 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.
+ */
+
+#include "libxl.h"
+#include "libxl_utils.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <uuid/uuid.h>
+#include <libconfig.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <xenctrl.h>
+
+void log_callback(void *userdata, int loglevel, const char *file, int line, 
const char *func, char *s)
+{
+    fprintf(stderr, "[%d] %s:%d:%s: %s\n", loglevel, file, line, func, s);
+}
+
+static void printf_info(libxl_domain_create_info *c_info,
+                        libxl_domain_build_info *b_info,
+                        libxl_device_disk *disks,
+                        int num_disks,
+                        libxl_device_nic *vifs,
+                        int num_vifs,
+                        libxl_device_model_info *dm_info)
+{
+    int i;
+    printf("*** domain_create_info ***\n");
+    printf("hvm: %d\n", c_info->hvm);
+    printf("hap: %d\n", c_info->hap);
+    printf("ssidref: %d\n", c_info->ssidref);
+    printf("name: %s\n", c_info->name);
+    printf("uuid: " UUID_FMT "\n", c_info->uuid[0], c_info->uuid[1], 
c_info->uuid[2], c_info->uuid[3],
+           c_info->uuid[4], c_info->uuid[5], c_info->uuid[6], c_info->uuid[7],
+           c_info->uuid[8], c_info->uuid[9], c_info->uuid[10], 
c_info->uuid[11],
+           c_info->uuid[12], c_info->uuid[13], c_info->uuid[14], 
c_info->uuid[15]);
+    if (c_info->xsdata)
+        printf("xsdata: contains data\n");
+    else
+        printf("xsdata: (null)\n");
+    if (c_info->platformdata)
+        printf("platformdata: contains data\n");
+    else
+        printf("platformdata: (null)\n");
+
+
+    printf("\n\n\n*** domain_build_info ***\n");
+    printf("timer_mode: %d\n", b_info->timer_mode);
+    printf("hpet: %d\n", b_info->hpet);
+    printf("vpt_align: %d\n", b_info->vpt_align);
+    printf("max_vcpus: %d\n", b_info->max_vcpus);
+    printf("max_memkb: %d\n", b_info->max_memkb);
+    printf("video_memkb: %d\n", b_info->video_memkb);
+    printf("shadow_memkb: %d\n", b_info->shadow_memkb);
+    printf("kernel: %s\n", b_info->kernel);
+    printf("hvm: %d\n", b_info->hvm);
+
+    if (b_info->hvm) {
+        printf("    pae: %d\n", b_info->u.hvm.pae);
+        printf("    apic: %d\n", b_info->u.hvm.apic);
+        printf("    acpi: %d\n", b_info->u.hvm.acpi);
+        printf("    nx: %d\n", b_info->u.hvm.nx);
+        printf("    viridian: %d\n", b_info->u.hvm.viridian);
+    } else {
+        printf("cmdline: %s\n", b_info->u.pv.cmdline);
+        printf("ramdisk: %s\n", b_info->u.pv.ramdisk);
+    }
+
+    for (i = 0; i < num_disks; i++) {
+        printf("\n\n\n*** disks_info: %d ***\n", i);
+        printf("backend_domid %d\n", disks[i].backend_domid);
+        printf("domid %d\n", disks[i].domid);
+        printf("physpath %s\n", disks[i].physpath);
+        printf("phystype %d\n", disks[i].phystype);
+        printf("virtpath %s\n", disks[i].virtpath);
+        printf("unpluggable %d\n", disks[i].unpluggable);
+        printf("readwrite %d\n", disks[i].readwrite);
+        printf("is_cdrom %d\n", disks[i].is_cdrom);
+    }
+
+    for (i = 0; i < num_vifs; i++) {
+        printf("\n\n\n*** vifs_info: %d ***\n", i);
+        printf("backend_domid %d\n", vifs[i].backend_domid);
+        printf("domid %d\n", vifs[i].domid);
+        printf("devid %d\n", vifs[i].devid);
+        printf("mtu %d\n", vifs[i].mtu);
+        printf("model %s\n", vifs[i].model);
+        printf("mac %02x:%02x:%02x:%02x:%02x:%02x\n", vifs[i].mac[0], 
vifs[i].mac[1], vifs[i].mac[2], vifs[i].mac[3], vifs[i].mac[4], vifs[i].mac[5]);
+        printf("smac %s\n", vifs[i].mac);
+    }
+
+    printf("\n\n\n*** device_model_info ***\n");
+    printf("domid: %d\n", dm_info->domid);
+    printf("dom_name: %s\n", dm_info->dom_name);
+    printf("device_model: %s\n", dm_info->device_model);
+    printf("videoram: %d\n", dm_info->videoram);
+    printf("stdvga: %d\n", dm_info->stdvga);
+    printf("vnc: %d\n", dm_info->vnc);
+    printf("vnclisten: %s\n", dm_info->vnclisten);
+    printf("vncdisplay: %d\n", dm_info->vncdisplay);
+    printf("vncunused: %d\n", dm_info->vncunused);
+    printf("keymap: %s\n", dm_info->keymap);
+    printf("sdl: %d\n", dm_info->sdl);
+    printf("opengl: %d\n", dm_info->opengl);
+    printf("nographic: %d\n", dm_info->nographic);
+    printf("serial: %s\n", dm_info->serial);
+    printf("boot: %s\n", dm_info->boot);
+    printf("usb: %d\n", dm_info->usb);
+    printf("usbdevice: %s\n", dm_info->usbdevice);
+    printf("apic: %d\n", dm_info->apic);
+}
+
+static char* compat_config_file(const char *filename)
+{
+    char t;
+    char *newfile = (char*) malloc(strlen(filename) + 4);
+    char *buf = (char *) malloc(2048);
+    int size = 2048, i;
+    FILE *s;
+    FILE *d;
+
+    sprintf(newfile, "%s.xl", filename);
+
+    s = fopen(filename, "r");
+    if (!s) {
+        perror("cannot open file for reading");
+        return NULL;
+    }
+    d = fopen(newfile, "w");
+    if (!d) {
+        fclose(s);
+        perror("cannot open file for writting");
+        return NULL;
+    }
+
+    while (!feof(s)) {
+        fgets(buf, size, s);
+        while (buf[strlen(buf) - 1] != '\n' && !feof(s)) {
+            size += 1024;
+            buf = realloc(buf, size + 1024);
+            fgets(buf + (size - 1025), 1025, s);
+        }
+        for (i = 0; i < strlen(buf); i++)
+            if (buf[i] == '\'')
+                buf[i] = '\"';
+        if (strchr(buf, '=') != NULL) {
+            if ((buf[strlen(buf) - 1] == '\n' && buf[strlen(buf) - 2] == ';') 
||
+                    buf[strlen(buf) - 1] == ';') {
+                fputs(buf, d);
+            } else {
+                t = buf[strlen(buf) - 1];
+                buf[strlen(buf) - 1] = ';';
+                fputs(buf, d);
+                fputc(t, d);
+            }
+        } else if (buf[0] == '#' || buf[0] == ' ' || buf[0] == '\n') {
+            fputs(buf, d);
+        }
+    }
+
+    fclose(s);
+    fclose(d);
+
+    free(buf);
+
+    return newfile;
+}
+
+void init_create_info(libxl_domain_create_info *c_info)
+{
+    memset(c_info, '\0', sizeof(*c_info));
+    c_info->xsdata = NULL;
+    c_info->platformdata = NULL;
+    c_info->hvm = 1;
+    c_info->ssidref = 0;
+}
+
+void init_build_info(libxl_domain_build_info *b_info, libxl_domain_create_info 
*c_info)
+{
+    memset(b_info, '\0', sizeof(*b_info));
+    b_info->timer_mode = -1;
+    b_info->hpet = 1;
+    b_info->vpt_align = -1;
+    b_info->max_vcpus = 1;
+    b_info->max_memkb = 32 * 1024;
+    b_info->shadow_memkb = libxl_get_required_shadow_memory(b_info->max_memkb, 
b_info->max_vcpus);
+    b_info->video_memkb = 8 * 1024;
+    b_info->kernel = "/usr/lib/xen/boot/hvmloader";
+    if (c_info->hvm) {
+        b_info->hvm = 1;
+        b_info->u.hvm.pae = 1;
+        b_info->u.hvm.apic = 1;
+        b_info->u.hvm.acpi = 1;
+        b_info->u.hvm.nx = 1;
+        b_info->u.hvm.viridian = 0;
+    }
+}
+
+void init_dm_info(libxl_device_model_info *dm_info,
+        libxl_domain_create_info *c_info, libxl_domain_build_info *b_info)
+{
+    memset(dm_info, '\0', sizeof(*dm_info));
+
+    dm_info->dom_name = c_info->name;
+    dm_info->device_model = "/usr/lib/xen/bin/qemu-dm";
+    dm_info->videoram = b_info->video_memkb / 1024;
+    dm_info->apic = b_info->u.hvm.apic;
+
+    dm_info->stdvga = 0;
+    dm_info->vnc = 1;
+    dm_info->vnclisten = "127.0.0.1";
+    dm_info->vncdisplay = 0;
+    dm_info->vncunused = 0;
+    dm_info->keymap = NULL;
+    dm_info->sdl = 0;
+    dm_info->opengl = 0;
+    dm_info->nographic = 0;
+    dm_info->serial = NULL;
+    dm_info->boot = "cda";
+    dm_info->usb = 0;
+    dm_info->usbdevice = NULL;
+}
+
+void init_nic_info(libxl_device_nic *nic_info, int devnum)
+{
+    memset(nic_info, '\0', sizeof(*nic_info));
+
+
+    nic_info->backend_domid = 0;
+    nic_info->domid = 0;
+    nic_info->devid = devnum;
+    nic_info->mtu = 1492;
+    nic_info->model = "e1000";
+    srand(time(0));
+    nic_info->mac[0] = 0x00; 
+    nic_info->mac[1] = 0x16;
+    nic_info->mac[2] = 0x3e;
+    nic_info->mac[3] = 1 + (int) (0x7f * (rand() / (RAND_MAX + 1.0)));
+    nic_info->mac[4] = 1 + (int) (0xff * (rand() / (RAND_MAX + 1.0)));
+    nic_info->mac[5] = 1 + (int) (0xff * (rand() / (RAND_MAX + 1.0)));
+    asprintf(&(nic_info->smac), "%02x:%02x:%02x:%02x:%02x:%02x", 
nic_info->mac[0], nic_info->mac[1], nic_info->mac[2], nic_info->mac[3], 
nic_info->mac[4], nic_info->mac[5]);
+    nic_info->ifname = NULL;
+    nic_info->bridge = "xenbr0";
+    nic_info->script = "/etc/xen/scripts/vif-bridge";
+    nic_info->nictype = NICTYPE_IOEMU;
+}
+
+void nic_info_domid_fixup(libxl_device_nic *nic_info, int domid)
+{
+    nic_info->domid = domid;
+    if (!nic_info->ifname)
+        asprintf(&(nic_info->ifname), "tap%d.%d", domid, nic_info->devid - 1);
+}
+
+void disk_info_domid_fixup(libxl_device_disk *disk_info, int domid)
+{
+    disk_info->domid = domid;
+}
+
+void device_model_info_domid_fixup(libxl_device_model_info *dm_info, int domid)
+{
+    dm_info->domid = domid;
+}
+
+static void parse_config_file(const char *filename,
+                              libxl_domain_create_info *c_info,
+                              libxl_domain_build_info *b_info,
+                              libxl_device_disk **disks,
+                              int *num_disks,
+                              libxl_device_nic **vifs,
+                              int *num_vifs,
+                              libxl_device_model_info *dm_info)
+{
+    const char *buf;
+    uint8_t uuid[16];
+    long l;
+    struct config_t config;
+    struct config_setting_t *vbds, *nics;
+
+    config_init (&config);
+
+    if (!config_read_file(&config, filename)) {
+        char *newfilename;
+        config_destroy(&config);
+        newfilename = compat_config_file(filename);
+        config_init (&config);
+        if (!config_read_file(&config, newfilename)) {
+            fprintf(stderr, "Failed to parse config file %s, try removing any 
embedded python code\n", config_error_text(&config));
+            exit(1);
+        }
+        free(newfilename);
+    }
+
+    init_create_info(c_info);
+
+    if (config_lookup_string (&config, "builder", &buf) == CONFIG_TRUE) {
+        if (!strncmp(buf, "hvm", strlen(buf)))
+            c_info->hvm = 1;
+        else
+            c_info->hvm = 0;
+    }
+
+    /* hap is missing */
+    if (config_lookup_string (&config, "name", &buf) == CONFIG_TRUE)
+        c_info->name = strdup(buf);
+    else
+        c_info->name = "test";
+    uuid_generate(uuid);
+    c_info->uuid = uuid;
+
+    init_build_info(b_info, c_info);
+
+    /* the following is the actual config parsing with overriding values in 
the structures */
+    if (config_lookup_int (&config, "vcpus", &l) == CONFIG_TRUE)
+        b_info->max_vcpus = l;
+
+    if (config_lookup_int (&config, "memory", &l) == CONFIG_TRUE)
+        b_info->max_memkb = l * 1024;
+
+    if (config_lookup_int (&config, "shadow_memory", &l) == CONFIG_TRUE)
+        b_info->shadow_memkb = l * 1024;
+
+    if (config_lookup_int (&config, "videoram", &l) == CONFIG_TRUE)
+        b_info->video_memkb = l * 1024;
+
+    if (config_lookup_string (&config, "kernel", &buf) == CONFIG_TRUE)
+        b_info->kernel = strdup(buf);
+
+    if (c_info->hvm == 1) {
+        if (config_lookup_int (&config, "pae", &l) == CONFIG_TRUE)
+            b_info->u.hvm.pae = l;
+        if (config_lookup_int (&config, "apic", &l) == CONFIG_TRUE)
+            b_info->u.hvm.apic = l;
+        if (config_lookup_int (&config, "acpi", &l) == CONFIG_TRUE)
+            b_info->u.hvm.acpi = l;
+        if (config_lookup_int (&config, "nx", &l) == CONFIG_TRUE)
+            b_info->u.hvm.nx = l;
+        if (config_lookup_int (&config, "viridian", &l) == CONFIG_TRUE)
+            b_info->u.hvm.viridian = l;
+    } else {
+        if (config_lookup_string (&config, "cmdline", &buf) == CONFIG_TRUE)
+            b_info->u.pv.cmdline = buf;
+        if (config_lookup_string (&config, "ramdisk", &buf) == CONFIG_TRUE)
+            b_info->u.pv.ramdisk = buf;
+    }
+
+    if ((vbds = config_lookup (&config, "disk")) != NULL) {
+        *num_disks = 0;
+        *disks = NULL;
+        while ((buf = config_setting_get_string_elem (vbds, *num_disks)) != 
NULL) {
+            char *buf2 = strdup(buf);
+            char *p, *p2;
+            *disks = (libxl_device_disk *) realloc(*disks, sizeof 
(libxl_device_disk) * ((*num_disks) + 1));
+            (*disks)[*num_disks].backend_domid = 0;
+            (*disks)[*num_disks].domid = 0;
+            (*disks)[*num_disks].unpluggable = 0;
+            p = strtok(buf2, ",:");
+            while (*p == ' ')
+                p++;
+            if (!strcmp(p, "phy")) {
+                (*disks)[*num_disks].phystype = PHYSTYPE_PHY;
+            } else if (!strcmp(p, "file")) {
+                (*disks)[*num_disks].phystype = PHYSTYPE_FILE;
+            } else if (!strcmp(p, "tap")) {
+                p = strtok(NULL, ":");
+                if (!strcmp(p, "aio")) {
+                    (*disks)[*num_disks].phystype = PHYSTYPE_AIO;
+                } else if (!strcmp(p, "vhd")) {
+                    (*disks)[*num_disks].phystype = PHYSTYPE_VHD;
+                } else if (!strcmp(p, "qcow")) {
+                    (*disks)[*num_disks].phystype = PHYSTYPE_QCOW;
+                } else if (!strcmp(p, "qcow2")) {
+                    (*disks)[*num_disks].phystype = PHYSTYPE_QCOW2;
+                }
+            }
+            p = strtok(NULL, ",");
+            while (*p == ' ')
+                p++;
+            (*disks)[*num_disks].physpath= strdup(p);
+            p = strtok(NULL, ",");
+            while (*p == ' ')
+                p++;
+            p2 = strchr(p, ':');
+            if (p2 == NULL) {
+                (*disks)[*num_disks].virtpath = strdup(p);
+                (*disks)[*num_disks].is_cdrom = 0;
+            } else {
+                *p2 = '\0';
+                (*disks)[*num_disks].virtpath = strdup(p);
+                if (!strcmp(p2 + 1, "cdrom"))
+                    (*disks)[*num_disks].is_cdrom = 1;
+                else
+                    (*disks)[*num_disks].is_cdrom = 0;
+            }
+            p = strtok(NULL, ",");
+            while (*p == ' ')
+                p++;
+            (*disks)[*num_disks].readwrite = (p[0] == 'w') ? 1 : 0;
+            free(buf2);
+            *num_disks = (*num_disks) + 1;
+        }
+    }
+
+    if ((nics = config_lookup (&config, "vif")) != NULL) {
+        *num_vifs = 0;
+        *vifs = NULL;
+        while ((buf = config_setting_get_string_elem (nics, *num_vifs)) != 
NULL) {
+            char *buf2 = strdup(buf);
+            char *p, *p2;
+            *vifs = (libxl_device_nic *) realloc(*vifs, sizeof 
(libxl_device_nic) * ((*num_vifs) + 1));
+            init_nic_info((*vifs) + (*num_vifs), (*num_vifs) + 1);
+            p = strtok(buf2, ",");
+            if (!p)
+                goto skip;
+            do {
+                while (*p == ' ')
+                    p++;
+                if ((p2 = strchr(p, '=')) == NULL)
+                    break;
+                *p2 = '\0';
+                if (!strcmp(p, "model")) {
+                    (*vifs)[*num_vifs].model = strdup(p2 + 1);
+                } else if (!strcmp(p, "mac")) {
+                    char *p3 = p2 + 1;
+                    (*vifs)[*num_vifs].smac = strdup(p3);
+                    *(p3 + 2) = '\0';
+                    (*vifs)[*num_vifs].mac[0] = strtol(p3, NULL, 16);
+                    p3 = p3 + 3;
+                    *(p3 + 2) = '\0';
+                    (*vifs)[*num_vifs].mac[1] = strtol(p3, NULL, 16);
+                    p3 = p3 + 3;
+                    *(p3 + 2) = '\0';
+                    (*vifs)[*num_vifs].mac[2] = strtol(p3, NULL, 16);
+                    p3 = p3 + 3;
+                    *(p3 + 2) = '\0';
+                    (*vifs)[*num_vifs].mac[3] = strtol(p3, NULL, 16);
+                    p3 = p3 + 3;
+                    *(p3 + 2) = '\0';
+                    (*vifs)[*num_vifs].mac[4] = strtol(p3, NULL, 16);
+                    p3 = p3 + 3;
+                    *(p3 + 2) = '\0';
+                    (*vifs)[*num_vifs].mac[5] = strtol(p3, NULL, 16);
+                } else if (!strcmp(p, "bridge")) {
+                    (*vifs)[*num_vifs].bridge = strdup(p2 + 1);
+                } else if (!strcmp(p, "type")) {
+                    if (!strcmp(p2 + 1, "ioemu"))
+                        (*vifs)[*num_vifs].nictype = NICTYPE_IOEMU;
+                    else
+                        (*vifs)[*num_vifs].nictype = NICTYPE_VIF;
+                } else if (!strcmp(p, "ip")) {
+                    inet_pton(AF_INET, p2 + 1, &((*vifs)[*num_vifs].ip));
+                } else if (!strcmp(p, "script")) {
+                    (*vifs)[*num_vifs].script = strdup(p2 + 1);
+                } else if (!strcmp(p, "vifname")) {
+                    (*vifs)[*num_vifs].ifname = strdup(p2 + 1);
+                } else if (!strcmp(p, "rate")) {
+                    fprintf(stderr, "the rate parameter for vifs is currently 
not supported\n");
+                } else if (!strcmp(p, "accel")) {
+                    fprintf(stderr, "the accel parameter for vifs is currently 
not supported\n");
+                }
+            } while ((p = strtok(NULL, ",")) != NULL);
+skip:
+            free(buf2);
+            *num_vifs = (*num_vifs) + 1;
+        }
+    }
+
+    /* init dm from c and b */
+    init_dm_info(dm_info, c_info, b_info);
+
+    /* then process config related to dm */
+    if (config_lookup_string (&config, "device_model", &buf) == CONFIG_TRUE)
+        dm_info->device_model = strdup(buf);
+    if (config_lookup_int (&config, "stdvga", &l) == CONFIG_TRUE)
+        dm_info->stdvga = l;
+    if (config_lookup_int (&config, "vnc", &l) == CONFIG_TRUE)
+        dm_info->vnc = l;
+    if (config_lookup_string (&config, "vnclisten", &buf) == CONFIG_TRUE)
+        dm_info->vnclisten = strdup(buf);
+    if (config_lookup_int (&config, "vncdisplay", &l) == CONFIG_TRUE)
+        dm_info->vncdisplay = l;
+    if (config_lookup_int (&config, "vncunused", &l) == CONFIG_TRUE)
+        dm_info->vncunused = l;
+    if (config_lookup_string (&config, "keymap", &buf) == CONFIG_TRUE)
+        dm_info->keymap = strdup(buf);
+    if (config_lookup_int (&config, "sdl", &l) == CONFIG_TRUE)
+        dm_info->sdl = l;
+    if (config_lookup_int (&config, "opengl", &l) == CONFIG_TRUE)
+        dm_info->opengl = l;
+    if (config_lookup_int (&config, "nographic", &l) == CONFIG_TRUE)
+        dm_info->nographic = l;
+    if (config_lookup_string (&config, "serial", &buf) == CONFIG_TRUE)
+        dm_info->serial = strdup(buf);
+    if (config_lookup_string (&config, "boot", &buf) == CONFIG_TRUE)
+        dm_info->boot = strdup(buf);
+    if (config_lookup_int (&config, "usb", &l) == CONFIG_TRUE)
+        dm_info->usb = l;
+    if (config_lookup_string (&config, "usbdevice", &buf) == CONFIG_TRUE)
+        dm_info->usbdevice = strdup(buf);
+
+    config_destroy(&config);
+}
+
+static void create_domain(int debug, const char *filename)
+{
+    struct libxl_ctx ctx;
+    uint32_t domid;
+    libxl_domain_create_info info1;
+    libxl_domain_build_info info2;
+    libxl_device_model_info dm_info;
+    libxl_device_disk *disks = NULL;
+    libxl_device_nic *vifs = NULL;
+    int num_disks = 0, num_vifs = 0;
+    int i;
+
+    printf("Parsing config file %s\n", filename);
+    parse_config_file(filename, &info1, &info2, &disks, &num_disks, &vifs, 
&num_vifs, &dm_info);
+    if (debug)
+        printf_info(&info1, &info2, disks, num_disks, vifs, num_vifs, 
&dm_info);
+
+    libxl_ctx_init(&ctx);
+    libxl_ctx_set_log(&ctx, log_callback, NULL);
+    libxl_domain_make(&ctx, &info1, &domid);
+    libxl_domain_build(&ctx, &info2, domid);
+
+    device_model_info_domid_fixup(&dm_info, domid);
+
+    for (i = 0; i < num_disks; i++) {
+        disk_info_domid_fixup(disks + i, domid);
+        libxl_device_disk_add(&ctx, domid, &disks[i]);
+    }
+    for (i = 0; i < num_vifs; i++) {
+        nic_info_domid_fixup(vifs + i, domid);
+        libxl_device_nic_add(&ctx, domid, &vifs[i]);
+    }
+    libxl_create_device_model(&ctx, &dm_info, vifs, num_vifs);
+    libxl_domain_unpause(&ctx, domid);
+
+}
+
+static void help(char *command)
+{
+    if (!command || !strcmp(command, "help")) {
+        printf("Usage xl <subcommand> [args]\n\n");
+        printf("xl full list of subcommands:\n\n");
+        printf(" create                                create a domain from 
config file <filename>\n\n");
+        printf(" list                          list information about all 
domains\n\n");
+        printf(" destroy                       terminate a domain 
immediately\n\n");
+    } else if(!strcmp(command, "create")) {
+        printf("Usage: xl create <ConfigFile> [options] [vars]\n\n");
+        printf("Create a domain based on <ConfigFile>.\n\n");
+        printf("Options:\n\n");
+        printf("-h                     Print this help.\n");
+        printf("-d                     Enable debug messages.\n");
+    } else if(!strcmp(command, "list")) {
+        printf("Usage: xl list [Domain]\n\n");
+        printf("List information about all/some domains.\n\n");
+    } else if(!strcmp(command, "destroy")) {
+        printf("Usage: xl destroy <Domain>\n\n");
+        printf("Terminate a domain immediately.\n\n");
+    }
+}
+
+void destroy_domain(char *p)
+{
+    struct libxl_ctx ctx;
+    uint32_t domid;
+
+    libxl_ctx_init(&ctx);
+    libxl_ctx_set_log(&ctx, log_callback, NULL);
+
+    if (libxl_param_to_domid(&ctx, p, &domid) < 0) {
+        fprintf(stderr, "%s is an invalid domain identifier\n", p);
+        exit(2);
+    }
+    libxl_domain_destroy(&ctx, domid, 0);
+}
+
+void list_domains(void)
+{
+    struct libxl_ctx ctx;
+    xc_dominfo_t *info;
+    int nb_domain, i;
+
+    libxl_ctx_init(&ctx);
+    libxl_ctx_set_log(&ctx, log_callback, NULL);
+
+    info = libxl_domain_infolist(&ctx, &nb_domain);
+
+    if (info < 0) {
+        fprintf(stderr, "libxl_domain_infolist failed.\n");
+        exit(1);
+    }
+    printf("Name                                        ID   Mem 
VCPUs\tState\tTime(s)\n");
+    for (i = 0; i < nb_domain; i++) {
+        printf("%-40s %5d %5lu %5d     %c%c%c%c%c%c %8.1f\n",
+                libxl_domid_to_name(&ctx, info[i].domid),
+                info[i].domid,
+                info[i].nr_pages * XC_PAGE_SIZE/(1024*1024),
+                info[i].nr_online_vcpus,
+                info[i].running ? 'r' : '-',
+                info[i].blocked ? 'b' : '-',
+                info[i].paused ? 'p' : '-',
+                info[i].shutdown ? 's' : '-',
+                info[i].crashed ? 'c' : '-',
+                info[i].dying ? 'd' : '-',
+                ((float)info[i].cpu_time / 1e9));
+    }
+}
+
+int main_destroy(int argc, char **argv)
+{
+    int opt;
+    char *p;
+
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("destroy");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+    if (optind >= argc) {
+        help("destroy");
+        exit(2);
+    }
+
+    p = argv[optind];
+
+    destroy_domain(p);
+    exit(0);
+}
+
+int main_list(int argc, char **argv)
+{
+    int opt;
+
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("list");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+
+    list_domains();
+    exit(0);
+}
+
+int main_create(int argc, char **argv)
+{
+    char *filename = NULL;
+    int debug = 0;
+    int opt;
+
+    while ((opt = getopt(argc, argv, "hd")) != -1) {
+        switch (opt) {
+        case 'd':
+            debug = 1;
+            break;
+        case 'h':
+            help("create");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+
+    if (optind >= argc) {
+        help("create");
+        exit(2);
+    }
+
+    filename = argv[optind];
+    create_domain(debug, filename);
+    exit(0);
+}
+
+int main(int argc, char **argv)
+{
+    if (argc < 2) {
+        help(NULL);
+        exit(1);
+    }
+
+    if (!strcmp(argv[1], "create")) {
+        main_create(argc - 1, argv + 1);
+    } else if (!strcmp(argv[1], "list")) {
+        main_list(argc - 1, argv + 1);
+    } else if (!strcmp(argv[1], "destroy")) {
+        main_destroy(argc - 1, argv + 1);
+    } else if (!strcmp(argv[1], "help")) {
+        if (argc > 2)
+            help(argv[2]);
+        else
+            help(NULL);
+        exit(0);
+    } else {
+        fprintf(stderr, "command not implemented\n");
+        exit(1);
+    }
+}
+

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

<Prev in Thread] Current Thread [Next in Thread>