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

[Xen-changelog] [xen-unstable] libxenlight: initial libxenlight implementation under tools/libxl



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1257796468 0
# Node ID 8a91056bea81b5caa8fbeea59094fbdb8d318d56
# Parent  9479190566fdd8c50af9f7b9d8aadb99d40f7472
libxenlight: initial libxenlight implementation under tools/libxl

Signed-off-by: Vincent Hanquez <Vincent.Hanquez@xxxxxxxxxxxxx>
Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
---
 tools/Makefile               |    1 
 tools/libxl/Makefile         |   72 ++++
 tools/libxl/flexarray.c      |   78 ++++
 tools/libxl/flexarray.h      |   33 +
 tools/libxl/libxl.c          |  742 +++++++++++++++++++++++++++++++++++++++++++
 tools/libxl/libxl.h          |  200 +++++++++++
 tools/libxl/libxl_device.c   |  241 +++++++++++++
 tools/libxl/libxl_dom.c      |  271 +++++++++++++++
 tools/libxl/libxl_exec.c     |   48 ++
 tools/libxl/libxl_internal.c |  159 +++++++++
 tools/libxl/libxl_internal.h |  135 +++++++
 tools/libxl/libxl_utils.c    |  159 +++++++++
 tools/libxl/libxl_utils.h    |   34 +
 tools/libxl/libxl_xshelp.c   |  108 ++++++
 tools/libxl/osdeps.c         |   62 +++
 tools/libxl/osdeps.h         |   24 +
 tools/libxl/xenguest.c       |   49 ++
 tools/libxl/xl.c             |  727 ++++++++++++++++++++++++++++++++++++++++++
 18 files changed, 3143 insertions(+)

diff -r 9479190566fd -r 8a91056bea81 tools/Makefile
--- a/tools/Makefile    Mon Nov 09 19:45:06 2009 +0000
+++ b/tools/Makefile    Mon Nov 09 19:54:28 2009 +0000
@@ -32,6 +32,7 @@ SUBDIRS-$(CONFIG_NetBSD) += fs-back
 SUBDIRS-$(CONFIG_NetBSD) += fs-back
 SUBDIRS-$(CONFIG_IOEMU) += ioemu-dir
 SUBDIRS-y += xenpmd
+SUBDIRS-y += libxl
 
 # These don't cross-compile
 ifeq ($(XEN_COMPILE_ARCH),$(XEN_TARGET_ARCH))
diff -r 9479190566fd -r 8a91056bea81 tools/libxl/Makefile
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/Makefile      Mon Nov 09 19:54:28 2009 +0000
@@ -0,0 +1,72 @@
+#
+# tools/libxl/Makefile
+#
+
+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) -f *.o *.so* *.a $(CLIENTS)
+       $(RM) -rf $(LIBCONFIG_SOURCE)
+
+distclean: clean
+       $(RM) -f $(LIBCONFIG_SOURCE).tar.gz
+
diff -r 9479190566fd -r 8a91056bea81 tools/libxl/flexarray.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/flexarray.c   Mon Nov 09 19:54:28 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 9479190566fd -r 8a91056bea81 tools/libxl/flexarray.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/flexarray.h   Mon Nov 09 19:54:28 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 9479190566fd -r 8a91056bea81 tools/libxl/libxl.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/libxl.c       Mon Nov 09 19:54:28 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 9479190566fd -r 8a91056bea81 tools/libxl/libxl.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/libxl.h       Mon Nov 09 19:54:28 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 9479190566fd -r 8a91056bea81 tools/libxl/libxl_device.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/libxl_device.c        Mon Nov 09 19:54:28 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 9479190566fd -r 8a91056bea81 tools/libxl/libxl_dom.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/libxl_dom.c   Mon Nov 09 19:54:28 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 9479190566fd -r 8a91056bea81 tools/libxl/libxl_exec.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/libxl_exec.c  Mon Nov 09 19:54:28 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 9479190566fd -r 8a91056bea81 tools/libxl/libxl_internal.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/libxl_internal.c      Mon Nov 09 19:54:28 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 9479190566fd -r 8a91056bea81 tools/libxl/libxl_internal.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/libxl_internal.h      Mon Nov 09 19:54:28 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 9479190566fd -r 8a91056bea81 tools/libxl/libxl_utils.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/libxl_utils.c Mon Nov 09 19:54:28 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 9479190566fd -r 8a91056bea81 tools/libxl/libxl_utils.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/libxl_utils.h Mon Nov 09 19:54:28 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 9479190566fd -r 8a91056bea81 tools/libxl/libxl_xshelp.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/libxl_xshelp.c        Mon Nov 09 19:54:28 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 9479190566fd -r 8a91056bea81 tools/libxl/osdeps.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/osdeps.c      Mon Nov 09 19:54:28 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 9479190566fd -r 8a91056bea81 tools/libxl/osdeps.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/osdeps.h      Mon Nov 09 19:54:28 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 9479190566fd -r 8a91056bea81 tools/libxl/xenguest.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/xenguest.c    Mon Nov 09 19:54:28 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 9479190566fd -r 8a91056bea81 tools/libxl/xl.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/xl.c  Mon Nov 09 19:54:28 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-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.