]> xenbits.xensource.com Git - libvirt.git/commitdiff
xenconfig: move contents to libxl driver and remove directory
authorJim Fehlig <jfehlig@suse.com>
Fri, 23 Aug 2019 18:34:46 +0000 (12:34 -0600)
committerJim Fehlig <jfehlig@suse.com>
Mon, 26 Aug 2019 17:06:12 +0000 (11:06 -0600)
After the legacy xen driver was removed the libxl driver became
the only consumer of xenconfig. Move the few files in xenconfig
to the libxl driver and remove the directory.

Signed-off-by: Jim Fehlig <jfehlig@suse.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
24 files changed:
cfg.mk
configure.ac
po/POTFILES
src/Makefile.am
src/libvirt_xenconfig.syms [deleted file]
src/libxl/Makefile.inc.am
src/libxl/xen_common.c [new file with mode: 0644]
src/libxl/xen_common.h [new file with mode: 0644]
src/libxl/xen_xl.c [new file with mode: 0644]
src/libxl/xen_xl.h [new file with mode: 0644]
src/libxl/xen_xm.c [new file with mode: 0644]
src/libxl/xen_xm.h [new file with mode: 0644]
src/libxl/xenxs_private.h [new file with mode: 0644]
src/xenapi/Makefile.inc.am
src/xenconfig/Makefile.inc.am [deleted file]
src/xenconfig/xen_common.c [deleted file]
src/xenconfig/xen_common.h [deleted file]
src/xenconfig/xen_xl.c [deleted file]
src/xenconfig/xen_xl.h [deleted file]
src/xenconfig/xen_xm.c [deleted file]
src/xenconfig/xen_xm.h [deleted file]
src/xenconfig/xenxs_private.h [deleted file]
tests/xlconfigtest.c
tests/xmconfigtest.c

diff --git a/cfg.mk b/cfg.mk
index c459ad443fe4caf3f51aad41eef36bf1ba9ad669..1f29729949b75e45c7d96262e22294079b82b9c7 100644 (file)
--- a/cfg.mk
+++ b/cfg.mk
@@ -791,7 +791,7 @@ sc_prohibit_cross_inclusion:
            access/ | conf/) safe="($$dir|conf|util)";; \
            cpu/| network/| node_device/| rpc/| security/| storage/) \
              safe="($$dir|util|conf|storage)";; \
-           xenapi/ | xenconfig/ ) safe="($$dir|util|conf|xen|cpu)";; \
+           xenapi/) safe="($$dir|util|conf|xen|cpu)";; \
            *) safe="($$dir|$(mid_dirs)|util)";; \
          esac; \
          in_vc_files="^src/$$dir" \
index a60543072dbb3a212cc1906de9cee6aa72a82b0f..890702a89d7f485aee993238254cacef0f7da8d9 100644 (file)
@@ -465,8 +465,6 @@ LIBVIRT_DRIVER_CHECK_LIBVIRTD
 LIBVIRT_DRIVER_CHECK_NETWORK
 LIBVIRT_DRIVER_CHECK_INTERFACE
 
-AM_CONDITIONAL([WITH_XENCONFIG], [test "$with_libxl" = "yes"])
-
 
 dnl
 dnl in case someone want to build static binaries
index c62bc32bb291e3f8c7cc8ba86d8234713cc5d121..e466e1bc553b64c3919e7d402bb152dd429d7346 100644 (file)
@@ -88,6 +88,9 @@ src/libxl/libxl_conf.c
 src/libxl/libxl_domain.c
 src/libxl/libxl_driver.c
 src/libxl/libxl_migration.c
+src/libxl/xen_common.c
+src/libxl/xen_xl.c
+src/libxl/xen_xm.c
 src/locking/lock_daemon.c
 src/locking/lock_daemon_dispatch.c
 src/locking/lock_driver_lockd.c
@@ -291,9 +294,6 @@ src/vz/vz_utils.c
 src/vz/vz_utils.h
 src/xenapi/xenapi_driver.c
 src/xenapi/xenapi_utils.c
-src/xenconfig/xen_common.c
-src/xenconfig/xen_xl.c
-src/xenconfig/xen_xm.c
 tests/virpolkittest.c
 tools/libvirt-guests.sh.in
 tools/virsh-checkpoint.c
index adaf61350a441b5bc903b5327ae88fbf6da9cb31..6626659113017ce437615a54400e1774fc067522 100644 (file)
@@ -118,7 +118,6 @@ include vbox/Makefile.inc.am
 include openvz/Makefile.inc.am
 include qemu/Makefile.inc.am
 include bhyve/Makefile.inc.am
-include xenconfig/Makefile.inc.am
 include libxl/Makefile.inc.am
 include xenapi/Makefile.inc.am
 include vz/Makefile.inc.am
diff --git a/src/libvirt_xenconfig.syms b/src/libvirt_xenconfig.syms
deleted file mode 100644 (file)
index 6e2e578..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#
-# These symbols are dependent upon --with-xen via WITH_XEN or --with-libxl via WITH_LIBXL.
-#
-
-# xenconfig/xen_xm.h
-xenFormatXM;
-xenParseXM;
-
-# Let emacs know we want case-insensitive sorting
-# Local Variables:
-# sort-fold-case: t
-# End:
index 1587404586b9e62ca3541a0a607ef6441ca8d321..560b214877a19527c1293949236c6bcc208024b6 100644 (file)
@@ -1,6 +1,13 @@
 # vim: filetype=automake
 
 LIBXL_DRIVER_SOURCES = \
+       libxl/xenxs_private.h \
+       libxl/xen_common.c \
+       libxl/xen_common.h \
+       libxl/xen_xl.c \
+       libxl/xen_xl.h \
+       libxl/xen_xm.c \
+       libxl/xen_xm.h \
        libxl/libxl_conf.c \
        libxl/libxl_conf.h \
        libxl/libxl_capabilities.c \
@@ -15,29 +22,13 @@ LIBXL_DRIVER_SOURCES = \
        libxl/libxl_migration.h \
        $(NULL)
 
-XENCONFIG_LIBXL_SOURCES = \
-       $(XENCONFIG_SOURCES) \
-       xenconfig/xen_xl.c \
-       xenconfig/xen_xl.h \
-       $(NULL)
-
 DRIVER_SOURCE_FILES += $(LIBXL_DRIVER_SOURCES)
 STATEFUL_DRIVER_SOURCE_FILES += $(LIBXL_DRIVER_SOURCES)
 EXTRA_DIST += \
        $(LIBXL_DRIVER_SOURCES) \
-       $(XENCONFIG_LIBXL_SOURCES) \
        $(NULL)
 
 if WITH_LIBXL
-noinst_LTLIBRARIES += libvirt_xenconfig_libxl.la
-libvirt_xenconfig_libxl_la_LIBADD = $(LIBXL_LIBS)
-libvirt_xenconfig_libxl_la_CFLAGS = \
-       -I$(srcdir)/conf \
-       -I$(srcdir)/libxl \
-       $(AM_CFLAGS) \
-       $(NULL)
-libvirt_xenconfig_libxl_la_SOURCES = $(XENCONFIG_LIBXL_SOURCES)
-
 noinst_LTLIBRARIES += libvirt_driver_libxl_impl.la
 libvirt_driver_libxl_la_SOURCES =
 libvirt_driver_libxl_la_LIBADD = \
@@ -54,14 +45,12 @@ libvirt_driver_libxl_impl_la_CFLAGS = \
        -I$(srcdir)/access \
        -I$(srcdir)/conf \
        -I$(srcdir)/secret \
-       -I$(srcdir)/xenconfig \
        $(AM_CFLAGS) \
        $(NULL)
 libvirt_driver_libxl_impl_la_LDFLAGS = $(AM_LDFLAGS)
 libvirt_driver_libxl_impl_la_LIBADD = \
        $(LIBXL_LIBS) \
        $(LIBXML_LIBS) \
-       libvirt_xenconfig_libxl.la \
        $(NULL)
 libvirt_driver_libxl_impl_la_SOURCES = $(LIBXL_DRIVER_SOURCES)
 
diff --git a/src/libxl/xen_common.c b/src/libxl/xen_common.c
new file mode 100644 (file)
index 0000000..7eb52c8
--- /dev/null
@@ -0,0 +1,2521 @@
+/*
+ * xen_common.c: Parsing and formatting functions for config common
+ * between XM and XL
+ *
+ * Copyright (C) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany.
+ * Copyright (C) 2006-2007, 2009-2016 Red Hat, Inc.
+ * Copyright (C) 2011 Univention GmbH
+ * Copyright (C) 2006 Daniel P. Berrange
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include <regex.h>
+
+#include "internal.h"
+#include "virerror.h"
+#include "virconf.h"
+#include "viralloc.h"
+#include "viruuid.h"
+#include "count-one-bits.h"
+#include "xenxs_private.h"
+#include "domain_conf.h"
+#include "virstring.h"
+#include "xen_common.h"
+
+#define VIR_FROM_THIS VIR_FROM_XEN
+
+/*
+ * Convenience method to grab a long int from the config file object
+ */
+int
+xenConfigGetBool(virConfPtr conf,
+                 const char *name,
+                 int *value,
+                 int def)
+{
+    virConfValuePtr val;
+
+    *value = 0;
+    if (!(val = virConfGetValue(conf, name))) {
+        *value = def;
+        return 0;
+    }
+
+    if (val->type == VIR_CONF_ULLONG) {
+        *value = val->l ? 1 : 0;
+    } else if (val->type == VIR_CONF_STRING) {
+        *value = STREQ(val->str, "1") ? 1 : 0;
+    } else {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("config value %s was malformed"), name);
+        return -1;
+    }
+    return 0;
+}
+
+
+/*
+ * Convenience method to grab a int from the config file object
+ */
+int
+xenConfigGetULong(virConfPtr conf,
+                  const char *name,
+                  unsigned long *value,
+                  unsigned long def)
+{
+    virConfValuePtr val;
+
+    *value = 0;
+    if (!(val = virConfGetValue(conf, name))) {
+        *value = def;
+        return 0;
+    }
+
+    if (val->type == VIR_CONF_ULLONG) {
+        *value = val->l;
+    } else if (val->type == VIR_CONF_STRING) {
+        if (virStrToLong_ul(val->str, NULL, 10, value) < 0) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("config value %s was malformed"), name);
+            return -1;
+        }
+    } else {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("config value %s was malformed"), name);
+        return -1;
+    }
+    return 0;
+}
+
+
+/*
+ * Convenience method to grab a int from the config file object
+ */
+static int
+xenConfigGetULongLong(virConfPtr conf,
+                      const char *name,
+                      unsigned long long *value,
+                      unsigned long long def)
+{
+    virConfValuePtr val;
+
+    *value = 0;
+    if (!(val = virConfGetValue(conf, name))) {
+        *value = def;
+        return 0;
+    }
+
+    if (val->type == VIR_CONF_ULLONG) {
+        *value = val->l;
+    } else if (val->type == VIR_CONF_STRING) {
+        if (virStrToLong_ull(val->str, NULL, 10, value) < 0) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("config value %s was malformed"), name);
+            return -1;
+        }
+    } else {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("config value %s was malformed"), name);
+        return -1;
+    }
+    return 0;
+}
+
+
+static int
+xenConfigCopyStringInternal(virConfPtr conf,
+                            const char *name,
+                            char **value,
+                            int allowMissing)
+{
+    int rc;
+
+    *value = NULL;
+    if ((rc = virConfGetValueString(conf, name, value)) < 0)
+        return -1;
+
+    if (rc == 0) {
+        if (allowMissing)
+            return 0;
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("config value %s was missing"), name);
+        return -1;
+    }
+
+    return 1;
+}
+
+
+int
+xenConfigCopyString(virConfPtr conf, const char *name, char **value)
+{
+    return xenConfigCopyStringInternal(conf, name, value, 0);
+}
+
+
+int
+xenConfigCopyStringOpt(virConfPtr conf, const char *name, char **value)
+{
+    return xenConfigCopyStringInternal(conf, name, value, 1);
+}
+
+
+/*
+ * Convenience method to grab a string UUID from the config file object
+ */
+static int
+xenConfigGetUUID(virConfPtr conf, const char *name, unsigned char *uuid)
+{
+    VIR_AUTOFREE(char *) string = NULL;
+    int rc;
+
+    if (!uuid || !name || !conf) {
+        virReportError(VIR_ERR_INVALID_ARG, "%s",
+                       _("Arguments must be non null"));
+        return -1;
+    }
+
+
+    if ((rc = virConfGetValueString(conf, name, &string)) < 0)
+        return -1;
+
+    if (rc == 0) {
+        if (virUUIDGenerate(uuid) < 0) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           "%s", _("Failed to generate UUID"));
+            return -1;
+        } else {
+            return 0;
+        }
+    }
+
+    if (!string) {
+        virReportError(VIR_ERR_CONF_SYNTAX,
+                       _("%s can't be empty"), name);
+        return -1;
+    }
+
+    if (virUUIDParse(string, uuid) < 0) {
+        virReportError(VIR_ERR_CONF_SYNTAX,
+                       _("%s not parseable"), string);
+        return -1;
+    }
+
+    return 0;
+}
+
+
+/*
+ * Convenience method to grab a string from the config file object
+ */
+int
+xenConfigGetString(virConfPtr conf,
+                   const char *name,
+                   char **value,
+                   const char *def)
+{
+    char *string = NULL;
+    int rc;
+
+    *value = NULL;
+    if ((rc = virConfGetValueString(conf, name, &string)) < 0)
+        return -1;
+
+    if (rc == 0 || !string) {
+        if (VIR_STRDUP(*value, def) < 0)
+            return -1;
+    } else {
+        *value = string;
+    }
+
+    return 0;
+}
+
+
+int
+xenConfigSetInt(virConfPtr conf, const char *setting, long long l)
+{
+    virConfValuePtr value = NULL;
+
+    if ((long)l != l) {
+        virReportError(VIR_ERR_OVERFLOW, _("failed to store %lld to %s"),
+                       l, setting);
+        return -1;
+    }
+    if (VIR_ALLOC(value) < 0)
+        return -1;
+
+    value->type = VIR_CONF_LLONG;
+    value->next = NULL;
+    value->l = l;
+
+    return virConfSetValue(conf, setting, value);
+}
+
+
+int
+xenConfigSetString(virConfPtr conf, const char *setting, const char *str)
+{
+    virConfValuePtr value = NULL;
+
+    if (VIR_ALLOC(value) < 0)
+        return -1;
+
+    value->type = VIR_CONF_STRING;
+    value->next = NULL;
+    if (VIR_STRDUP(value->str, str) < 0) {
+        VIR_FREE(value);
+        return -1;
+    }
+
+    return virConfSetValue(conf, setting, value);
+}
+
+
+static int
+xenParseMem(virConfPtr conf, virDomainDefPtr def)
+{
+    unsigned long long memory;
+
+    if (xenConfigGetULongLong(conf, "memory", &def->mem.cur_balloon,
+                                MIN_XEN_GUEST_SIZE * 2) < 0)
+        return -1;
+
+    if (xenConfigGetULongLong(conf, "maxmem", &memory,
+                                def->mem.cur_balloon) < 0)
+        return -1;
+
+    def->mem.cur_balloon *= 1024;
+    virDomainDefSetMemoryTotal(def, memory * 1024);
+
+    return 0;
+}
+
+
+static int
+xenParseTimeOffset(virConfPtr conf, virDomainDefPtr def)
+{
+    int vmlocaltime;
+
+    if (xenConfigGetBool(conf, "localtime", &vmlocaltime, 0) < 0)
+        return -1;
+
+    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
+        unsigned long rtc_timeoffset;
+        def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_VARIABLE;
+        if (xenConfigGetULong(conf, "rtc_timeoffset", &rtc_timeoffset, 0) < 0)
+            return -1;
+
+        def->clock.data.variable.adjustment = (int)rtc_timeoffset;
+        def->clock.data.variable.basis = vmlocaltime ?
+            VIR_DOMAIN_CLOCK_BASIS_LOCALTIME :
+            VIR_DOMAIN_CLOCK_BASIS_UTC;
+    } else {
+        /* PV domains do not have an emulated RTC and the offset is fixed. */
+        def->clock.offset = vmlocaltime ?
+            VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME :
+            VIR_DOMAIN_CLOCK_OFFSET_UTC;
+        def->clock.data.utc_reset = true;
+    } /* !hvm */
+
+    return 0;
+}
+
+
+static int
+xenParseEventsActions(virConfPtr conf, virDomainDefPtr def)
+{
+    VIR_AUTOFREE(char *) on_poweroff = NULL;
+    VIR_AUTOFREE(char *) on_reboot = NULL;
+    VIR_AUTOFREE(char *) on_crash = NULL;
+
+    if (xenConfigGetString(conf, "on_poweroff", &on_poweroff, "destroy") < 0)
+        return -1;
+
+    if ((def->onPoweroff = virDomainLifecycleActionTypeFromString(on_poweroff)) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("unexpected value %s for on_poweroff"), on_poweroff);
+        return -1;
+    }
+
+    if (xenConfigGetString(conf, "on_reboot", &on_reboot, "restart") < 0)
+        return -1;
+
+    if ((def->onReboot = virDomainLifecycleActionTypeFromString(on_reboot)) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("unexpected value %s for on_reboot"), on_reboot);
+        return -1;
+    }
+
+    if (xenConfigGetString(conf, "on_crash", &on_crash, "restart") < 0)
+        return -1;
+
+    if ((def->onCrash = virDomainLifecycleActionTypeFromString(on_crash)) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("unexpected value %s for on_crash"), on_crash);
+        return -1;
+    }
+
+    return 0;
+}
+
+
+static virDomainHostdevDefPtr
+xenParsePCI(char *entry)
+{
+    virDomainHostdevDefPtr hostdev = NULL;
+    char domain[5];
+    char bus[3];
+    char slot[3];
+    char func[2];
+    char *key, *nextkey;
+    int domainID;
+    int busID;
+    int slotID;
+    int funcID;
+
+    domain[0] = bus[0] = slot[0] = func[0] = '\0';
+
+    /* pci=['0000:00:1b.0','0000:00:13.0'] */
+    if (!(key = entry))
+        return NULL;
+    if (!(nextkey = strchr(key, ':')))
+        return NULL;
+    if (virStrncpy(domain, key, (nextkey - key), sizeof(domain)) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Domain %s too big for destination"), key);
+        return NULL;
+    }
+
+    key = nextkey + 1;
+    if (!(nextkey = strchr(key, ':')))
+        return NULL;
+    if (virStrncpy(bus, key, (nextkey - key), sizeof(bus)) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Bus %s too big for destination"), key);
+        return NULL;
+    }
+
+    key = nextkey + 1;
+    if (!(nextkey = strchr(key, '.')))
+        return NULL;
+    if (virStrncpy(slot, key, (nextkey - key), sizeof(slot)) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Slot %s too big for destination"), key);
+        return NULL;
+    }
+
+    key = nextkey + 1;
+    if (strlen(key) != 1)
+        return NULL;
+    if (virStrncpy(func, key, 1, sizeof(func)) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Function %s too big for destination"), key);
+        return NULL;
+    }
+
+    if (virStrToLong_i(domain, NULL, 16, &domainID) < 0)
+        return NULL;
+    if (virStrToLong_i(bus, NULL, 16, &busID) < 0)
+        return NULL;
+    if (virStrToLong_i(slot, NULL, 16, &slotID) < 0)
+        return NULL;
+    if (virStrToLong_i(func, NULL, 16, &funcID) < 0)
+        return NULL;
+
+    if (!(hostdev = virDomainHostdevDefNew()))
+       return NULL;
+
+    hostdev->managed = false;
+    hostdev->source.subsys.type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI;
+    hostdev->source.subsys.u.pci.addr.domain = domainID;
+    hostdev->source.subsys.u.pci.addr.bus = busID;
+    hostdev->source.subsys.u.pci.addr.slot = slotID;
+    hostdev->source.subsys.u.pci.addr.function = funcID;
+
+    return hostdev;
+}
+
+
+static int
+xenHandleConfGetValueStringListErrors(int ret)
+{
+    if (ret < 0) {
+        /* It means virConfGetValueStringList() didn't fail because the
+         * cval->type switch fell through - since we're passing
+         * @compatString == false - assumes failures for memory allocation
+         * and VIR_CONF_LIST traversal failure should cause -1 to be
+         * returned to the caller with the error message set. */
+        if (virGetLastErrorCode() != VIR_ERR_INTERNAL_ERROR)
+            return -1;
+
+        /* If we did fall through the switch, then ignore and clear the
+         * last error. */
+        virResetLastError();
+    }
+    return 0;
+}
+
+
+static int
+xenParsePCIList(virConfPtr conf, virDomainDefPtr def)
+{
+    VIR_AUTOSTRINGLIST pcis = NULL;
+    char **entries = NULL;
+    int rc;
+
+    if ((rc = virConfGetValueStringList(conf, "pci", false, &pcis)) <= 0)
+        return xenHandleConfGetValueStringListErrors(rc);
+
+    for (entries = pcis; *entries; entries++) {
+        char *entry = *entries;
+        virDomainHostdevDefPtr hostdev;
+
+        if (!(hostdev = xenParsePCI(entry)))
+            return -1;
+
+        if (VIR_APPEND_ELEMENT(def->hostdevs, def->nhostdevs, hostdev) < 0) {
+            virDomainHostdevDefFree(hostdev);
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+
+static int
+xenParseCPUFeatures(virConfPtr conf,
+                    virDomainDefPtr def,
+                    virDomainXMLOptionPtr xmlopt)
+{
+    unsigned long count = 0;
+    VIR_AUTOFREE(char *) cpus = NULL;
+    VIR_AUTOFREE(char *) tsc_mode = NULL;
+    int val = 0;
+    virDomainTimerDefPtr timer;
+
+    if (xenConfigGetULong(conf, "vcpus", &count, 1) < 0)
+        return -1;
+
+    if (virDomainDefSetVcpusMax(def, count, xmlopt) < 0)
+        return -1;
+
+    if (virDomainDefSetVcpus(def, count) < 0)
+        return -1;
+
+    if (virConfGetValue(conf, "maxvcpus")) {
+        if (xenConfigGetULong(conf, "maxvcpus", &count, 0) < 0)
+            return -1;
+
+        if (virDomainDefSetVcpusMax(def, count, xmlopt) < 0)
+            return -1;
+    }
+
+    if (xenConfigGetString(conf, "cpus", &cpus, NULL) < 0)
+        return -1;
+
+    if (cpus && (virBitmapParse(cpus, &def->cpumask, 4096) < 0))
+        return -1;
+
+    if (xenConfigGetString(conf, "tsc_mode", &tsc_mode, NULL) < 0)
+        return -1;
+
+    if (tsc_mode) {
+        if (VIR_EXPAND_N(def->clock.timers, def->clock.ntimers, 1) < 0 ||
+            VIR_ALLOC(timer) < 0)
+            return -1;
+
+        timer->name = VIR_DOMAIN_TIMER_NAME_TSC;
+        timer->present = 1;
+        timer->tickpolicy = -1;
+        timer->mode = VIR_DOMAIN_TIMER_MODE_AUTO;
+        timer->track = -1;
+        if (STREQ_NULLABLE(tsc_mode, "always_emulate"))
+            timer->mode = VIR_DOMAIN_TIMER_MODE_EMULATE;
+        else if (STREQ_NULLABLE(tsc_mode, "native"))
+            timer->mode = VIR_DOMAIN_TIMER_MODE_NATIVE;
+        else if (STREQ_NULLABLE(tsc_mode, "native_paravirt"))
+            timer->mode = VIR_DOMAIN_TIMER_MODE_PARAVIRT;
+
+        def->clock.timers[def->clock.ntimers - 1] = timer;
+    }
+
+    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
+        if (xenConfigGetBool(conf, "pae", &val, 1) < 0)
+            return -1;
+
+        else if (val)
+            def->features[VIR_DOMAIN_FEATURE_PAE] = VIR_TRISTATE_SWITCH_ON;
+        if (xenConfigGetBool(conf, "acpi", &val, 1) < 0)
+            return -1;
+
+        else if (val)
+            def->features[VIR_DOMAIN_FEATURE_ACPI] = VIR_TRISTATE_SWITCH_ON;
+        if (xenConfigGetBool(conf, "apic", &val, 1) < 0)
+            return -1;
+
+        else if (val)
+            def->features[VIR_DOMAIN_FEATURE_APIC] = VIR_TRISTATE_SWITCH_ON;
+        if (xenConfigGetBool(conf, "hap", &val, 1) < 0)
+            return -1;
+
+        else if (!val)
+            def->features[VIR_DOMAIN_FEATURE_HAP] = VIR_TRISTATE_SWITCH_OFF;
+        if (xenConfigGetBool(conf, "viridian", &val, 0) < 0)
+            return -1;
+
+        else if (val)
+            def->features[VIR_DOMAIN_FEATURE_VIRIDIAN] = VIR_TRISTATE_SWITCH_ON;
+
+        if (xenConfigGetBool(conf, "hpet", &val, -1) < 0)
+            return -1;
+
+        if (val != -1) {
+            if (VIR_EXPAND_N(def->clock.timers, def->clock.ntimers, 1) < 0 ||
+                VIR_ALLOC(timer) < 0)
+                return -1;
+
+            timer->name = VIR_DOMAIN_TIMER_NAME_HPET;
+            timer->present = val;
+            timer->tickpolicy = -1;
+            timer->mode = -1;
+            timer->track = -1;
+
+            def->clock.timers[def->clock.ntimers - 1] = timer;
+        }
+    }
+
+    return 0;
+}
+
+
+#define MAX_VFB 1024
+
+static int
+xenParseVfb(virConfPtr conf, virDomainDefPtr def)
+{
+    int val;
+    char *listenAddr = NULL;
+    int hvm = def->os.type == VIR_DOMAIN_OSTYPE_HVM;
+    virDomainGraphicsDefPtr graphics = NULL;
+
+    if (hvm) {
+        if (xenConfigGetBool(conf, "vnc", &val, 0) < 0)
+            goto cleanup;
+        if (val) {
+            if (VIR_ALLOC(graphics) < 0)
+                goto cleanup;
+            graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_VNC;
+            if (xenConfigGetBool(conf, "vncunused", &val, 1) < 0)
+                goto cleanup;
+            graphics->data.vnc.autoport = val ? 1 : 0;
+            if (!graphics->data.vnc.autoport) {
+                unsigned long vncdisplay;
+                if (xenConfigGetULong(conf, "vncdisplay", &vncdisplay, 0) < 0)
+                    goto cleanup;
+                graphics->data.vnc.port = (int)vncdisplay + 5900;
+            }
+
+            if (xenConfigCopyStringOpt(conf, "vnclisten", &listenAddr) < 0)
+                goto cleanup;
+            if (virDomainGraphicsListenAppendAddress(graphics, listenAddr) < 0)
+                goto cleanup;
+            VIR_FREE(listenAddr);
+
+            if (xenConfigCopyStringOpt(conf, "vncpasswd", &graphics->data.vnc.auth.passwd) < 0)
+                goto cleanup;
+            if (xenConfigCopyStringOpt(conf, "keymap", &graphics->data.vnc.keymap) < 0)
+                goto cleanup;
+            if (VIR_ALLOC_N(def->graphics, 1) < 0)
+                goto cleanup;
+            def->graphics[0] = graphics;
+            def->ngraphics = 1;
+            graphics = NULL;
+        } else {
+            if (xenConfigGetBool(conf, "sdl", &val, 0) < 0)
+                goto cleanup;
+            if (val) {
+                if (VIR_ALLOC(graphics) < 0)
+                    goto cleanup;
+                graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_SDL;
+                if (xenConfigCopyStringOpt(conf, "display", &graphics->data.sdl.display) < 0)
+                    goto cleanup;
+                if (xenConfigCopyStringOpt(conf, "xauthority", &graphics->data.sdl.xauth) < 0)
+                    goto cleanup;
+                if (VIR_ALLOC_N(def->graphics, 1) < 0)
+                    goto cleanup;
+                def->graphics[0] = graphics;
+                def->ngraphics = 1;
+                graphics = NULL;
+            }
+        }
+    }
+
+    if (!hvm && def->graphics == NULL) { /* New PV guests use this format */
+        VIR_AUTOSTRINGLIST vfbs = NULL;
+        int rc;
+
+        if ((rc = virConfGetValueStringList(conf, "vfb", false, &vfbs)) == 1) {
+            char vfb[MAX_VFB];
+            char *key = vfb;
+
+            if (virStrcpyStatic(vfb, *vfbs) < 0) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("VFB %s too big for destination"),
+                               *vfbs);
+                goto cleanup;
+            }
+
+            if (VIR_ALLOC(graphics) < 0)
+                goto cleanup;
+            if (strstr(key, "type=sdl"))
+                graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_SDL;
+            else
+                graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_VNC;
+            while (key) {
+                char *nextkey = strchr(key, ',');
+                char *end = nextkey;
+                if (nextkey) {
+                    *end = '\0';
+                    nextkey++;
+                }
+
+                if (!strchr(key, '='))
+                    break;
+                if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
+                    if (STRPREFIX(key, "vncunused=")) {
+                        if (STREQ(key + 10, "1"))
+                            graphics->data.vnc.autoport = true;
+                    } else if (STRPREFIX(key, "vnclisten=")) {
+                        if (VIR_STRDUP(listenAddr, key+10) < 0)
+                            goto cleanup;
+                    } else if (STRPREFIX(key, "vncpasswd=")) {
+                        if (VIR_STRDUP(graphics->data.vnc.auth.passwd, key + 10) < 0)
+                            goto cleanup;
+                    } else if (STRPREFIX(key, "keymap=")) {
+                        if (VIR_STRDUP(graphics->data.vnc.keymap, key + 7) < 0)
+                            goto cleanup;
+                    } else if (STRPREFIX(key, "vncdisplay=")) {
+                        if (virStrToLong_i(key + 11, NULL, 10,
+                                           &graphics->data.vnc.port) < 0) {
+                            virReportError(VIR_ERR_INTERNAL_ERROR,
+                                           _("invalid vncdisplay value '%s'"),
+                                           key + 11);
+                            goto cleanup;
+                        }
+                        graphics->data.vnc.port += 5900;
+                    }
+                } else {
+                    if (STRPREFIX(key, "display=")) {
+                        if (VIR_STRDUP(graphics->data.sdl.display, key + 8) < 0)
+                            goto cleanup;
+                    } else if (STRPREFIX(key, "xauthority=")) {
+                        if (VIR_STRDUP(graphics->data.sdl.xauth, key + 11) < 0)
+                            goto cleanup;
+                    }
+                }
+
+                while (nextkey && (nextkey[0] == ',' ||
+                                   nextkey[0] == ' ' ||
+                                   nextkey[0] == '\t'))
+                    nextkey++;
+                key = nextkey;
+            }
+            if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
+                if (virDomainGraphicsListenAppendAddress(graphics,
+                                                         listenAddr) < 0)
+                    goto cleanup;
+                VIR_FREE(listenAddr);
+            }
+            if (VIR_ALLOC_N(def->graphics, 1) < 0)
+                goto cleanup;
+            def->graphics[0] = graphics;
+            def->ngraphics = 1;
+            graphics = NULL;
+        } else {
+            if (xenHandleConfGetValueStringListErrors(rc) < 0)
+                goto cleanup;
+        }
+    }
+
+    return 0;
+
+ cleanup:
+    virDomainGraphicsDefFree(graphics);
+    VIR_FREE(listenAddr);
+    return -1;
+}
+
+
+/**
+  * xenParseSxprChar:
+  * @value: A string describing a character device.
+  * @tty: the console pty path
+  *
+  * Parse the xend S-expression for description of a character device.
+  *
+  * Returns a character device object or NULL in case of failure.
+  */
+static virDomainChrDefPtr
+xenParseSxprChar(const char *value,
+                 const char *tty)
+{
+    const char *prefix;
+    char *tmp;
+    virDomainChrDefPtr def;
+
+    if (!(def = virDomainChrDefNew(NULL)))
+        return NULL;
+
+    prefix = value;
+
+    if (value[0] == '/') {
+        def->source->type = VIR_DOMAIN_CHR_TYPE_DEV;
+        if (VIR_STRDUP(def->source->data.file.path, value) < 0)
+            goto error;
+    } else {
+        if ((tmp = strchr(value, ':')) != NULL) {
+            *tmp = '\0';
+            value = tmp + 1;
+        }
+
+        if (STRPREFIX(prefix, "telnet")) {
+            def->source->type = VIR_DOMAIN_CHR_TYPE_TCP;
+            def->source->data.tcp.protocol = VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET;
+        } else {
+            if ((def->source->type = virDomainChrTypeFromString(prefix)) < 0) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("unknown chr device type '%s'"), prefix);
+                goto error;
+            }
+        }
+    }
+
+    switch (def->source->type) {
+    case VIR_DOMAIN_CHR_TYPE_PTY:
+        if (VIR_STRDUP(def->source->data.file.path, tty) < 0)
+            goto error;
+        break;
+
+    case VIR_DOMAIN_CHR_TYPE_FILE:
+    case VIR_DOMAIN_CHR_TYPE_PIPE:
+        if (VIR_STRDUP(def->source->data.file.path, value) < 0)
+            goto error;
+        break;
+
+    case VIR_DOMAIN_CHR_TYPE_TCP:
+    {
+        const char *offset = strchr(value, ':');
+        const char *offset2;
+
+        if (offset == NULL) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           "%s", _("malformed char device string"));
+            goto error;
+        }
+
+        if (offset != value &&
+            VIR_STRNDUP(def->source->data.tcp.host, value, offset - value) < 0)
+            goto error;
+
+        offset2 = strchr(offset, ',');
+        offset++;
+        if (VIR_STRNDUP(def->source->data.tcp.service, offset,
+                        offset2 ? offset2 - offset : -1) < 0)
+            goto error;
+
+        if (offset2 && strstr(offset2, ",server"))
+            def->source->data.tcp.listen = true;
+    }
+    break;
+
+    case VIR_DOMAIN_CHR_TYPE_UDP:
+    {
+        const char *offset = strchr(value, ':');
+        const char *offset2, *offset3;
+
+        if (offset == NULL) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           "%s", _("malformed char device string"));
+            goto error;
+        }
+
+        if (offset != value &&
+            VIR_STRNDUP(def->source->data.udp.connectHost, value, offset - value) < 0)
+            goto error;
+
+        offset2 = strchr(offset, '@');
+        if (offset2 != NULL) {
+            if (VIR_STRNDUP(def->source->data.udp.connectService,
+                            offset + 1, offset2 - offset - 1) < 0)
+                goto error;
+
+            offset3 = strchr(offset2, ':');
+            if (offset3 == NULL) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               "%s", _("malformed char device string"));
+                goto error;
+            }
+
+            if (offset3 > (offset2 + 1) &&
+                VIR_STRNDUP(def->source->data.udp.bindHost,
+                            offset2 + 1, offset3 - offset2 - 1) < 0)
+                goto error;
+
+            if (VIR_STRDUP(def->source->data.udp.bindService, offset3 + 1) < 0)
+                goto error;
+        } else {
+            if (VIR_STRDUP(def->source->data.udp.connectService, offset + 1) < 0)
+                goto error;
+        }
+    }
+    break;
+
+    case VIR_DOMAIN_CHR_TYPE_UNIX:
+    {
+        const char *offset = strchr(value, ',');
+        if (VIR_STRNDUP(def->source->data.nix.path, value,
+                        offset ? offset - value : -1) < 0)
+            goto error;
+
+        if (offset != NULL &&
+            strstr(offset, ",server") != NULL)
+            def->source->data.nix.listen = true;
+    }
+    break;
+    }
+
+    return def;
+
+ error:
+    virDomainChrDefFree(def);
+    return NULL;
+}
+
+
+static int
+xenParseCharDev(virConfPtr conf, virDomainDefPtr def, const char *nativeFormat)
+{
+    VIR_AUTOSTRINGLIST serials = NULL;
+    virDomainChrDefPtr chr = NULL;
+
+    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
+        VIR_AUTOFREE(char *) parallel = NULL;
+        int rc;
+
+        if (xenConfigGetString(conf, "parallel", &parallel, NULL) < 0)
+            goto cleanup;
+        if (parallel && STRNEQ(parallel, "none") &&
+            !(chr = xenParseSxprChar(parallel, NULL)))
+            goto cleanup;
+        if (chr) {
+            if (VIR_ALLOC_N(def->parallels, 1) < 0)
+                goto cleanup;
+
+            chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL;
+            chr->target.port = 0;
+            def->parallels[0] = chr;
+            def->nparallels++;
+            chr = NULL;
+        }
+
+        /* Try to get the list of values to support multiple serial ports */
+        if ((rc = virConfGetValueStringList(conf, "serial", false, &serials)) == 1) {
+            char **entries;
+            int portnum = -1;
+
+            if (STREQ(nativeFormat, XEN_CONFIG_FORMAT_XM)) {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                               _("Multiple serial devices are not supported by xen-xm"));
+                goto cleanup;
+            }
+
+            for (entries = serials; *entries; entries++) {
+                char *port = *entries;
+
+                portnum++;
+                if (STREQ(port, "none"))
+                    continue;
+
+                if (!(chr = xenParseSxprChar(port, NULL)))
+                    goto cleanup;
+                chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL;
+                chr->target.port = portnum;
+                if (VIR_APPEND_ELEMENT(def->serials, def->nserials, chr) < 0)
+                    goto cleanup;
+            }
+        } else {
+            VIR_AUTOFREE(char *) serial = NULL;
+
+            if (xenHandleConfGetValueStringListErrors(rc) < 0)
+                goto cleanup;
+
+            /* If domain is not using multiple serial ports we parse data old way */
+            if (xenConfigGetString(conf, "serial", &serial, NULL) < 0)
+                goto cleanup;
+            if (serial && STRNEQ(serial, "none") &&
+                !(chr = xenParseSxprChar(serial, NULL)))
+                goto cleanup;
+            if (chr) {
+                if (VIR_ALLOC_N(def->serials, 1) < 0)
+                    goto cleanup;
+                chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL;
+                chr->target.port = 0;
+                def->serials[0] = chr;
+                def->nserials++;
+            }
+        }
+    } else {
+        if (VIR_ALLOC_N(def->consoles, 1) < 0)
+            goto cleanup;
+        def->nconsoles = 1;
+        if (!(def->consoles[0] = xenParseSxprChar("pty", NULL)))
+            goto cleanup;
+        def->consoles[0]->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE;
+        def->consoles[0]->target.port = 0;
+        def->consoles[0]->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_XEN;
+    }
+
+    return 0;
+
+ cleanup:
+    virDomainChrDefFree(chr);
+    return -1;
+}
+
+
+static int
+xenParseVifBridge(virDomainNetDefPtr net, char *bridge)
+{
+    char *vlanstr;
+    unsigned int tag;
+
+    if ((vlanstr = strchr(bridge, '.'))) {
+        /* 'bridge' string contains a bridge name and single vlan tag */
+        if (VIR_STRNDUP(net->data.bridge.brname, bridge, vlanstr - bridge) < 0)
+            return -1;
+
+        vlanstr++;
+        if (virStrToLong_ui(vlanstr, NULL, 10, &tag) < 0)
+            return -1;
+
+        if (VIR_ALLOC_N(net->vlan.tag, 1) < 0)
+            return -1;
+
+        net->vlan.tag[0] = tag;
+        net->vlan.nTags = 1;
+
+        if (VIR_ALLOC(net->virtPortProfile) < 0)
+            return -1;
+
+        net->virtPortProfile->virtPortType = VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH;
+        return 0;
+    } else if ((vlanstr = strchr(bridge, ':'))) {
+        /* 'bridge' string contains a bridge name and one or more vlan trunks */
+        size_t i;
+        size_t nvlans = 0;
+        char **vlanstr_list = virStringSplit(bridge, ":", 0);
+
+        if (!vlanstr_list)
+            return -1;
+
+        if (VIR_STRDUP(net->data.bridge.brname, vlanstr_list[0]) < 0) {
+            virStringListFree(vlanstr_list);
+            return -1;
+        }
+
+        for (i = 1; vlanstr_list[i]; i++)
+            nvlans++;
+
+        if (VIR_ALLOC_N(net->vlan.tag, nvlans) < 0) {
+            virStringListFree(vlanstr_list);
+            return -1;
+        }
+
+        for (i = 1; i <= nvlans; i++) {
+            if (virStrToLong_ui(vlanstr_list[i], NULL, 10, &tag) < 0) {
+                virStringListFree(vlanstr_list);
+                return -1;
+            }
+            net->vlan.tag[i - 1] = tag;
+        }
+        net->vlan.nTags = nvlans;
+        net->vlan.trunk = true;
+        virStringListFree(vlanstr_list);
+
+        if (VIR_ALLOC(net->virtPortProfile) < 0)
+            return -1;
+
+        net->virtPortProfile->virtPortType = VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH;
+        return 0;
+    } else {
+        /* 'bridge' string only contains the bridge name */
+        if (VIR_STRDUP(net->data.bridge.brname, bridge) < 0)
+            return -1;
+    }
+
+    return 0;
+}
+
+
+static const char *vif_bytes_per_sec_re = "^[0-9]+[GMK]?[Bb]/s$";
+
+static int
+xenParseSxprVifRate(const char *rate, unsigned long long *kbytes_per_sec)
+{
+    char *trate = NULL;
+    char *p;
+    regex_t rec;
+    int err;
+    char *suffix;
+    unsigned long long tmp;
+    int ret = -1;
+
+    if (VIR_STRDUP(trate, rate) < 0)
+        return -1;
+
+    p = strchr(trate, '@');
+    if (p != NULL)
+        *p = 0;
+
+    err = regcomp(&rec, vif_bytes_per_sec_re, REG_EXTENDED|REG_NOSUB);
+    if (err != 0) {
+        char error[100];
+        regerror(err, &rec, error, sizeof(error));
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Failed to compile regular expression '%s': %s"),
+                       vif_bytes_per_sec_re, error);
+        goto cleanup;
+    }
+
+    if (regexec(&rec, trate, 0, NULL, 0)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Invalid rate '%s' specified"), rate);
+        goto cleanup;
+    }
+
+    if (virStrToLong_ull(rate, &suffix, 10, &tmp)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Failed to parse rate '%s'"), rate);
+        goto cleanup;
+    }
+
+    if (*suffix == 'G')
+       tmp *= 1024 * 1024;
+    else if (*suffix == 'M')
+       tmp *= 1024;
+
+    if (*suffix == 'b' || *(suffix + 1) == 'b')
+       tmp /= 8;
+
+    *kbytes_per_sec = tmp;
+    ret = 0;
+
+ cleanup:
+    regfree(&rec);
+    VIR_FREE(trate);
+    return ret;
+}
+
+
+static virDomainNetDefPtr
+xenParseVif(char *entry, const char *vif_typename)
+{
+    virDomainNetDefPtr net = NULL;
+    virDomainNetDefPtr ret = NULL;
+    char *script = NULL;
+    char model[10];
+    char type[10];
+    char ip[128];
+    char mac[18];
+    char bridge[50];
+    char vifname[50];
+    char rate[50];
+    char *key;
+
+    bridge[0] = '\0';
+    mac[0] = '\0';
+    ip[0] = '\0';
+    model[0] = '\0';
+    type[0] = '\0';
+    vifname[0] = '\0';
+    rate[0] = '\0';
+
+    key = entry;
+    while (key) {
+        char *data;
+        char *nextkey = strchr(key, ',');
+
+        if (!(data = strchr(key, '=')))
+            return NULL;
+        data++;
+
+        if (STRPREFIX(key, "mac=")) {
+            int len = nextkey ? (nextkey - data) : strlen(data);
+            if (virStrncpy(mac, data, len, sizeof(mac)) < 0) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("MAC address %s too big for destination"),
+                               data);
+                return NULL;
+            }
+        } else if (STRPREFIX(key, "bridge=")) {
+            int len = nextkey ? (nextkey - data) : strlen(data);
+            if (virStrncpy(bridge, data, len, sizeof(bridge)) < 0) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("Bridge %s too big for destination"),
+                               data);
+                return NULL;
+            }
+        } else if (STRPREFIX(key, "script=")) {
+            int len = nextkey ? (nextkey - data) : strlen(data);
+            VIR_FREE(script);
+            if (VIR_STRNDUP(script, data, len) < 0)
+                return NULL;
+        } else if (STRPREFIX(key, "model=")) {
+            int len = nextkey ? (nextkey - data) : strlen(data);
+            if (virStrncpy(model, data, len, sizeof(model)) < 0) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("Model %s too big for destination"),
+                               data);
+                return NULL;
+            }
+        } else if (STRPREFIX(key, "type=")) {
+            int len = nextkey ? (nextkey - data) : strlen(data);
+            if (virStrncpy(type, data, len, sizeof(type)) < 0) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("Type %s too big for destination"),
+                               data);
+                return NULL;
+            }
+        } else if (STRPREFIX(key, "vifname=")) {
+            int len = nextkey ? (nextkey - data) : strlen(data);
+            if (virStrncpy(vifname, data, len, sizeof(vifname)) < 0) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("Vifname %s too big for destination"),
+                               data);
+                return NULL;
+            }
+        } else if (STRPREFIX(key, "ip=")) {
+            int len = nextkey ? (nextkey - data) : strlen(data);
+            if (virStrncpy(ip, data, len, sizeof(ip)) < 0) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("IP %s too big for destination"), data);
+                return NULL;
+            }
+        } else if (STRPREFIX(key, "rate=")) {
+            int len = nextkey ? (nextkey - data) : strlen(data);
+            if (virStrncpy(rate, data, len, sizeof(rate)) < 0) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("rate %s too big for destination"), data);
+                return NULL;
+            }
+        }
+
+        while (nextkey && (nextkey[0] == ',' ||
+                           nextkey[0] == ' ' ||
+                           nextkey[0] == '\t'))
+            nextkey++;
+        key = nextkey;
+    }
+
+    if (VIR_ALLOC(net) < 0)
+        goto cleanup;
+
+    if (mac[0]) {
+        if (virMacAddrParse(mac, &net->mac) < 0) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("malformed mac address '%s'"), mac);
+            goto cleanup;
+        }
+    }
+
+    if (bridge[0] || STREQ_NULLABLE(script, "vif-bridge") ||
+        STREQ_NULLABLE(script, "vif-vnic")) {
+        net->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
+    } else {
+        net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
+    }
+
+    if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE && bridge[0]) {
+        if (xenParseVifBridge(net, bridge) < 0)
+            goto cleanup;
+    }
+    if (ip[0]) {
+        char **ip_list = virStringSplit(ip, " ", 0);
+        size_t i;
+
+        if (!ip_list)
+            goto cleanup;
+
+        for (i = 0; ip_list[i]; i++) {
+            if (virDomainNetAppendIPAddress(net, ip_list[i], 0, 0) < 0) {
+                virStringListFree(ip_list);
+                goto cleanup;
+            }
+        }
+        virStringListFree(ip_list);
+    }
+
+    if (script && script[0] &&
+        VIR_STRDUP(net->script, script) < 0)
+        goto cleanup;
+
+    if (model[0]) {
+        if (virDomainNetSetModelString(net, model) < 0)
+            goto cleanup;
+    } else {
+        if (type[0] && STREQ(type, vif_typename))
+            net->model = VIR_DOMAIN_NET_MODEL_NETFRONT;
+    }
+
+    if (vifname[0] &&
+        VIR_STRDUP(net->ifname, vifname) < 0)
+        goto cleanup;
+
+    if (rate[0]) {
+        virNetDevBandwidthPtr bandwidth;
+        unsigned long long kbytes_per_sec;
+
+        if (xenParseSxprVifRate(rate, &kbytes_per_sec) < 0)
+            goto cleanup;
+
+        if (VIR_ALLOC(bandwidth) < 0)
+            goto cleanup;
+
+        if (VIR_ALLOC(bandwidth->out) < 0) {
+            VIR_FREE(bandwidth);
+            goto cleanup;
+        }
+
+        bandwidth->out->average = kbytes_per_sec;
+        net->bandwidth = bandwidth;
+    }
+
+    VIR_STEAL_PTR(ret, net);
+
+ cleanup:
+    virDomainNetDefFree(net);
+    VIR_FREE(script);
+    return ret;
+}
+
+
+static int
+xenParseVifList(virConfPtr conf, virDomainDefPtr def, const char *vif_typename)
+{
+    virConfValuePtr list = virConfGetValue(conf, "vif");
+
+    if (!list || list->type != VIR_CONF_LIST)
+        return 0;
+
+    for (list = list->list; list; list = list->next) {
+        virDomainNetDefPtr net = NULL;
+        int rc;
+
+        if ((list->type != VIR_CONF_STRING) || (list->str == NULL))
+            continue;
+
+        if (!(net = xenParseVif(list->str, vif_typename)))
+            return -1;
+
+        rc = VIR_APPEND_ELEMENT(def->nets, def->nnets, net);
+        if (rc < 0) {
+            virDomainNetDefFree(net);
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+
+/**
+ * xenParseSxprSound:
+ * @def: the domain config
+ * @str: comma separated list of sound models
+ *
+ * This parses out sound devices from the domain S-expression
+ *
+ * Returns 0 if successful or -1 if failed.
+ */
+static int
+xenParseSxprSound(virDomainDefPtr def,
+                  const char *str)
+{
+    if (STREQ(str, "all")) {
+        size_t i;
+
+        /*
+         * Special compatibility code for Xen with a bogus
+         * sound=all in config.
+         *
+         * NB deliberately, don't include all possible
+         * sound models anymore, just the 2 that were
+         * historically present in Xen's QEMU.
+         *
+         * ie just es1370 + sb16.
+         *
+         * Hence use of MODEL_ES1370 + 1, instead of MODEL_LAST
+         */
+
+        if (VIR_ALLOC_N(def->sounds,
+                        VIR_DOMAIN_SOUND_MODEL_ES1370 + 1) < 0)
+            return -1;
+
+
+        for (i = 0; i < (VIR_DOMAIN_SOUND_MODEL_ES1370 + 1); i++) {
+            virDomainSoundDefPtr sound;
+            if (VIR_ALLOC(sound) < 0)
+                return -1;
+            sound->model = i;
+            def->sounds[def->nsounds++] = sound;
+        }
+    } else {
+        char model[10];
+        const char *offset = str, *offset2;
+
+        do {
+            int len;
+            virDomainSoundDefPtr sound;
+            offset2 = strchr(offset, ',');
+            if (offset2)
+                len = (offset2 - offset);
+            else
+                len = strlen(offset);
+            if (virStrncpy(model, offset, len, sizeof(model)) < 0) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("Sound model %s too big for destination"),
+                               offset);
+                return -1;
+            }
+
+            if (VIR_ALLOC(sound) < 0)
+                return -1;
+
+            if ((sound->model = virDomainSoundModelTypeFromString(model)) < 0) {
+                VIR_FREE(sound);
+                return -1;
+            }
+
+            if (VIR_APPEND_ELEMENT(def->sounds, def->nsounds, sound) < 0) {
+                virDomainSoundDefFree(sound);
+                return -1;
+            }
+
+            offset = offset2 ? offset2 + 1 : NULL;
+        } while (offset);
+    }
+
+    return 0;
+}
+
+
+static int
+xenParseEmulatedDevices(virConfPtr conf, virDomainDefPtr def)
+{
+    VIR_AUTOFREE(char *) str = NULL;
+
+    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
+        if (xenConfigGetString(conf, "soundhw", &str, NULL) < 0)
+            return -1;
+
+        if (str &&
+            xenParseSxprSound(def, str) < 0)
+            return -1;
+    }
+
+    return 0;
+}
+
+
+static int
+xenParseGeneralMeta(virConfPtr conf, virDomainDefPtr def, virCapsPtr caps)
+{
+    virCapsDomainDataPtr capsdata = NULL;
+    VIR_AUTOFREE(char *) str = NULL;
+    int ret = -1;
+
+    if (xenConfigCopyString(conf, "name", &def->name) < 0)
+        goto out;
+
+    if (xenConfigGetUUID(conf, "uuid", def->uuid) < 0)
+        goto out;
+
+    def->os.type = VIR_DOMAIN_OSTYPE_XEN;
+
+    if (xenConfigGetString(conf, "type", &str, NULL) == 0 && str) {
+        if (STREQ(str, "pv")) {
+            def->os.type = VIR_DOMAIN_OSTYPE_XEN;
+        } else if (STREQ(str, "pvh")) {
+            def->os.type = VIR_DOMAIN_OSTYPE_XENPVH;
+        } else if (STREQ(str, "hvm")) {
+            def->os.type = VIR_DOMAIN_OSTYPE_HVM;
+        } else {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           _("type %s is not supported"), str);
+            return -1;
+        }
+    } else {
+        if ((xenConfigGetString(conf, "builder", &str, "linux") == 0) &&
+            STREQ(str, "hvm")) {
+            def->os.type = VIR_DOMAIN_OSTYPE_HVM;
+        }
+    }
+
+    if (!(capsdata = virCapabilitiesDomainDataLookup(caps, def->os.type,
+            VIR_ARCH_NONE, def->virtType, NULL, NULL)))
+        goto out;
+
+    def->os.arch = capsdata->arch;
+    if (VIR_STRDUP(def->os.machine, capsdata->machinetype) < 0)
+        goto out;
+
+    ret = 0;
+ out:
+    VIR_FREE(capsdata);
+    return ret;
+}
+
+
+/*
+ * A convenience function for parsing all config common to both XM and XL
+ */
+int
+xenParseConfigCommon(virConfPtr conf,
+                     virDomainDefPtr def,
+                     virCapsPtr caps,
+                     const char *nativeFormat,
+                     virDomainXMLOptionPtr xmlopt)
+{
+    if (xenParseGeneralMeta(conf, def, caps) < 0)
+        return -1;
+
+    if (xenParseMem(conf, def) < 0)
+        return -1;
+
+    if (xenParseEventsActions(conf, def) < 0)
+        return -1;
+
+    if (xenParseCPUFeatures(conf, def, xmlopt) < 0)
+        return -1;
+
+    if (xenParseTimeOffset(conf, def) < 0)
+        return -1;
+
+    if (xenConfigCopyStringOpt(conf, "device_model", &def->emulator) < 0)
+        return -1;
+
+    if (STREQ(nativeFormat, XEN_CONFIG_FORMAT_XL)) {
+        if (xenParseVifList(conf, def, "vif") < 0)
+            return -1;
+    } else if (STREQ(nativeFormat, XEN_CONFIG_FORMAT_XM)) {
+        if (xenParseVifList(conf, def, "netfront") < 0)
+            return -1;
+    } else {
+        virReportError(VIR_ERR_INVALID_ARG,
+                       _("unsupported config type %s"), nativeFormat);
+        return -1;
+    }
+
+    if (xenParsePCIList(conf, def) < 0)
+        return -1;
+
+    if (xenParseEmulatedDevices(conf, def) < 0)
+        return -1;
+
+    if (xenParseVfb(conf, def) < 0)
+        return -1;
+
+    if (xenParseCharDev(conf, def, nativeFormat) < 0)
+        return -1;
+
+    return 0;
+}
+
+
+/**
+ * xenFormatSxprChr:
+ * @def: the domain config
+ * @buf: a buffer for the result S-expression
+ *
+ * Convert the character device part of the domain config into a S-expression
+ * in buf.
+ *
+ * Returns 0 in case of success, -1 in case of error
+ */
+static int
+xenFormatSxprChr(virDomainChrDefPtr def,
+                 virBufferPtr buf)
+{
+    const char *type = virDomainChrTypeToString(def->source->type);
+
+    if (!type) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       "%s", _("unexpected chr device type"));
+        return -1;
+    }
+
+    switch (def->source->type) {
+    case VIR_DOMAIN_CHR_TYPE_NULL:
+    case VIR_DOMAIN_CHR_TYPE_STDIO:
+    case VIR_DOMAIN_CHR_TYPE_VC:
+    case VIR_DOMAIN_CHR_TYPE_PTY:
+        virBufferAdd(buf, type, -1);
+        break;
+
+    case VIR_DOMAIN_CHR_TYPE_FILE:
+    case VIR_DOMAIN_CHR_TYPE_PIPE:
+        virBufferAsprintf(buf, "%s:", type);
+        virBufferEscapeSexpr(buf, "%s", def->source->data.file.path);
+        break;
+
+    case VIR_DOMAIN_CHR_TYPE_DEV:
+        virBufferEscapeSexpr(buf, "%s", def->source->data.file.path);
+        break;
+
+    case VIR_DOMAIN_CHR_TYPE_TCP:
+        virBufferAsprintf(buf, "%s:%s:%s%s",
+                          (def->source->data.tcp.protocol
+                           == VIR_DOMAIN_CHR_TCP_PROTOCOL_RAW ?
+                           "tcp" : "telnet"),
+                          NULLSTR_EMPTY(def->source->data.tcp.host),
+                          NULLSTR_EMPTY(def->source->data.tcp.service),
+                          (def->source->data.tcp.listen ?
+                           ",server,nowait" : ""));
+        break;
+
+    case VIR_DOMAIN_CHR_TYPE_UDP:
+        virBufferAsprintf(buf, "%s:%s:%s@%s:%s", type,
+                          NULLSTR_EMPTY(def->source->data.udp.connectHost),
+                          NULLSTR_EMPTY(def->source->data.udp.connectService),
+                          NULLSTR_EMPTY(def->source->data.udp.bindHost),
+                          NULLSTR_EMPTY(def->source->data.udp.bindService));
+        break;
+
+    case VIR_DOMAIN_CHR_TYPE_UNIX:
+        virBufferAsprintf(buf, "%s:", type);
+        virBufferEscapeSexpr(buf, "%s", def->source->data.nix.path);
+        if (def->source->data.nix.listen)
+            virBufferAddLit(buf, ",server,nowait");
+        break;
+
+    default:
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("unsupported chr device type '%s'"), type);
+        return -1;
+    }
+
+    if (virBufferCheckError(buf) < 0)
+        return -1;
+
+    return 0;
+}
+
+
+static int
+xenFormatSerial(virConfValuePtr list, virDomainChrDefPtr serial)
+{
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    virConfValuePtr val, tmp;
+    int ret;
+
+    if (serial) {
+        ret = xenFormatSxprChr(serial, &buf);
+        if (ret < 0)
+            goto cleanup;
+    } else {
+        virBufferAddLit(&buf, "none");
+    }
+    if (virBufferCheckError(&buf) < 0)
+        goto cleanup;
+
+    if (VIR_ALLOC(val) < 0)
+        goto cleanup;
+
+    val->type = VIR_CONF_STRING;
+    val->str = virBufferContentAndReset(&buf);
+    tmp = list->list;
+    while (tmp && tmp->next)
+        tmp = tmp->next;
+    if (tmp)
+        tmp->next = val;
+    else
+        list->list = val;
+
+    return 0;
+
+ cleanup:
+    virBufferFreeAndReset(&buf);
+    return -1;
+}
+
+char *
+xenMakeIPList(virNetDevIPInfoPtr guestIP)
+{
+    size_t i;
+    char **address_array;
+    char *ret = NULL;
+
+    if (VIR_ALLOC_N(address_array, guestIP->nips + 1) < 0)
+        return NULL;
+
+    for (i = 0; i < guestIP->nips; i++) {
+        address_array[i] = virSocketAddrFormat(&guestIP->ips[i]->address);
+        if (!address_array[i])
+            goto cleanup;
+    }
+    ret = virStringListJoin((const char**)address_array, " ");
+
+ cleanup:
+    virStringListFree(address_array);
+    return ret;
+}
+
+static int
+xenFormatNet(virConnectPtr conn,
+             virConfValuePtr list,
+             virDomainNetDefPtr net,
+             int hvm,
+             const char *vif_typename)
+{
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    virConfValuePtr val, tmp;
+    char macaddr[VIR_MAC_STRING_BUFLEN];
+
+    virBufferAsprintf(&buf, "mac=%s", virMacAddrFormat(&net->mac, macaddr));
+
+    switch (net->type) {
+    case VIR_DOMAIN_NET_TYPE_BRIDGE:
+    {
+        virNetDevVPortProfilePtr port_profile = virDomainNetGetActualVirtPortProfile(net);
+        virNetDevVlanPtr virt_vlan = virDomainNetGetActualVlan(net);
+        const char *script = net->script;
+        size_t i;
+
+        virBufferAsprintf(&buf, ",bridge=%s", net->data.bridge.brname);
+        if (port_profile &&
+            port_profile->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH) {
+            if (!script)
+                script = "vif-openvswitch";
+            /*
+             * libxl_device_nic->bridge supports an extended format for
+             * specifying VLAN tags and trunks
+             *
+             * BRIDGE_NAME[.VLAN][:TRUNK:TRUNK]
+             */
+            if (virt_vlan && virt_vlan->nTags > 0) {
+                if (virt_vlan->trunk) {
+                    for (i = 0; i < virt_vlan->nTags; i++)
+                        virBufferAsprintf(&buf, ":%d", virt_vlan->tag[i]);
+                } else {
+                    virBufferAsprintf(&buf, ".%d", virt_vlan->tag[0]);
+                }
+            }
+        }
+
+        if (net->guestIP.nips > 0) {
+            char *ipStr = xenMakeIPList(&net->guestIP);
+            virBufferAsprintf(&buf, ",ip=%s", ipStr);
+            VIR_FREE(ipStr);
+        }
+        virBufferAsprintf(&buf, ",script=%s", script ? script : DEFAULT_VIF_SCRIPT);
+    }
+    break;
+
+    case VIR_DOMAIN_NET_TYPE_ETHERNET:
+        if (net->script)
+            virBufferAsprintf(&buf, ",script=%s", net->script);
+        if (net->guestIP.nips > 0) {
+            char *ipStr = xenMakeIPList(&net->guestIP);
+            virBufferAsprintf(&buf, ",ip=%s", ipStr);
+            VIR_FREE(ipStr);
+        }
+        break;
+
+    case VIR_DOMAIN_NET_TYPE_NETWORK:
+    {
+        virNetworkPtr network = virNetworkLookupByName(conn, net->data.network.name);
+        char *bridge;
+        if (!network) {
+            virReportError(VIR_ERR_NO_NETWORK, "%s",
+                           net->data.network.name);
+            return -1;
+        }
+        bridge = virNetworkGetBridgeName(network);
+        virObjectUnref(network);
+        if (!bridge) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("network %s is not active"),
+                           net->data.network.name);
+            return -1;
+        }
+
+        virBufferAsprintf(&buf, ",bridge=%s", bridge);
+        virBufferAsprintf(&buf, ",script=%s", DEFAULT_VIF_SCRIPT);
+    }
+    break;
+
+    case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
+    case VIR_DOMAIN_NET_TYPE_SERVER:
+    case VIR_DOMAIN_NET_TYPE_CLIENT:
+    case VIR_DOMAIN_NET_TYPE_MCAST:
+    case VIR_DOMAIN_NET_TYPE_INTERNAL:
+    case VIR_DOMAIN_NET_TYPE_DIRECT:
+    case VIR_DOMAIN_NET_TYPE_HOSTDEV:
+    case VIR_DOMAIN_NET_TYPE_UDP:
+    case VIR_DOMAIN_NET_TYPE_USER:
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Unsupported net type '%s'"),
+                       virDomainNetTypeToString(net->type));
+        goto cleanup;
+
+    case VIR_DOMAIN_NET_TYPE_LAST:
+    default:
+        virReportEnumRangeError(virDomainNetType, net->type);
+        goto cleanup;
+    }
+
+    if (virDomainNetGetModelString(net)) {
+        if (!hvm) {
+            virBufferAsprintf(&buf, ",model=%s",
+                              virDomainNetGetModelString(net));
+        } else {
+            if (net->model == VIR_DOMAIN_NET_MODEL_NETFRONT)
+                virBufferAsprintf(&buf, ",type=%s", vif_typename);
+            else
+                virBufferAsprintf(&buf, ",model=%s",
+                                  virDomainNetGetModelString(net));
+        }
+    }
+
+    if (net->ifname)
+        virBufferAsprintf(&buf, ",vifname=%s",
+                          net->ifname);
+
+    if (net->bandwidth && net->bandwidth->out && net->bandwidth->out->average)
+        virBufferAsprintf(&buf, ",rate=%lluKB/s", net->bandwidth->out->average);
+
+    if (virBufferCheckError(&buf) < 0)
+        goto cleanup;
+
+    if (VIR_ALLOC(val) < 0)
+        goto cleanup;
+
+    val->type = VIR_CONF_STRING;
+    val->str = virBufferContentAndReset(&buf);
+    tmp = list->list;
+    while (tmp && tmp->next)
+        tmp = tmp->next;
+    if (tmp)
+        tmp->next = val;
+    else
+        list->list = val;
+
+    return 0;
+
+ cleanup:
+    virBufferFreeAndReset(&buf);
+    return -1;
+}
+
+
+static int
+xenFormatPCI(virConfPtr conf, virDomainDefPtr def)
+{
+    virConfValuePtr pciVal = NULL;
+    int hasPCI = 0;
+    size_t i;
+
+    for (i = 0; i < def->nhostdevs; i++)
+        if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+            def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
+            hasPCI = 1;
+
+    if (!hasPCI)
+        return 0;
+
+    if (VIR_ALLOC(pciVal) < 0)
+        return -1;
+
+    pciVal->type = VIR_CONF_LIST;
+    pciVal->list = NULL;
+
+    for (i = 0; i < def->nhostdevs; i++) {
+        if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+            def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
+            virConfValuePtr val, tmp;
+            char *buf;
+
+            if (virAsprintf(&buf, "%04x:%02x:%02x.%x",
+                            def->hostdevs[i]->source.subsys.u.pci.addr.domain,
+                            def->hostdevs[i]->source.subsys.u.pci.addr.bus,
+                            def->hostdevs[i]->source.subsys.u.pci.addr.slot,
+                            def->hostdevs[i]->source.subsys.u.pci.addr.function) < 0)
+                goto error;
+
+            if (VIR_ALLOC(val) < 0) {
+                VIR_FREE(buf);
+                goto error;
+            }
+            val->type = VIR_CONF_STRING;
+            val->str = buf;
+            tmp = pciVal->list;
+            while (tmp && tmp->next)
+                tmp = tmp->next;
+            if (tmp)
+                tmp->next = val;
+            else
+                pciVal->list = val;
+        }
+    }
+
+    if (pciVal->list != NULL) {
+        int ret = virConfSetValue(conf, "pci", pciVal);
+        pciVal = NULL;
+        if (ret < 0)
+            return -1;
+    }
+    VIR_FREE(pciVal);
+
+    return 0;
+
+ error:
+    virConfFreeValue(pciVal);
+    return -1;
+}
+
+
+static int
+xenFormatGeneralMeta(virConfPtr conf, virDomainDefPtr def)
+{
+    char uuid[VIR_UUID_STRING_BUFLEN];
+
+    if (xenConfigSetString(conf, "name", def->name) < 0)
+        return -1;
+
+    virUUIDFormat(def->uuid, uuid);
+    if (xenConfigSetString(conf, "uuid", uuid) < 0)
+        return -1;
+
+    return 0;
+}
+
+
+static int
+xenFormatMem(virConfPtr conf, virDomainDefPtr def)
+{
+    if (xenConfigSetInt(conf, "maxmem",
+                        VIR_DIV_UP(virDomainDefGetMemoryTotal(def), 1024)) < 0)
+        return -1;
+
+    if (xenConfigSetInt(conf, "memory",
+                        VIR_DIV_UP(def->mem.cur_balloon, 1024)) < 0)
+        return -1;
+
+    return 0;
+}
+
+
+static int
+xenFormatTimeOffset(virConfPtr conf, virDomainDefPtr def)
+{
+    int vmlocaltime;
+
+    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
+        /* >=3.1 HV: VARIABLE */
+        int rtc_timeoffset;
+
+        switch (def->clock.offset) {
+        case VIR_DOMAIN_CLOCK_OFFSET_VARIABLE:
+            vmlocaltime = (int)def->clock.data.variable.basis;
+            rtc_timeoffset = def->clock.data.variable.adjustment;
+            break;
+        case VIR_DOMAIN_CLOCK_OFFSET_UTC:
+            if (def->clock.data.utc_reset) {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                               _("unsupported clock adjustment='reset'"));
+                return -1;
+            }
+            vmlocaltime = 0;
+            rtc_timeoffset = 0;
+            break;
+        case VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME:
+            if (def->clock.data.utc_reset) {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                               _("unsupported clock adjustment='reset'"));
+                return -1;
+            }
+            vmlocaltime = 1;
+            rtc_timeoffset = 0;
+            break;
+        default:
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           _("unsupported clock offset='%s'"),
+                           virDomainClockOffsetTypeToString(def->clock.offset));
+            return -1;
+        }
+        if (xenConfigSetInt(conf, "rtc_timeoffset", rtc_timeoffset) < 0)
+            return -1;
+    } else {
+        /* PV: UTC and LOCALTIME */
+        switch (def->clock.offset) {
+        case VIR_DOMAIN_CLOCK_OFFSET_UTC:
+            vmlocaltime = 0;
+            break;
+        case VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME:
+            vmlocaltime = 1;
+            break;
+        default:
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           _("unsupported clock offset='%s'"),
+                           virDomainClockOffsetTypeToString(def->clock.offset));
+            return -1;
+        }
+    } /* !hvm */
+
+    if (xenConfigSetInt(conf, "localtime", vmlocaltime) < 0)
+        return -1;
+
+    return 0;
+}
+
+
+static int
+xenFormatEventActions(virConfPtr conf, virDomainDefPtr def)
+{
+    const char *lifecycle = NULL;
+
+    if (!(lifecycle = virDomainLifecycleActionTypeToString(def->onPoweroff))) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("unexpected lifecycle action %d"), def->onPoweroff);
+        return -1;
+    }
+    if (xenConfigSetString(conf, "on_poweroff", lifecycle) < 0)
+        return -1;
+
+
+    if (!(lifecycle = virDomainLifecycleActionTypeToString(def->onReboot))) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("unexpected lifecycle action %d"), def->onReboot);
+        return -1;
+    }
+    if (xenConfigSetString(conf, "on_reboot", lifecycle) < 0)
+        return -1;
+
+
+    if (!(lifecycle = virDomainLifecycleActionTypeToString(def->onCrash))) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("unexpected lifecycle action %d"), def->onCrash);
+        return -1;
+    }
+    if (xenConfigSetString(conf, "on_crash", lifecycle) < 0)
+        return -1;
+
+    return 0;
+}
+
+
+static int
+xenFormatCharDev(virConfPtr conf, virDomainDefPtr def,
+                 const char *nativeFormat)
+{
+    size_t i;
+
+    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
+        if (def->nparallels) {
+            virBuffer buf = VIR_BUFFER_INITIALIZER;
+            char *str;
+            int ret;
+
+            ret = xenFormatSxprChr(def->parallels[0], &buf);
+            str = virBufferContentAndReset(&buf);
+            if (ret == 0)
+                ret = xenConfigSetString(conf, "parallel", str);
+            VIR_FREE(str);
+            if (ret < 0)
+                return -1;
+        } else {
+            if (xenConfigSetString(conf, "parallel", "none") < 0)
+                return -1;
+        }
+
+        if (def->nserials) {
+            if ((def->nserials == 1) && (def->serials[0]->target.port == 0)) {
+                virBuffer buf = VIR_BUFFER_INITIALIZER;
+                char *str;
+                int ret;
+
+                ret = xenFormatSxprChr(def->serials[0], &buf);
+                str = virBufferContentAndReset(&buf);
+                if (ret == 0)
+                    ret = xenConfigSetString(conf, "serial", str);
+                VIR_FREE(str);
+                if (ret < 0)
+                    return -1;
+            } else {
+                size_t j = 0;
+                int maxport = -1, port;
+                virConfValuePtr serialVal = NULL;
+
+                if (STREQ(nativeFormat, XEN_CONFIG_FORMAT_XM)) {
+                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                                   _("Multiple serial devices are not supported by xen-xm"));
+                    return -1;
+                }
+
+                if (VIR_ALLOC(serialVal) < 0)
+                    return -1;
+
+                serialVal->type = VIR_CONF_LIST;
+                serialVal->list = NULL;
+
+                for (i = 0; i < def->nserials; i++)
+                    if (def->serials[i]->target.port > maxport)
+                        maxport = def->serials[i]->target.port;
+
+                for (port = 0; port <= maxport; port++) {
+                    virDomainChrDefPtr chr = NULL;
+
+                    for (j = 0; j < def->nserials; j++) {
+                        if (def->serials[j]->target.port == port) {
+                            chr = def->serials[j];
+                            break;
+                        }
+                    }
+
+                    if (xenFormatSerial(serialVal, chr) < 0) {
+                        VIR_FREE(serialVal);
+                        return -1;
+                    }
+                }
+
+                if (serialVal->list != NULL) {
+                    int ret = virConfSetValue(conf, "serial", serialVal);
+
+                    serialVal = NULL;
+                    if (ret < 0)
+                        return -1;
+                }
+                VIR_FREE(serialVal);
+            }
+        } else {
+            if (xenConfigSetString(conf, "serial", "none") < 0)
+                return -1;
+        }
+    }
+
+    return 0;
+}
+
+
+static int
+xenFormatCPUAllocation(virConfPtr conf, virDomainDefPtr def)
+{
+    int ret = -1;
+    char *cpus = NULL;
+
+    if (virDomainDefGetVcpus(def) < virDomainDefGetVcpusMax(def) &&
+        xenConfigSetInt(conf, "maxvcpus", virDomainDefGetVcpusMax(def)) < 0)
+        goto cleanup;
+    if (xenConfigSetInt(conf, "vcpus", virDomainDefGetVcpus(def)) < 0)
+        goto cleanup;
+
+    if ((def->cpumask != NULL) &&
+        ((cpus = virBitmapFormat(def->cpumask)) == NULL)) {
+        goto cleanup;
+    }
+
+    if (cpus &&
+        xenConfigSetString(conf, "cpus", cpus) < 0)
+        goto cleanup;
+
+    ret = 0;
+
+ cleanup:
+    VIR_FREE(cpus);
+    return ret;
+}
+
+
+static int
+xenFormatCPUFeatures(virConfPtr conf, virDomainDefPtr def)
+{
+    size_t i;
+    bool hvm = !!(def->os.type == VIR_DOMAIN_OSTYPE_HVM);
+
+    if (hvm) {
+        if (xenConfigSetInt(conf, "pae",
+                            (def->features[VIR_DOMAIN_FEATURE_PAE] ==
+                            VIR_TRISTATE_SWITCH_ON) ? 1 : 0) < 0)
+            return -1;
+
+        if (xenConfigSetInt(conf, "acpi",
+                            (def->features[VIR_DOMAIN_FEATURE_ACPI] ==
+                            VIR_TRISTATE_SWITCH_ON) ? 1 : 0) < 0)
+            return -1;
+
+        if (xenConfigSetInt(conf, "apic",
+                            (def->features[VIR_DOMAIN_FEATURE_APIC] ==
+                            VIR_TRISTATE_SWITCH_ON) ? 1 : 0) < 0)
+            return -1;
+
+        if (def->features[VIR_DOMAIN_FEATURE_HAP] == VIR_TRISTATE_SWITCH_OFF) {
+            if (xenConfigSetInt(conf, "hap", 0) < 0)
+                return -1;
+        }
+
+        if (xenConfigSetInt(conf, "viridian",
+                            (def->features[VIR_DOMAIN_FEATURE_VIRIDIAN] ==
+                             VIR_TRISTATE_SWITCH_ON) ? 1 : 0) < 0)
+            return -1;
+    }
+
+    for (i = 0; i < def->clock.ntimers; i++) {
+        switch ((virDomainTimerNameType)def->clock.timers[i]->name) {
+        case VIR_DOMAIN_TIMER_NAME_TSC:
+            switch (def->clock.timers[i]->mode) {
+            case VIR_DOMAIN_TIMER_MODE_NATIVE:
+                if (xenConfigSetString(conf, "tsc_mode", "native") < 0)
+                    return -1;
+                break;
+            case VIR_DOMAIN_TIMER_MODE_PARAVIRT:
+                if (xenConfigSetString(conf, "tsc_mode", "native_paravirt") < 0)
+                    return -1;
+                break;
+            case VIR_DOMAIN_TIMER_MODE_EMULATE:
+                if (xenConfigSetString(conf, "tsc_mode", "always_emulate") < 0)
+                    return -1;
+                break;
+            default:
+                if (xenConfigSetString(conf, "tsc_mode", "default") < 0)
+                    return -1;
+            }
+            break;
+
+        case VIR_DOMAIN_TIMER_NAME_HPET:
+            if (hvm) {
+                int enable_hpet = def->clock.timers[i]->present != 0;
+
+                /* disable hpet if 'present' is 0, enable otherwise */
+                if (xenConfigSetInt(conf, "hpet", enable_hpet) < 0)
+                    return -1;
+            } else {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                               _("unsupported timer type (name) '%s'"),
+                               virDomainTimerNameTypeToString(def->clock.timers[i]->name));
+                return -1;
+            }
+            break;
+
+        case VIR_DOMAIN_TIMER_NAME_PLATFORM:
+        case VIR_DOMAIN_TIMER_NAME_KVMCLOCK:
+        case VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK:
+        case VIR_DOMAIN_TIMER_NAME_RTC:
+        case VIR_DOMAIN_TIMER_NAME_PIT:
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           _("unsupported timer type (name) '%s'"),
+                           virDomainTimerNameTypeToString(def->clock.timers[i]->name));
+            return -1;
+
+        case VIR_DOMAIN_TIMER_NAME_LAST:
+            break;
+        }
+    }
+
+    return 0;
+}
+
+
+static int
+xenFormatEmulator(virConfPtr conf, virDomainDefPtr def)
+{
+    if (def->emulator &&
+        xenConfigSetString(conf, "device_model", def->emulator) < 0)
+        return -1;
+
+    return 0;
+}
+
+
+static int
+xenFormatVfb(virConfPtr conf, virDomainDefPtr def)
+{
+    int hvm = def->os.type == VIR_DOMAIN_OSTYPE_HVM ? 1 : 0;
+
+    if (def->ngraphics == 1 &&
+        def->graphics[0]->type != VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
+        if (hvm) {
+            if (def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
+                if (xenConfigSetInt(conf, "sdl", 1) < 0)
+                    return -1;
+
+                if (xenConfigSetInt(conf, "vnc", 0) < 0)
+                    return -1;
+
+                if (def->graphics[0]->data.sdl.display &&
+                    xenConfigSetString(conf, "display",
+                                       def->graphics[0]->data.sdl.display) < 0)
+                    return -1;
+
+                if (def->graphics[0]->data.sdl.xauth &&
+                    xenConfigSetString(conf, "xauthority",
+                                       def->graphics[0]->data.sdl.xauth) < 0)
+                    return -1;
+            } else {
+                virDomainGraphicsListenDefPtr glisten;
+
+                if (xenConfigSetInt(conf, "sdl", 0) < 0)
+                    return -1;
+
+                if (xenConfigSetInt(conf, "vnc", 1) < 0)
+                    return -1;
+
+                if (xenConfigSetInt(conf, "vncunused",
+                              def->graphics[0]->data.vnc.autoport ? 1 : 0) < 0)
+                    return -1;
+
+                if (!def->graphics[0]->data.vnc.autoport &&
+                    xenConfigSetInt(conf, "vncdisplay",
+                                    def->graphics[0]->data.vnc.port - 5900) < 0)
+                    return -1;
+
+                if ((glisten = virDomainGraphicsGetListen(def->graphics[0], 0)) &&
+                    glisten->address &&
+                    xenConfigSetString(conf, "vnclisten", glisten->address) < 0)
+                    return -1;
+
+                if (def->graphics[0]->data.vnc.auth.passwd &&
+                    xenConfigSetString(conf, "vncpasswd",
+                                       def->graphics[0]->data.vnc.auth.passwd) < 0)
+                    return -1;
+
+                if (def->graphics[0]->data.vnc.keymap &&
+                    xenConfigSetString(conf, "keymap",
+                                       def->graphics[0]->data.vnc.keymap) < 0)
+                    return -1;
+            }
+        } else {
+            virConfValuePtr vfb, disp;
+            char *vfbstr = NULL;
+            virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+            if (def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
+                virBufferAddLit(&buf, "type=sdl");
+                if (def->graphics[0]->data.sdl.display)
+                    virBufferAsprintf(&buf, ",display=%s",
+                                      def->graphics[0]->data.sdl.display);
+                if (def->graphics[0]->data.sdl.xauth)
+                    virBufferAsprintf(&buf, ",xauthority=%s",
+                                      def->graphics[0]->data.sdl.xauth);
+            } else {
+                virDomainGraphicsListenDefPtr glisten
+                    = virDomainGraphicsGetListen(def->graphics[0], 0);
+
+                virBufferAddLit(&buf, "type=vnc");
+                virBufferAsprintf(&buf, ",vncunused=%d",
+                                  def->graphics[0]->data.vnc.autoport ? 1 : 0);
+                if (!def->graphics[0]->data.vnc.autoport)
+                    virBufferAsprintf(&buf, ",vncdisplay=%d",
+                                      def->graphics[0]->data.vnc.port - 5900);
+                if (glisten && glisten->address)
+                    virBufferAsprintf(&buf, ",vnclisten=%s", glisten->address);
+                if (def->graphics[0]->data.vnc.auth.passwd)
+                    virBufferAsprintf(&buf, ",vncpasswd=%s",
+                                      def->graphics[0]->data.vnc.auth.passwd);
+                if (def->graphics[0]->data.vnc.keymap)
+                    virBufferAsprintf(&buf, ",keymap=%s",
+                                      def->graphics[0]->data.vnc.keymap);
+            }
+            if (virBufferCheckError(&buf) < 0)
+                return -1;
+
+            vfbstr = virBufferContentAndReset(&buf);
+
+            if (VIR_ALLOC(vfb) < 0) {
+                VIR_FREE(vfbstr);
+                return -1;
+            }
+
+            if (VIR_ALLOC(disp) < 0) {
+                VIR_FREE(vfb);
+                VIR_FREE(vfbstr);
+                return -1;
+            }
+
+            vfb->type = VIR_CONF_LIST;
+            vfb->list = disp;
+            disp->type = VIR_CONF_STRING;
+            disp->str = vfbstr;
+
+            if (virConfSetValue(conf, "vfb", vfb) < 0)
+                return -1;
+        }
+    }
+
+    return 0;
+}
+
+
+static int
+xenFormatSound(virConfPtr conf, virDomainDefPtr def)
+{
+    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
+    const char * model;
+    VIR_AUTOFREE(char *) str = NULL;
+    size_t i;
+
+    if (def->os.type != VIR_DOMAIN_OSTYPE_HVM ||
+        !def->sounds)
+        return 0;
+
+    for (i = 0; i < def->nsounds; i++) {
+        if (!(model = virDomainSoundModelTypeToString(def->sounds[i]->model))) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("unexpected sound model %d"),
+                           def->sounds[i]->model);
+            return -1;
+        }
+        if (i)
+            virBufferAddChar(&buf, ',');
+        virBufferEscapeSexpr(&buf, "%s", model);
+    }
+
+    if (virBufferCheckError(&buf) < 0)
+        return -1;
+
+    str = virBufferContentAndReset(&buf);
+
+    return xenConfigSetString(conf, "soundhw", str);
+}
+
+
+static int
+xenFormatVif(virConfPtr conf,
+             virConnectPtr conn,
+             virDomainDefPtr def,
+             const char *vif_typename)
+{
+    virConfValuePtr netVal = NULL;
+    size_t i;
+    int hvm = def->os.type == VIR_DOMAIN_OSTYPE_HVM;
+
+    if (VIR_ALLOC(netVal) < 0)
+        goto cleanup;
+    netVal->type = VIR_CONF_LIST;
+    netVal->list = NULL;
+
+    for (i = 0; i < def->nnets; i++) {
+        if (xenFormatNet(conn, netVal, def->nets[i],
+                         hvm, vif_typename) < 0)
+            goto cleanup;
+    }
+
+    if (netVal->list != NULL) {
+        int ret = virConfSetValue(conf, "vif", netVal);
+        netVal = NULL;
+        if (ret < 0)
+            goto cleanup;
+    }
+
+    VIR_FREE(netVal);
+    return 0;
+
+ cleanup:
+    virConfFreeValue(netVal);
+    return -1;
+}
+
+
+/*
+ * A convenience function for formatting all config common to both XM and XL
+ */
+int
+xenFormatConfigCommon(virConfPtr conf,
+                      virDomainDefPtr def,
+                      virConnectPtr conn,
+                      const char *nativeFormat)
+{
+    if (xenFormatGeneralMeta(conf, def) < 0)
+        return -1;
+
+    if (xenFormatMem(conf, def) < 0)
+        return -1;
+
+    if (xenFormatCPUAllocation(conf, def) < 0)
+        return -1;
+
+    if (xenFormatCPUFeatures(conf, def) < 0)
+        return -1;
+
+    if (xenFormatTimeOffset(conf, def) < 0)
+        return -1;
+
+    if (xenFormatEventActions(conf, def) < 0)
+        return -1;
+
+    if (xenFormatEmulator(conf, def) < 0)
+        return -1;
+
+    if (xenFormatVfb(conf, def) < 0)
+        return -1;
+
+    if (STREQ(nativeFormat, XEN_CONFIG_FORMAT_XL)) {
+        if (xenFormatVif(conf, conn, def, "vif") < 0)
+            return -1;
+    } else if (STREQ(nativeFormat, XEN_CONFIG_FORMAT_XM)) {
+        if (xenFormatVif(conf, conn, def, "netfront") < 0)
+            return -1;
+    } else {
+        virReportError(VIR_ERR_INVALID_ARG,
+                       _("unsupported config type %s"), nativeFormat);
+        return -1;
+    }
+
+    if (xenFormatPCI(conf, def) < 0)
+        return -1;
+
+    if (xenFormatCharDev(conf, def, nativeFormat) < 0)
+        return -1;
+
+    if (xenFormatSound(conf, def) < 0)
+        return -1;
+
+    return 0;
+}
+
+
+int
+xenDomainDefAddImplicitInputDevice(virDomainDefPtr def)
+{
+    virDomainInputBus implicitInputBus = VIR_DOMAIN_INPUT_BUS_XEN;
+
+    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM)
+        implicitInputBus = VIR_DOMAIN_INPUT_BUS_PS2;
+
+    if (virDomainDefMaybeAddInput(def,
+                                  VIR_DOMAIN_INPUT_TYPE_MOUSE,
+                                  implicitInputBus) < 0)
+        return -1;
+
+    if (virDomainDefMaybeAddInput(def,
+                                  VIR_DOMAIN_INPUT_TYPE_KBD,
+                                  implicitInputBus) < 0)
+        return -1;
+
+    return 0;
+}
diff --git a/src/libxl/xen_common.h b/src/libxl/xen_common.h
new file mode 100644 (file)
index 0000000..231fa0d
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * xen_common.h: Parsing and formatting functions for config common
+ *
+ * Copyright (C) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "internal.h"
+#include "virconf.h"
+#include "domain_conf.h"
+
+#define XEN_CONFIG_FORMAT_XL    "xen-xl"
+#define XEN_CONFIG_FORMAT_XM    "xen-xm"
+#define XEN_CONFIG_FORMAT_SEXPR "xen-sxpr"
+
+int xenConfigGetString(virConfPtr conf,
+                       const char *name,
+                       char **value,
+                       const char *def);
+
+int xenConfigGetBool(virConfPtr conf, const char *name, int *value, int def);
+
+int xenConfigSetInt(virConfPtr conf, const char *name, long long value);
+
+int xenConfigSetString(virConfPtr conf, const char *setting, const char *value);
+
+int xenConfigGetULong(virConfPtr conf,
+                      const char *name,
+                      unsigned long *value,
+                      unsigned long def);
+
+int
+xenConfigCopyString(virConfPtr conf,
+                    const char *name,
+                    char **value);
+
+int xenConfigCopyStringOpt(virConfPtr conf,
+                           const char *name,
+                           char **value);
+
+int xenParseConfigCommon(virConfPtr conf,
+                         virDomainDefPtr def,
+                         virCapsPtr caps,
+                         const char *nativeFormat,
+                         virDomainXMLOptionPtr xmlopt);
+
+int xenFormatConfigCommon(virConfPtr conf,
+                          virDomainDefPtr def,
+                          virConnectPtr conn,
+                          const char *nativeFormat);
+
+char *xenMakeIPList(virNetDevIPInfoPtr guestIP);
+
+int xenDomainDefAddImplicitInputDevice(virDomainDefPtr def);
diff --git a/src/libxl/xen_xl.c b/src/libxl/xen_xl.c
new file mode 100644 (file)
index 0000000..ca094d3
--- /dev/null
@@ -0,0 +1,2249 @@
+/*
+ * xen_xl.c: Xen XL parsing functions
+ *
+ * Copyright (c) 2015 SUSE LINUX Products GmbH, Nuernberg, Germany.
+ * Copyright (C) 2014 David Kiarie Kahurani
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include <libxl.h>
+
+#include "virconf.h"
+#include "virerror.h"
+#include "virlog.h"
+#include "domain_conf.h"
+#include "viralloc.h"
+#include "virstring.h"
+#include "virstoragefile.h"
+#include "xen_xl.h"
+#include "libxl_capabilities.h"
+#include "cpu/cpu.h"
+
+#define VIR_FROM_THIS VIR_FROM_XENXL
+
+VIR_LOG_INIT("xen.xen_xl");
+
+/*
+ * Xen provides a libxl utility library, with several useful functions,
+ * specifically xlu_disk_parse for parsing xl disk config strings.
+ * Although the libxlutil library is installed, until recently the
+ * corresponding header file wasn't.  Use the header file if detected during
+ * configure, otherwise provide extern declarations for any functions used.
+ */
+#ifdef HAVE_LIBXLUTIL_H
+# include <libxlutil.h>
+#else
+typedef struct XLU_Config XLU_Config;
+
+extern XLU_Config *xlu_cfg_init(FILE *report,
+                                const char *report_filename);
+
+extern void xlu_cfg_destroy(XLU_Config*);
+
+extern int xlu_disk_parse(XLU_Config *cfg,
+                          int nspecs,
+                          const char *const *specs,
+                          libxl_device_disk *disk);
+#endif
+
+static int xenParseCmdline(virConfPtr conf, char **r_cmdline)
+{
+    char *cmdline = NULL;
+    VIR_AUTOFREE(char *) root = NULL;
+    VIR_AUTOFREE(char *) extra = NULL;
+    VIR_AUTOFREE(char *) buf = NULL;
+
+    if (xenConfigGetString(conf, "cmdline", &buf, NULL) < 0)
+        return -1;
+
+    if (xenConfigGetString(conf, "root", &root, NULL) < 0)
+        return -1;
+
+    if (xenConfigGetString(conf, "extra", &extra, NULL) < 0)
+        return -1;
+
+    if (buf) {
+        if (VIR_STRDUP(cmdline, buf) < 0)
+            return -1;
+        if (root || extra)
+            VIR_WARN("ignoring root= and extra= in favour of cmdline=");
+    } else {
+        if (root && extra) {
+            if (virAsprintf(&cmdline, "root=%s %s", root, extra) < 0)
+                return -1;
+        } else if (root) {
+            if (virAsprintf(&cmdline, "root=%s", root) < 0)
+                return -1;
+        } else if (extra) {
+            if (VIR_STRDUP(cmdline, extra) < 0)
+                return -1;
+        }
+    }
+
+    *r_cmdline = cmdline;
+    return 0;
+}
+
+static int
+xenParseXLOS(virConfPtr conf, virDomainDefPtr def, virCapsPtr caps)
+{
+    size_t i;
+
+    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
+        VIR_AUTOFREE(char *) bios = NULL;
+        VIR_AUTOFREE(char *) boot = NULL;
+        int val = 0;
+
+        if (xenConfigGetString(conf, "bios", &bios, NULL) < 0)
+            return -1;
+
+        if (bios && STREQ(bios, "ovmf")) {
+            if (VIR_ALLOC(def->os.loader) < 0)
+                return -1;
+
+            def->os.loader->type = VIR_DOMAIN_LOADER_TYPE_PFLASH;
+            def->os.loader->readonly = VIR_TRISTATE_BOOL_YES;
+
+            if (VIR_STRDUP(def->os.loader->path,
+                           LIBXL_FIRMWARE_DIR "/ovmf.bin") < 0)
+                return -1;
+        } else {
+            for (i = 0; i < caps->nguests; i++) {
+                if (caps->guests[i]->ostype == VIR_DOMAIN_OSTYPE_HVM &&
+                    caps->guests[i]->arch.id == def->os.arch) {
+                    if (VIR_ALLOC(def->os.loader) < 0 ||
+                        VIR_STRDUP(def->os.loader->path,
+                                   caps->guests[i]->arch.defaultInfo.loader) < 0)
+                        return -1;
+                }
+            }
+        }
+
+#ifdef LIBXL_HAVE_BUILDINFO_KERNEL
+        if (xenConfigCopyStringOpt(conf, "kernel", &def->os.kernel) < 0)
+            return -1;
+
+        if (xenConfigCopyStringOpt(conf, "ramdisk", &def->os.initrd) < 0)
+            return -1;
+
+        if (xenParseCmdline(conf, &def->os.cmdline) < 0)
+            return -1;
+#endif
+
+        if (xenConfigGetString(conf, "boot", &boot, "c") < 0)
+            return -1;
+
+        for (i = 0; i < VIR_DOMAIN_BOOT_LAST && boot[i]; i++) {
+            switch (boot[i]) {
+            case 'a':
+                def->os.bootDevs[i] = VIR_DOMAIN_BOOT_FLOPPY;
+                break;
+            case 'd':
+                def->os.bootDevs[i] = VIR_DOMAIN_BOOT_CDROM;
+                break;
+            case 'n':
+                def->os.bootDevs[i] = VIR_DOMAIN_BOOT_NET;
+                break;
+            case 'c':
+            default:
+                def->os.bootDevs[i] = VIR_DOMAIN_BOOT_DISK;
+                break;
+            }
+            def->os.nBootDevs++;
+        }
+
+        if (xenConfigGetBool(conf, "nestedhvm", &val, -1) < 0)
+            return -1;
+
+        if (val != -1) {
+            const char *vtfeature = "vmx";
+
+            if (caps && caps->host.cpu && ARCH_IS_X86(def->os.arch)) {
+                if (virCPUCheckFeature(caps->host.arch, caps->host.cpu, "vmx"))
+                    vtfeature = "vmx";
+                else if (virCPUCheckFeature(caps->host.arch, caps->host.cpu, "svm"))
+                    vtfeature = "svm";
+            }
+
+            if (!def->cpu) {
+                virCPUDefPtr cpu;
+                if (VIR_ALLOC(cpu) < 0)
+                    return -1;
+
+                cpu->mode = VIR_CPU_MODE_HOST_PASSTHROUGH;
+                cpu->type = VIR_CPU_TYPE_GUEST;
+                cpu->nfeatures = 0;
+                cpu->nfeatures_max = 0;
+                def->cpu = cpu;
+            }
+
+            if (val == 0) {
+                if (virCPUDefAddFeature(def->cpu,
+                                        vtfeature,
+                                        VIR_CPU_FEATURE_DISABLE) < 0)
+                    return -1;
+            }
+        }
+    } else {
+        if (xenConfigCopyStringOpt(conf, "bootloader", &def->os.bootloader) < 0)
+            return -1;
+        if (xenConfigCopyStringOpt(conf, "bootargs", &def->os.bootloaderArgs) < 0)
+            return -1;
+
+        if (xenConfigCopyStringOpt(conf, "kernel", &def->os.kernel) < 0)
+            return -1;
+
+        if (xenConfigCopyStringOpt(conf, "ramdisk", &def->os.initrd) < 0)
+            return -1;
+
+        if (xenParseCmdline(conf, &def->os.cmdline) < 0)
+            return -1;
+    }
+
+    return 0;
+}
+
+/*
+ * Translate CPU feature name from libvirt to libxl (from_libxl=false) or from
+ * libxl to libvirt (from_libxl=true).
+ */
+const char *
+xenTranslateCPUFeature(const char *feature_name, bool from_libxl)
+{
+    static const char *translation_table[][2] = {
+        /* libvirt name, libxl name */
+        { "cx16", "cmpxchg16" },
+        { "cid", "cntxid" },
+        { "ds_cpl", "dscpl" },
+        { "pclmuldq", "pclmulqdq" },
+        { "pni", "sse3" },
+        { "ht", "htt" },
+        { "pn", "psn" },
+        { "clflush", "clfsh" },
+        { "sep", "sysenter" },
+        { "cx8", "cmpxchg8" },
+        { "nodeid_msr", "nodeid" },
+        { "cr8legacy", "altmovcr8" },
+        { "lahf_lm", "lahfsahf" },
+        { "cmp_legacy", "cmplegacy" },
+        { "fxsr_opt", "ffxsr" },
+        { "pdpe1gb", "page1gb" },
+        { "spec-ctrl", "ibrsb" },
+    };
+    size_t i;
+
+    for (i = 0; i < ARRAY_CARDINALITY(translation_table); i++)
+        if (STREQ(translation_table[i][from_libxl], feature_name))
+            return translation_table[i][!from_libxl];
+    return feature_name;
+}
+
+static int
+xenParseXLCPUID(virConfPtr conf, virDomainDefPtr def)
+{
+    VIR_AUTOFREE(char *) cpuid_str = NULL;
+    char **cpuid_pairs = NULL;
+    char **name_and_value = NULL;
+    size_t i;
+    int ret = -1;
+    int policy;
+
+    if (xenConfigGetString(conf, "cpuid", &cpuid_str, NULL) < 0)
+        return -1;
+
+    if (!cpuid_str)
+        return 0;
+
+    if (!def->cpu) {
+        if (VIR_ALLOC(def->cpu) < 0)
+            goto cleanup;
+        def->cpu->mode = VIR_CPU_MODE_HOST_PASSTHROUGH;
+        def->cpu->type = VIR_CPU_TYPE_GUEST;
+        def->cpu->nfeatures = 0;
+        def->cpu->nfeatures_max = 0;
+    }
+
+    cpuid_pairs = virStringSplit(cpuid_str, ",", 0);
+    if (!cpuid_pairs)
+        goto cleanup;
+
+    if (!cpuid_pairs[0]) {
+        ret = 0;
+        goto cleanup;
+    }
+
+    if (STRNEQ(cpuid_pairs[0], "host")) {
+        virReportError(VIR_ERR_CONF_SYNTAX,
+                       _("cpuid starting with %s is not supported, only libxl format is"),
+                       cpuid_pairs[0]);
+        goto cleanup;
+    }
+
+    for (i = 1; cpuid_pairs[i]; i++) {
+        name_and_value = virStringSplit(cpuid_pairs[i], "=", 2);
+        if (!name_and_value)
+            goto cleanup;
+        if (!name_and_value[0] || !name_and_value[1]) {
+            virReportError(VIR_ERR_CONF_SYNTAX,
+                           _("Invalid libxl cpuid key=value element: %s"),
+                           cpuid_pairs[i]);
+            goto cleanup;
+        }
+        if (STREQ(name_and_value[1], "1")) {
+            policy = VIR_CPU_FEATURE_FORCE;
+        } else if (STREQ(name_and_value[1], "0")) {
+            policy = VIR_CPU_FEATURE_DISABLE;
+        } else if (STREQ(name_and_value[1], "x")) {
+            policy = VIR_CPU_FEATURE_OPTIONAL;
+        } else if (STREQ(name_and_value[1], "k")) {
+            policy = VIR_CPU_FEATURE_OPTIONAL;
+        } else if (STREQ(name_and_value[1], "s")) {
+            policy = VIR_CPU_FEATURE_OPTIONAL;
+        } else {
+            virReportError(VIR_ERR_CONF_SYNTAX,
+                           _("Invalid libxl cpuid value: %s"),
+                           cpuid_pairs[i]);
+            goto cleanup;
+        }
+
+        if (virCPUDefAddFeature(def->cpu,
+                                xenTranslateCPUFeature(name_and_value[0], true),
+                                policy) < 0)
+            goto cleanup;
+
+        virStringListFree(name_and_value);
+        name_and_value = NULL;
+    }
+
+    ret = 0;
+
+ cleanup:
+    virStringListFree(name_and_value);
+    virStringListFree(cpuid_pairs);
+    return ret;
+}
+
+
+static int
+xenParseXLSpice(virConfPtr conf, virDomainDefPtr def)
+{
+    virDomainGraphicsDefPtr graphics = NULL;
+    unsigned long port;
+    char *listenAddr = NULL;
+    int val;
+
+    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
+        if (xenConfigGetBool(conf, "spice", &val, 0) < 0)
+            return -1;
+
+        if (val) {
+            if (VIR_ALLOC(graphics) < 0)
+                return -1;
+
+            graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_SPICE;
+            if (xenConfigCopyStringOpt(conf, "spicehost", &listenAddr) < 0)
+                goto cleanup;
+            if (virDomainGraphicsListenAppendAddress(graphics, listenAddr) < 0)
+                goto cleanup;
+            VIR_FREE(listenAddr);
+
+            if (xenConfigGetULong(conf, "spicetls_port", &port, 0) < 0)
+                goto cleanup;
+            graphics->data.spice.tlsPort = (int)port;
+
+            if (xenConfigGetULong(conf, "spiceport", &port, 0) < 0)
+                goto cleanup;
+
+            graphics->data.spice.port = (int)port;
+
+            if (!graphics->data.spice.tlsPort &&
+                !graphics->data.spice.port)
+            graphics->data.spice.autoport = 1;
+
+            if (xenConfigGetBool(conf, "spicedisable_ticketing", &val, 0) < 0)
+                goto cleanup;
+            if (!val) {
+                if (xenConfigCopyString(conf, "spicepasswd",
+                                        &graphics->data.spice.auth.passwd) < 0)
+                    goto cleanup;
+            }
+
+            if (xenConfigGetBool(conf, "spiceagent_mouse",
+                                 &val, 0) < 0)
+                goto cleanup;
+            if (val) {
+                graphics->data.spice.mousemode =
+                    VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_CLIENT;
+            } else {
+                graphics->data.spice.mousemode =
+                    VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_SERVER;
+            }
+
+            if (xenConfigGetBool(conf, "spice_clipboard_sharing", &val, 0) < 0)
+                goto cleanup;
+            if (val)
+                graphics->data.spice.copypaste = VIR_TRISTATE_BOOL_YES;
+            else
+                graphics->data.spice.copypaste = VIR_TRISTATE_BOOL_NO;
+
+            if (VIR_ALLOC_N(def->graphics, 1) < 0)
+                goto cleanup;
+            def->graphics[0] = graphics;
+            def->ngraphics = 1;
+        }
+    }
+
+    return 0;
+
+ cleanup:
+    VIR_FREE(listenAddr);
+    virDomainGraphicsDefFree(graphics);
+    return -1;
+}
+
+#ifdef LIBXL_HAVE_VNUMA
+static int
+xenParseXLVnuma(virConfPtr conf,
+                virDomainDefPtr def)
+{
+    int ret = -1;
+    char *tmp = NULL;
+    char **token = NULL;
+    size_t vcpus = 0;
+    size_t nr_nodes = 0;
+    size_t vnodeCnt = 0;
+    virCPUDefPtr cpu = NULL;
+    virConfValuePtr list;
+    virConfValuePtr vnode;
+    virDomainNumaPtr numa;
+
+    numa = def->numa;
+    if (numa == NULL)
+        return -1;
+
+    list = virConfGetValue(conf, "vnuma");
+    if (!list || list->type != VIR_CONF_LIST)
+        return 0;
+
+    vnode = list->list;
+    while (vnode && vnode->type == VIR_CONF_LIST) {
+        vnode = vnode->next;
+        nr_nodes++;
+    }
+
+    if (!virDomainNumaSetNodeCount(numa, nr_nodes))
+        goto cleanup;
+
+    if (VIR_ALLOC(cpu) < 0)
+        goto cleanup;
+
+    list = list->list;
+    while (list) {
+        int pnode = -1;
+        virBitmapPtr cpumask = NULL;
+        unsigned long long kbsize = 0;
+
+        /* Is there a sublist (vnode)? */
+        if (list && list->type == VIR_CONF_LIST) {
+            vnode = list->list;
+
+            while (vnode && vnode->type == VIR_CONF_STRING) {
+                const char *data;
+                const char *str = vnode->str;
+
+                if (!str ||
+                   !(data = strrchr(str, '='))) {
+                    virReportError(VIR_ERR_INTERNAL_ERROR,
+                                   _("vnuma vnode invalid format '%s'"),
+                                   str);
+                    goto cleanup;
+                }
+                data++;
+
+                if (*data) {
+                    char vtoken[64];
+
+                    if (STRPREFIX(str, "pnode")) {
+                        unsigned int cellid;
+
+                        if (virStrcpyStatic(vtoken, data) < 0) {
+                            virReportError(VIR_ERR_INTERNAL_ERROR,
+                                           _("vnuma vnode %zu pnode '%s' too long for destination"),
+                                           vnodeCnt, data);
+                            goto cleanup;
+                        }
+
+                        if ((virStrToLong_ui(vtoken, NULL, 10, &cellid) < 0) ||
+                            (cellid >= nr_nodes)) {
+                            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                                           _("vnuma vnode %zu contains invalid pnode value '%s'"),
+                                           vnodeCnt, data);
+                            goto cleanup;
+                        }
+                        pnode = cellid;
+                    } else if (STRPREFIX(str, "size")) {
+                        if (virStrcpyStatic(vtoken, data) < 0) {
+                            virReportError(VIR_ERR_INTERNAL_ERROR,
+                                           _("vnuma vnode %zu size '%s' too long for destination"),
+                                           vnodeCnt, data);
+                            goto cleanup;
+                        }
+
+                        if (virStrToLong_ull(vtoken, NULL, 10, &kbsize) < 0)
+                            goto cleanup;
+
+                        virDomainNumaSetNodeMemorySize(numa, vnodeCnt, (kbsize * 1024));
+
+                    } else if (STRPREFIX(str, "vcpus")) {
+                        if (virStrcpyStatic(vtoken, data) < 0) {
+                            virReportError(VIR_ERR_INTERNAL_ERROR,
+                                           _("vnuma vnode %zu vcpus '%s' too long for destination"),
+                                           vnodeCnt, data);
+                            goto cleanup;
+                        }
+
+                        if ((virBitmapParse(vtoken, &cpumask, VIR_DOMAIN_CPUMASK_LEN) < 0) ||
+                            (virDomainNumaSetNodeCpumask(numa, vnodeCnt, cpumask) == NULL))
+                            goto cleanup;
+
+                        vcpus += virBitmapCountBits(cpumask);
+
+                    } else if (STRPREFIX(str, "vdistances")) {
+                        size_t i, ndistances;
+                        unsigned int value;
+
+                        if (virStrcpyStatic(vtoken, data) < 0) {
+                            virReportError(VIR_ERR_INTERNAL_ERROR,
+                                           _("vnuma vnode %zu vdistances '%s' too long for destination"),
+                                           vnodeCnt, data);
+                            goto cleanup;
+                        }
+
+                        VIR_FREE(tmp);
+                        if (VIR_STRDUP(tmp, vtoken) < 0)
+                            goto cleanup;
+
+                        virStringListFree(token);
+                        if (!(token = virStringSplitCount(tmp, ",", 0, &ndistances)))
+                            goto cleanup;
+
+                        if (ndistances != nr_nodes) {
+                            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                                       _("vnuma pnode %d configured '%s' (count %zu) doesn't fit the number of specified vnodes %zu"),
+                                       pnode, str, ndistances, nr_nodes);
+                            goto cleanup;
+                        }
+
+                        if (virDomainNumaSetNodeDistanceCount(numa, vnodeCnt, ndistances) != ndistances)
+                            goto cleanup;
+
+                        for (i = 0; i < ndistances; i++) {
+                            if ((virStrToLong_ui(token[i], NULL, 10, &value) < 0) ||
+                                (virDomainNumaSetNodeDistance(numa, vnodeCnt, i, value) != value))
+                                goto cleanup;
+                        }
+
+                    } else {
+                        virReportError(VIR_ERR_CONF_SYNTAX,
+                                       _("Invalid vnuma configuration for vnode %zu"),
+                                       vnodeCnt);
+                        goto cleanup;
+                    }
+                }
+                vnode = vnode->next;
+            }
+        }
+
+        if ((pnode < 0) ||
+            (cpumask == NULL) ||
+            (kbsize == 0)) {
+            virReportError(VIR_ERR_CONF_SYNTAX,
+                           _("Incomplete vnuma configuration for vnode %zu"),
+                           vnodeCnt);
+            goto cleanup;
+        }
+
+        list = list->next;
+        vnodeCnt++;
+    }
+
+    if (def->maxvcpus == 0)
+        def->maxvcpus = vcpus;
+
+    if (def->maxvcpus < vcpus) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("vnuma configuration contains %zu vcpus, which is greater than %zu maxvcpus"),
+                       vcpus, def->maxvcpus);
+        goto cleanup;
+    }
+
+    cpu->type = VIR_CPU_TYPE_GUEST;
+    def->cpu = cpu;
+
+    ret = 0;
+
+ cleanup:
+    if (ret)
+        VIR_FREE(cpu);
+    virStringListFree(token);
+    VIR_FREE(tmp);
+
+    return ret;
+}
+#endif
+
+#ifdef LIBXL_HAVE_BUILDINFO_GRANT_LIMITS
+static int
+xenParseXLGntLimits(virConfPtr conf, virDomainDefPtr def)
+{
+    unsigned long max_gntframes;
+    int ctlr_idx;
+    virDomainControllerDefPtr xenbus_ctlr;
+
+    if (xenConfigGetULong(conf, "max_grant_frames", &max_gntframes, 0) < 0)
+        return -1;
+
+    if (max_gntframes <= 0)
+        return 0;
+
+    ctlr_idx = virDomainControllerFindByType(def, VIR_DOMAIN_CONTROLLER_TYPE_XENBUS);
+    if (ctlr_idx == -1)
+        xenbus_ctlr = virDomainDefAddController(def, VIR_DOMAIN_CONTROLLER_TYPE_XENBUS, -1, -1);
+    else
+        xenbus_ctlr = def->controllers[ctlr_idx];
+
+    if (xenbus_ctlr == NULL)
+        return -1;
+
+    xenbus_ctlr->opts.xenbusopts.maxGrantFrames = max_gntframes;
+    return 0;
+}
+#endif
+
+static int
+xenParseXLDiskSrc(virDomainDiskDefPtr disk, char *srcstr)
+{
+    char *tmpstr = NULL;
+    int ret = -1;
+
+    /* A NULL source is valid, e.g. an empty CDROM */
+    if (srcstr == NULL)
+        return 0;
+
+    if (STRPREFIX(srcstr, "rbd:")) {
+        if (!(tmpstr = virStringReplace(srcstr, "\\\\", "\\")))
+            goto cleanup;
+
+        virDomainDiskSetType(disk, VIR_STORAGE_TYPE_NETWORK);
+        disk->src->protocol = VIR_STORAGE_NET_PROTOCOL_RBD;
+        ret = virStorageSourceParseRBDColonString(tmpstr, disk->src);
+    } else {
+        if (virDomainDiskSetSource(disk, srcstr) < 0)
+            goto cleanup;
+
+        ret = 0;
+    }
+
+ cleanup:
+    VIR_FREE(tmpstr);
+    return ret;
+}
+
+
+/*
+ * For details on xl disk config syntax, see
+ * docs/misc/xl-disk-configuration.txt in the Xen sources.  The important
+ * section of text is:
+ *
+ *   More formally, the string is a series of comma-separated keyword/value
+ *   pairs, flags and positional parameters.  Parameters which are not bare
+ *   keywords and which do not contain "=" symbols are assigned to the
+ *   so-far-unspecified positional parameters, in the order below.  The
+ *   positional parameters may also be specified explicitly by name.
+ *
+ *   Each parameter may be specified at most once, either as a positional
+ *   parameter or a named parameter.  Default values apply if the parameter
+ *   is not specified, or if it is specified with an empty value (whether
+ *   positionally or explicitly).
+ *
+ *   Whitespace may appear before each parameter and will be ignored.
+ *
+ * The order of the positional parameters mentioned in the quoted text is:
+ *
+ *   target,format,vdev,access
+ *
+ * The following options must be specified by key=value:
+ *
+ *   devtype=<devtype>
+ *   backendtype=<backend-type>
+ *
+ * The following options are currently not supported:
+ *
+ *   backend=<domain-name>
+ *   script=<script>
+ *   direct-io-safe
+ *
+ */
+static int
+xenParseXLDisk(virConfPtr conf, virDomainDefPtr def)
+{
+    int ret = -1;
+    virConfValuePtr list = virConfGetValue(conf, "disk");
+    XLU_Config *xluconf;
+    libxl_device_disk *libxldisk;
+    virDomainDiskDefPtr disk = NULL;
+
+    if (VIR_ALLOC(libxldisk) < 0)
+        return -1;
+
+    if (!(xluconf = xlu_cfg_init(stderr, "command line")))
+        goto cleanup;
+
+    if (list && list->type == VIR_CONF_LIST) {
+        list = list->list;
+        while (list) {
+            const char *disk_spec = list->str;
+
+            if (list->type != VIR_CONF_STRING || list->str == NULL)
+                goto skipdisk;
+
+            libxl_device_disk_init(libxldisk);
+
+            if (xlu_disk_parse(xluconf, 1, &disk_spec, libxldisk))
+                goto fail;
+
+            if (!(disk = virDomainDiskDefNew(NULL)))
+                goto fail;
+
+            if (xenParseXLDiskSrc(disk, libxldisk->pdev_path) < 0)
+                goto fail;
+
+            if (VIR_STRDUP(disk->dst, libxldisk->vdev) < 0)
+                goto fail;
+
+            disk->src->readonly = !libxldisk->readwrite;
+            disk->removable = libxldisk->removable;
+
+            if (libxldisk->is_cdrom) {
+                if (virDomainDiskSetDriver(disk, "qemu") < 0)
+                    goto fail;
+
+                virDomainDiskSetType(disk, VIR_STORAGE_TYPE_FILE);
+                disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
+                if (!disk->src->path || STREQ(disk->src->path, ""))
+                    disk->src->format = VIR_STORAGE_FILE_NONE;
+                else
+                    disk->src->format = VIR_STORAGE_FILE_RAW;
+            } else {
+                switch (libxldisk->format) {
+                case LIBXL_DISK_FORMAT_QCOW:
+                    disk->src->format = VIR_STORAGE_FILE_QCOW;
+                    break;
+
+                case LIBXL_DISK_FORMAT_QCOW2:
+                    disk->src->format = VIR_STORAGE_FILE_QCOW2;
+                    break;
+
+                case LIBXL_DISK_FORMAT_VHD:
+                    disk->src->format = VIR_STORAGE_FILE_VHD;
+                    break;
+
+                case LIBXL_DISK_FORMAT_RAW:
+                case LIBXL_DISK_FORMAT_UNKNOWN:
+                    disk->src->format = VIR_STORAGE_FILE_RAW;
+                    break;
+
+                case LIBXL_DISK_FORMAT_EMPTY:
+                    break;
+
+#ifdef LIBXL_HAVE_QED
+                case LIBXL_DISK_FORMAT_QED:
+                    disk->src->format = VIR_STORAGE_FILE_QED;
+                    break;
+#endif
+
+                default:
+                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                                   _("disk image format not supported: %s"),
+                                   libxl_disk_format_to_string(libxldisk->format));
+                    goto fail;
+                }
+
+                switch (libxldisk->backend) {
+                case LIBXL_DISK_BACKEND_QDISK:
+                case LIBXL_DISK_BACKEND_UNKNOWN:
+                    if (virDomainDiskSetDriver(disk, "qemu") < 0)
+                        goto fail;
+                    if (virDomainDiskGetType(disk) == VIR_STORAGE_TYPE_NONE)
+                        virDomainDiskSetType(disk, VIR_STORAGE_TYPE_FILE);
+                    break;
+
+                case LIBXL_DISK_BACKEND_TAP:
+                    if (virDomainDiskSetDriver(disk, "tap") < 0)
+                        goto fail;
+                    virDomainDiskSetType(disk, VIR_STORAGE_TYPE_FILE);
+                    break;
+
+                case LIBXL_DISK_BACKEND_PHY:
+                    if (virDomainDiskSetDriver(disk, "phy") < 0)
+                        goto fail;
+                    virDomainDiskSetType(disk, VIR_STORAGE_TYPE_BLOCK);
+                    break;
+                default:
+                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                                   _("disk backend not supported: %s"),
+                                   libxl_disk_backend_to_string(libxldisk->backend));
+                    goto fail;
+                }
+            }
+
+            if (STRPREFIX(libxldisk->vdev, "xvd") ||
+                def->os.type != VIR_DOMAIN_OSTYPE_HVM)
+                disk->bus = VIR_DOMAIN_DISK_BUS_XEN;
+            else if (STRPREFIX(libxldisk->vdev, "sd"))
+                disk->bus = VIR_DOMAIN_DISK_BUS_SCSI;
+            else
+                disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
+
+            if (VIR_APPEND_ELEMENT(def->disks, def->ndisks, disk) < 0)
+                goto fail;
+
+            libxl_device_disk_dispose(libxldisk);
+
+        skipdisk:
+            list = list->next;
+        }
+    }
+    ret = 0;
+
+ cleanup:
+    virDomainDiskDefFree(disk);
+    xlu_cfg_destroy(xluconf);
+    VIR_FREE(libxldisk);
+    return ret;
+
+ fail:
+    libxl_device_disk_dispose(libxldisk);
+    goto cleanup;
+}
+
+static int
+xenParseXLInputDevs(virConfPtr conf, virDomainDefPtr def)
+{
+    const char *str;
+    virConfValuePtr val;
+
+    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
+        val = virConfGetValue(conf, "usbdevice");
+        /* usbdevice can be defined as either a single string or a list */
+        if (val && val->type == VIR_CONF_LIST) {
+#ifdef LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST
+            val = val->list;
+#else
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("multiple USB devices not supported"));
+            return -1;
+#endif
+        }
+        /* otherwise val->next is NULL, so can be handled by the same code */
+        while (val) {
+            if (val->type != VIR_CONF_STRING) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("config value %s was malformed"),
+                               "usbdevice");
+                return -1;
+            }
+            str = val->str;
+
+            if (str &&
+                    (STREQ(str, "tablet") ||
+                     STREQ(str, "mouse") ||
+                     STREQ(str, "keyboard"))) {
+                virDomainInputDefPtr input;
+                if (VIR_ALLOC(input) < 0)
+                    return -1;
+
+                input->bus = VIR_DOMAIN_INPUT_BUS_USB;
+                if (STREQ(str, "mouse"))
+                    input->type = VIR_DOMAIN_INPUT_TYPE_MOUSE;
+                else if (STREQ(str, "tablet"))
+                    input->type = VIR_DOMAIN_INPUT_TYPE_TABLET;
+                else if (STREQ(str, "keyboard"))
+                    input->type = VIR_DOMAIN_INPUT_TYPE_KBD;
+                if (VIR_APPEND_ELEMENT(def->inputs, def->ninputs, input) < 0) {
+                    virDomainInputDefFree(input);
+                    return -1;
+                }
+            }
+            val = val->next;
+        }
+    }
+    return 0;
+}
+
+static int
+xenParseXLUSBController(virConfPtr conf, virDomainDefPtr def)
+{
+    virConfValuePtr list = virConfGetValue(conf, "usbctrl");
+    virDomainControllerDefPtr controller = NULL;
+
+    if (list && list->type == VIR_CONF_LIST) {
+        list = list->list;
+        while (list) {
+            char type[8];
+            char version[4];
+            char ports[4];
+            char *key;
+            int usbctrl_version = 2; /* by default USB 2.0 */
+            int usbctrl_ports = 8; /* by default 8 ports */
+            int usbctrl_type = -1;
+
+            type[0] = version[0] = ports[0] = '\0';
+
+            if ((list->type != VIR_CONF_STRING) || (list->str == NULL))
+                goto skipusbctrl;
+            /* usbctrl=['type=pv,version=2,ports=8'] */
+            key = list->str;
+            while (key) {
+                char *data;
+                char *nextkey = strchr(key, ',');
+
+                if (!(data = strchr(key, '=')))
+                    goto skipusbctrl;
+                data++;
+
+                if (STRPREFIX(key, "type=")) {
+                    int len = nextkey ? (nextkey - data) : strlen(data);
+                    if (virStrncpy(type, data, len, sizeof(type)) < 0) {
+                        virReportError(VIR_ERR_INTERNAL_ERROR,
+                                       _("type %s invalid"),
+                                       data);
+                        goto skipusbctrl;
+                    }
+                } else if (STRPREFIX(key, "version=")) {
+                    int len = nextkey ? (nextkey - data) : strlen(data);
+                    if (virStrncpy(version, data, len, sizeof(version)) < 0) {
+                        virReportError(VIR_ERR_INTERNAL_ERROR,
+                                       _("version %s invalid"),
+                                       data);
+                        goto skipusbctrl;
+                    }
+                    if (virStrToLong_i(version, NULL, 16, &usbctrl_version) < 0)
+                        goto skipusbctrl;
+                } else if (STRPREFIX(key, "ports=")) {
+                    int len = nextkey ? (nextkey - data) : strlen(data);
+                    if (virStrncpy(ports, data, len, sizeof(ports)) < 0) {
+                        virReportError(VIR_ERR_INTERNAL_ERROR,
+                                       _("version %s invalid"),
+                                       data);
+                        goto skipusbctrl;
+                    }
+                    if (virStrToLong_i(ports, NULL, 16, &usbctrl_ports) < 0)
+                        goto skipusbctrl;
+                }
+
+                while (nextkey && (nextkey[0] == ',' ||
+                                   nextkey[0] == ' ' ||
+                                   nextkey[0] == '\t'))
+                    nextkey++;
+                key = nextkey;
+            }
+
+            if (type[0] == '\0') {
+                if (usbctrl_version == 1)
+                    usbctrl_type = VIR_DOMAIN_CONTROLLER_MODEL_USB_QUSB1;
+                else
+                    usbctrl_type = VIR_DOMAIN_CONTROLLER_MODEL_USB_QUSB2;
+            } else {
+                if (STREQLEN(type, "qusb", 4)) {
+                    if (usbctrl_version == 1)
+                        usbctrl_type = VIR_DOMAIN_CONTROLLER_MODEL_USB_QUSB1;
+                    else
+                        usbctrl_type = VIR_DOMAIN_CONTROLLER_MODEL_USB_QUSB2;
+                } else {
+                    goto skipusbctrl;
+                }
+            }
+
+            if (!(controller = virDomainControllerDefNew(VIR_DOMAIN_CONTROLLER_TYPE_USB)))
+                return -1;
+
+            controller->type = VIR_DOMAIN_CONTROLLER_TYPE_USB;
+            controller->model = usbctrl_type;
+            controller->opts.usbopts.ports = usbctrl_ports;
+
+            if (VIR_APPEND_ELEMENT(def->controllers, def->ncontrollers, controller) < 0) {
+                virDomainControllerDefFree(controller);
+                return -1;
+            }
+
+        skipusbctrl:
+            list = list->next;
+        }
+    }
+
+    return 0;
+}
+
+static int
+xenParseXLUSB(virConfPtr conf, virDomainDefPtr def)
+{
+    virConfValuePtr list = virConfGetValue(conf, "usbdev");
+    virDomainHostdevDefPtr hostdev = NULL;
+
+    if (list && list->type == VIR_CONF_LIST) {
+        list = list->list;
+        while (list) {
+            char bus[3];
+            char device[3];
+            char *key;
+            int busNum;
+            int devNum;
+
+            bus[0] = device[0] = '\0';
+
+            if ((list->type != VIR_CONF_STRING) || (list->str == NULL))
+                goto skipusb;
+            /* usbdev=['hostbus=1,hostaddr=3'] */
+            key = list->str;
+            while (key) {
+                char *data;
+                char *nextkey = strchr(key, ',');
+
+                if (!(data = strchr(key, '=')))
+                    goto skipusb;
+                data++;
+
+                if (STRPREFIX(key, "hostbus=")) {
+                    int len = nextkey ? (nextkey - data) : strlen(data);
+                    if (virStrncpy(bus, data, len, sizeof(bus)) < 0) {
+                        virReportError(VIR_ERR_INTERNAL_ERROR,
+                                       _("bus %s too big for destination"),
+                                       data);
+                        goto skipusb;
+                    }
+                } else if (STRPREFIX(key, "hostaddr=")) {
+                    int len = nextkey ? (nextkey - data) : strlen(data);
+                    if (virStrncpy(device, data, len, sizeof(device)) < 0) {
+                        virReportError(VIR_ERR_INTERNAL_ERROR,
+                                       _("device %s too big for destination"),
+                                       data);
+                        goto skipusb;
+                    }
+                }
+
+                while (nextkey && (nextkey[0] == ',' ||
+                                   nextkey[0] == ' ' ||
+                                   nextkey[0] == '\t'))
+                    nextkey++;
+                key = nextkey;
+            }
+
+            if (virStrToLong_i(bus, NULL, 16, &busNum) < 0)
+                goto skipusb;
+            if (virStrToLong_i(device, NULL, 16, &devNum) < 0)
+                goto skipusb;
+            if (!(hostdev = virDomainHostdevDefNew()))
+               return -1;
+
+            hostdev->managed = false;
+            hostdev->source.subsys.type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB;
+            hostdev->source.subsys.u.usb.bus = busNum;
+            hostdev->source.subsys.u.usb.device = devNum;
+
+            if (VIR_APPEND_ELEMENT(def->hostdevs, def->nhostdevs, hostdev) < 0) {
+                virDomainHostdevDefFree(hostdev);
+                return -1;
+            }
+
+        skipusb:
+            list = list->next;
+        }
+    }
+
+    return 0;
+}
+
+static int
+xenParseXLChannel(virConfPtr conf, virDomainDefPtr def)
+{
+    virConfValuePtr list = virConfGetValue(conf, "channel");
+    virDomainChrDefPtr channel = NULL;
+    char *name = NULL;
+    char *path = NULL;
+
+    if (list && list->type == VIR_CONF_LIST) {
+        list = list->list;
+        while (list) {
+            char type[10];
+            char *key;
+
+            if ((list->type != VIR_CONF_STRING) || (list->str == NULL))
+                goto skipchannel;
+
+            key = list->str;
+            while (key) {
+                char *data;
+                char *nextkey = strchr(key, ',');
+
+                if (!(data = strchr(key, '=')))
+                    goto skipchannel;
+                data++;
+
+                if (STRPREFIX(key, "connection=")) {
+                    int len = nextkey ? (nextkey - data) : strlen(data);
+                    if (virStrncpy(type, data, len, sizeof(type)) < 0) {
+                        virReportError(VIR_ERR_INTERNAL_ERROR,
+                                       _("connection %s too big"), data);
+                        goto skipchannel;
+                    }
+                } else if (STRPREFIX(key, "name=")) {
+                    int len = nextkey ? (nextkey - data) : strlen(data);
+                    VIR_FREE(name);
+                    if (VIR_STRNDUP(name, data, len) < 0)
+                        goto cleanup;
+                } else if (STRPREFIX(key, "path=")) {
+                    int len = nextkey ? (nextkey - data) : strlen(data);
+                    VIR_FREE(path);
+                    if (VIR_STRNDUP(path, data, len) < 0)
+                        goto cleanup;
+                }
+
+                while (nextkey && (nextkey[0] == ',' ||
+                                   nextkey[0] == ' ' ||
+                                   nextkey[0] == '\t'))
+                    nextkey++;
+                key = nextkey;
+            }
+
+            if (!(channel = virDomainChrDefNew(NULL)))
+                goto cleanup;
+
+            if (STRPREFIX(type, "socket")) {
+                channel->source->type = VIR_DOMAIN_CHR_TYPE_UNIX;
+                channel->source->data.nix.listen = 1;
+                channel->source->data.nix.path = path;
+                path = NULL;
+            } else if (STRPREFIX(type, "pty")) {
+                channel->source->type = VIR_DOMAIN_CHR_TYPE_PTY;
+                VIR_FREE(path);
+            } else {
+                goto cleanup;
+            }
+
+            channel->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL;
+            channel->targetType = VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_XEN;
+            channel->target.name = name;
+            name = NULL;
+
+            if (VIR_APPEND_ELEMENT(def->channels, def->nchannels, channel) < 0)
+                goto cleanup;
+
+        skipchannel:
+            list = list->next;
+        }
+    }
+
+    return 0;
+
+ cleanup:
+    virDomainChrDefFree(channel);
+    VIR_FREE(path);
+    VIR_FREE(name);
+    return -1;
+}
+
+virDomainDefPtr
+xenParseXL(virConfPtr conf,
+           virCapsPtr caps,
+           virDomainXMLOptionPtr xmlopt)
+{
+    virDomainDefPtr def = NULL;
+
+    if (!(def = virDomainDefNew()))
+        return NULL;
+
+    def->virtType = VIR_DOMAIN_VIRT_XEN;
+    def->id = -1;
+
+    if (xenParseConfigCommon(conf, def, caps, XEN_CONFIG_FORMAT_XL,
+                             xmlopt) < 0)
+        goto cleanup;
+
+    if (xenParseXLOS(conf, def, caps) < 0)
+        goto cleanup;
+
+#ifdef LIBXL_HAVE_VNUMA
+    if (xenParseXLVnuma(conf, def) < 0)
+        goto cleanup;
+#endif
+
+#ifdef LIBXL_HAVE_BUILDINFO_GRANT_LIMITS
+    if (xenParseXLGntLimits(conf, def) < 0)
+        goto cleanup;
+#endif
+
+    if (xenParseXLCPUID(conf, def) < 0)
+        goto cleanup;
+
+    if (xenParseXLDisk(conf, def) < 0)
+        goto cleanup;
+
+    if (xenParseXLSpice(conf, def) < 0)
+        goto cleanup;
+
+    if (xenParseXLInputDevs(conf, def) < 0)
+        goto cleanup;
+
+    if (xenParseXLUSB(conf, def) < 0)
+        goto cleanup;
+
+    if (xenParseXLUSBController(conf, def) < 0)
+        goto cleanup;
+
+    if (xenParseXLChannel(conf, def) < 0)
+        goto cleanup;
+
+    if (virDomainDefPostParse(def, caps, VIR_DOMAIN_DEF_PARSE_ABI_UPDATE,
+                              xmlopt, NULL) < 0)
+        goto cleanup;
+
+    return def;
+
+ cleanup:
+    virDomainDefFree(def);
+    return NULL;
+}
+
+
+static int
+xenFormatXLOS(virConfPtr conf, virDomainDefPtr def)
+{
+    size_t i;
+
+    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
+        char boot[VIR_DOMAIN_BOOT_LAST+1];
+        if (xenConfigSetString(conf, "builder", "hvm") < 0)
+            return -1;
+
+        if (def->os.loader &&
+            def->os.loader->type == VIR_DOMAIN_LOADER_TYPE_PFLASH) {
+            if (xenConfigSetString(conf, "bios", "ovmf") < 0)
+                return -1;
+        }
+
+#ifdef LIBXL_HAVE_BUILDINFO_KERNEL
+        if (def->os.kernel &&
+            xenConfigSetString(conf, "kernel", def->os.kernel) < 0)
+            return -1;
+
+        if (def->os.initrd &&
+            xenConfigSetString(conf, "ramdisk", def->os.initrd) < 0)
+            return -1;
+
+        if (def->os.cmdline &&
+            xenConfigSetString(conf, "cmdline", def->os.cmdline) < 0)
+            return -1;
+#endif
+
+        for (i = 0; i < def->os.nBootDevs; i++) {
+            switch (def->os.bootDevs[i]) {
+            case VIR_DOMAIN_BOOT_FLOPPY:
+                boot[i] = 'a';
+                break;
+            case VIR_DOMAIN_BOOT_CDROM:
+                boot[i] = 'd';
+                break;
+            case VIR_DOMAIN_BOOT_NET:
+                boot[i] = 'n';
+                break;
+            case VIR_DOMAIN_BOOT_DISK:
+            default:
+                boot[i] = 'c';
+                break;
+            }
+        }
+
+        if (!def->os.nBootDevs) {
+            boot[0] = 'c';
+            boot[1] = '\0';
+        } else {
+            boot[def->os.nBootDevs] = '\0';
+        }
+
+        if (xenConfigSetString(conf, "boot", boot) < 0)
+            return -1;
+
+        if (def->cpu &&
+            def->cpu->mode == VIR_CPU_MODE_HOST_PASSTHROUGH) {
+            bool hasHwVirt = true;
+
+            if (def->cpu->nfeatures) {
+                for (i = 0; i < def->cpu->nfeatures; i++) {
+
+                    switch (def->cpu->features[i].policy) {
+                        case VIR_CPU_FEATURE_DISABLE:
+                        case VIR_CPU_FEATURE_FORBID:
+                            if (STREQ(def->cpu->features[i].name, "vmx") ||
+                                STREQ(def->cpu->features[i].name, "svm"))
+                                hasHwVirt = false;
+                            break;
+
+                        case VIR_CPU_FEATURE_FORCE:
+                        case VIR_CPU_FEATURE_REQUIRE:
+                        case VIR_CPU_FEATURE_OPTIONAL:
+                        case VIR_CPU_FEATURE_LAST:
+                            break;
+                    }
+                }
+            }
+
+            if (xenConfigSetInt(conf, "nestedhvm", hasHwVirt) < 0)
+                return -1;
+        }
+
+        /* XXX floppy disks */
+    } else {
+        if (def->os.type == VIR_DOMAIN_OSTYPE_XENPVH) {
+            if (xenConfigSetString(conf, "type", "pvh") < 0)
+                return -1;
+        }
+
+        if (def->os.bootloader &&
+             xenConfigSetString(conf, "bootloader", def->os.bootloader) < 0)
+            return -1;
+
+         if (def->os.bootloaderArgs &&
+             xenConfigSetString(conf, "bootargs", def->os.bootloaderArgs) < 0)
+            return -1;
+
+         if (def->os.kernel &&
+             xenConfigSetString(conf, "kernel", def->os.kernel) < 0)
+            return -1;
+
+         if (def->os.initrd &&
+             xenConfigSetString(conf, "ramdisk", def->os.initrd) < 0)
+            return -1;
+
+         if (def->os.cmdline &&
+             xenConfigSetString(conf, "cmdline", def->os.cmdline) < 0)
+            return -1;
+     } /* !hvm */
+
+    return 0;
+}
+
+static int
+xenFormatXLCPUID(virConfPtr conf, virDomainDefPtr def)
+{
+    char **cpuid_pairs = NULL;
+    char *cpuid_string = NULL;
+    size_t i, j;
+    int ret = -1;
+
+    if (!def->cpu)
+        return 0;
+
+    if (def->cpu->mode != VIR_CPU_MODE_HOST_PASSTHROUGH) {
+        VIR_WARN("ignoring CPU mode '%s', only host-passthrough mode "
+                 "is supported", virCPUModeTypeToString(def->cpu->mode));
+        return 0;
+    }
+
+    /* "host" + all features + NULL */
+    if (VIR_ALLOC_N(cpuid_pairs, def->cpu->nfeatures + 2) < 0)
+        return -1;
+
+    if (VIR_STRDUP(cpuid_pairs[0], "host") < 0)
+        goto cleanup;
+
+    j = 1;
+    for (i = 0; i < def->cpu->nfeatures; i++) {
+        const char *feature_name = xenTranslateCPUFeature(
+                def->cpu->features[i].name,
+                false);
+        const char *policy = NULL;
+
+        if (STREQ(feature_name, "vmx") || STREQ(feature_name, "svm"))
+            /* ignore vmx/svm in cpuid option, translated into nestedhvm
+             * elsewhere */
+            continue;
+
+        switch (def->cpu->features[i].policy) {
+            case VIR_CPU_FEATURE_FORCE:
+            case VIR_CPU_FEATURE_REQUIRE:
+                policy = "1";
+                break;
+            case VIR_CPU_FEATURE_OPTIONAL:
+                policy = "x";
+                break;
+            case VIR_CPU_FEATURE_DISABLE:
+            case VIR_CPU_FEATURE_FORBID:
+                policy = "0";
+                break;
+        }
+        if (virAsprintf(&cpuid_pairs[j++], "%s=%s",
+                        feature_name,
+                        policy) < 0)
+            goto cleanup;
+    }
+    cpuid_pairs[j] = NULL;
+
+    if (j > 1) {
+        cpuid_string = virStringListJoin((const char **)cpuid_pairs, ",");
+        if (!cpuid_string)
+            goto cleanup;
+
+        if (xenConfigSetString(conf, "cpuid", cpuid_string) < 0)
+            goto cleanup;
+    }
+
+    ret = 0;
+
+ cleanup:
+    virStringListFree(cpuid_pairs);
+    VIR_FREE(cpuid_string);
+    return ret;
+}
+
+#ifdef LIBXL_HAVE_VNUMA
+static int
+xenFormatXLVnode(virConfValuePtr list,
+                 virBufferPtr buf)
+{
+    int ret = -1;
+    virConfValuePtr numaPnode, tmp;
+
+    if (virBufferCheckError(buf) < 0)
+        goto cleanup;
+
+    if (VIR_ALLOC(numaPnode) < 0)
+        goto cleanup;
+
+    /* Place VNODE directive */
+    numaPnode->type = VIR_CONF_STRING;
+    numaPnode->str = virBufferContentAndReset(buf);
+
+    tmp = list->list;
+    while (tmp && tmp->next)
+        tmp = tmp->next;
+    if (tmp)
+        tmp->next = numaPnode;
+    else
+        list->list = numaPnode;
+    ret = 0;
+
+ cleanup:
+    virBufferFreeAndReset(buf);
+    return ret;
+}
+
+static int
+xenFormatXLVnuma(virConfValuePtr list,
+                 virDomainNumaPtr numa,
+                 size_t node,
+                 size_t nr_nodes)
+{
+    int ret = -1;
+    size_t i;
+
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    virConfValuePtr numaVnode, tmp;
+
+    size_t nodeSize = virDomainNumaGetNodeMemorySize(numa, node) / 1024;
+    char *nodeVcpus = virBitmapFormat(virDomainNumaGetNodeCpumask(numa, node));
+
+    if (VIR_ALLOC(numaVnode) < 0)
+        goto cleanup;
+
+    numaVnode->type = VIR_CONF_LIST;
+    numaVnode->list = NULL;
+
+    /* pnode */
+    virBufferAsprintf(&buf, "pnode=%zu", node);
+    xenFormatXLVnode(numaVnode, &buf);
+
+    /* size */
+    virBufferAsprintf(&buf, "size=%zu", nodeSize);
+    xenFormatXLVnode(numaVnode, &buf);
+
+    /* vcpus */
+    virBufferAsprintf(&buf, "vcpus=%s", nodeVcpus);
+    xenFormatXLVnode(numaVnode, &buf);
+
+    /* distances */
+    virBufferAddLit(&buf, "vdistances=");
+    for (i = 0; i < nr_nodes; i++) {
+        virBufferAsprintf(&buf, "%zu",
+            virDomainNumaGetNodeDistance(numa, node, i));
+        if ((nr_nodes - i) > 1)
+            virBufferAddLit(&buf, ",");
+    }
+    xenFormatXLVnode(numaVnode, &buf);
+
+    tmp = list->list;
+    while (tmp && tmp->next)
+        tmp = tmp->next;
+    if (tmp)
+        tmp->next = numaVnode;
+    else
+        list->list = numaVnode;
+    ret = 0;
+
+ cleanup:
+    VIR_FREE(nodeVcpus);
+    return ret;
+}
+
+static int
+xenFormatXLDomainVnuma(virConfPtr conf,
+                       virDomainDefPtr def)
+{
+    virDomainNumaPtr numa = def->numa;
+    virConfValuePtr vnumaVal;
+    size_t i;
+    size_t nr_nodes;
+
+    if (numa == NULL)
+        return -1;
+
+    if (VIR_ALLOC(vnumaVal) < 0)
+        return -1;
+
+    vnumaVal->type = VIR_CONF_LIST;
+    vnumaVal->list = NULL;
+
+    nr_nodes = virDomainNumaGetNodeCount(numa);
+    for (i = 0; i < nr_nodes; i++) {
+        if (xenFormatXLVnuma(vnumaVal, numa, i, nr_nodes) < 0)
+            goto cleanup;
+    }
+
+    if (vnumaVal->list != NULL) {
+        int ret = virConfSetValue(conf, "vnuma", vnumaVal);
+            vnumaVal = NULL;
+            if (ret < 0)
+                return -1;
+    }
+    VIR_FREE(vnumaVal);
+
+    return 0;
+
+ cleanup:
+    virConfFreeValue(vnumaVal);
+    return -1;
+}
+#endif
+
+#ifdef LIBXL_HAVE_BUILDINFO_GRANT_LIMITS
+static int
+xenFormatXLGntLimits(virConfPtr conf, virDomainDefPtr def)
+{
+    size_t i;
+
+    for (i = 0; i < def->ncontrollers; i++) {
+        if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_XENBUS &&
+            def->controllers[i]->opts.xenbusopts.maxGrantFrames > 0) {
+            if (xenConfigSetInt(conf, "max_grant_frames",
+                                def->controllers[i]->opts.xenbusopts.maxGrantFrames) < 0)
+                return -1;
+        }
+    }
+    return 0;
+}
+#endif
+
+static char *
+xenFormatXLDiskSrcNet(virStorageSourcePtr src)
+{
+    char *ret = NULL;
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    size_t i;
+
+    switch ((virStorageNetProtocol) src->protocol) {
+    case VIR_STORAGE_NET_PROTOCOL_NBD:
+    case VIR_STORAGE_NET_PROTOCOL_HTTP:
+    case VIR_STORAGE_NET_PROTOCOL_HTTPS:
+    case VIR_STORAGE_NET_PROTOCOL_FTP:
+    case VIR_STORAGE_NET_PROTOCOL_FTPS:
+    case VIR_STORAGE_NET_PROTOCOL_TFTP:
+    case VIR_STORAGE_NET_PROTOCOL_ISCSI:
+    case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
+    case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG:
+    case VIR_STORAGE_NET_PROTOCOL_SSH:
+    case VIR_STORAGE_NET_PROTOCOL_VXHS:
+    case VIR_STORAGE_NET_PROTOCOL_LAST:
+    case VIR_STORAGE_NET_PROTOCOL_NONE:
+        virReportError(VIR_ERR_NO_SUPPORT,
+                       _("Unsupported network block protocol '%s'"),
+                       virStorageNetProtocolTypeToString(src->protocol));
+        goto cleanup;
+
+    case VIR_STORAGE_NET_PROTOCOL_RBD:
+        if (strchr(src->path, ':')) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           _("':' not allowed in RBD source volume name '%s'"),
+                           src->path);
+            goto cleanup;
+        }
+
+        virBufferStrcat(&buf, "rbd:", src->volume, "/", src->path, NULL);
+
+        virBufferAddLit(&buf, ":auth_supported=none");
+
+        if (src->nhosts > 0) {
+            virBufferAddLit(&buf, ":mon_host=");
+            for (i = 0; i < src->nhosts; i++) {
+                if (i)
+                    virBufferAddLit(&buf, "\\\\;");
+
+                /* assume host containing : is ipv6 */
+                if (strchr(src->hosts[i].name, ':'))
+                    virBufferEscape(&buf, '\\', ":", "[%s]",
+                                    src->hosts[i].name);
+                else
+                    virBufferAsprintf(&buf, "%s", src->hosts[i].name);
+
+                if (src->hosts[i].port)
+                    virBufferAsprintf(&buf, "\\\\:%u", src->hosts[i].port);
+            }
+        }
+
+        if (virBufferCheckError(&buf) < 0)
+            goto cleanup;
+
+        ret = virBufferContentAndReset(&buf);
+        break;
+    }
+
+ cleanup:
+    virBufferFreeAndReset(&buf);
+
+    return ret;
+}
+
+
+static int
+xenFormatXLDiskSrc(virStorageSourcePtr src, char **srcstr)
+{
+    int actualType = virStorageSourceGetActualType(src);
+
+    *srcstr = NULL;
+
+    if (virStorageSourceIsEmpty(src))
+        return 0;
+
+    switch ((virStorageType)actualType) {
+    case VIR_STORAGE_TYPE_BLOCK:
+    case VIR_STORAGE_TYPE_FILE:
+    case VIR_STORAGE_TYPE_DIR:
+        if (VIR_STRDUP(*srcstr, src->path) < 0)
+            return -1;
+        break;
+
+    case VIR_STORAGE_TYPE_NETWORK:
+        if (!(*srcstr = xenFormatXLDiskSrcNet(src)))
+            return -1;
+        break;
+
+    case VIR_STORAGE_TYPE_VOLUME:
+    case VIR_STORAGE_TYPE_NONE:
+    case VIR_STORAGE_TYPE_LAST:
+        break;
+    }
+
+    return 0;
+}
+
+
+static int
+xenFormatXLDisk(virConfValuePtr list, virDomainDiskDefPtr disk)
+{
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    virConfValuePtr val, tmp;
+    int format = virDomainDiskGetFormat(disk);
+    const char *driver = virDomainDiskGetDriver(disk);
+    char *target = NULL;
+    int ret = -1;
+
+    /* format */
+    virBufferAddLit(&buf, "format=");
+    switch (format) {
+        case VIR_STORAGE_FILE_RAW:
+            virBufferAddLit(&buf, "raw");
+            break;
+        case VIR_STORAGE_FILE_VHD:
+            virBufferAddLit(&buf, "xvhd");
+            break;
+        case VIR_STORAGE_FILE_QCOW:
+            virBufferAddLit(&buf, "qcow");
+            break;
+        case VIR_STORAGE_FILE_QCOW2:
+            virBufferAddLit(&buf, "qcow2");
+            break;
+        case VIR_STORAGE_FILE_QED:
+            virBufferAddLit(&buf, "qed");
+            break;
+      /* set default */
+        default:
+            virBufferAddLit(&buf, "raw");
+    }
+
+    /* device */
+    virBufferAsprintf(&buf, ",vdev=%s", disk->dst);
+
+    /* access */
+    virBufferAddLit(&buf, ",access=");
+    if (disk->src->readonly)
+        virBufferAddLit(&buf, "ro");
+    else if (disk->src->shared)
+        virBufferAddLit(&buf, "!");
+    else
+        virBufferAddLit(&buf, "rw");
+    if (disk->transient) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("transient disks not supported yet"));
+        goto cleanup;
+    }
+
+    /* backendtype */
+    if (driver) {
+        virBufferAddLit(&buf, ",backendtype=");
+        if (STREQ(driver, "qemu") || STREQ(driver, "file"))
+            virBufferAddLit(&buf, "qdisk");
+        else if (STREQ(driver, "tap"))
+            virBufferAddLit(&buf, "tap");
+        else if (STREQ(driver, "phy"))
+            virBufferAddLit(&buf, "phy");
+    }
+
+    /* devtype */
+    if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM)
+        virBufferAddLit(&buf, ",devtype=cdrom");
+
+    /*
+     * target
+     * From $xensrc/docs/misc/xl-disk-configuration.txt:
+     * When this parameter is specified by name, ie with the "target="
+     * syntax in the configuration file, it consumes the whole rest of the
+     * <diskspec> including trailing whitespaces.  Therefore in that case
+     * it must come last.
+     */
+    if (xenFormatXLDiskSrc(disk->src, &target) < 0)
+        goto cleanup;
+
+    if (target)
+        virBufferAsprintf(&buf, ",target=%s", target);
+
+    if (virBufferCheckError(&buf) < 0)
+        goto cleanup;
+
+    if (VIR_ALLOC(val) < 0)
+        goto cleanup;
+
+    val->type = VIR_CONF_STRING;
+    val->str = virBufferContentAndReset(&buf);
+    tmp = list->list;
+    while (tmp && tmp->next)
+        tmp = tmp->next;
+    if (tmp)
+        tmp->next = val;
+    else
+        list->list = val;
+    ret = 0;
+
+ cleanup:
+    VIR_FREE(target);
+    virBufferFreeAndReset(&buf);
+    return ret;
+}
+
+
+static int
+xenFormatXLDomainDisks(virConfPtr conf, virDomainDefPtr def)
+{
+    virConfValuePtr diskVal;
+    size_t i;
+
+    if (VIR_ALLOC(diskVal) < 0)
+        return -1;
+
+    diskVal->type = VIR_CONF_LIST;
+    diskVal->list = NULL;
+
+    for (i = 0; i < def->ndisks; i++) {
+        if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY)
+            continue;
+
+        if (xenFormatXLDisk(diskVal, def->disks[i]) < 0)
+            goto cleanup;
+    }
+
+    if (diskVal->list != NULL) {
+        int ret = virConfSetValue(conf, "disk", diskVal);
+        diskVal = NULL;
+        if (ret < 0)
+            return -1;
+    }
+    VIR_FREE(diskVal);
+
+    return 0;
+
+ cleanup:
+    virConfFreeValue(diskVal);
+    return -1;
+}
+
+
+static int
+xenFormatXLSpice(virConfPtr conf, virDomainDefPtr def)
+{
+    virDomainGraphicsListenDefPtr glisten;
+    virDomainGraphicsDefPtr graphics;
+
+    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM && def->graphics) {
+        graphics = def->graphics[0];
+
+        if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
+            /* set others to false but may not be necessary */
+            if (xenConfigSetInt(conf, "sdl", 0) < 0)
+                return -1;
+
+            if (xenConfigSetInt(conf, "vnc", 0) < 0)
+                return -1;
+
+            if (xenConfigSetInt(conf, "spice", 1) < 0)
+                return -1;
+
+            if ((glisten = virDomainGraphicsGetListen(graphics, 0)) &&
+                glisten->address &&
+                xenConfigSetString(conf, "spicehost", glisten->address) < 0)
+                return -1;
+
+            if (xenConfigSetInt(conf, "spiceport",
+                                graphics->data.spice.port) < 0)
+                return -1;
+
+            if (xenConfigSetInt(conf, "spicetls_port",
+                                graphics->data.spice.tlsPort) < 0)
+                return -1;
+
+            if (graphics->data.spice.auth.passwd) {
+                if (xenConfigSetInt(conf, "spicedisable_ticketing", 0) < 0)
+                    return -1;
+
+                if (xenConfigSetString(conf, "spicepasswd",
+                                       graphics->data.spice.auth.passwd) < 0)
+                    return -1;
+            } else {
+                if (xenConfigSetInt(conf, "spicedisable_ticketing", 1) < 0)
+                    return -1;
+            }
+
+            if (graphics->data.spice.mousemode) {
+                switch (graphics->data.spice.mousemode) {
+                case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_SERVER:
+                    if (xenConfigSetInt(conf, "spiceagent_mouse", 0) < 0)
+                        return -1;
+                    break;
+                case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_CLIENT:
+                    if (xenConfigSetInt(conf, "spiceagent_mouse", 1) < 0)
+                        return -1;
+                    /*
+                     * spicevdagent must be enabled if using client
+                     * mode mouse
+                     */
+                    if (xenConfigSetInt(conf, "spicevdagent", 1) < 0)
+                        return -1;
+                    break;
+                case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_DEFAULT:
+                    break;
+                case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_LAST:
+                default:
+                    virReportEnumRangeError(virDomainGraphicsSpiceMouseMode,
+                                            graphics->data.spice.mousemode);
+                    return -1;
+                }
+            }
+
+            if (graphics->data.spice.copypaste == VIR_TRISTATE_BOOL_YES) {
+                if (xenConfigSetInt(conf, "spice_clipboard_sharing", 1) < 0)
+                    return -1;
+                /*
+                 * spicevdagent must be enabled if spice_clipboard_sharing
+                 * is enabled
+                 */
+                if (xenConfigSetInt(conf, "spicevdagent", 1) < 0)
+                    return -1;
+            }
+        }
+    }
+
+    return 0;
+}
+
+static int
+xenFormatXLInputDevs(virConfPtr conf, virDomainDefPtr def)
+{
+    size_t i;
+    const char *devtype;
+    virConfValuePtr usbdevices = NULL, lastdev;
+
+    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
+        if (VIR_ALLOC(usbdevices) < 0)
+            goto error;
+
+        usbdevices->type = VIR_CONF_LIST;
+        usbdevices->list = NULL;
+        lastdev = NULL;
+        for (i = 0; i < def->ninputs; i++) {
+            if (def->inputs[i]->bus == VIR_DOMAIN_INPUT_BUS_USB) {
+                if (xenConfigSetInt(conf, "usb", 1) < 0)
+                    goto error;
+
+                switch (def->inputs[i]->type) {
+                    case VIR_DOMAIN_INPUT_TYPE_MOUSE:
+                        devtype = "mouse";
+                        break;
+                    case VIR_DOMAIN_INPUT_TYPE_TABLET:
+                        devtype = "tablet";
+                        break;
+                    case VIR_DOMAIN_INPUT_TYPE_KBD:
+                        devtype = "keyboard";
+                        break;
+                    default:
+                        continue;
+                }
+
+                if (lastdev == NULL) {
+                    if (VIR_ALLOC(lastdev) < 0)
+                        goto error;
+                    usbdevices->list = lastdev;
+                } else {
+                    if (VIR_ALLOC(lastdev->next) < 0)
+                        goto error;
+                    lastdev = lastdev->next;
+                }
+                lastdev->type = VIR_CONF_STRING;
+                if (VIR_STRDUP(lastdev->str, devtype) < 0)
+                    goto error;
+            }
+        }
+        if (usbdevices->list != NULL) {
+            if (usbdevices->list->next == NULL) {
+                /* for compatibility with Xen <= 4.2, use old syntax when
+                 * only one device present */
+                if (xenConfigSetString(conf, "usbdevice", usbdevices->list->str) < 0)
+                    goto error;
+                virConfFreeValue(usbdevices);
+            } else {
+                virConfSetValue(conf, "usbdevice", usbdevices);
+            }
+        } else {
+            VIR_FREE(usbdevices);
+        }
+    }
+
+    return 0;
+ error:
+    virConfFreeValue(usbdevices);
+    return -1;
+}
+
+static int
+xenFormatXLUSBController(virConfPtr conf,
+                         virDomainDefPtr def)
+{
+    virConfValuePtr usbctrlVal = NULL;
+    int hasUSBCtrl = 0;
+    size_t i;
+
+    for (i = 0; i < def->ncontrollers; i++) {
+        if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_USB) {
+            hasUSBCtrl = 1;
+            break;
+        }
+    }
+
+    if (!hasUSBCtrl)
+        return 0;
+
+    if (VIR_ALLOC(usbctrlVal) < 0)
+        return -1;
+
+    usbctrlVal->type = VIR_CONF_LIST;
+    usbctrlVal->list = NULL;
+
+    for (i = 0; i < def->ncontrollers; i++) {
+        if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_USB) {
+            virConfValuePtr val, tmp;
+            virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+            if (def->controllers[i]->model != -1) {
+                switch (def->controllers[i]->model) {
+                case VIR_DOMAIN_CONTROLLER_MODEL_USB_QUSB1:
+                    virBufferAddLit(&buf, "type=qusb,version=1,");
+                    break;
+
+                case VIR_DOMAIN_CONTROLLER_MODEL_USB_QUSB2:
+                    virBufferAddLit(&buf, "type=qusb,version=2,");
+                    break;
+
+                default:
+                    goto error;
+                }
+            }
+
+            if (def->controllers[i]->opts.usbopts.ports != -1)
+                virBufferAsprintf(&buf, "ports=%x",
+                                  def->controllers[i]->opts.usbopts.ports);
+
+            if (VIR_ALLOC(val) < 0) {
+                virBufferFreeAndReset(&buf);
+                goto error;
+            }
+            val->type = VIR_CONF_STRING;
+            val->str = virBufferContentAndReset(&buf);
+            tmp = usbctrlVal->list;
+            while (tmp && tmp->next)
+                tmp = tmp->next;
+            if (tmp)
+                tmp->next = val;
+            else
+                usbctrlVal->list = val;
+        }
+    }
+
+    if (usbctrlVal->list != NULL) {
+        int ret = virConfSetValue(conf, "usbctrl", usbctrlVal);
+        usbctrlVal = NULL;
+        if (ret < 0)
+            return -1;
+    }
+    VIR_FREE(usbctrlVal);
+
+    return 0;
+
+ error:
+    virConfFreeValue(usbctrlVal);
+    return -1;
+}
+
+
+static int
+xenFormatXLUSB(virConfPtr conf,
+               virDomainDefPtr def)
+{
+    virConfValuePtr usbVal = NULL;
+    int hasUSB = 0;
+    size_t i;
+
+    for (i = 0; i < def->nhostdevs; i++) {
+        if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+            def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
+            hasUSB = 1;
+            break;
+        }
+    }
+
+    if (!hasUSB)
+        return 0;
+
+    if (VIR_ALLOC(usbVal) < 0)
+        return -1;
+
+    usbVal->type = VIR_CONF_LIST;
+    usbVal->list = NULL;
+
+    for (i = 0; i < def->nhostdevs; i++) {
+        if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+            def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
+            virConfValuePtr val, tmp;
+            char *buf;
+
+            if (virAsprintf(&buf, "hostbus=%x,hostaddr=%x",
+                            def->hostdevs[i]->source.subsys.u.usb.bus,
+                            def->hostdevs[i]->source.subsys.u.usb.device) < 0)
+                goto error;
+
+            if (VIR_ALLOC(val) < 0) {
+                VIR_FREE(buf);
+                goto error;
+            }
+            val->type = VIR_CONF_STRING;
+            val->str = buf;
+            tmp = usbVal->list;
+            while (tmp && tmp->next)
+                tmp = tmp->next;
+            if (tmp)
+                tmp->next = val;
+            else
+                usbVal->list = val;
+        }
+    }
+
+    if (usbVal->list != NULL) {
+        int ret = virConfSetValue(conf, "usbdev", usbVal);
+        usbVal = NULL;
+        if (ret < 0)
+            return -1;
+    }
+    VIR_FREE(usbVal);
+
+    return 0;
+
+ error:
+    virConfFreeValue(usbVal);
+    return -1;
+}
+
+static int
+xenFormatXLChannel(virConfValuePtr list, virDomainChrDefPtr channel)
+{
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    int sourceType = channel->source->type;
+    virConfValuePtr val, tmp;
+
+    /* connection */
+    virBufferAddLit(&buf, "connection=");
+    switch (sourceType) {
+        case VIR_DOMAIN_CHR_TYPE_PTY:
+            virBufferAddLit(&buf, "pty,");
+            break;
+        case VIR_DOMAIN_CHR_TYPE_UNIX:
+            virBufferAddLit(&buf, "socket,");
+            /* path */
+            if (channel->source->data.nix.path)
+                virBufferAsprintf(&buf, "path=%s,",
+                                  channel->source->data.nix.path);
+            break;
+        default:
+            goto cleanup;
+    }
+
+    /* name */
+    virBufferAsprintf(&buf, "name=%s", channel->target.name);
+
+    if (VIR_ALLOC(val) < 0)
+        goto cleanup;
+
+    val->type = VIR_CONF_STRING;
+    val->str = virBufferContentAndReset(&buf);
+    tmp = list->list;
+    while (tmp && tmp->next)
+        tmp = tmp->next;
+    if (tmp)
+        tmp->next = val;
+    else
+        list->list = val;
+    return 0;
+
+ cleanup:
+    virBufferFreeAndReset(&buf);
+    return -1;
+}
+
+static int
+xenFormatXLDomainChannels(virConfPtr conf, virDomainDefPtr def)
+{
+    virConfValuePtr channelVal = NULL;
+    size_t i;
+
+    if (VIR_ALLOC(channelVal) < 0)
+        goto cleanup;
+
+    channelVal->type = VIR_CONF_LIST;
+    channelVal->list = NULL;
+
+    for (i = 0; i < def->nchannels; i++) {
+        virDomainChrDefPtr chr = def->channels[i];
+
+        if (chr->targetType != VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_XEN)
+            continue;
+
+        if (xenFormatXLChannel(channelVal, def->channels[i]) < 0)
+            goto cleanup;
+    }
+
+    if (channelVal->list != NULL) {
+        int ret = virConfSetValue(conf, "channel", channelVal);
+        channelVal = NULL;
+        if (ret < 0)
+            goto cleanup;
+    }
+
+    VIR_FREE(channelVal);
+    return 0;
+
+ cleanup:
+    virConfFreeValue(channelVal);
+    return -1;
+}
+
+virConfPtr
+xenFormatXL(virDomainDefPtr def, virConnectPtr conn)
+{
+    virConfPtr conf = NULL;
+
+    if (!(conf = virConfNew()))
+        goto cleanup;
+
+    if (xenFormatConfigCommon(conf, def, conn, XEN_CONFIG_FORMAT_XL) < 0)
+        goto cleanup;
+
+    if (xenFormatXLOS(conf, def) < 0)
+        goto cleanup;
+
+    if (xenFormatXLCPUID(conf, def) < 0)
+        goto cleanup;
+
+#ifdef LIBXL_HAVE_VNUMA
+    if (xenFormatXLDomainVnuma(conf, def) < 0)
+        goto cleanup;
+#endif
+
+#ifdef LIBXL_HAVE_BUILDINFO_GRANT_LIMITS
+    if (xenFormatXLGntLimits(conf, def) < 0)
+        goto cleanup;
+#endif
+
+    if (xenFormatXLDomainDisks(conf, def) < 0)
+        goto cleanup;
+
+    if (xenFormatXLSpice(conf, def) < 0)
+        goto cleanup;
+
+    if (xenFormatXLInputDevs(conf, def) < 0)
+        goto cleanup;
+
+    if (xenFormatXLUSB(conf, def) < 0)
+        goto cleanup;
+
+    if (xenFormatXLUSBController(conf, def) < 0)
+        goto cleanup;
+
+    if (xenFormatXLDomainChannels(conf, def) < 0)
+        goto cleanup;
+
+    return conf;
+
+ cleanup:
+    if (conf)
+        virConfFree(conf);
+    return NULL;
+}
diff --git a/src/libxl/xen_xl.h b/src/libxl/xen_xl.h
new file mode 100644 (file)
index 0000000..24f6470
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * xen_xl.h: Xen XL parsing functions
+ *
+ * Copyright (c) 2015 SUSE LINUX Products GmbH, Nuernberg, Germany.
+ * Copyright (c) 2014 David Kiarie Kahurani
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include "virconf.h"
+#include "domain_conf.h"
+#include "xen_common.h"
+
+virDomainDefPtr xenParseXL(virConfPtr conn,
+                           virCapsPtr caps,
+                           virDomainXMLOptionPtr xmlopt);
+
+virConfPtr xenFormatXL(virDomainDefPtr def, virConnectPtr);
+
+const char *xenTranslateCPUFeature(const char *feature_name, bool from_libxl);
diff --git a/src/libxl/xen_xm.c b/src/libxl/xen_xm.c
new file mode 100644 (file)
index 0000000..b8dee09
--- /dev/null
@@ -0,0 +1,625 @@
+/*
+ * xen_xm.c: Xen XM parsing functions
+ *
+ * Copyright (C) 2006-2007, 2009-2014 Red Hat, Inc.
+ * Copyright (C) 2011 Univention GmbH
+ * Copyright (C) 2006 Daniel P. Berrange
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "internal.h"
+#include "virerror.h"
+#include "virconf.h"
+#include "viralloc.h"
+#include "verify.h"
+#include "xenxs_private.h"
+#include "xen_xm.h"
+#include "domain_conf.h"
+#include "virstring.h"
+#include "xen_common.h"
+
+#define VIR_FROM_THIS VIR_FROM_XENXM
+
+static int
+xenParseXMOS(virConfPtr conf, virDomainDefPtr def)
+{
+    size_t i;
+
+    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
+        VIR_AUTOFREE(char *) boot = NULL;
+
+        if (VIR_ALLOC(def->os.loader) < 0 ||
+            xenConfigCopyString(conf, "kernel", &def->os.loader->path) < 0)
+            return -1;
+
+        if (xenConfigGetString(conf, "boot", &boot, "c") < 0)
+            return -1;
+
+        for (i = 0; i < VIR_DOMAIN_BOOT_LAST && boot[i]; i++) {
+            switch (boot[i]) {
+            case 'a':
+                def->os.bootDevs[i] = VIR_DOMAIN_BOOT_FLOPPY;
+                break;
+            case 'd':
+                def->os.bootDevs[i] = VIR_DOMAIN_BOOT_CDROM;
+                break;
+            case 'n':
+                def->os.bootDevs[i] = VIR_DOMAIN_BOOT_NET;
+                break;
+            case 'c':
+            default:
+                def->os.bootDevs[i] = VIR_DOMAIN_BOOT_DISK;
+                break;
+            }
+            def->os.nBootDevs++;
+        }
+    } else {
+        VIR_AUTOFREE(char *) extra = NULL;
+        VIR_AUTOFREE(char *) root = NULL;
+
+        if (xenConfigCopyStringOpt(conf, "bootloader", &def->os.bootloader) < 0)
+            return -1;
+        if (xenConfigCopyStringOpt(conf, "bootargs", &def->os.bootloaderArgs) < 0)
+            return -1;
+
+        if (xenConfigCopyStringOpt(conf, "kernel", &def->os.kernel) < 0)
+            return -1;
+
+        if (xenConfigCopyStringOpt(conf, "ramdisk", &def->os.initrd) < 0)
+            return -1;
+
+        if (xenConfigGetString(conf, "extra", &extra, NULL) < 0)
+            return -1;
+
+        if (xenConfigGetString(conf, "root", &root, NULL) < 0)
+            return -1;
+
+        if (root && extra) {
+            if (virAsprintf(&def->os.cmdline, "root=%s %s", root, extra) < 0)
+                return -1;
+        } else if (root) {
+            if (virAsprintf(&def->os.cmdline, "root=%s", root) < 0)
+                return -1;
+        } else if (extra) {
+            if (VIR_STRDUP(def->os.cmdline, extra) < 0)
+                return -1;
+        }
+    }
+
+    return 0;
+}
+
+
+static virDomainDiskDefPtr
+xenParseXMDisk(char *entry, int hvm)
+{
+    virDomainDiskDefPtr disk = NULL;
+    char *head;
+    char *offset;
+    char *tmp;
+    const char *src;
+
+    if (!(disk = virDomainDiskDefNew(NULL)))
+        return NULL;
+
+    head = entry;
+    /*
+     * Disks have 3 components, SOURCE,DEST-DEVICE,MODE
+     * eg, phy:/dev/HostVG/XenGuest1,xvda,w
+     * The SOURCE is usually prefixed with a driver type,
+     * and optionally driver sub-type
+     * The DEST-DEVICE is optionally post-fixed with disk type
+     */
+
+    /* Extract the source file path*/
+    if (!(offset = strchr(head, ',')))
+        goto error;
+
+    if (offset == head) {
+        /* No source file given, eg CDROM with no media */
+        ignore_value(virDomainDiskSetSource(disk, NULL));
+    } else {
+        if (VIR_STRNDUP(tmp, head, offset - head) < 0)
+            goto error;
+
+        if (virDomainDiskSetSource(disk, tmp) < 0) {
+            VIR_FREE(tmp);
+            goto error;
+        }
+        VIR_FREE(tmp);
+    }
+
+    head = offset + 1;
+    /* Remove legacy ioemu: junk */
+    if (STRPREFIX(head, "ioemu:"))
+        head = head + 6;
+
+    /* Extract the dest device name */
+    if (!(offset = strchr(head, ',')))
+        goto error;
+
+    if (VIR_ALLOC_N(disk->dst, (offset - head) + 1) < 0)
+        goto error;
+
+    if (virStrncpy(disk->dst, head, offset - head,
+                   (offset - head) + 1) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Dest file %s too big for destination"), head);
+        goto error;
+    }
+
+    head = offset + 1;
+    /* Extract source driver type */
+    src = virDomainDiskGetSource(disk);
+    if (src) {
+        size_t len;
+        /* The main type  phy:, file:, tap: ... */
+        if ((tmp = strchr(src, ':')) != NULL) {
+            len = tmp - src;
+            if (VIR_STRNDUP(tmp, src, len) < 0)
+                goto error;
+
+            if (virDomainDiskSetDriver(disk, tmp) < 0) {
+                VIR_FREE(tmp);
+                goto error;
+            }
+            VIR_FREE(tmp);
+
+            /* Strip the prefix we found off the source file name */
+            if (virDomainDiskSetSource(disk, src + len + 1) < 0)
+                goto error;
+
+            src = virDomainDiskGetSource(disk);
+        }
+
+        /* And the sub-type for tap:XXX: type */
+        if (STREQ_NULLABLE(virDomainDiskGetDriver(disk), "tap") ||
+            STREQ_NULLABLE(virDomainDiskGetDriver(disk), "tap2")) {
+            char *driverType;
+
+            if (!(tmp = strchr(src, ':')))
+                goto error;
+            len = tmp - src;
+
+            if (VIR_STRNDUP(driverType, src, len) < 0)
+                goto error;
+
+            if (STREQ(driverType, "aio"))
+                virDomainDiskSetFormat(disk, VIR_STORAGE_FILE_RAW);
+            else
+                virDomainDiskSetFormat(disk,
+                                       virStorageFileFormatTypeFromString(driverType));
+            VIR_FREE(driverType);
+            if (virDomainDiskGetFormat(disk) <= 0) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("Unknown driver type %s"),
+                               src);
+                goto error;
+            }
+
+            /* Strip the prefix we found off the source file name */
+            if (virDomainDiskSetSource(disk, src + len + 1) < 0)
+                goto error;
+            src = virDomainDiskGetSource(disk);
+        }
+    }
+
+    /* No source, or driver name, so fix to phy: */
+    if (!virDomainDiskGetDriver(disk) &&
+        virDomainDiskSetDriver(disk, "phy") < 0)
+        goto error;
+
+    /* phy: type indicates a block device */
+    virDomainDiskSetType(disk,
+                         STREQ(virDomainDiskGetDriver(disk), "phy") ?
+                         VIR_STORAGE_TYPE_BLOCK :
+                         VIR_STORAGE_TYPE_FILE);
+
+    /* Check for a :cdrom/:disk postfix */
+    disk->device = VIR_DOMAIN_DISK_DEVICE_DISK;
+    if ((tmp = strchr(disk->dst, ':')) != NULL) {
+        if (STREQ(tmp, ":cdrom"))
+            disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
+        tmp[0] = '\0';
+    }
+
+    if (STRPREFIX(disk->dst, "xvd") || !hvm)
+        disk->bus = VIR_DOMAIN_DISK_BUS_XEN;
+    else if (STRPREFIX(disk->dst, "sd"))
+        disk->bus = VIR_DOMAIN_DISK_BUS_SCSI;
+    else
+        disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
+
+    if (STREQ(head, "r") || STREQ(head, "ro"))
+        disk->src->readonly = true;
+    else if (STREQ(head, "w!") || STREQ(head, "!"))
+        disk->src->shared = true;
+
+    return disk;
+
+ error:
+    virDomainDiskDefFree(disk);
+    return NULL;
+}
+
+
+static int
+xenParseXMDiskList(virConfPtr conf, virDomainDefPtr def)
+{
+    char **disks = NULL, **entries;
+    int hvm = def->os.type == VIR_DOMAIN_OSTYPE_HVM;
+    int ret = -1;
+    int rc;
+
+    rc = virConfGetValueStringList(conf, "disk", false, &disks);
+    if (rc <= 0)
+        return rc;
+
+    for (entries = disks; *entries; entries++) {
+        virDomainDiskDefPtr disk;
+        char *entry = *entries;
+
+        if (!(disk = xenParseXMDisk(entry, hvm)))
+            continue;
+
+        /* Maintain list in sorted order according to target device name */
+        rc = VIR_APPEND_ELEMENT(def->disks, def->ndisks, disk);
+        virDomainDiskDefFree(disk);
+
+        if (rc < 0)
+            goto cleanup;
+    }
+
+    ret = 0;
+
+ cleanup:
+    virStringListFree(disks);
+    return ret;
+}
+
+
+static int
+xenFormatXMDisk(virConfValuePtr list,
+                virDomainDiskDefPtr disk)
+{
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    virConfValuePtr val, tmp;
+    const char *src = virDomainDiskGetSource(disk);
+    int format = virDomainDiskGetFormat(disk);
+    const char *driver = virDomainDiskGetDriver(disk);
+
+    if (src) {
+        if (format) {
+            const char *type;
+
+            if (format == VIR_STORAGE_FILE_RAW)
+                type = "aio";
+            else
+                type = virStorageFileFormatTypeToString(format);
+
+            if (driver) {
+                virBufferAsprintf(&buf, "%s:", driver);
+                if (STREQ(driver, "tap") || STREQ(driver, "tap2"))
+                    virBufferAsprintf(&buf, "%s:", type);
+            }
+        } else {
+            switch (virDomainDiskGetType(disk)) {
+            case VIR_STORAGE_TYPE_FILE:
+                virBufferAddLit(&buf, "file:");
+                break;
+            case VIR_STORAGE_TYPE_BLOCK:
+                virBufferAddLit(&buf, "phy:");
+                break;
+            default:
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("unsupported disk type %s"),
+                               virStorageTypeToString(virDomainDiskGetType(disk)));
+                goto cleanup;
+            }
+        }
+        virBufferAdd(&buf, src, -1);
+    }
+    virBufferAddLit(&buf, ",");
+
+    virBufferAdd(&buf, disk->dst, -1);
+    if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM)
+        virBufferAddLit(&buf, ":cdrom");
+
+    if (disk->src->readonly)
+        virBufferAddLit(&buf, ",r");
+    else if (disk->src->shared)
+        virBufferAddLit(&buf, ",!");
+    else
+        virBufferAddLit(&buf, ",w");
+    if (disk->transient) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("transient disks not supported yet"));
+        return -1;
+    }
+
+    if (virBufferCheckError(&buf) < 0)
+        goto cleanup;
+
+    if (VIR_ALLOC(val) < 0)
+        goto cleanup;
+
+    val->type = VIR_CONF_STRING;
+    val->str = virBufferContentAndReset(&buf);
+    tmp = list->list;
+    while (tmp && tmp->next)
+        tmp = tmp->next;
+    if (tmp)
+        tmp->next = val;
+    else
+        list->list = val;
+
+    return 0;
+
+ cleanup:
+    virBufferFreeAndReset(&buf);
+    return -1;
+}
+
+
+static int
+xenFormatXMDisks(virConfPtr conf, virDomainDefPtr def)
+{
+    virConfValuePtr diskVal = NULL;
+    size_t i = 0;
+
+    if (VIR_ALLOC(diskVal) < 0)
+        goto cleanup;
+
+    diskVal->type = VIR_CONF_LIST;
+    diskVal->list = NULL;
+
+    for (i = 0; i < def->ndisks; i++) {
+        if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY)
+            continue;
+
+        if (xenFormatXMDisk(diskVal, def->disks[i]) < 0)
+            goto cleanup;
+    }
+
+    if (diskVal->list != NULL) {
+        int ret = virConfSetValue(conf, "disk", diskVal);
+        diskVal = NULL;
+        if (ret < 0)
+            goto cleanup;
+    }
+    VIR_FREE(diskVal);
+
+    return 0;
+
+ cleanup:
+    virConfFreeValue(diskVal);
+    return -1;
+}
+
+
+static int
+xenParseXMInputDevs(virConfPtr conf, virDomainDefPtr def)
+{
+    VIR_AUTOFREE(char *) str = NULL;
+
+    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
+        if (xenConfigGetString(conf, "usbdevice", &str, NULL) < 0)
+            return -1;
+        if (str &&
+                (STREQ(str, "tablet") ||
+                 STREQ(str, "mouse") ||
+                 STREQ(str, "keyboard"))) {
+            virDomainInputDefPtr input;
+            if (VIR_ALLOC(input) < 0)
+                return -1;
+
+            input->bus = VIR_DOMAIN_INPUT_BUS_USB;
+            if (STREQ(str, "mouse"))
+                input->type = VIR_DOMAIN_INPUT_TYPE_MOUSE;
+            else if (STREQ(str, "tablet"))
+                input->type = VIR_DOMAIN_INPUT_TYPE_TABLET;
+            else if (STREQ(str, "keyboard"))
+                input->type = VIR_DOMAIN_INPUT_TYPE_KBD;
+            if (VIR_APPEND_ELEMENT(def->inputs, def->ninputs, input) < 0) {
+                virDomainInputDefFree(input);
+                return -1;
+            }
+        }
+    }
+    return 0;
+}
+
+/*
+ * Convert an XM config record into a virDomainDef object.
+ */
+virDomainDefPtr
+xenParseXM(virConfPtr conf,
+           virCapsPtr caps,
+           virDomainXMLOptionPtr xmlopt)
+{
+    virDomainDefPtr def = NULL;
+
+    if (!(def = virDomainDefNew()))
+        return NULL;
+
+    def->virtType = VIR_DOMAIN_VIRT_XEN;
+    def->id = -1;
+
+    if (xenParseConfigCommon(conf, def, caps, XEN_CONFIG_FORMAT_XM,
+                             xmlopt) < 0)
+        goto cleanup;
+
+    if (xenParseXMOS(conf, def) < 0)
+         goto cleanup;
+
+    if (xenParseXMDiskList(conf, def) < 0)
+         goto cleanup;
+
+    if (xenParseXMInputDevs(conf, def) < 0)
+         goto cleanup;
+
+    if (virDomainDefPostParse(def, caps, VIR_DOMAIN_DEF_PARSE_ABI_UPDATE,
+                              xmlopt, NULL) < 0)
+        goto cleanup;
+
+    return def;
+
+ cleanup:
+    virDomainDefFree(def);
+    return NULL;
+}
+
+static int
+xenFormatXMOS(virConfPtr conf, virDomainDefPtr def)
+{
+    size_t i;
+
+    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
+        char boot[VIR_DOMAIN_BOOT_LAST+1];
+        if (xenConfigSetString(conf, "builder", "hvm") < 0)
+            return -1;
+
+        if (def->os.loader && def->os.loader->path &&
+            xenConfigSetString(conf, "kernel", def->os.loader->path) < 0)
+            return -1;
+
+        for (i = 0; i < def->os.nBootDevs; i++) {
+            switch (def->os.bootDevs[i]) {
+            case VIR_DOMAIN_BOOT_FLOPPY:
+                boot[i] = 'a';
+                break;
+            case VIR_DOMAIN_BOOT_CDROM:
+                boot[i] = 'd';
+                break;
+            case VIR_DOMAIN_BOOT_NET:
+                boot[i] = 'n';
+                break;
+            case VIR_DOMAIN_BOOT_DISK:
+            default:
+                boot[i] = 'c';
+                break;
+            }
+        }
+
+        if (!def->os.nBootDevs) {
+            boot[0] = 'c';
+            boot[1] = '\0';
+        } else {
+            boot[def->os.nBootDevs] = '\0';
+        }
+
+        if (xenConfigSetString(conf, "boot", boot) < 0)
+            return -1;
+
+        /* XXX floppy disks */
+    } else {
+        if (def->os.bootloader &&
+             xenConfigSetString(conf, "bootloader", def->os.bootloader) < 0)
+            return -1;
+
+         if (def->os.bootloaderArgs &&
+             xenConfigSetString(conf, "bootargs", def->os.bootloaderArgs) < 0)
+            return -1;
+
+         if (def->os.kernel &&
+             xenConfigSetString(conf, "kernel", def->os.kernel) < 0)
+            return -1;
+
+         if (def->os.initrd &&
+             xenConfigSetString(conf, "ramdisk", def->os.initrd) < 0)
+            return -1;
+
+         if (def->os.cmdline &&
+             xenConfigSetString(conf, "extra", def->os.cmdline) < 0)
+            return -1;
+     } /* !hvm */
+
+    return 0;
+}
+
+
+static int
+xenFormatXMInputDevs(virConfPtr conf, virDomainDefPtr def)
+{
+    size_t i;
+    const char *devtype;
+
+    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
+        for (i = 0; i < def->ninputs; i++) {
+            if (def->inputs[i]->bus == VIR_DOMAIN_INPUT_BUS_USB) {
+                if (xenConfigSetInt(conf, "usb", 1) < 0)
+                    return -1;
+
+                switch (def->inputs[i]->type) {
+                    case VIR_DOMAIN_INPUT_TYPE_MOUSE:
+                        devtype = "mouse";
+                        break;
+                    case VIR_DOMAIN_INPUT_TYPE_TABLET:
+                        devtype = "tablet";
+                        break;
+                    case VIR_DOMAIN_INPUT_TYPE_KBD:
+                        devtype = "keyboard";
+                        break;
+                    default:
+                        continue;
+                }
+                if (xenConfigSetString(conf, "usbdevice", devtype) < 0)
+                    return -1;
+                break;
+            }
+        }
+    }
+    return 0;
+}
+
+
+/* Computing the vcpu_avail bitmask works because MAX_VIRT_CPUS is
+   either 32, or 64 on a platform where long is big enough.  */
+verify(MAX_VIRT_CPUS <= sizeof(1UL) * CHAR_BIT);
+
+/*
+ * Convert a virDomainDef object into an XM config record.
+ */
+virConfPtr
+xenFormatXM(virConnectPtr conn,
+            virDomainDefPtr def)
+{
+    virConfPtr conf = NULL;
+
+    if (!(conf = virConfNew()))
+        goto cleanup;
+
+    if (xenFormatConfigCommon(conf, def, conn, XEN_CONFIG_FORMAT_XM) < 0)
+        goto cleanup;
+
+    if (xenFormatXMOS(conf, def) < 0)
+        goto cleanup;
+
+    if (xenFormatXMDisks(conf, def) < 0)
+        goto cleanup;
+
+    if (xenFormatXMInputDevs(conf, def) < 0)
+        goto cleanup;
+
+    return conf;
+
+ cleanup:
+    if (conf)
+        virConfFree(conf);
+    return NULL;
+}
diff --git a/src/libxl/xen_xm.h b/src/libxl/xen_xm.h
new file mode 100644 (file)
index 0000000..5546b2d
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * xen_xm.h: Xen XM parsing functions
+ *
+ * Copyright (C) 2011 Univention GmbH
+ * Copyright (C) 2006-2007, 2009-2010 Red Hat, Inc.
+ * Copyright (C) 2006 Daniel P. Berrange
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "internal.h"
+#include "virconf.h"
+#include "domain_conf.h"
+
+virConfPtr xenFormatXM(virConnectPtr conn, virDomainDefPtr def);
+
+virDomainDefPtr xenParseXM(virConfPtr conf,
+                           virCapsPtr caps, virDomainXMLOptionPtr xmlopt);
diff --git a/src/libxl/xenxs_private.h b/src/libxl/xenxs_private.h
new file mode 100644 (file)
index 0000000..2b0877d
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * xenxs_private.h: Private definitions for Xen parsing
+ *
+ * Copyright (C) 2007, 2010, 2012 Red Hat, Inc.
+ * Copyright (C) 2011 Univention GmbH
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "internal.h"
+
+#include <xen/xen.h>
+
+/* xen-unstable changeset 19788 removed MAX_VIRT_CPUS from public
+ * headers.  Its semantic was retained with XEN_LEGACY_MAX_VCPUS.
+ * Ensure MAX_VIRT_CPUS is defined accordingly.
+ */
+#if !defined(MAX_VIRT_CPUS) && defined(XEN_LEGACY_MAX_VCPUS)
+# define MAX_VIRT_CPUS XEN_LEGACY_MAX_VCPUS
+#endif
+
+#define MIN_XEN_GUEST_SIZE 64  /* 64 megabytes */
+
+#ifdef __sun
+# define DEFAULT_VIF_SCRIPT "vif-vnic"
+#else
+# define DEFAULT_VIF_SCRIPT "vif-bridge"
+#endif
index b6e4ed0bdb76ae17b8cb2665edb8857be767c6c2..aedef4e2a06981be391a9b31002592412d14bb7a 100644 (file)
@@ -18,7 +18,6 @@ libvirt_driver_xenapi_la_CFLAGS = \
        $(XENAPI_CFLAGS) \
        $(CURL_CFLAGS) \
        -I$(srcdir)/conf \
-       -I$(srcdir)/xenconfig \
        $(AM_CFLAGS) \
        $(NULL)
 libvirt_driver_xenapi_la_LDFLAGS = $(AM_LDFLAGS)
diff --git a/src/xenconfig/Makefile.inc.am b/src/xenconfig/Makefile.inc.am
deleted file mode 100644 (file)
index 5785b49..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-# vim: filetype=automake
-
-XENCONFIG_SOURCES = \
-       xenconfig/xenxs_private.h \
-       xenconfig/xen_common.c \
-       xenconfig/xen_common.h \
-       xenconfig/xen_xm.c \
-       xenconfig/xen_xm.h \
-       $(NULL)
-
-EXTRA_DIST += $(XENCONFIG_SOURCES)
-
-if WITH_XENCONFIG
-noinst_LTLIBRARIES += libvirt_xenconfig.la
-libvirt_la_BUILT_LIBADD += libvirt_xenconfig.la
-libvirt_xenconfig_la_CFLAGS = \
-       -I$(srcdir)/conf \
-       $(AM_CFLAGS) \
-       $(NULL)
-libvirt_xenconfig_la_SOURCES = $(XENCONFIG_SOURCES)
-
-endif WITH_XENCONFIG
-
-if WITH_XENCONFIG
-USED_SYM_FILES += $(srcdir)/libvirt_xenconfig.syms
-else ! WITH_XENCONFIG
-SYM_FILES += $(srcdir)/libvirt_xenconfig.syms
-endif ! WITH_XENCONFIG
diff --git a/src/xenconfig/xen_common.c b/src/xenconfig/xen_common.c
deleted file mode 100644 (file)
index 7eb52c8..0000000
+++ /dev/null
@@ -1,2521 +0,0 @@
-/*
- * xen_common.c: Parsing and formatting functions for config common
- * between XM and XL
- *
- * Copyright (C) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany.
- * Copyright (C) 2006-2007, 2009-2016 Red Hat, Inc.
- * Copyright (C) 2011 Univention GmbH
- * Copyright (C) 2006 Daniel P. Berrange
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library.  If not, see
- * <http://www.gnu.org/licenses/>.
- */
-
-#include <config.h>
-
-#include <regex.h>
-
-#include "internal.h"
-#include "virerror.h"
-#include "virconf.h"
-#include "viralloc.h"
-#include "viruuid.h"
-#include "count-one-bits.h"
-#include "xenxs_private.h"
-#include "domain_conf.h"
-#include "virstring.h"
-#include "xen_common.h"
-
-#define VIR_FROM_THIS VIR_FROM_XEN
-
-/*
- * Convenience method to grab a long int from the config file object
- */
-int
-xenConfigGetBool(virConfPtr conf,
-                 const char *name,
-                 int *value,
-                 int def)
-{
-    virConfValuePtr val;
-
-    *value = 0;
-    if (!(val = virConfGetValue(conf, name))) {
-        *value = def;
-        return 0;
-    }
-
-    if (val->type == VIR_CONF_ULLONG) {
-        *value = val->l ? 1 : 0;
-    } else if (val->type == VIR_CONF_STRING) {
-        *value = STREQ(val->str, "1") ? 1 : 0;
-    } else {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("config value %s was malformed"), name);
-        return -1;
-    }
-    return 0;
-}
-
-
-/*
- * Convenience method to grab a int from the config file object
- */
-int
-xenConfigGetULong(virConfPtr conf,
-                  const char *name,
-                  unsigned long *value,
-                  unsigned long def)
-{
-    virConfValuePtr val;
-
-    *value = 0;
-    if (!(val = virConfGetValue(conf, name))) {
-        *value = def;
-        return 0;
-    }
-
-    if (val->type == VIR_CONF_ULLONG) {
-        *value = val->l;
-    } else if (val->type == VIR_CONF_STRING) {
-        if (virStrToLong_ul(val->str, NULL, 10, value) < 0) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("config value %s was malformed"), name);
-            return -1;
-        }
-    } else {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("config value %s was malformed"), name);
-        return -1;
-    }
-    return 0;
-}
-
-
-/*
- * Convenience method to grab a int from the config file object
- */
-static int
-xenConfigGetULongLong(virConfPtr conf,
-                      const char *name,
-                      unsigned long long *value,
-                      unsigned long long def)
-{
-    virConfValuePtr val;
-
-    *value = 0;
-    if (!(val = virConfGetValue(conf, name))) {
-        *value = def;
-        return 0;
-    }
-
-    if (val->type == VIR_CONF_ULLONG) {
-        *value = val->l;
-    } else if (val->type == VIR_CONF_STRING) {
-        if (virStrToLong_ull(val->str, NULL, 10, value) < 0) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("config value %s was malformed"), name);
-            return -1;
-        }
-    } else {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("config value %s was malformed"), name);
-        return -1;
-    }
-    return 0;
-}
-
-
-static int
-xenConfigCopyStringInternal(virConfPtr conf,
-                            const char *name,
-                            char **value,
-                            int allowMissing)
-{
-    int rc;
-
-    *value = NULL;
-    if ((rc = virConfGetValueString(conf, name, value)) < 0)
-        return -1;
-
-    if (rc == 0) {
-        if (allowMissing)
-            return 0;
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("config value %s was missing"), name);
-        return -1;
-    }
-
-    return 1;
-}
-
-
-int
-xenConfigCopyString(virConfPtr conf, const char *name, char **value)
-{
-    return xenConfigCopyStringInternal(conf, name, value, 0);
-}
-
-
-int
-xenConfigCopyStringOpt(virConfPtr conf, const char *name, char **value)
-{
-    return xenConfigCopyStringInternal(conf, name, value, 1);
-}
-
-
-/*
- * Convenience method to grab a string UUID from the config file object
- */
-static int
-xenConfigGetUUID(virConfPtr conf, const char *name, unsigned char *uuid)
-{
-    VIR_AUTOFREE(char *) string = NULL;
-    int rc;
-
-    if (!uuid || !name || !conf) {
-        virReportError(VIR_ERR_INVALID_ARG, "%s",
-                       _("Arguments must be non null"));
-        return -1;
-    }
-
-
-    if ((rc = virConfGetValueString(conf, name, &string)) < 0)
-        return -1;
-
-    if (rc == 0) {
-        if (virUUIDGenerate(uuid) < 0) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           "%s", _("Failed to generate UUID"));
-            return -1;
-        } else {
-            return 0;
-        }
-    }
-
-    if (!string) {
-        virReportError(VIR_ERR_CONF_SYNTAX,
-                       _("%s can't be empty"), name);
-        return -1;
-    }
-
-    if (virUUIDParse(string, uuid) < 0) {
-        virReportError(VIR_ERR_CONF_SYNTAX,
-                       _("%s not parseable"), string);
-        return -1;
-    }
-
-    return 0;
-}
-
-
-/*
- * Convenience method to grab a string from the config file object
- */
-int
-xenConfigGetString(virConfPtr conf,
-                   const char *name,
-                   char **value,
-                   const char *def)
-{
-    char *string = NULL;
-    int rc;
-
-    *value = NULL;
-    if ((rc = virConfGetValueString(conf, name, &string)) < 0)
-        return -1;
-
-    if (rc == 0 || !string) {
-        if (VIR_STRDUP(*value, def) < 0)
-            return -1;
-    } else {
-        *value = string;
-    }
-
-    return 0;
-}
-
-
-int
-xenConfigSetInt(virConfPtr conf, const char *setting, long long l)
-{
-    virConfValuePtr value = NULL;
-
-    if ((long)l != l) {
-        virReportError(VIR_ERR_OVERFLOW, _("failed to store %lld to %s"),
-                       l, setting);
-        return -1;
-    }
-    if (VIR_ALLOC(value) < 0)
-        return -1;
-
-    value->type = VIR_CONF_LLONG;
-    value->next = NULL;
-    value->l = l;
-
-    return virConfSetValue(conf, setting, value);
-}
-
-
-int
-xenConfigSetString(virConfPtr conf, const char *setting, const char *str)
-{
-    virConfValuePtr value = NULL;
-
-    if (VIR_ALLOC(value) < 0)
-        return -1;
-
-    value->type = VIR_CONF_STRING;
-    value->next = NULL;
-    if (VIR_STRDUP(value->str, str) < 0) {
-        VIR_FREE(value);
-        return -1;
-    }
-
-    return virConfSetValue(conf, setting, value);
-}
-
-
-static int
-xenParseMem(virConfPtr conf, virDomainDefPtr def)
-{
-    unsigned long long memory;
-
-    if (xenConfigGetULongLong(conf, "memory", &def->mem.cur_balloon,
-                                MIN_XEN_GUEST_SIZE * 2) < 0)
-        return -1;
-
-    if (xenConfigGetULongLong(conf, "maxmem", &memory,
-                                def->mem.cur_balloon) < 0)
-        return -1;
-
-    def->mem.cur_balloon *= 1024;
-    virDomainDefSetMemoryTotal(def, memory * 1024);
-
-    return 0;
-}
-
-
-static int
-xenParseTimeOffset(virConfPtr conf, virDomainDefPtr def)
-{
-    int vmlocaltime;
-
-    if (xenConfigGetBool(conf, "localtime", &vmlocaltime, 0) < 0)
-        return -1;
-
-    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
-        unsigned long rtc_timeoffset;
-        def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_VARIABLE;
-        if (xenConfigGetULong(conf, "rtc_timeoffset", &rtc_timeoffset, 0) < 0)
-            return -1;
-
-        def->clock.data.variable.adjustment = (int)rtc_timeoffset;
-        def->clock.data.variable.basis = vmlocaltime ?
-            VIR_DOMAIN_CLOCK_BASIS_LOCALTIME :
-            VIR_DOMAIN_CLOCK_BASIS_UTC;
-    } else {
-        /* PV domains do not have an emulated RTC and the offset is fixed. */
-        def->clock.offset = vmlocaltime ?
-            VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME :
-            VIR_DOMAIN_CLOCK_OFFSET_UTC;
-        def->clock.data.utc_reset = true;
-    } /* !hvm */
-
-    return 0;
-}
-
-
-static int
-xenParseEventsActions(virConfPtr conf, virDomainDefPtr def)
-{
-    VIR_AUTOFREE(char *) on_poweroff = NULL;
-    VIR_AUTOFREE(char *) on_reboot = NULL;
-    VIR_AUTOFREE(char *) on_crash = NULL;
-
-    if (xenConfigGetString(conf, "on_poweroff", &on_poweroff, "destroy") < 0)
-        return -1;
-
-    if ((def->onPoweroff = virDomainLifecycleActionTypeFromString(on_poweroff)) < 0) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("unexpected value %s for on_poweroff"), on_poweroff);
-        return -1;
-    }
-
-    if (xenConfigGetString(conf, "on_reboot", &on_reboot, "restart") < 0)
-        return -1;
-
-    if ((def->onReboot = virDomainLifecycleActionTypeFromString(on_reboot)) < 0) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("unexpected value %s for on_reboot"), on_reboot);
-        return -1;
-    }
-
-    if (xenConfigGetString(conf, "on_crash", &on_crash, "restart") < 0)
-        return -1;
-
-    if ((def->onCrash = virDomainLifecycleActionTypeFromString(on_crash)) < 0) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("unexpected value %s for on_crash"), on_crash);
-        return -1;
-    }
-
-    return 0;
-}
-
-
-static virDomainHostdevDefPtr
-xenParsePCI(char *entry)
-{
-    virDomainHostdevDefPtr hostdev = NULL;
-    char domain[5];
-    char bus[3];
-    char slot[3];
-    char func[2];
-    char *key, *nextkey;
-    int domainID;
-    int busID;
-    int slotID;
-    int funcID;
-
-    domain[0] = bus[0] = slot[0] = func[0] = '\0';
-
-    /* pci=['0000:00:1b.0','0000:00:13.0'] */
-    if (!(key = entry))
-        return NULL;
-    if (!(nextkey = strchr(key, ':')))
-        return NULL;
-    if (virStrncpy(domain, key, (nextkey - key), sizeof(domain)) < 0) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Domain %s too big for destination"), key);
-        return NULL;
-    }
-
-    key = nextkey + 1;
-    if (!(nextkey = strchr(key, ':')))
-        return NULL;
-    if (virStrncpy(bus, key, (nextkey - key), sizeof(bus)) < 0) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Bus %s too big for destination"), key);
-        return NULL;
-    }
-
-    key = nextkey + 1;
-    if (!(nextkey = strchr(key, '.')))
-        return NULL;
-    if (virStrncpy(slot, key, (nextkey - key), sizeof(slot)) < 0) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Slot %s too big for destination"), key);
-        return NULL;
-    }
-
-    key = nextkey + 1;
-    if (strlen(key) != 1)
-        return NULL;
-    if (virStrncpy(func, key, 1, sizeof(func)) < 0) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Function %s too big for destination"), key);
-        return NULL;
-    }
-
-    if (virStrToLong_i(domain, NULL, 16, &domainID) < 0)
-        return NULL;
-    if (virStrToLong_i(bus, NULL, 16, &busID) < 0)
-        return NULL;
-    if (virStrToLong_i(slot, NULL, 16, &slotID) < 0)
-        return NULL;
-    if (virStrToLong_i(func, NULL, 16, &funcID) < 0)
-        return NULL;
-
-    if (!(hostdev = virDomainHostdevDefNew()))
-       return NULL;
-
-    hostdev->managed = false;
-    hostdev->source.subsys.type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI;
-    hostdev->source.subsys.u.pci.addr.domain = domainID;
-    hostdev->source.subsys.u.pci.addr.bus = busID;
-    hostdev->source.subsys.u.pci.addr.slot = slotID;
-    hostdev->source.subsys.u.pci.addr.function = funcID;
-
-    return hostdev;
-}
-
-
-static int
-xenHandleConfGetValueStringListErrors(int ret)
-{
-    if (ret < 0) {
-        /* It means virConfGetValueStringList() didn't fail because the
-         * cval->type switch fell through - since we're passing
-         * @compatString == false - assumes failures for memory allocation
-         * and VIR_CONF_LIST traversal failure should cause -1 to be
-         * returned to the caller with the error message set. */
-        if (virGetLastErrorCode() != VIR_ERR_INTERNAL_ERROR)
-            return -1;
-
-        /* If we did fall through the switch, then ignore and clear the
-         * last error. */
-        virResetLastError();
-    }
-    return 0;
-}
-
-
-static int
-xenParsePCIList(virConfPtr conf, virDomainDefPtr def)
-{
-    VIR_AUTOSTRINGLIST pcis = NULL;
-    char **entries = NULL;
-    int rc;
-
-    if ((rc = virConfGetValueStringList(conf, "pci", false, &pcis)) <= 0)
-        return xenHandleConfGetValueStringListErrors(rc);
-
-    for (entries = pcis; *entries; entries++) {
-        char *entry = *entries;
-        virDomainHostdevDefPtr hostdev;
-
-        if (!(hostdev = xenParsePCI(entry)))
-            return -1;
-
-        if (VIR_APPEND_ELEMENT(def->hostdevs, def->nhostdevs, hostdev) < 0) {
-            virDomainHostdevDefFree(hostdev);
-            return -1;
-        }
-    }
-
-    return 0;
-}
-
-
-static int
-xenParseCPUFeatures(virConfPtr conf,
-                    virDomainDefPtr def,
-                    virDomainXMLOptionPtr xmlopt)
-{
-    unsigned long count = 0;
-    VIR_AUTOFREE(char *) cpus = NULL;
-    VIR_AUTOFREE(char *) tsc_mode = NULL;
-    int val = 0;
-    virDomainTimerDefPtr timer;
-
-    if (xenConfigGetULong(conf, "vcpus", &count, 1) < 0)
-        return -1;
-
-    if (virDomainDefSetVcpusMax(def, count, xmlopt) < 0)
-        return -1;
-
-    if (virDomainDefSetVcpus(def, count) < 0)
-        return -1;
-
-    if (virConfGetValue(conf, "maxvcpus")) {
-        if (xenConfigGetULong(conf, "maxvcpus", &count, 0) < 0)
-            return -1;
-
-        if (virDomainDefSetVcpusMax(def, count, xmlopt) < 0)
-            return -1;
-    }
-
-    if (xenConfigGetString(conf, "cpus", &cpus, NULL) < 0)
-        return -1;
-
-    if (cpus && (virBitmapParse(cpus, &def->cpumask, 4096) < 0))
-        return -1;
-
-    if (xenConfigGetString(conf, "tsc_mode", &tsc_mode, NULL) < 0)
-        return -1;
-
-    if (tsc_mode) {
-        if (VIR_EXPAND_N(def->clock.timers, def->clock.ntimers, 1) < 0 ||
-            VIR_ALLOC(timer) < 0)
-            return -1;
-
-        timer->name = VIR_DOMAIN_TIMER_NAME_TSC;
-        timer->present = 1;
-        timer->tickpolicy = -1;
-        timer->mode = VIR_DOMAIN_TIMER_MODE_AUTO;
-        timer->track = -1;
-        if (STREQ_NULLABLE(tsc_mode, "always_emulate"))
-            timer->mode = VIR_DOMAIN_TIMER_MODE_EMULATE;
-        else if (STREQ_NULLABLE(tsc_mode, "native"))
-            timer->mode = VIR_DOMAIN_TIMER_MODE_NATIVE;
-        else if (STREQ_NULLABLE(tsc_mode, "native_paravirt"))
-            timer->mode = VIR_DOMAIN_TIMER_MODE_PARAVIRT;
-
-        def->clock.timers[def->clock.ntimers - 1] = timer;
-    }
-
-    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
-        if (xenConfigGetBool(conf, "pae", &val, 1) < 0)
-            return -1;
-
-        else if (val)
-            def->features[VIR_DOMAIN_FEATURE_PAE] = VIR_TRISTATE_SWITCH_ON;
-        if (xenConfigGetBool(conf, "acpi", &val, 1) < 0)
-            return -1;
-
-        else if (val)
-            def->features[VIR_DOMAIN_FEATURE_ACPI] = VIR_TRISTATE_SWITCH_ON;
-        if (xenConfigGetBool(conf, "apic", &val, 1) < 0)
-            return -1;
-
-        else if (val)
-            def->features[VIR_DOMAIN_FEATURE_APIC] = VIR_TRISTATE_SWITCH_ON;
-        if (xenConfigGetBool(conf, "hap", &val, 1) < 0)
-            return -1;
-
-        else if (!val)
-            def->features[VIR_DOMAIN_FEATURE_HAP] = VIR_TRISTATE_SWITCH_OFF;
-        if (xenConfigGetBool(conf, "viridian", &val, 0) < 0)
-            return -1;
-
-        else if (val)
-            def->features[VIR_DOMAIN_FEATURE_VIRIDIAN] = VIR_TRISTATE_SWITCH_ON;
-
-        if (xenConfigGetBool(conf, "hpet", &val, -1) < 0)
-            return -1;
-
-        if (val != -1) {
-            if (VIR_EXPAND_N(def->clock.timers, def->clock.ntimers, 1) < 0 ||
-                VIR_ALLOC(timer) < 0)
-                return -1;
-
-            timer->name = VIR_DOMAIN_TIMER_NAME_HPET;
-            timer->present = val;
-            timer->tickpolicy = -1;
-            timer->mode = -1;
-            timer->track = -1;
-
-            def->clock.timers[def->clock.ntimers - 1] = timer;
-        }
-    }
-
-    return 0;
-}
-
-
-#define MAX_VFB 1024
-
-static int
-xenParseVfb(virConfPtr conf, virDomainDefPtr def)
-{
-    int val;
-    char *listenAddr = NULL;
-    int hvm = def->os.type == VIR_DOMAIN_OSTYPE_HVM;
-    virDomainGraphicsDefPtr graphics = NULL;
-
-    if (hvm) {
-        if (xenConfigGetBool(conf, "vnc", &val, 0) < 0)
-            goto cleanup;
-        if (val) {
-            if (VIR_ALLOC(graphics) < 0)
-                goto cleanup;
-            graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_VNC;
-            if (xenConfigGetBool(conf, "vncunused", &val, 1) < 0)
-                goto cleanup;
-            graphics->data.vnc.autoport = val ? 1 : 0;
-            if (!graphics->data.vnc.autoport) {
-                unsigned long vncdisplay;
-                if (xenConfigGetULong(conf, "vncdisplay", &vncdisplay, 0) < 0)
-                    goto cleanup;
-                graphics->data.vnc.port = (int)vncdisplay + 5900;
-            }
-
-            if (xenConfigCopyStringOpt(conf, "vnclisten", &listenAddr) < 0)
-                goto cleanup;
-            if (virDomainGraphicsListenAppendAddress(graphics, listenAddr) < 0)
-                goto cleanup;
-            VIR_FREE(listenAddr);
-
-            if (xenConfigCopyStringOpt(conf, "vncpasswd", &graphics->data.vnc.auth.passwd) < 0)
-                goto cleanup;
-            if (xenConfigCopyStringOpt(conf, "keymap", &graphics->data.vnc.keymap) < 0)
-                goto cleanup;
-            if (VIR_ALLOC_N(def->graphics, 1) < 0)
-                goto cleanup;
-            def->graphics[0] = graphics;
-            def->ngraphics = 1;
-            graphics = NULL;
-        } else {
-            if (xenConfigGetBool(conf, "sdl", &val, 0) < 0)
-                goto cleanup;
-            if (val) {
-                if (VIR_ALLOC(graphics) < 0)
-                    goto cleanup;
-                graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_SDL;
-                if (xenConfigCopyStringOpt(conf, "display", &graphics->data.sdl.display) < 0)
-                    goto cleanup;
-                if (xenConfigCopyStringOpt(conf, "xauthority", &graphics->data.sdl.xauth) < 0)
-                    goto cleanup;
-                if (VIR_ALLOC_N(def->graphics, 1) < 0)
-                    goto cleanup;
-                def->graphics[0] = graphics;
-                def->ngraphics = 1;
-                graphics = NULL;
-            }
-        }
-    }
-
-    if (!hvm && def->graphics == NULL) { /* New PV guests use this format */
-        VIR_AUTOSTRINGLIST vfbs = NULL;
-        int rc;
-
-        if ((rc = virConfGetValueStringList(conf, "vfb", false, &vfbs)) == 1) {
-            char vfb[MAX_VFB];
-            char *key = vfb;
-
-            if (virStrcpyStatic(vfb, *vfbs) < 0) {
-                virReportError(VIR_ERR_INTERNAL_ERROR,
-                               _("VFB %s too big for destination"),
-                               *vfbs);
-                goto cleanup;
-            }
-
-            if (VIR_ALLOC(graphics) < 0)
-                goto cleanup;
-            if (strstr(key, "type=sdl"))
-                graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_SDL;
-            else
-                graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_VNC;
-            while (key) {
-                char *nextkey = strchr(key, ',');
-                char *end = nextkey;
-                if (nextkey) {
-                    *end = '\0';
-                    nextkey++;
-                }
-
-                if (!strchr(key, '='))
-                    break;
-                if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
-                    if (STRPREFIX(key, "vncunused=")) {
-                        if (STREQ(key + 10, "1"))
-                            graphics->data.vnc.autoport = true;
-                    } else if (STRPREFIX(key, "vnclisten=")) {
-                        if (VIR_STRDUP(listenAddr, key+10) < 0)
-                            goto cleanup;
-                    } else if (STRPREFIX(key, "vncpasswd=")) {
-                        if (VIR_STRDUP(graphics->data.vnc.auth.passwd, key + 10) < 0)
-                            goto cleanup;
-                    } else if (STRPREFIX(key, "keymap=")) {
-                        if (VIR_STRDUP(graphics->data.vnc.keymap, key + 7) < 0)
-                            goto cleanup;
-                    } else if (STRPREFIX(key, "vncdisplay=")) {
-                        if (virStrToLong_i(key + 11, NULL, 10,
-                                           &graphics->data.vnc.port) < 0) {
-                            virReportError(VIR_ERR_INTERNAL_ERROR,
-                                           _("invalid vncdisplay value '%s'"),
-                                           key + 11);
-                            goto cleanup;
-                        }
-                        graphics->data.vnc.port += 5900;
-                    }
-                } else {
-                    if (STRPREFIX(key, "display=")) {
-                        if (VIR_STRDUP(graphics->data.sdl.display, key + 8) < 0)
-                            goto cleanup;
-                    } else if (STRPREFIX(key, "xauthority=")) {
-                        if (VIR_STRDUP(graphics->data.sdl.xauth, key + 11) < 0)
-                            goto cleanup;
-                    }
-                }
-
-                while (nextkey && (nextkey[0] == ',' ||
-                                   nextkey[0] == ' ' ||
-                                   nextkey[0] == '\t'))
-                    nextkey++;
-                key = nextkey;
-            }
-            if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
-                if (virDomainGraphicsListenAppendAddress(graphics,
-                                                         listenAddr) < 0)
-                    goto cleanup;
-                VIR_FREE(listenAddr);
-            }
-            if (VIR_ALLOC_N(def->graphics, 1) < 0)
-                goto cleanup;
-            def->graphics[0] = graphics;
-            def->ngraphics = 1;
-            graphics = NULL;
-        } else {
-            if (xenHandleConfGetValueStringListErrors(rc) < 0)
-                goto cleanup;
-        }
-    }
-
-    return 0;
-
- cleanup:
-    virDomainGraphicsDefFree(graphics);
-    VIR_FREE(listenAddr);
-    return -1;
-}
-
-
-/**
-  * xenParseSxprChar:
-  * @value: A string describing a character device.
-  * @tty: the console pty path
-  *
-  * Parse the xend S-expression for description of a character device.
-  *
-  * Returns a character device object or NULL in case of failure.
-  */
-static virDomainChrDefPtr
-xenParseSxprChar(const char *value,
-                 const char *tty)
-{
-    const char *prefix;
-    char *tmp;
-    virDomainChrDefPtr def;
-
-    if (!(def = virDomainChrDefNew(NULL)))
-        return NULL;
-
-    prefix = value;
-
-    if (value[0] == '/') {
-        def->source->type = VIR_DOMAIN_CHR_TYPE_DEV;
-        if (VIR_STRDUP(def->source->data.file.path, value) < 0)
-            goto error;
-    } else {
-        if ((tmp = strchr(value, ':')) != NULL) {
-            *tmp = '\0';
-            value = tmp + 1;
-        }
-
-        if (STRPREFIX(prefix, "telnet")) {
-            def->source->type = VIR_DOMAIN_CHR_TYPE_TCP;
-            def->source->data.tcp.protocol = VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET;
-        } else {
-            if ((def->source->type = virDomainChrTypeFromString(prefix)) < 0) {
-                virReportError(VIR_ERR_INTERNAL_ERROR,
-                               _("unknown chr device type '%s'"), prefix);
-                goto error;
-            }
-        }
-    }
-
-    switch (def->source->type) {
-    case VIR_DOMAIN_CHR_TYPE_PTY:
-        if (VIR_STRDUP(def->source->data.file.path, tty) < 0)
-            goto error;
-        break;
-
-    case VIR_DOMAIN_CHR_TYPE_FILE:
-    case VIR_DOMAIN_CHR_TYPE_PIPE:
-        if (VIR_STRDUP(def->source->data.file.path, value) < 0)
-            goto error;
-        break;
-
-    case VIR_DOMAIN_CHR_TYPE_TCP:
-    {
-        const char *offset = strchr(value, ':');
-        const char *offset2;
-
-        if (offset == NULL) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           "%s", _("malformed char device string"));
-            goto error;
-        }
-
-        if (offset != value &&
-            VIR_STRNDUP(def->source->data.tcp.host, value, offset - value) < 0)
-            goto error;
-
-        offset2 = strchr(offset, ',');
-        offset++;
-        if (VIR_STRNDUP(def->source->data.tcp.service, offset,
-                        offset2 ? offset2 - offset : -1) < 0)
-            goto error;
-
-        if (offset2 && strstr(offset2, ",server"))
-            def->source->data.tcp.listen = true;
-    }
-    break;
-
-    case VIR_DOMAIN_CHR_TYPE_UDP:
-    {
-        const char *offset = strchr(value, ':');
-        const char *offset2, *offset3;
-
-        if (offset == NULL) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           "%s", _("malformed char device string"));
-            goto error;
-        }
-
-        if (offset != value &&
-            VIR_STRNDUP(def->source->data.udp.connectHost, value, offset - value) < 0)
-            goto error;
-
-        offset2 = strchr(offset, '@');
-        if (offset2 != NULL) {
-            if (VIR_STRNDUP(def->source->data.udp.connectService,
-                            offset + 1, offset2 - offset - 1) < 0)
-                goto error;
-
-            offset3 = strchr(offset2, ':');
-            if (offset3 == NULL) {
-                virReportError(VIR_ERR_INTERNAL_ERROR,
-                               "%s", _("malformed char device string"));
-                goto error;
-            }
-
-            if (offset3 > (offset2 + 1) &&
-                VIR_STRNDUP(def->source->data.udp.bindHost,
-                            offset2 + 1, offset3 - offset2 - 1) < 0)
-                goto error;
-
-            if (VIR_STRDUP(def->source->data.udp.bindService, offset3 + 1) < 0)
-                goto error;
-        } else {
-            if (VIR_STRDUP(def->source->data.udp.connectService, offset + 1) < 0)
-                goto error;
-        }
-    }
-    break;
-
-    case VIR_DOMAIN_CHR_TYPE_UNIX:
-    {
-        const char *offset = strchr(value, ',');
-        if (VIR_STRNDUP(def->source->data.nix.path, value,
-                        offset ? offset - value : -1) < 0)
-            goto error;
-
-        if (offset != NULL &&
-            strstr(offset, ",server") != NULL)
-            def->source->data.nix.listen = true;
-    }
-    break;
-    }
-
-    return def;
-
- error:
-    virDomainChrDefFree(def);
-    return NULL;
-}
-
-
-static int
-xenParseCharDev(virConfPtr conf, virDomainDefPtr def, const char *nativeFormat)
-{
-    VIR_AUTOSTRINGLIST serials = NULL;
-    virDomainChrDefPtr chr = NULL;
-
-    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
-        VIR_AUTOFREE(char *) parallel = NULL;
-        int rc;
-
-        if (xenConfigGetString(conf, "parallel", &parallel, NULL) < 0)
-            goto cleanup;
-        if (parallel && STRNEQ(parallel, "none") &&
-            !(chr = xenParseSxprChar(parallel, NULL)))
-            goto cleanup;
-        if (chr) {
-            if (VIR_ALLOC_N(def->parallels, 1) < 0)
-                goto cleanup;
-
-            chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL;
-            chr->target.port = 0;
-            def->parallels[0] = chr;
-            def->nparallels++;
-            chr = NULL;
-        }
-
-        /* Try to get the list of values to support multiple serial ports */
-        if ((rc = virConfGetValueStringList(conf, "serial", false, &serials)) == 1) {
-            char **entries;
-            int portnum = -1;
-
-            if (STREQ(nativeFormat, XEN_CONFIG_FORMAT_XM)) {
-                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                               _("Multiple serial devices are not supported by xen-xm"));
-                goto cleanup;
-            }
-
-            for (entries = serials; *entries; entries++) {
-                char *port = *entries;
-
-                portnum++;
-                if (STREQ(port, "none"))
-                    continue;
-
-                if (!(chr = xenParseSxprChar(port, NULL)))
-                    goto cleanup;
-                chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL;
-                chr->target.port = portnum;
-                if (VIR_APPEND_ELEMENT(def->serials, def->nserials, chr) < 0)
-                    goto cleanup;
-            }
-        } else {
-            VIR_AUTOFREE(char *) serial = NULL;
-
-            if (xenHandleConfGetValueStringListErrors(rc) < 0)
-                goto cleanup;
-
-            /* If domain is not using multiple serial ports we parse data old way */
-            if (xenConfigGetString(conf, "serial", &serial, NULL) < 0)
-                goto cleanup;
-            if (serial && STRNEQ(serial, "none") &&
-                !(chr = xenParseSxprChar(serial, NULL)))
-                goto cleanup;
-            if (chr) {
-                if (VIR_ALLOC_N(def->serials, 1) < 0)
-                    goto cleanup;
-                chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL;
-                chr->target.port = 0;
-                def->serials[0] = chr;
-                def->nserials++;
-            }
-        }
-    } else {
-        if (VIR_ALLOC_N(def->consoles, 1) < 0)
-            goto cleanup;
-        def->nconsoles = 1;
-        if (!(def->consoles[0] = xenParseSxprChar("pty", NULL)))
-            goto cleanup;
-        def->consoles[0]->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE;
-        def->consoles[0]->target.port = 0;
-        def->consoles[0]->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_XEN;
-    }
-
-    return 0;
-
- cleanup:
-    virDomainChrDefFree(chr);
-    return -1;
-}
-
-
-static int
-xenParseVifBridge(virDomainNetDefPtr net, char *bridge)
-{
-    char *vlanstr;
-    unsigned int tag;
-
-    if ((vlanstr = strchr(bridge, '.'))) {
-        /* 'bridge' string contains a bridge name and single vlan tag */
-        if (VIR_STRNDUP(net->data.bridge.brname, bridge, vlanstr - bridge) < 0)
-            return -1;
-
-        vlanstr++;
-        if (virStrToLong_ui(vlanstr, NULL, 10, &tag) < 0)
-            return -1;
-
-        if (VIR_ALLOC_N(net->vlan.tag, 1) < 0)
-            return -1;
-
-        net->vlan.tag[0] = tag;
-        net->vlan.nTags = 1;
-
-        if (VIR_ALLOC(net->virtPortProfile) < 0)
-            return -1;
-
-        net->virtPortProfile->virtPortType = VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH;
-        return 0;
-    } else if ((vlanstr = strchr(bridge, ':'))) {
-        /* 'bridge' string contains a bridge name and one or more vlan trunks */
-        size_t i;
-        size_t nvlans = 0;
-        char **vlanstr_list = virStringSplit(bridge, ":", 0);
-
-        if (!vlanstr_list)
-            return -1;
-
-        if (VIR_STRDUP(net->data.bridge.brname, vlanstr_list[0]) < 0) {
-            virStringListFree(vlanstr_list);
-            return -1;
-        }
-
-        for (i = 1; vlanstr_list[i]; i++)
-            nvlans++;
-
-        if (VIR_ALLOC_N(net->vlan.tag, nvlans) < 0) {
-            virStringListFree(vlanstr_list);
-            return -1;
-        }
-
-        for (i = 1; i <= nvlans; i++) {
-            if (virStrToLong_ui(vlanstr_list[i], NULL, 10, &tag) < 0) {
-                virStringListFree(vlanstr_list);
-                return -1;
-            }
-            net->vlan.tag[i - 1] = tag;
-        }
-        net->vlan.nTags = nvlans;
-        net->vlan.trunk = true;
-        virStringListFree(vlanstr_list);
-
-        if (VIR_ALLOC(net->virtPortProfile) < 0)
-            return -1;
-
-        net->virtPortProfile->virtPortType = VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH;
-        return 0;
-    } else {
-        /* 'bridge' string only contains the bridge name */
-        if (VIR_STRDUP(net->data.bridge.brname, bridge) < 0)
-            return -1;
-    }
-
-    return 0;
-}
-
-
-static const char *vif_bytes_per_sec_re = "^[0-9]+[GMK]?[Bb]/s$";
-
-static int
-xenParseSxprVifRate(const char *rate, unsigned long long *kbytes_per_sec)
-{
-    char *trate = NULL;
-    char *p;
-    regex_t rec;
-    int err;
-    char *suffix;
-    unsigned long long tmp;
-    int ret = -1;
-
-    if (VIR_STRDUP(trate, rate) < 0)
-        return -1;
-
-    p = strchr(trate, '@');
-    if (p != NULL)
-        *p = 0;
-
-    err = regcomp(&rec, vif_bytes_per_sec_re, REG_EXTENDED|REG_NOSUB);
-    if (err != 0) {
-        char error[100];
-        regerror(err, &rec, error, sizeof(error));
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Failed to compile regular expression '%s': %s"),
-                       vif_bytes_per_sec_re, error);
-        goto cleanup;
-    }
-
-    if (regexec(&rec, trate, 0, NULL, 0)) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Invalid rate '%s' specified"), rate);
-        goto cleanup;
-    }
-
-    if (virStrToLong_ull(rate, &suffix, 10, &tmp)) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Failed to parse rate '%s'"), rate);
-        goto cleanup;
-    }
-
-    if (*suffix == 'G')
-       tmp *= 1024 * 1024;
-    else if (*suffix == 'M')
-       tmp *= 1024;
-
-    if (*suffix == 'b' || *(suffix + 1) == 'b')
-       tmp /= 8;
-
-    *kbytes_per_sec = tmp;
-    ret = 0;
-
- cleanup:
-    regfree(&rec);
-    VIR_FREE(trate);
-    return ret;
-}
-
-
-static virDomainNetDefPtr
-xenParseVif(char *entry, const char *vif_typename)
-{
-    virDomainNetDefPtr net = NULL;
-    virDomainNetDefPtr ret = NULL;
-    char *script = NULL;
-    char model[10];
-    char type[10];
-    char ip[128];
-    char mac[18];
-    char bridge[50];
-    char vifname[50];
-    char rate[50];
-    char *key;
-
-    bridge[0] = '\0';
-    mac[0] = '\0';
-    ip[0] = '\0';
-    model[0] = '\0';
-    type[0] = '\0';
-    vifname[0] = '\0';
-    rate[0] = '\0';
-
-    key = entry;
-    while (key) {
-        char *data;
-        char *nextkey = strchr(key, ',');
-
-        if (!(data = strchr(key, '=')))
-            return NULL;
-        data++;
-
-        if (STRPREFIX(key, "mac=")) {
-            int len = nextkey ? (nextkey - data) : strlen(data);
-            if (virStrncpy(mac, data, len, sizeof(mac)) < 0) {
-                virReportError(VIR_ERR_INTERNAL_ERROR,
-                               _("MAC address %s too big for destination"),
-                               data);
-                return NULL;
-            }
-        } else if (STRPREFIX(key, "bridge=")) {
-            int len = nextkey ? (nextkey - data) : strlen(data);
-            if (virStrncpy(bridge, data, len, sizeof(bridge)) < 0) {
-                virReportError(VIR_ERR_INTERNAL_ERROR,
-                               _("Bridge %s too big for destination"),
-                               data);
-                return NULL;
-            }
-        } else if (STRPREFIX(key, "script=")) {
-            int len = nextkey ? (nextkey - data) : strlen(data);
-            VIR_FREE(script);
-            if (VIR_STRNDUP(script, data, len) < 0)
-                return NULL;
-        } else if (STRPREFIX(key, "model=")) {
-            int len = nextkey ? (nextkey - data) : strlen(data);
-            if (virStrncpy(model, data, len, sizeof(model)) < 0) {
-                virReportError(VIR_ERR_INTERNAL_ERROR,
-                               _("Model %s too big for destination"),
-                               data);
-                return NULL;
-            }
-        } else if (STRPREFIX(key, "type=")) {
-            int len = nextkey ? (nextkey - data) : strlen(data);
-            if (virStrncpy(type, data, len, sizeof(type)) < 0) {
-                virReportError(VIR_ERR_INTERNAL_ERROR,
-                               _("Type %s too big for destination"),
-                               data);
-                return NULL;
-            }
-        } else if (STRPREFIX(key, "vifname=")) {
-            int len = nextkey ? (nextkey - data) : strlen(data);
-            if (virStrncpy(vifname, data, len, sizeof(vifname)) < 0) {
-                virReportError(VIR_ERR_INTERNAL_ERROR,
-                               _("Vifname %s too big for destination"),
-                               data);
-                return NULL;
-            }
-        } else if (STRPREFIX(key, "ip=")) {
-            int len = nextkey ? (nextkey - data) : strlen(data);
-            if (virStrncpy(ip, data, len, sizeof(ip)) < 0) {
-                virReportError(VIR_ERR_INTERNAL_ERROR,
-                               _("IP %s too big for destination"), data);
-                return NULL;
-            }
-        } else if (STRPREFIX(key, "rate=")) {
-            int len = nextkey ? (nextkey - data) : strlen(data);
-            if (virStrncpy(rate, data, len, sizeof(rate)) < 0) {
-                virReportError(VIR_ERR_INTERNAL_ERROR,
-                               _("rate %s too big for destination"), data);
-                return NULL;
-            }
-        }
-
-        while (nextkey && (nextkey[0] == ',' ||
-                           nextkey[0] == ' ' ||
-                           nextkey[0] == '\t'))
-            nextkey++;
-        key = nextkey;
-    }
-
-    if (VIR_ALLOC(net) < 0)
-        goto cleanup;
-
-    if (mac[0]) {
-        if (virMacAddrParse(mac, &net->mac) < 0) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("malformed mac address '%s'"), mac);
-            goto cleanup;
-        }
-    }
-
-    if (bridge[0] || STREQ_NULLABLE(script, "vif-bridge") ||
-        STREQ_NULLABLE(script, "vif-vnic")) {
-        net->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
-    } else {
-        net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
-    }
-
-    if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE && bridge[0]) {
-        if (xenParseVifBridge(net, bridge) < 0)
-            goto cleanup;
-    }
-    if (ip[0]) {
-        char **ip_list = virStringSplit(ip, " ", 0);
-        size_t i;
-
-        if (!ip_list)
-            goto cleanup;
-
-        for (i = 0; ip_list[i]; i++) {
-            if (virDomainNetAppendIPAddress(net, ip_list[i], 0, 0) < 0) {
-                virStringListFree(ip_list);
-                goto cleanup;
-            }
-        }
-        virStringListFree(ip_list);
-    }
-
-    if (script && script[0] &&
-        VIR_STRDUP(net->script, script) < 0)
-        goto cleanup;
-
-    if (model[0]) {
-        if (virDomainNetSetModelString(net, model) < 0)
-            goto cleanup;
-    } else {
-        if (type[0] && STREQ(type, vif_typename))
-            net->model = VIR_DOMAIN_NET_MODEL_NETFRONT;
-    }
-
-    if (vifname[0] &&
-        VIR_STRDUP(net->ifname, vifname) < 0)
-        goto cleanup;
-
-    if (rate[0]) {
-        virNetDevBandwidthPtr bandwidth;
-        unsigned long long kbytes_per_sec;
-
-        if (xenParseSxprVifRate(rate, &kbytes_per_sec) < 0)
-            goto cleanup;
-
-        if (VIR_ALLOC(bandwidth) < 0)
-            goto cleanup;
-
-        if (VIR_ALLOC(bandwidth->out) < 0) {
-            VIR_FREE(bandwidth);
-            goto cleanup;
-        }
-
-        bandwidth->out->average = kbytes_per_sec;
-        net->bandwidth = bandwidth;
-    }
-
-    VIR_STEAL_PTR(ret, net);
-
- cleanup:
-    virDomainNetDefFree(net);
-    VIR_FREE(script);
-    return ret;
-}
-
-
-static int
-xenParseVifList(virConfPtr conf, virDomainDefPtr def, const char *vif_typename)
-{
-    virConfValuePtr list = virConfGetValue(conf, "vif");
-
-    if (!list || list->type != VIR_CONF_LIST)
-        return 0;
-
-    for (list = list->list; list; list = list->next) {
-        virDomainNetDefPtr net = NULL;
-        int rc;
-
-        if ((list->type != VIR_CONF_STRING) || (list->str == NULL))
-            continue;
-
-        if (!(net = xenParseVif(list->str, vif_typename)))
-            return -1;
-
-        rc = VIR_APPEND_ELEMENT(def->nets, def->nnets, net);
-        if (rc < 0) {
-            virDomainNetDefFree(net);
-            return -1;
-        }
-    }
-
-    return 0;
-}
-
-
-/**
- * xenParseSxprSound:
- * @def: the domain config
- * @str: comma separated list of sound models
- *
- * This parses out sound devices from the domain S-expression
- *
- * Returns 0 if successful or -1 if failed.
- */
-static int
-xenParseSxprSound(virDomainDefPtr def,
-                  const char *str)
-{
-    if (STREQ(str, "all")) {
-        size_t i;
-
-        /*
-         * Special compatibility code for Xen with a bogus
-         * sound=all in config.
-         *
-         * NB deliberately, don't include all possible
-         * sound models anymore, just the 2 that were
-         * historically present in Xen's QEMU.
-         *
-         * ie just es1370 + sb16.
-         *
-         * Hence use of MODEL_ES1370 + 1, instead of MODEL_LAST
-         */
-
-        if (VIR_ALLOC_N(def->sounds,
-                        VIR_DOMAIN_SOUND_MODEL_ES1370 + 1) < 0)
-            return -1;
-
-
-        for (i = 0; i < (VIR_DOMAIN_SOUND_MODEL_ES1370 + 1); i++) {
-            virDomainSoundDefPtr sound;
-            if (VIR_ALLOC(sound) < 0)
-                return -1;
-            sound->model = i;
-            def->sounds[def->nsounds++] = sound;
-        }
-    } else {
-        char model[10];
-        const char *offset = str, *offset2;
-
-        do {
-            int len;
-            virDomainSoundDefPtr sound;
-            offset2 = strchr(offset, ',');
-            if (offset2)
-                len = (offset2 - offset);
-            else
-                len = strlen(offset);
-            if (virStrncpy(model, offset, len, sizeof(model)) < 0) {
-                virReportError(VIR_ERR_INTERNAL_ERROR,
-                               _("Sound model %s too big for destination"),
-                               offset);
-                return -1;
-            }
-
-            if (VIR_ALLOC(sound) < 0)
-                return -1;
-
-            if ((sound->model = virDomainSoundModelTypeFromString(model)) < 0) {
-                VIR_FREE(sound);
-                return -1;
-            }
-
-            if (VIR_APPEND_ELEMENT(def->sounds, def->nsounds, sound) < 0) {
-                virDomainSoundDefFree(sound);
-                return -1;
-            }
-
-            offset = offset2 ? offset2 + 1 : NULL;
-        } while (offset);
-    }
-
-    return 0;
-}
-
-
-static int
-xenParseEmulatedDevices(virConfPtr conf, virDomainDefPtr def)
-{
-    VIR_AUTOFREE(char *) str = NULL;
-
-    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
-        if (xenConfigGetString(conf, "soundhw", &str, NULL) < 0)
-            return -1;
-
-        if (str &&
-            xenParseSxprSound(def, str) < 0)
-            return -1;
-    }
-
-    return 0;
-}
-
-
-static int
-xenParseGeneralMeta(virConfPtr conf, virDomainDefPtr def, virCapsPtr caps)
-{
-    virCapsDomainDataPtr capsdata = NULL;
-    VIR_AUTOFREE(char *) str = NULL;
-    int ret = -1;
-
-    if (xenConfigCopyString(conf, "name", &def->name) < 0)
-        goto out;
-
-    if (xenConfigGetUUID(conf, "uuid", def->uuid) < 0)
-        goto out;
-
-    def->os.type = VIR_DOMAIN_OSTYPE_XEN;
-
-    if (xenConfigGetString(conf, "type", &str, NULL) == 0 && str) {
-        if (STREQ(str, "pv")) {
-            def->os.type = VIR_DOMAIN_OSTYPE_XEN;
-        } else if (STREQ(str, "pvh")) {
-            def->os.type = VIR_DOMAIN_OSTYPE_XENPVH;
-        } else if (STREQ(str, "hvm")) {
-            def->os.type = VIR_DOMAIN_OSTYPE_HVM;
-        } else {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                           _("type %s is not supported"), str);
-            return -1;
-        }
-    } else {
-        if ((xenConfigGetString(conf, "builder", &str, "linux") == 0) &&
-            STREQ(str, "hvm")) {
-            def->os.type = VIR_DOMAIN_OSTYPE_HVM;
-        }
-    }
-
-    if (!(capsdata = virCapabilitiesDomainDataLookup(caps, def->os.type,
-            VIR_ARCH_NONE, def->virtType, NULL, NULL)))
-        goto out;
-
-    def->os.arch = capsdata->arch;
-    if (VIR_STRDUP(def->os.machine, capsdata->machinetype) < 0)
-        goto out;
-
-    ret = 0;
- out:
-    VIR_FREE(capsdata);
-    return ret;
-}
-
-
-/*
- * A convenience function for parsing all config common to both XM and XL
- */
-int
-xenParseConfigCommon(virConfPtr conf,
-                     virDomainDefPtr def,
-                     virCapsPtr caps,
-                     const char *nativeFormat,
-                     virDomainXMLOptionPtr xmlopt)
-{
-    if (xenParseGeneralMeta(conf, def, caps) < 0)
-        return -1;
-
-    if (xenParseMem(conf, def) < 0)
-        return -1;
-
-    if (xenParseEventsActions(conf, def) < 0)
-        return -1;
-
-    if (xenParseCPUFeatures(conf, def, xmlopt) < 0)
-        return -1;
-
-    if (xenParseTimeOffset(conf, def) < 0)
-        return -1;
-
-    if (xenConfigCopyStringOpt(conf, "device_model", &def->emulator) < 0)
-        return -1;
-
-    if (STREQ(nativeFormat, XEN_CONFIG_FORMAT_XL)) {
-        if (xenParseVifList(conf, def, "vif") < 0)
-            return -1;
-    } else if (STREQ(nativeFormat, XEN_CONFIG_FORMAT_XM)) {
-        if (xenParseVifList(conf, def, "netfront") < 0)
-            return -1;
-    } else {
-        virReportError(VIR_ERR_INVALID_ARG,
-                       _("unsupported config type %s"), nativeFormat);
-        return -1;
-    }
-
-    if (xenParsePCIList(conf, def) < 0)
-        return -1;
-
-    if (xenParseEmulatedDevices(conf, def) < 0)
-        return -1;
-
-    if (xenParseVfb(conf, def) < 0)
-        return -1;
-
-    if (xenParseCharDev(conf, def, nativeFormat) < 0)
-        return -1;
-
-    return 0;
-}
-
-
-/**
- * xenFormatSxprChr:
- * @def: the domain config
- * @buf: a buffer for the result S-expression
- *
- * Convert the character device part of the domain config into a S-expression
- * in buf.
- *
- * Returns 0 in case of success, -1 in case of error
- */
-static int
-xenFormatSxprChr(virDomainChrDefPtr def,
-                 virBufferPtr buf)
-{
-    const char *type = virDomainChrTypeToString(def->source->type);
-
-    if (!type) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       "%s", _("unexpected chr device type"));
-        return -1;
-    }
-
-    switch (def->source->type) {
-    case VIR_DOMAIN_CHR_TYPE_NULL:
-    case VIR_DOMAIN_CHR_TYPE_STDIO:
-    case VIR_DOMAIN_CHR_TYPE_VC:
-    case VIR_DOMAIN_CHR_TYPE_PTY:
-        virBufferAdd(buf, type, -1);
-        break;
-
-    case VIR_DOMAIN_CHR_TYPE_FILE:
-    case VIR_DOMAIN_CHR_TYPE_PIPE:
-        virBufferAsprintf(buf, "%s:", type);
-        virBufferEscapeSexpr(buf, "%s", def->source->data.file.path);
-        break;
-
-    case VIR_DOMAIN_CHR_TYPE_DEV:
-        virBufferEscapeSexpr(buf, "%s", def->source->data.file.path);
-        break;
-
-    case VIR_DOMAIN_CHR_TYPE_TCP:
-        virBufferAsprintf(buf, "%s:%s:%s%s",
-                          (def->source->data.tcp.protocol
-                           == VIR_DOMAIN_CHR_TCP_PROTOCOL_RAW ?
-                           "tcp" : "telnet"),
-                          NULLSTR_EMPTY(def->source->data.tcp.host),
-                          NULLSTR_EMPTY(def->source->data.tcp.service),
-                          (def->source->data.tcp.listen ?
-                           ",server,nowait" : ""));
-        break;
-
-    case VIR_DOMAIN_CHR_TYPE_UDP:
-        virBufferAsprintf(buf, "%s:%s:%s@%s:%s", type,
-                          NULLSTR_EMPTY(def->source->data.udp.connectHost),
-                          NULLSTR_EMPTY(def->source->data.udp.connectService),
-                          NULLSTR_EMPTY(def->source->data.udp.bindHost),
-                          NULLSTR_EMPTY(def->source->data.udp.bindService));
-        break;
-
-    case VIR_DOMAIN_CHR_TYPE_UNIX:
-        virBufferAsprintf(buf, "%s:", type);
-        virBufferEscapeSexpr(buf, "%s", def->source->data.nix.path);
-        if (def->source->data.nix.listen)
-            virBufferAddLit(buf, ",server,nowait");
-        break;
-
-    default:
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                       _("unsupported chr device type '%s'"), type);
-        return -1;
-    }
-
-    if (virBufferCheckError(buf) < 0)
-        return -1;
-
-    return 0;
-}
-
-
-static int
-xenFormatSerial(virConfValuePtr list, virDomainChrDefPtr serial)
-{
-    virBuffer buf = VIR_BUFFER_INITIALIZER;
-    virConfValuePtr val, tmp;
-    int ret;
-
-    if (serial) {
-        ret = xenFormatSxprChr(serial, &buf);
-        if (ret < 0)
-            goto cleanup;
-    } else {
-        virBufferAddLit(&buf, "none");
-    }
-    if (virBufferCheckError(&buf) < 0)
-        goto cleanup;
-
-    if (VIR_ALLOC(val) < 0)
-        goto cleanup;
-
-    val->type = VIR_CONF_STRING;
-    val->str = virBufferContentAndReset(&buf);
-    tmp = list->list;
-    while (tmp && tmp->next)
-        tmp = tmp->next;
-    if (tmp)
-        tmp->next = val;
-    else
-        list->list = val;
-
-    return 0;
-
- cleanup:
-    virBufferFreeAndReset(&buf);
-    return -1;
-}
-
-char *
-xenMakeIPList(virNetDevIPInfoPtr guestIP)
-{
-    size_t i;
-    char **address_array;
-    char *ret = NULL;
-
-    if (VIR_ALLOC_N(address_array, guestIP->nips + 1) < 0)
-        return NULL;
-
-    for (i = 0; i < guestIP->nips; i++) {
-        address_array[i] = virSocketAddrFormat(&guestIP->ips[i]->address);
-        if (!address_array[i])
-            goto cleanup;
-    }
-    ret = virStringListJoin((const char**)address_array, " ");
-
- cleanup:
-    virStringListFree(address_array);
-    return ret;
-}
-
-static int
-xenFormatNet(virConnectPtr conn,
-             virConfValuePtr list,
-             virDomainNetDefPtr net,
-             int hvm,
-             const char *vif_typename)
-{
-    virBuffer buf = VIR_BUFFER_INITIALIZER;
-    virConfValuePtr val, tmp;
-    char macaddr[VIR_MAC_STRING_BUFLEN];
-
-    virBufferAsprintf(&buf, "mac=%s", virMacAddrFormat(&net->mac, macaddr));
-
-    switch (net->type) {
-    case VIR_DOMAIN_NET_TYPE_BRIDGE:
-    {
-        virNetDevVPortProfilePtr port_profile = virDomainNetGetActualVirtPortProfile(net);
-        virNetDevVlanPtr virt_vlan = virDomainNetGetActualVlan(net);
-        const char *script = net->script;
-        size_t i;
-
-        virBufferAsprintf(&buf, ",bridge=%s", net->data.bridge.brname);
-        if (port_profile &&
-            port_profile->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH) {
-            if (!script)
-                script = "vif-openvswitch";
-            /*
-             * libxl_device_nic->bridge supports an extended format for
-             * specifying VLAN tags and trunks
-             *
-             * BRIDGE_NAME[.VLAN][:TRUNK:TRUNK]
-             */
-            if (virt_vlan && virt_vlan->nTags > 0) {
-                if (virt_vlan->trunk) {
-                    for (i = 0; i < virt_vlan->nTags; i++)
-                        virBufferAsprintf(&buf, ":%d", virt_vlan->tag[i]);
-                } else {
-                    virBufferAsprintf(&buf, ".%d", virt_vlan->tag[0]);
-                }
-            }
-        }
-
-        if (net->guestIP.nips > 0) {
-            char *ipStr = xenMakeIPList(&net->guestIP);
-            virBufferAsprintf(&buf, ",ip=%s", ipStr);
-            VIR_FREE(ipStr);
-        }
-        virBufferAsprintf(&buf, ",script=%s", script ? script : DEFAULT_VIF_SCRIPT);
-    }
-    break;
-
-    case VIR_DOMAIN_NET_TYPE_ETHERNET:
-        if (net->script)
-            virBufferAsprintf(&buf, ",script=%s", net->script);
-        if (net->guestIP.nips > 0) {
-            char *ipStr = xenMakeIPList(&net->guestIP);
-            virBufferAsprintf(&buf, ",ip=%s", ipStr);
-            VIR_FREE(ipStr);
-        }
-        break;
-
-    case VIR_DOMAIN_NET_TYPE_NETWORK:
-    {
-        virNetworkPtr network = virNetworkLookupByName(conn, net->data.network.name);
-        char *bridge;
-        if (!network) {
-            virReportError(VIR_ERR_NO_NETWORK, "%s",
-                           net->data.network.name);
-            return -1;
-        }
-        bridge = virNetworkGetBridgeName(network);
-        virObjectUnref(network);
-        if (!bridge) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("network %s is not active"),
-                           net->data.network.name);
-            return -1;
-        }
-
-        virBufferAsprintf(&buf, ",bridge=%s", bridge);
-        virBufferAsprintf(&buf, ",script=%s", DEFAULT_VIF_SCRIPT);
-    }
-    break;
-
-    case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
-    case VIR_DOMAIN_NET_TYPE_SERVER:
-    case VIR_DOMAIN_NET_TYPE_CLIENT:
-    case VIR_DOMAIN_NET_TYPE_MCAST:
-    case VIR_DOMAIN_NET_TYPE_INTERNAL:
-    case VIR_DOMAIN_NET_TYPE_DIRECT:
-    case VIR_DOMAIN_NET_TYPE_HOSTDEV:
-    case VIR_DOMAIN_NET_TYPE_UDP:
-    case VIR_DOMAIN_NET_TYPE_USER:
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Unsupported net type '%s'"),
-                       virDomainNetTypeToString(net->type));
-        goto cleanup;
-
-    case VIR_DOMAIN_NET_TYPE_LAST:
-    default:
-        virReportEnumRangeError(virDomainNetType, net->type);
-        goto cleanup;
-    }
-
-    if (virDomainNetGetModelString(net)) {
-        if (!hvm) {
-            virBufferAsprintf(&buf, ",model=%s",
-                              virDomainNetGetModelString(net));
-        } else {
-            if (net->model == VIR_DOMAIN_NET_MODEL_NETFRONT)
-                virBufferAsprintf(&buf, ",type=%s", vif_typename);
-            else
-                virBufferAsprintf(&buf, ",model=%s",
-                                  virDomainNetGetModelString(net));
-        }
-    }
-
-    if (net->ifname)
-        virBufferAsprintf(&buf, ",vifname=%s",
-                          net->ifname);
-
-    if (net->bandwidth && net->bandwidth->out && net->bandwidth->out->average)
-        virBufferAsprintf(&buf, ",rate=%lluKB/s", net->bandwidth->out->average);
-
-    if (virBufferCheckError(&buf) < 0)
-        goto cleanup;
-
-    if (VIR_ALLOC(val) < 0)
-        goto cleanup;
-
-    val->type = VIR_CONF_STRING;
-    val->str = virBufferContentAndReset(&buf);
-    tmp = list->list;
-    while (tmp && tmp->next)
-        tmp = tmp->next;
-    if (tmp)
-        tmp->next = val;
-    else
-        list->list = val;
-
-    return 0;
-
- cleanup:
-    virBufferFreeAndReset(&buf);
-    return -1;
-}
-
-
-static int
-xenFormatPCI(virConfPtr conf, virDomainDefPtr def)
-{
-    virConfValuePtr pciVal = NULL;
-    int hasPCI = 0;
-    size_t i;
-
-    for (i = 0; i < def->nhostdevs; i++)
-        if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
-            def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
-            hasPCI = 1;
-
-    if (!hasPCI)
-        return 0;
-
-    if (VIR_ALLOC(pciVal) < 0)
-        return -1;
-
-    pciVal->type = VIR_CONF_LIST;
-    pciVal->list = NULL;
-
-    for (i = 0; i < def->nhostdevs; i++) {
-        if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
-            def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
-            virConfValuePtr val, tmp;
-            char *buf;
-
-            if (virAsprintf(&buf, "%04x:%02x:%02x.%x",
-                            def->hostdevs[i]->source.subsys.u.pci.addr.domain,
-                            def->hostdevs[i]->source.subsys.u.pci.addr.bus,
-                            def->hostdevs[i]->source.subsys.u.pci.addr.slot,
-                            def->hostdevs[i]->source.subsys.u.pci.addr.function) < 0)
-                goto error;
-
-            if (VIR_ALLOC(val) < 0) {
-                VIR_FREE(buf);
-                goto error;
-            }
-            val->type = VIR_CONF_STRING;
-            val->str = buf;
-            tmp = pciVal->list;
-            while (tmp && tmp->next)
-                tmp = tmp->next;
-            if (tmp)
-                tmp->next = val;
-            else
-                pciVal->list = val;
-        }
-    }
-
-    if (pciVal->list != NULL) {
-        int ret = virConfSetValue(conf, "pci", pciVal);
-        pciVal = NULL;
-        if (ret < 0)
-            return -1;
-    }
-    VIR_FREE(pciVal);
-
-    return 0;
-
- error:
-    virConfFreeValue(pciVal);
-    return -1;
-}
-
-
-static int
-xenFormatGeneralMeta(virConfPtr conf, virDomainDefPtr def)
-{
-    char uuid[VIR_UUID_STRING_BUFLEN];
-
-    if (xenConfigSetString(conf, "name", def->name) < 0)
-        return -1;
-
-    virUUIDFormat(def->uuid, uuid);
-    if (xenConfigSetString(conf, "uuid", uuid) < 0)
-        return -1;
-
-    return 0;
-}
-
-
-static int
-xenFormatMem(virConfPtr conf, virDomainDefPtr def)
-{
-    if (xenConfigSetInt(conf, "maxmem",
-                        VIR_DIV_UP(virDomainDefGetMemoryTotal(def), 1024)) < 0)
-        return -1;
-
-    if (xenConfigSetInt(conf, "memory",
-                        VIR_DIV_UP(def->mem.cur_balloon, 1024)) < 0)
-        return -1;
-
-    return 0;
-}
-
-
-static int
-xenFormatTimeOffset(virConfPtr conf, virDomainDefPtr def)
-{
-    int vmlocaltime;
-
-    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
-        /* >=3.1 HV: VARIABLE */
-        int rtc_timeoffset;
-
-        switch (def->clock.offset) {
-        case VIR_DOMAIN_CLOCK_OFFSET_VARIABLE:
-            vmlocaltime = (int)def->clock.data.variable.basis;
-            rtc_timeoffset = def->clock.data.variable.adjustment;
-            break;
-        case VIR_DOMAIN_CLOCK_OFFSET_UTC:
-            if (def->clock.data.utc_reset) {
-                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                               _("unsupported clock adjustment='reset'"));
-                return -1;
-            }
-            vmlocaltime = 0;
-            rtc_timeoffset = 0;
-            break;
-        case VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME:
-            if (def->clock.data.utc_reset) {
-                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                               _("unsupported clock adjustment='reset'"));
-                return -1;
-            }
-            vmlocaltime = 1;
-            rtc_timeoffset = 0;
-            break;
-        default:
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                           _("unsupported clock offset='%s'"),
-                           virDomainClockOffsetTypeToString(def->clock.offset));
-            return -1;
-        }
-        if (xenConfigSetInt(conf, "rtc_timeoffset", rtc_timeoffset) < 0)
-            return -1;
-    } else {
-        /* PV: UTC and LOCALTIME */
-        switch (def->clock.offset) {
-        case VIR_DOMAIN_CLOCK_OFFSET_UTC:
-            vmlocaltime = 0;
-            break;
-        case VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME:
-            vmlocaltime = 1;
-            break;
-        default:
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                           _("unsupported clock offset='%s'"),
-                           virDomainClockOffsetTypeToString(def->clock.offset));
-            return -1;
-        }
-    } /* !hvm */
-
-    if (xenConfigSetInt(conf, "localtime", vmlocaltime) < 0)
-        return -1;
-
-    return 0;
-}
-
-
-static int
-xenFormatEventActions(virConfPtr conf, virDomainDefPtr def)
-{
-    const char *lifecycle = NULL;
-
-    if (!(lifecycle = virDomainLifecycleActionTypeToString(def->onPoweroff))) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("unexpected lifecycle action %d"), def->onPoweroff);
-        return -1;
-    }
-    if (xenConfigSetString(conf, "on_poweroff", lifecycle) < 0)
-        return -1;
-
-
-    if (!(lifecycle = virDomainLifecycleActionTypeToString(def->onReboot))) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("unexpected lifecycle action %d"), def->onReboot);
-        return -1;
-    }
-    if (xenConfigSetString(conf, "on_reboot", lifecycle) < 0)
-        return -1;
-
-
-    if (!(lifecycle = virDomainLifecycleActionTypeToString(def->onCrash))) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("unexpected lifecycle action %d"), def->onCrash);
-        return -1;
-    }
-    if (xenConfigSetString(conf, "on_crash", lifecycle) < 0)
-        return -1;
-
-    return 0;
-}
-
-
-static int
-xenFormatCharDev(virConfPtr conf, virDomainDefPtr def,
-                 const char *nativeFormat)
-{
-    size_t i;
-
-    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
-        if (def->nparallels) {
-            virBuffer buf = VIR_BUFFER_INITIALIZER;
-            char *str;
-            int ret;
-
-            ret = xenFormatSxprChr(def->parallels[0], &buf);
-            str = virBufferContentAndReset(&buf);
-            if (ret == 0)
-                ret = xenConfigSetString(conf, "parallel", str);
-            VIR_FREE(str);
-            if (ret < 0)
-                return -1;
-        } else {
-            if (xenConfigSetString(conf, "parallel", "none") < 0)
-                return -1;
-        }
-
-        if (def->nserials) {
-            if ((def->nserials == 1) && (def->serials[0]->target.port == 0)) {
-                virBuffer buf = VIR_BUFFER_INITIALIZER;
-                char *str;
-                int ret;
-
-                ret = xenFormatSxprChr(def->serials[0], &buf);
-                str = virBufferContentAndReset(&buf);
-                if (ret == 0)
-                    ret = xenConfigSetString(conf, "serial", str);
-                VIR_FREE(str);
-                if (ret < 0)
-                    return -1;
-            } else {
-                size_t j = 0;
-                int maxport = -1, port;
-                virConfValuePtr serialVal = NULL;
-
-                if (STREQ(nativeFormat, XEN_CONFIG_FORMAT_XM)) {
-                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                                   _("Multiple serial devices are not supported by xen-xm"));
-                    return -1;
-                }
-
-                if (VIR_ALLOC(serialVal) < 0)
-                    return -1;
-
-                serialVal->type = VIR_CONF_LIST;
-                serialVal->list = NULL;
-
-                for (i = 0; i < def->nserials; i++)
-                    if (def->serials[i]->target.port > maxport)
-                        maxport = def->serials[i]->target.port;
-
-                for (port = 0; port <= maxport; port++) {
-                    virDomainChrDefPtr chr = NULL;
-
-                    for (j = 0; j < def->nserials; j++) {
-                        if (def->serials[j]->target.port == port) {
-                            chr = def->serials[j];
-                            break;
-                        }
-                    }
-
-                    if (xenFormatSerial(serialVal, chr) < 0) {
-                        VIR_FREE(serialVal);
-                        return -1;
-                    }
-                }
-
-                if (serialVal->list != NULL) {
-                    int ret = virConfSetValue(conf, "serial", serialVal);
-
-                    serialVal = NULL;
-                    if (ret < 0)
-                        return -1;
-                }
-                VIR_FREE(serialVal);
-            }
-        } else {
-            if (xenConfigSetString(conf, "serial", "none") < 0)
-                return -1;
-        }
-    }
-
-    return 0;
-}
-
-
-static int
-xenFormatCPUAllocation(virConfPtr conf, virDomainDefPtr def)
-{
-    int ret = -1;
-    char *cpus = NULL;
-
-    if (virDomainDefGetVcpus(def) < virDomainDefGetVcpusMax(def) &&
-        xenConfigSetInt(conf, "maxvcpus", virDomainDefGetVcpusMax(def)) < 0)
-        goto cleanup;
-    if (xenConfigSetInt(conf, "vcpus", virDomainDefGetVcpus(def)) < 0)
-        goto cleanup;
-
-    if ((def->cpumask != NULL) &&
-        ((cpus = virBitmapFormat(def->cpumask)) == NULL)) {
-        goto cleanup;
-    }
-
-    if (cpus &&
-        xenConfigSetString(conf, "cpus", cpus) < 0)
-        goto cleanup;
-
-    ret = 0;
-
- cleanup:
-    VIR_FREE(cpus);
-    return ret;
-}
-
-
-static int
-xenFormatCPUFeatures(virConfPtr conf, virDomainDefPtr def)
-{
-    size_t i;
-    bool hvm = !!(def->os.type == VIR_DOMAIN_OSTYPE_HVM);
-
-    if (hvm) {
-        if (xenConfigSetInt(conf, "pae",
-                            (def->features[VIR_DOMAIN_FEATURE_PAE] ==
-                            VIR_TRISTATE_SWITCH_ON) ? 1 : 0) < 0)
-            return -1;
-
-        if (xenConfigSetInt(conf, "acpi",
-                            (def->features[VIR_DOMAIN_FEATURE_ACPI] ==
-                            VIR_TRISTATE_SWITCH_ON) ? 1 : 0) < 0)
-            return -1;
-
-        if (xenConfigSetInt(conf, "apic",
-                            (def->features[VIR_DOMAIN_FEATURE_APIC] ==
-                            VIR_TRISTATE_SWITCH_ON) ? 1 : 0) < 0)
-            return -1;
-
-        if (def->features[VIR_DOMAIN_FEATURE_HAP] == VIR_TRISTATE_SWITCH_OFF) {
-            if (xenConfigSetInt(conf, "hap", 0) < 0)
-                return -1;
-        }
-
-        if (xenConfigSetInt(conf, "viridian",
-                            (def->features[VIR_DOMAIN_FEATURE_VIRIDIAN] ==
-                             VIR_TRISTATE_SWITCH_ON) ? 1 : 0) < 0)
-            return -1;
-    }
-
-    for (i = 0; i < def->clock.ntimers; i++) {
-        switch ((virDomainTimerNameType)def->clock.timers[i]->name) {
-        case VIR_DOMAIN_TIMER_NAME_TSC:
-            switch (def->clock.timers[i]->mode) {
-            case VIR_DOMAIN_TIMER_MODE_NATIVE:
-                if (xenConfigSetString(conf, "tsc_mode", "native") < 0)
-                    return -1;
-                break;
-            case VIR_DOMAIN_TIMER_MODE_PARAVIRT:
-                if (xenConfigSetString(conf, "tsc_mode", "native_paravirt") < 0)
-                    return -1;
-                break;
-            case VIR_DOMAIN_TIMER_MODE_EMULATE:
-                if (xenConfigSetString(conf, "tsc_mode", "always_emulate") < 0)
-                    return -1;
-                break;
-            default:
-                if (xenConfigSetString(conf, "tsc_mode", "default") < 0)
-                    return -1;
-            }
-            break;
-
-        case VIR_DOMAIN_TIMER_NAME_HPET:
-            if (hvm) {
-                int enable_hpet = def->clock.timers[i]->present != 0;
-
-                /* disable hpet if 'present' is 0, enable otherwise */
-                if (xenConfigSetInt(conf, "hpet", enable_hpet) < 0)
-                    return -1;
-            } else {
-                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                               _("unsupported timer type (name) '%s'"),
-                               virDomainTimerNameTypeToString(def->clock.timers[i]->name));
-                return -1;
-            }
-            break;
-
-        case VIR_DOMAIN_TIMER_NAME_PLATFORM:
-        case VIR_DOMAIN_TIMER_NAME_KVMCLOCK:
-        case VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK:
-        case VIR_DOMAIN_TIMER_NAME_RTC:
-        case VIR_DOMAIN_TIMER_NAME_PIT:
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                           _("unsupported timer type (name) '%s'"),
-                           virDomainTimerNameTypeToString(def->clock.timers[i]->name));
-            return -1;
-
-        case VIR_DOMAIN_TIMER_NAME_LAST:
-            break;
-        }
-    }
-
-    return 0;
-}
-
-
-static int
-xenFormatEmulator(virConfPtr conf, virDomainDefPtr def)
-{
-    if (def->emulator &&
-        xenConfigSetString(conf, "device_model", def->emulator) < 0)
-        return -1;
-
-    return 0;
-}
-
-
-static int
-xenFormatVfb(virConfPtr conf, virDomainDefPtr def)
-{
-    int hvm = def->os.type == VIR_DOMAIN_OSTYPE_HVM ? 1 : 0;
-
-    if (def->ngraphics == 1 &&
-        def->graphics[0]->type != VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
-        if (hvm) {
-            if (def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
-                if (xenConfigSetInt(conf, "sdl", 1) < 0)
-                    return -1;
-
-                if (xenConfigSetInt(conf, "vnc", 0) < 0)
-                    return -1;
-
-                if (def->graphics[0]->data.sdl.display &&
-                    xenConfigSetString(conf, "display",
-                                       def->graphics[0]->data.sdl.display) < 0)
-                    return -1;
-
-                if (def->graphics[0]->data.sdl.xauth &&
-                    xenConfigSetString(conf, "xauthority",
-                                       def->graphics[0]->data.sdl.xauth) < 0)
-                    return -1;
-            } else {
-                virDomainGraphicsListenDefPtr glisten;
-
-                if (xenConfigSetInt(conf, "sdl", 0) < 0)
-                    return -1;
-
-                if (xenConfigSetInt(conf, "vnc", 1) < 0)
-                    return -1;
-
-                if (xenConfigSetInt(conf, "vncunused",
-                              def->graphics[0]->data.vnc.autoport ? 1 : 0) < 0)
-                    return -1;
-
-                if (!def->graphics[0]->data.vnc.autoport &&
-                    xenConfigSetInt(conf, "vncdisplay",
-                                    def->graphics[0]->data.vnc.port - 5900) < 0)
-                    return -1;
-
-                if ((glisten = virDomainGraphicsGetListen(def->graphics[0], 0)) &&
-                    glisten->address &&
-                    xenConfigSetString(conf, "vnclisten", glisten->address) < 0)
-                    return -1;
-
-                if (def->graphics[0]->data.vnc.auth.passwd &&
-                    xenConfigSetString(conf, "vncpasswd",
-                                       def->graphics[0]->data.vnc.auth.passwd) < 0)
-                    return -1;
-
-                if (def->graphics[0]->data.vnc.keymap &&
-                    xenConfigSetString(conf, "keymap",
-                                       def->graphics[0]->data.vnc.keymap) < 0)
-                    return -1;
-            }
-        } else {
-            virConfValuePtr vfb, disp;
-            char *vfbstr = NULL;
-            virBuffer buf = VIR_BUFFER_INITIALIZER;
-
-            if (def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
-                virBufferAddLit(&buf, "type=sdl");
-                if (def->graphics[0]->data.sdl.display)
-                    virBufferAsprintf(&buf, ",display=%s",
-                                      def->graphics[0]->data.sdl.display);
-                if (def->graphics[0]->data.sdl.xauth)
-                    virBufferAsprintf(&buf, ",xauthority=%s",
-                                      def->graphics[0]->data.sdl.xauth);
-            } else {
-                virDomainGraphicsListenDefPtr glisten
-                    = virDomainGraphicsGetListen(def->graphics[0], 0);
-
-                virBufferAddLit(&buf, "type=vnc");
-                virBufferAsprintf(&buf, ",vncunused=%d",
-                                  def->graphics[0]->data.vnc.autoport ? 1 : 0);
-                if (!def->graphics[0]->data.vnc.autoport)
-                    virBufferAsprintf(&buf, ",vncdisplay=%d",
-                                      def->graphics[0]->data.vnc.port - 5900);
-                if (glisten && glisten->address)
-                    virBufferAsprintf(&buf, ",vnclisten=%s", glisten->address);
-                if (def->graphics[0]->data.vnc.auth.passwd)
-                    virBufferAsprintf(&buf, ",vncpasswd=%s",
-                                      def->graphics[0]->data.vnc.auth.passwd);
-                if (def->graphics[0]->data.vnc.keymap)
-                    virBufferAsprintf(&buf, ",keymap=%s",
-                                      def->graphics[0]->data.vnc.keymap);
-            }
-            if (virBufferCheckError(&buf) < 0)
-                return -1;
-
-            vfbstr = virBufferContentAndReset(&buf);
-
-            if (VIR_ALLOC(vfb) < 0) {
-                VIR_FREE(vfbstr);
-                return -1;
-            }
-
-            if (VIR_ALLOC(disp) < 0) {
-                VIR_FREE(vfb);
-                VIR_FREE(vfbstr);
-                return -1;
-            }
-
-            vfb->type = VIR_CONF_LIST;
-            vfb->list = disp;
-            disp->type = VIR_CONF_STRING;
-            disp->str = vfbstr;
-
-            if (virConfSetValue(conf, "vfb", vfb) < 0)
-                return -1;
-        }
-    }
-
-    return 0;
-}
-
-
-static int
-xenFormatSound(virConfPtr conf, virDomainDefPtr def)
-{
-    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
-    const char * model;
-    VIR_AUTOFREE(char *) str = NULL;
-    size_t i;
-
-    if (def->os.type != VIR_DOMAIN_OSTYPE_HVM ||
-        !def->sounds)
-        return 0;
-
-    for (i = 0; i < def->nsounds; i++) {
-        if (!(model = virDomainSoundModelTypeToString(def->sounds[i]->model))) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("unexpected sound model %d"),
-                           def->sounds[i]->model);
-            return -1;
-        }
-        if (i)
-            virBufferAddChar(&buf, ',');
-        virBufferEscapeSexpr(&buf, "%s", model);
-    }
-
-    if (virBufferCheckError(&buf) < 0)
-        return -1;
-
-    str = virBufferContentAndReset(&buf);
-
-    return xenConfigSetString(conf, "soundhw", str);
-}
-
-
-static int
-xenFormatVif(virConfPtr conf,
-             virConnectPtr conn,
-             virDomainDefPtr def,
-             const char *vif_typename)
-{
-    virConfValuePtr netVal = NULL;
-    size_t i;
-    int hvm = def->os.type == VIR_DOMAIN_OSTYPE_HVM;
-
-    if (VIR_ALLOC(netVal) < 0)
-        goto cleanup;
-    netVal->type = VIR_CONF_LIST;
-    netVal->list = NULL;
-
-    for (i = 0; i < def->nnets; i++) {
-        if (xenFormatNet(conn, netVal, def->nets[i],
-                         hvm, vif_typename) < 0)
-            goto cleanup;
-    }
-
-    if (netVal->list != NULL) {
-        int ret = virConfSetValue(conf, "vif", netVal);
-        netVal = NULL;
-        if (ret < 0)
-            goto cleanup;
-    }
-
-    VIR_FREE(netVal);
-    return 0;
-
- cleanup:
-    virConfFreeValue(netVal);
-    return -1;
-}
-
-
-/*
- * A convenience function for formatting all config common to both XM and XL
- */
-int
-xenFormatConfigCommon(virConfPtr conf,
-                      virDomainDefPtr def,
-                      virConnectPtr conn,
-                      const char *nativeFormat)
-{
-    if (xenFormatGeneralMeta(conf, def) < 0)
-        return -1;
-
-    if (xenFormatMem(conf, def) < 0)
-        return -1;
-
-    if (xenFormatCPUAllocation(conf, def) < 0)
-        return -1;
-
-    if (xenFormatCPUFeatures(conf, def) < 0)
-        return -1;
-
-    if (xenFormatTimeOffset(conf, def) < 0)
-        return -1;
-
-    if (xenFormatEventActions(conf, def) < 0)
-        return -1;
-
-    if (xenFormatEmulator(conf, def) < 0)
-        return -1;
-
-    if (xenFormatVfb(conf, def) < 0)
-        return -1;
-
-    if (STREQ(nativeFormat, XEN_CONFIG_FORMAT_XL)) {
-        if (xenFormatVif(conf, conn, def, "vif") < 0)
-            return -1;
-    } else if (STREQ(nativeFormat, XEN_CONFIG_FORMAT_XM)) {
-        if (xenFormatVif(conf, conn, def, "netfront") < 0)
-            return -1;
-    } else {
-        virReportError(VIR_ERR_INVALID_ARG,
-                       _("unsupported config type %s"), nativeFormat);
-        return -1;
-    }
-
-    if (xenFormatPCI(conf, def) < 0)
-        return -1;
-
-    if (xenFormatCharDev(conf, def, nativeFormat) < 0)
-        return -1;
-
-    if (xenFormatSound(conf, def) < 0)
-        return -1;
-
-    return 0;
-}
-
-
-int
-xenDomainDefAddImplicitInputDevice(virDomainDefPtr def)
-{
-    virDomainInputBus implicitInputBus = VIR_DOMAIN_INPUT_BUS_XEN;
-
-    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM)
-        implicitInputBus = VIR_DOMAIN_INPUT_BUS_PS2;
-
-    if (virDomainDefMaybeAddInput(def,
-                                  VIR_DOMAIN_INPUT_TYPE_MOUSE,
-                                  implicitInputBus) < 0)
-        return -1;
-
-    if (virDomainDefMaybeAddInput(def,
-                                  VIR_DOMAIN_INPUT_TYPE_KBD,
-                                  implicitInputBus) < 0)
-        return -1;
-
-    return 0;
-}
diff --git a/src/xenconfig/xen_common.h b/src/xenconfig/xen_common.h
deleted file mode 100644 (file)
index 231fa0d..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * xen_common.h: Parsing and formatting functions for config common
- *
- * Copyright (C) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library.  If not, see
- * <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#include "internal.h"
-#include "virconf.h"
-#include "domain_conf.h"
-
-#define XEN_CONFIG_FORMAT_XL    "xen-xl"
-#define XEN_CONFIG_FORMAT_XM    "xen-xm"
-#define XEN_CONFIG_FORMAT_SEXPR "xen-sxpr"
-
-int xenConfigGetString(virConfPtr conf,
-                       const char *name,
-                       char **value,
-                       const char *def);
-
-int xenConfigGetBool(virConfPtr conf, const char *name, int *value, int def);
-
-int xenConfigSetInt(virConfPtr conf, const char *name, long long value);
-
-int xenConfigSetString(virConfPtr conf, const char *setting, const char *value);
-
-int xenConfigGetULong(virConfPtr conf,
-                      const char *name,
-                      unsigned long *value,
-                      unsigned long def);
-
-int
-xenConfigCopyString(virConfPtr conf,
-                    const char *name,
-                    char **value);
-
-int xenConfigCopyStringOpt(virConfPtr conf,
-                           const char *name,
-                           char **value);
-
-int xenParseConfigCommon(virConfPtr conf,
-                         virDomainDefPtr def,
-                         virCapsPtr caps,
-                         const char *nativeFormat,
-                         virDomainXMLOptionPtr xmlopt);
-
-int xenFormatConfigCommon(virConfPtr conf,
-                          virDomainDefPtr def,
-                          virConnectPtr conn,
-                          const char *nativeFormat);
-
-char *xenMakeIPList(virNetDevIPInfoPtr guestIP);
-
-int xenDomainDefAddImplicitInputDevice(virDomainDefPtr def);
diff --git a/src/xenconfig/xen_xl.c b/src/xenconfig/xen_xl.c
deleted file mode 100644 (file)
index ca094d3..0000000
+++ /dev/null
@@ -1,2249 +0,0 @@
-/*
- * xen_xl.c: Xen XL parsing functions
- *
- * Copyright (c) 2015 SUSE LINUX Products GmbH, Nuernberg, Germany.
- * Copyright (C) 2014 David Kiarie Kahurani
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library.  If not, see
- * <http://www.gnu.org/licenses/>.
- */
-
-#include <config.h>
-
-#include <libxl.h>
-
-#include "virconf.h"
-#include "virerror.h"
-#include "virlog.h"
-#include "domain_conf.h"
-#include "viralloc.h"
-#include "virstring.h"
-#include "virstoragefile.h"
-#include "xen_xl.h"
-#include "libxl_capabilities.h"
-#include "cpu/cpu.h"
-
-#define VIR_FROM_THIS VIR_FROM_XENXL
-
-VIR_LOG_INIT("xen.xen_xl");
-
-/*
- * Xen provides a libxl utility library, with several useful functions,
- * specifically xlu_disk_parse for parsing xl disk config strings.
- * Although the libxlutil library is installed, until recently the
- * corresponding header file wasn't.  Use the header file if detected during
- * configure, otherwise provide extern declarations for any functions used.
- */
-#ifdef HAVE_LIBXLUTIL_H
-# include <libxlutil.h>
-#else
-typedef struct XLU_Config XLU_Config;
-
-extern XLU_Config *xlu_cfg_init(FILE *report,
-                                const char *report_filename);
-
-extern void xlu_cfg_destroy(XLU_Config*);
-
-extern int xlu_disk_parse(XLU_Config *cfg,
-                          int nspecs,
-                          const char *const *specs,
-                          libxl_device_disk *disk);
-#endif
-
-static int xenParseCmdline(virConfPtr conf, char **r_cmdline)
-{
-    char *cmdline = NULL;
-    VIR_AUTOFREE(char *) root = NULL;
-    VIR_AUTOFREE(char *) extra = NULL;
-    VIR_AUTOFREE(char *) buf = NULL;
-
-    if (xenConfigGetString(conf, "cmdline", &buf, NULL) < 0)
-        return -1;
-
-    if (xenConfigGetString(conf, "root", &root, NULL) < 0)
-        return -1;
-
-    if (xenConfigGetString(conf, "extra", &extra, NULL) < 0)
-        return -1;
-
-    if (buf) {
-        if (VIR_STRDUP(cmdline, buf) < 0)
-            return -1;
-        if (root || extra)
-            VIR_WARN("ignoring root= and extra= in favour of cmdline=");
-    } else {
-        if (root && extra) {
-            if (virAsprintf(&cmdline, "root=%s %s", root, extra) < 0)
-                return -1;
-        } else if (root) {
-            if (virAsprintf(&cmdline, "root=%s", root) < 0)
-                return -1;
-        } else if (extra) {
-            if (VIR_STRDUP(cmdline, extra) < 0)
-                return -1;
-        }
-    }
-
-    *r_cmdline = cmdline;
-    return 0;
-}
-
-static int
-xenParseXLOS(virConfPtr conf, virDomainDefPtr def, virCapsPtr caps)
-{
-    size_t i;
-
-    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
-        VIR_AUTOFREE(char *) bios = NULL;
-        VIR_AUTOFREE(char *) boot = NULL;
-        int val = 0;
-
-        if (xenConfigGetString(conf, "bios", &bios, NULL) < 0)
-            return -1;
-
-        if (bios && STREQ(bios, "ovmf")) {
-            if (VIR_ALLOC(def->os.loader) < 0)
-                return -1;
-
-            def->os.loader->type = VIR_DOMAIN_LOADER_TYPE_PFLASH;
-            def->os.loader->readonly = VIR_TRISTATE_BOOL_YES;
-
-            if (VIR_STRDUP(def->os.loader->path,
-                           LIBXL_FIRMWARE_DIR "/ovmf.bin") < 0)
-                return -1;
-        } else {
-            for (i = 0; i < caps->nguests; i++) {
-                if (caps->guests[i]->ostype == VIR_DOMAIN_OSTYPE_HVM &&
-                    caps->guests[i]->arch.id == def->os.arch) {
-                    if (VIR_ALLOC(def->os.loader) < 0 ||
-                        VIR_STRDUP(def->os.loader->path,
-                                   caps->guests[i]->arch.defaultInfo.loader) < 0)
-                        return -1;
-                }
-            }
-        }
-
-#ifdef LIBXL_HAVE_BUILDINFO_KERNEL
-        if (xenConfigCopyStringOpt(conf, "kernel", &def->os.kernel) < 0)
-            return -1;
-
-        if (xenConfigCopyStringOpt(conf, "ramdisk", &def->os.initrd) < 0)
-            return -1;
-
-        if (xenParseCmdline(conf, &def->os.cmdline) < 0)
-            return -1;
-#endif
-
-        if (xenConfigGetString(conf, "boot", &boot, "c") < 0)
-            return -1;
-
-        for (i = 0; i < VIR_DOMAIN_BOOT_LAST && boot[i]; i++) {
-            switch (boot[i]) {
-            case 'a':
-                def->os.bootDevs[i] = VIR_DOMAIN_BOOT_FLOPPY;
-                break;
-            case 'd':
-                def->os.bootDevs[i] = VIR_DOMAIN_BOOT_CDROM;
-                break;
-            case 'n':
-                def->os.bootDevs[i] = VIR_DOMAIN_BOOT_NET;
-                break;
-            case 'c':
-            default:
-                def->os.bootDevs[i] = VIR_DOMAIN_BOOT_DISK;
-                break;
-            }
-            def->os.nBootDevs++;
-        }
-
-        if (xenConfigGetBool(conf, "nestedhvm", &val, -1) < 0)
-            return -1;
-
-        if (val != -1) {
-            const char *vtfeature = "vmx";
-
-            if (caps && caps->host.cpu && ARCH_IS_X86(def->os.arch)) {
-                if (virCPUCheckFeature(caps->host.arch, caps->host.cpu, "vmx"))
-                    vtfeature = "vmx";
-                else if (virCPUCheckFeature(caps->host.arch, caps->host.cpu, "svm"))
-                    vtfeature = "svm";
-            }
-
-            if (!def->cpu) {
-                virCPUDefPtr cpu;
-                if (VIR_ALLOC(cpu) < 0)
-                    return -1;
-
-                cpu->mode = VIR_CPU_MODE_HOST_PASSTHROUGH;
-                cpu->type = VIR_CPU_TYPE_GUEST;
-                cpu->nfeatures = 0;
-                cpu->nfeatures_max = 0;
-                def->cpu = cpu;
-            }
-
-            if (val == 0) {
-                if (virCPUDefAddFeature(def->cpu,
-                                        vtfeature,
-                                        VIR_CPU_FEATURE_DISABLE) < 0)
-                    return -1;
-            }
-        }
-    } else {
-        if (xenConfigCopyStringOpt(conf, "bootloader", &def->os.bootloader) < 0)
-            return -1;
-        if (xenConfigCopyStringOpt(conf, "bootargs", &def->os.bootloaderArgs) < 0)
-            return -1;
-
-        if (xenConfigCopyStringOpt(conf, "kernel", &def->os.kernel) < 0)
-            return -1;
-
-        if (xenConfigCopyStringOpt(conf, "ramdisk", &def->os.initrd) < 0)
-            return -1;
-
-        if (xenParseCmdline(conf, &def->os.cmdline) < 0)
-            return -1;
-    }
-
-    return 0;
-}
-
-/*
- * Translate CPU feature name from libvirt to libxl (from_libxl=false) or from
- * libxl to libvirt (from_libxl=true).
- */
-const char *
-xenTranslateCPUFeature(const char *feature_name, bool from_libxl)
-{
-    static const char *translation_table[][2] = {
-        /* libvirt name, libxl name */
-        { "cx16", "cmpxchg16" },
-        { "cid", "cntxid" },
-        { "ds_cpl", "dscpl" },
-        { "pclmuldq", "pclmulqdq" },
-        { "pni", "sse3" },
-        { "ht", "htt" },
-        { "pn", "psn" },
-        { "clflush", "clfsh" },
-        { "sep", "sysenter" },
-        { "cx8", "cmpxchg8" },
-        { "nodeid_msr", "nodeid" },
-        { "cr8legacy", "altmovcr8" },
-        { "lahf_lm", "lahfsahf" },
-        { "cmp_legacy", "cmplegacy" },
-        { "fxsr_opt", "ffxsr" },
-        { "pdpe1gb", "page1gb" },
-        { "spec-ctrl", "ibrsb" },
-    };
-    size_t i;
-
-    for (i = 0; i < ARRAY_CARDINALITY(translation_table); i++)
-        if (STREQ(translation_table[i][from_libxl], feature_name))
-            return translation_table[i][!from_libxl];
-    return feature_name;
-}
-
-static int
-xenParseXLCPUID(virConfPtr conf, virDomainDefPtr def)
-{
-    VIR_AUTOFREE(char *) cpuid_str = NULL;
-    char **cpuid_pairs = NULL;
-    char **name_and_value = NULL;
-    size_t i;
-    int ret = -1;
-    int policy;
-
-    if (xenConfigGetString(conf, "cpuid", &cpuid_str, NULL) < 0)
-        return -1;
-
-    if (!cpuid_str)
-        return 0;
-
-    if (!def->cpu) {
-        if (VIR_ALLOC(def->cpu) < 0)
-            goto cleanup;
-        def->cpu->mode = VIR_CPU_MODE_HOST_PASSTHROUGH;
-        def->cpu->type = VIR_CPU_TYPE_GUEST;
-        def->cpu->nfeatures = 0;
-        def->cpu->nfeatures_max = 0;
-    }
-
-    cpuid_pairs = virStringSplit(cpuid_str, ",", 0);
-    if (!cpuid_pairs)
-        goto cleanup;
-
-    if (!cpuid_pairs[0]) {
-        ret = 0;
-        goto cleanup;
-    }
-
-    if (STRNEQ(cpuid_pairs[0], "host")) {
-        virReportError(VIR_ERR_CONF_SYNTAX,
-                       _("cpuid starting with %s is not supported, only libxl format is"),
-                       cpuid_pairs[0]);
-        goto cleanup;
-    }
-
-    for (i = 1; cpuid_pairs[i]; i++) {
-        name_and_value = virStringSplit(cpuid_pairs[i], "=", 2);
-        if (!name_and_value)
-            goto cleanup;
-        if (!name_and_value[0] || !name_and_value[1]) {
-            virReportError(VIR_ERR_CONF_SYNTAX,
-                           _("Invalid libxl cpuid key=value element: %s"),
-                           cpuid_pairs[i]);
-            goto cleanup;
-        }
-        if (STREQ(name_and_value[1], "1")) {
-            policy = VIR_CPU_FEATURE_FORCE;
-        } else if (STREQ(name_and_value[1], "0")) {
-            policy = VIR_CPU_FEATURE_DISABLE;
-        } else if (STREQ(name_and_value[1], "x")) {
-            policy = VIR_CPU_FEATURE_OPTIONAL;
-        } else if (STREQ(name_and_value[1], "k")) {
-            policy = VIR_CPU_FEATURE_OPTIONAL;
-        } else if (STREQ(name_and_value[1], "s")) {
-            policy = VIR_CPU_FEATURE_OPTIONAL;
-        } else {
-            virReportError(VIR_ERR_CONF_SYNTAX,
-                           _("Invalid libxl cpuid value: %s"),
-                           cpuid_pairs[i]);
-            goto cleanup;
-        }
-
-        if (virCPUDefAddFeature(def->cpu,
-                                xenTranslateCPUFeature(name_and_value[0], true),
-                                policy) < 0)
-            goto cleanup;
-
-        virStringListFree(name_and_value);
-        name_and_value = NULL;
-    }
-
-    ret = 0;
-
- cleanup:
-    virStringListFree(name_and_value);
-    virStringListFree(cpuid_pairs);
-    return ret;
-}
-
-
-static int
-xenParseXLSpice(virConfPtr conf, virDomainDefPtr def)
-{
-    virDomainGraphicsDefPtr graphics = NULL;
-    unsigned long port;
-    char *listenAddr = NULL;
-    int val;
-
-    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
-        if (xenConfigGetBool(conf, "spice", &val, 0) < 0)
-            return -1;
-
-        if (val) {
-            if (VIR_ALLOC(graphics) < 0)
-                return -1;
-
-            graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_SPICE;
-            if (xenConfigCopyStringOpt(conf, "spicehost", &listenAddr) < 0)
-                goto cleanup;
-            if (virDomainGraphicsListenAppendAddress(graphics, listenAddr) < 0)
-                goto cleanup;
-            VIR_FREE(listenAddr);
-
-            if (xenConfigGetULong(conf, "spicetls_port", &port, 0) < 0)
-                goto cleanup;
-            graphics->data.spice.tlsPort = (int)port;
-
-            if (xenConfigGetULong(conf, "spiceport", &port, 0) < 0)
-                goto cleanup;
-
-            graphics->data.spice.port = (int)port;
-
-            if (!graphics->data.spice.tlsPort &&
-                !graphics->data.spice.port)
-            graphics->data.spice.autoport = 1;
-
-            if (xenConfigGetBool(conf, "spicedisable_ticketing", &val, 0) < 0)
-                goto cleanup;
-            if (!val) {
-                if (xenConfigCopyString(conf, "spicepasswd",
-                                        &graphics->data.spice.auth.passwd) < 0)
-                    goto cleanup;
-            }
-
-            if (xenConfigGetBool(conf, "spiceagent_mouse",
-                                 &val, 0) < 0)
-                goto cleanup;
-            if (val) {
-                graphics->data.spice.mousemode =
-                    VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_CLIENT;
-            } else {
-                graphics->data.spice.mousemode =
-                    VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_SERVER;
-            }
-
-            if (xenConfigGetBool(conf, "spice_clipboard_sharing", &val, 0) < 0)
-                goto cleanup;
-            if (val)
-                graphics->data.spice.copypaste = VIR_TRISTATE_BOOL_YES;
-            else
-                graphics->data.spice.copypaste = VIR_TRISTATE_BOOL_NO;
-
-            if (VIR_ALLOC_N(def->graphics, 1) < 0)
-                goto cleanup;
-            def->graphics[0] = graphics;
-            def->ngraphics = 1;
-        }
-    }
-
-    return 0;
-
- cleanup:
-    VIR_FREE(listenAddr);
-    virDomainGraphicsDefFree(graphics);
-    return -1;
-}
-
-#ifdef LIBXL_HAVE_VNUMA
-static int
-xenParseXLVnuma(virConfPtr conf,
-                virDomainDefPtr def)
-{
-    int ret = -1;
-    char *tmp = NULL;
-    char **token = NULL;
-    size_t vcpus = 0;
-    size_t nr_nodes = 0;
-    size_t vnodeCnt = 0;
-    virCPUDefPtr cpu = NULL;
-    virConfValuePtr list;
-    virConfValuePtr vnode;
-    virDomainNumaPtr numa;
-
-    numa = def->numa;
-    if (numa == NULL)
-        return -1;
-
-    list = virConfGetValue(conf, "vnuma");
-    if (!list || list->type != VIR_CONF_LIST)
-        return 0;
-
-    vnode = list->list;
-    while (vnode && vnode->type == VIR_CONF_LIST) {
-        vnode = vnode->next;
-        nr_nodes++;
-    }
-
-    if (!virDomainNumaSetNodeCount(numa, nr_nodes))
-        goto cleanup;
-
-    if (VIR_ALLOC(cpu) < 0)
-        goto cleanup;
-
-    list = list->list;
-    while (list) {
-        int pnode = -1;
-        virBitmapPtr cpumask = NULL;
-        unsigned long long kbsize = 0;
-
-        /* Is there a sublist (vnode)? */
-        if (list && list->type == VIR_CONF_LIST) {
-            vnode = list->list;
-
-            while (vnode && vnode->type == VIR_CONF_STRING) {
-                const char *data;
-                const char *str = vnode->str;
-
-                if (!str ||
-                   !(data = strrchr(str, '='))) {
-                    virReportError(VIR_ERR_INTERNAL_ERROR,
-                                   _("vnuma vnode invalid format '%s'"),
-                                   str);
-                    goto cleanup;
-                }
-                data++;
-
-                if (*data) {
-                    char vtoken[64];
-
-                    if (STRPREFIX(str, "pnode")) {
-                        unsigned int cellid;
-
-                        if (virStrcpyStatic(vtoken, data) < 0) {
-                            virReportError(VIR_ERR_INTERNAL_ERROR,
-                                           _("vnuma vnode %zu pnode '%s' too long for destination"),
-                                           vnodeCnt, data);
-                            goto cleanup;
-                        }
-
-                        if ((virStrToLong_ui(vtoken, NULL, 10, &cellid) < 0) ||
-                            (cellid >= nr_nodes)) {
-                            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                                           _("vnuma vnode %zu contains invalid pnode value '%s'"),
-                                           vnodeCnt, data);
-                            goto cleanup;
-                        }
-                        pnode = cellid;
-                    } else if (STRPREFIX(str, "size")) {
-                        if (virStrcpyStatic(vtoken, data) < 0) {
-                            virReportError(VIR_ERR_INTERNAL_ERROR,
-                                           _("vnuma vnode %zu size '%s' too long for destination"),
-                                           vnodeCnt, data);
-                            goto cleanup;
-                        }
-
-                        if (virStrToLong_ull(vtoken, NULL, 10, &kbsize) < 0)
-                            goto cleanup;
-
-                        virDomainNumaSetNodeMemorySize(numa, vnodeCnt, (kbsize * 1024));
-
-                    } else if (STRPREFIX(str, "vcpus")) {
-                        if (virStrcpyStatic(vtoken, data) < 0) {
-                            virReportError(VIR_ERR_INTERNAL_ERROR,
-                                           _("vnuma vnode %zu vcpus '%s' too long for destination"),
-                                           vnodeCnt, data);
-                            goto cleanup;
-                        }
-
-                        if ((virBitmapParse(vtoken, &cpumask, VIR_DOMAIN_CPUMASK_LEN) < 0) ||
-                            (virDomainNumaSetNodeCpumask(numa, vnodeCnt, cpumask) == NULL))
-                            goto cleanup;
-
-                        vcpus += virBitmapCountBits(cpumask);
-
-                    } else if (STRPREFIX(str, "vdistances")) {
-                        size_t i, ndistances;
-                        unsigned int value;
-
-                        if (virStrcpyStatic(vtoken, data) < 0) {
-                            virReportError(VIR_ERR_INTERNAL_ERROR,
-                                           _("vnuma vnode %zu vdistances '%s' too long for destination"),
-                                           vnodeCnt, data);
-                            goto cleanup;
-                        }
-
-                        VIR_FREE(tmp);
-                        if (VIR_STRDUP(tmp, vtoken) < 0)
-                            goto cleanup;
-
-                        virStringListFree(token);
-                        if (!(token = virStringSplitCount(tmp, ",", 0, &ndistances)))
-                            goto cleanup;
-
-                        if (ndistances != nr_nodes) {
-                            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                                       _("vnuma pnode %d configured '%s' (count %zu) doesn't fit the number of specified vnodes %zu"),
-                                       pnode, str, ndistances, nr_nodes);
-                            goto cleanup;
-                        }
-
-                        if (virDomainNumaSetNodeDistanceCount(numa, vnodeCnt, ndistances) != ndistances)
-                            goto cleanup;
-
-                        for (i = 0; i < ndistances; i++) {
-                            if ((virStrToLong_ui(token[i], NULL, 10, &value) < 0) ||
-                                (virDomainNumaSetNodeDistance(numa, vnodeCnt, i, value) != value))
-                                goto cleanup;
-                        }
-
-                    } else {
-                        virReportError(VIR_ERR_CONF_SYNTAX,
-                                       _("Invalid vnuma configuration for vnode %zu"),
-                                       vnodeCnt);
-                        goto cleanup;
-                    }
-                }
-                vnode = vnode->next;
-            }
-        }
-
-        if ((pnode < 0) ||
-            (cpumask == NULL) ||
-            (kbsize == 0)) {
-            virReportError(VIR_ERR_CONF_SYNTAX,
-                           _("Incomplete vnuma configuration for vnode %zu"),
-                           vnodeCnt);
-            goto cleanup;
-        }
-
-        list = list->next;
-        vnodeCnt++;
-    }
-
-    if (def->maxvcpus == 0)
-        def->maxvcpus = vcpus;
-
-    if (def->maxvcpus < vcpus) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                       _("vnuma configuration contains %zu vcpus, which is greater than %zu maxvcpus"),
-                       vcpus, def->maxvcpus);
-        goto cleanup;
-    }
-
-    cpu->type = VIR_CPU_TYPE_GUEST;
-    def->cpu = cpu;
-
-    ret = 0;
-
- cleanup:
-    if (ret)
-        VIR_FREE(cpu);
-    virStringListFree(token);
-    VIR_FREE(tmp);
-
-    return ret;
-}
-#endif
-
-#ifdef LIBXL_HAVE_BUILDINFO_GRANT_LIMITS
-static int
-xenParseXLGntLimits(virConfPtr conf, virDomainDefPtr def)
-{
-    unsigned long max_gntframes;
-    int ctlr_idx;
-    virDomainControllerDefPtr xenbus_ctlr;
-
-    if (xenConfigGetULong(conf, "max_grant_frames", &max_gntframes, 0) < 0)
-        return -1;
-
-    if (max_gntframes <= 0)
-        return 0;
-
-    ctlr_idx = virDomainControllerFindByType(def, VIR_DOMAIN_CONTROLLER_TYPE_XENBUS);
-    if (ctlr_idx == -1)
-        xenbus_ctlr = virDomainDefAddController(def, VIR_DOMAIN_CONTROLLER_TYPE_XENBUS, -1, -1);
-    else
-        xenbus_ctlr = def->controllers[ctlr_idx];
-
-    if (xenbus_ctlr == NULL)
-        return -1;
-
-    xenbus_ctlr->opts.xenbusopts.maxGrantFrames = max_gntframes;
-    return 0;
-}
-#endif
-
-static int
-xenParseXLDiskSrc(virDomainDiskDefPtr disk, char *srcstr)
-{
-    char *tmpstr = NULL;
-    int ret = -1;
-
-    /* A NULL source is valid, e.g. an empty CDROM */
-    if (srcstr == NULL)
-        return 0;
-
-    if (STRPREFIX(srcstr, "rbd:")) {
-        if (!(tmpstr = virStringReplace(srcstr, "\\\\", "\\")))
-            goto cleanup;
-
-        virDomainDiskSetType(disk, VIR_STORAGE_TYPE_NETWORK);
-        disk->src->protocol = VIR_STORAGE_NET_PROTOCOL_RBD;
-        ret = virStorageSourceParseRBDColonString(tmpstr, disk->src);
-    } else {
-        if (virDomainDiskSetSource(disk, srcstr) < 0)
-            goto cleanup;
-
-        ret = 0;
-    }
-
- cleanup:
-    VIR_FREE(tmpstr);
-    return ret;
-}
-
-
-/*
- * For details on xl disk config syntax, see
- * docs/misc/xl-disk-configuration.txt in the Xen sources.  The important
- * section of text is:
- *
- *   More formally, the string is a series of comma-separated keyword/value
- *   pairs, flags and positional parameters.  Parameters which are not bare
- *   keywords and which do not contain "=" symbols are assigned to the
- *   so-far-unspecified positional parameters, in the order below.  The
- *   positional parameters may also be specified explicitly by name.
- *
- *   Each parameter may be specified at most once, either as a positional
- *   parameter or a named parameter.  Default values apply if the parameter
- *   is not specified, or if it is specified with an empty value (whether
- *   positionally or explicitly).
- *
- *   Whitespace may appear before each parameter and will be ignored.
- *
- * The order of the positional parameters mentioned in the quoted text is:
- *
- *   target,format,vdev,access
- *
- * The following options must be specified by key=value:
- *
- *   devtype=<devtype>
- *   backendtype=<backend-type>
- *
- * The following options are currently not supported:
- *
- *   backend=<domain-name>
- *   script=<script>
- *   direct-io-safe
- *
- */
-static int
-xenParseXLDisk(virConfPtr conf, virDomainDefPtr def)
-{
-    int ret = -1;
-    virConfValuePtr list = virConfGetValue(conf, "disk");
-    XLU_Config *xluconf;
-    libxl_device_disk *libxldisk;
-    virDomainDiskDefPtr disk = NULL;
-
-    if (VIR_ALLOC(libxldisk) < 0)
-        return -1;
-
-    if (!(xluconf = xlu_cfg_init(stderr, "command line")))
-        goto cleanup;
-
-    if (list && list->type == VIR_CONF_LIST) {
-        list = list->list;
-        while (list) {
-            const char *disk_spec = list->str;
-
-            if (list->type != VIR_CONF_STRING || list->str == NULL)
-                goto skipdisk;
-
-            libxl_device_disk_init(libxldisk);
-
-            if (xlu_disk_parse(xluconf, 1, &disk_spec, libxldisk))
-                goto fail;
-
-            if (!(disk = virDomainDiskDefNew(NULL)))
-                goto fail;
-
-            if (xenParseXLDiskSrc(disk, libxldisk->pdev_path) < 0)
-                goto fail;
-
-            if (VIR_STRDUP(disk->dst, libxldisk->vdev) < 0)
-                goto fail;
-
-            disk->src->readonly = !libxldisk->readwrite;
-            disk->removable = libxldisk->removable;
-
-            if (libxldisk->is_cdrom) {
-                if (virDomainDiskSetDriver(disk, "qemu") < 0)
-                    goto fail;
-
-                virDomainDiskSetType(disk, VIR_STORAGE_TYPE_FILE);
-                disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
-                if (!disk->src->path || STREQ(disk->src->path, ""))
-                    disk->src->format = VIR_STORAGE_FILE_NONE;
-                else
-                    disk->src->format = VIR_STORAGE_FILE_RAW;
-            } else {
-                switch (libxldisk->format) {
-                case LIBXL_DISK_FORMAT_QCOW:
-                    disk->src->format = VIR_STORAGE_FILE_QCOW;
-                    break;
-
-                case LIBXL_DISK_FORMAT_QCOW2:
-                    disk->src->format = VIR_STORAGE_FILE_QCOW2;
-                    break;
-
-                case LIBXL_DISK_FORMAT_VHD:
-                    disk->src->format = VIR_STORAGE_FILE_VHD;
-                    break;
-
-                case LIBXL_DISK_FORMAT_RAW:
-                case LIBXL_DISK_FORMAT_UNKNOWN:
-                    disk->src->format = VIR_STORAGE_FILE_RAW;
-                    break;
-
-                case LIBXL_DISK_FORMAT_EMPTY:
-                    break;
-
-#ifdef LIBXL_HAVE_QED
-                case LIBXL_DISK_FORMAT_QED:
-                    disk->src->format = VIR_STORAGE_FILE_QED;
-                    break;
-#endif
-
-                default:
-                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                                   _("disk image format not supported: %s"),
-                                   libxl_disk_format_to_string(libxldisk->format));
-                    goto fail;
-                }
-
-                switch (libxldisk->backend) {
-                case LIBXL_DISK_BACKEND_QDISK:
-                case LIBXL_DISK_BACKEND_UNKNOWN:
-                    if (virDomainDiskSetDriver(disk, "qemu") < 0)
-                        goto fail;
-                    if (virDomainDiskGetType(disk) == VIR_STORAGE_TYPE_NONE)
-                        virDomainDiskSetType(disk, VIR_STORAGE_TYPE_FILE);
-                    break;
-
-                case LIBXL_DISK_BACKEND_TAP:
-                    if (virDomainDiskSetDriver(disk, "tap") < 0)
-                        goto fail;
-                    virDomainDiskSetType(disk, VIR_STORAGE_TYPE_FILE);
-                    break;
-
-                case LIBXL_DISK_BACKEND_PHY:
-                    if (virDomainDiskSetDriver(disk, "phy") < 0)
-                        goto fail;
-                    virDomainDiskSetType(disk, VIR_STORAGE_TYPE_BLOCK);
-                    break;
-                default:
-                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                                   _("disk backend not supported: %s"),
-                                   libxl_disk_backend_to_string(libxldisk->backend));
-                    goto fail;
-                }
-            }
-
-            if (STRPREFIX(libxldisk->vdev, "xvd") ||
-                def->os.type != VIR_DOMAIN_OSTYPE_HVM)
-                disk->bus = VIR_DOMAIN_DISK_BUS_XEN;
-            else if (STRPREFIX(libxldisk->vdev, "sd"))
-                disk->bus = VIR_DOMAIN_DISK_BUS_SCSI;
-            else
-                disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
-
-            if (VIR_APPEND_ELEMENT(def->disks, def->ndisks, disk) < 0)
-                goto fail;
-
-            libxl_device_disk_dispose(libxldisk);
-
-        skipdisk:
-            list = list->next;
-        }
-    }
-    ret = 0;
-
- cleanup:
-    virDomainDiskDefFree(disk);
-    xlu_cfg_destroy(xluconf);
-    VIR_FREE(libxldisk);
-    return ret;
-
- fail:
-    libxl_device_disk_dispose(libxldisk);
-    goto cleanup;
-}
-
-static int
-xenParseXLInputDevs(virConfPtr conf, virDomainDefPtr def)
-{
-    const char *str;
-    virConfValuePtr val;
-
-    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
-        val = virConfGetValue(conf, "usbdevice");
-        /* usbdevice can be defined as either a single string or a list */
-        if (val && val->type == VIR_CONF_LIST) {
-#ifdef LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST
-            val = val->list;
-#else
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                           _("multiple USB devices not supported"));
-            return -1;
-#endif
-        }
-        /* otherwise val->next is NULL, so can be handled by the same code */
-        while (val) {
-            if (val->type != VIR_CONF_STRING) {
-                virReportError(VIR_ERR_INTERNAL_ERROR,
-                               _("config value %s was malformed"),
-                               "usbdevice");
-                return -1;
-            }
-            str = val->str;
-
-            if (str &&
-                    (STREQ(str, "tablet") ||
-                     STREQ(str, "mouse") ||
-                     STREQ(str, "keyboard"))) {
-                virDomainInputDefPtr input;
-                if (VIR_ALLOC(input) < 0)
-                    return -1;
-
-                input->bus = VIR_DOMAIN_INPUT_BUS_USB;
-                if (STREQ(str, "mouse"))
-                    input->type = VIR_DOMAIN_INPUT_TYPE_MOUSE;
-                else if (STREQ(str, "tablet"))
-                    input->type = VIR_DOMAIN_INPUT_TYPE_TABLET;
-                else if (STREQ(str, "keyboard"))
-                    input->type = VIR_DOMAIN_INPUT_TYPE_KBD;
-                if (VIR_APPEND_ELEMENT(def->inputs, def->ninputs, input) < 0) {
-                    virDomainInputDefFree(input);
-                    return -1;
-                }
-            }
-            val = val->next;
-        }
-    }
-    return 0;
-}
-
-static int
-xenParseXLUSBController(virConfPtr conf, virDomainDefPtr def)
-{
-    virConfValuePtr list = virConfGetValue(conf, "usbctrl");
-    virDomainControllerDefPtr controller = NULL;
-
-    if (list && list->type == VIR_CONF_LIST) {
-        list = list->list;
-        while (list) {
-            char type[8];
-            char version[4];
-            char ports[4];
-            char *key;
-            int usbctrl_version = 2; /* by default USB 2.0 */
-            int usbctrl_ports = 8; /* by default 8 ports */
-            int usbctrl_type = -1;
-
-            type[0] = version[0] = ports[0] = '\0';
-
-            if ((list->type != VIR_CONF_STRING) || (list->str == NULL))
-                goto skipusbctrl;
-            /* usbctrl=['type=pv,version=2,ports=8'] */
-            key = list->str;
-            while (key) {
-                char *data;
-                char *nextkey = strchr(key, ',');
-
-                if (!(data = strchr(key, '=')))
-                    goto skipusbctrl;
-                data++;
-
-                if (STRPREFIX(key, "type=")) {
-                    int len = nextkey ? (nextkey - data) : strlen(data);
-                    if (virStrncpy(type, data, len, sizeof(type)) < 0) {
-                        virReportError(VIR_ERR_INTERNAL_ERROR,
-                                       _("type %s invalid"),
-                                       data);
-                        goto skipusbctrl;
-                    }
-                } else if (STRPREFIX(key, "version=")) {
-                    int len = nextkey ? (nextkey - data) : strlen(data);
-                    if (virStrncpy(version, data, len, sizeof(version)) < 0) {
-                        virReportError(VIR_ERR_INTERNAL_ERROR,
-                                       _("version %s invalid"),
-                                       data);
-                        goto skipusbctrl;
-                    }
-                    if (virStrToLong_i(version, NULL, 16, &usbctrl_version) < 0)
-                        goto skipusbctrl;
-                } else if (STRPREFIX(key, "ports=")) {
-                    int len = nextkey ? (nextkey - data) : strlen(data);
-                    if (virStrncpy(ports, data, len, sizeof(ports)) < 0) {
-                        virReportError(VIR_ERR_INTERNAL_ERROR,
-                                       _("version %s invalid"),
-                                       data);
-                        goto skipusbctrl;
-                    }
-                    if (virStrToLong_i(ports, NULL, 16, &usbctrl_ports) < 0)
-                        goto skipusbctrl;
-                }
-
-                while (nextkey && (nextkey[0] == ',' ||
-                                   nextkey[0] == ' ' ||
-                                   nextkey[0] == '\t'))
-                    nextkey++;
-                key = nextkey;
-            }
-
-            if (type[0] == '\0') {
-                if (usbctrl_version == 1)
-                    usbctrl_type = VIR_DOMAIN_CONTROLLER_MODEL_USB_QUSB1;
-                else
-                    usbctrl_type = VIR_DOMAIN_CONTROLLER_MODEL_USB_QUSB2;
-            } else {
-                if (STREQLEN(type, "qusb", 4)) {
-                    if (usbctrl_version == 1)
-                        usbctrl_type = VIR_DOMAIN_CONTROLLER_MODEL_USB_QUSB1;
-                    else
-                        usbctrl_type = VIR_DOMAIN_CONTROLLER_MODEL_USB_QUSB2;
-                } else {
-                    goto skipusbctrl;
-                }
-            }
-
-            if (!(controller = virDomainControllerDefNew(VIR_DOMAIN_CONTROLLER_TYPE_USB)))
-                return -1;
-
-            controller->type = VIR_DOMAIN_CONTROLLER_TYPE_USB;
-            controller->model = usbctrl_type;
-            controller->opts.usbopts.ports = usbctrl_ports;
-
-            if (VIR_APPEND_ELEMENT(def->controllers, def->ncontrollers, controller) < 0) {
-                virDomainControllerDefFree(controller);
-                return -1;
-            }
-
-        skipusbctrl:
-            list = list->next;
-        }
-    }
-
-    return 0;
-}
-
-static int
-xenParseXLUSB(virConfPtr conf, virDomainDefPtr def)
-{
-    virConfValuePtr list = virConfGetValue(conf, "usbdev");
-    virDomainHostdevDefPtr hostdev = NULL;
-
-    if (list && list->type == VIR_CONF_LIST) {
-        list = list->list;
-        while (list) {
-            char bus[3];
-            char device[3];
-            char *key;
-            int busNum;
-            int devNum;
-
-            bus[0] = device[0] = '\0';
-
-            if ((list->type != VIR_CONF_STRING) || (list->str == NULL))
-                goto skipusb;
-            /* usbdev=['hostbus=1,hostaddr=3'] */
-            key = list->str;
-            while (key) {
-                char *data;
-                char *nextkey = strchr(key, ',');
-
-                if (!(data = strchr(key, '=')))
-                    goto skipusb;
-                data++;
-
-                if (STRPREFIX(key, "hostbus=")) {
-                    int len = nextkey ? (nextkey - data) : strlen(data);
-                    if (virStrncpy(bus, data, len, sizeof(bus)) < 0) {
-                        virReportError(VIR_ERR_INTERNAL_ERROR,
-                                       _("bus %s too big for destination"),
-                                       data);
-                        goto skipusb;
-                    }
-                } else if (STRPREFIX(key, "hostaddr=")) {
-                    int len = nextkey ? (nextkey - data) : strlen(data);
-                    if (virStrncpy(device, data, len, sizeof(device)) < 0) {
-                        virReportError(VIR_ERR_INTERNAL_ERROR,
-                                       _("device %s too big for destination"),
-                                       data);
-                        goto skipusb;
-                    }
-                }
-
-                while (nextkey && (nextkey[0] == ',' ||
-                                   nextkey[0] == ' ' ||
-                                   nextkey[0] == '\t'))
-                    nextkey++;
-                key = nextkey;
-            }
-
-            if (virStrToLong_i(bus, NULL, 16, &busNum) < 0)
-                goto skipusb;
-            if (virStrToLong_i(device, NULL, 16, &devNum) < 0)
-                goto skipusb;
-            if (!(hostdev = virDomainHostdevDefNew()))
-               return -1;
-
-            hostdev->managed = false;
-            hostdev->source.subsys.type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB;
-            hostdev->source.subsys.u.usb.bus = busNum;
-            hostdev->source.subsys.u.usb.device = devNum;
-
-            if (VIR_APPEND_ELEMENT(def->hostdevs, def->nhostdevs, hostdev) < 0) {
-                virDomainHostdevDefFree(hostdev);
-                return -1;
-            }
-
-        skipusb:
-            list = list->next;
-        }
-    }
-
-    return 0;
-}
-
-static int
-xenParseXLChannel(virConfPtr conf, virDomainDefPtr def)
-{
-    virConfValuePtr list = virConfGetValue(conf, "channel");
-    virDomainChrDefPtr channel = NULL;
-    char *name = NULL;
-    char *path = NULL;
-
-    if (list && list->type == VIR_CONF_LIST) {
-        list = list->list;
-        while (list) {
-            char type[10];
-            char *key;
-
-            if ((list->type != VIR_CONF_STRING) || (list->str == NULL))
-                goto skipchannel;
-
-            key = list->str;
-            while (key) {
-                char *data;
-                char *nextkey = strchr(key, ',');
-
-                if (!(data = strchr(key, '=')))
-                    goto skipchannel;
-                data++;
-
-                if (STRPREFIX(key, "connection=")) {
-                    int len = nextkey ? (nextkey - data) : strlen(data);
-                    if (virStrncpy(type, data, len, sizeof(type)) < 0) {
-                        virReportError(VIR_ERR_INTERNAL_ERROR,
-                                       _("connection %s too big"), data);
-                        goto skipchannel;
-                    }
-                } else if (STRPREFIX(key, "name=")) {
-                    int len = nextkey ? (nextkey - data) : strlen(data);
-                    VIR_FREE(name);
-                    if (VIR_STRNDUP(name, data, len) < 0)
-                        goto cleanup;
-                } else if (STRPREFIX(key, "path=")) {
-                    int len = nextkey ? (nextkey - data) : strlen(data);
-                    VIR_FREE(path);
-                    if (VIR_STRNDUP(path, data, len) < 0)
-                        goto cleanup;
-                }
-
-                while (nextkey && (nextkey[0] == ',' ||
-                                   nextkey[0] == ' ' ||
-                                   nextkey[0] == '\t'))
-                    nextkey++;
-                key = nextkey;
-            }
-
-            if (!(channel = virDomainChrDefNew(NULL)))
-                goto cleanup;
-
-            if (STRPREFIX(type, "socket")) {
-                channel->source->type = VIR_DOMAIN_CHR_TYPE_UNIX;
-                channel->source->data.nix.listen = 1;
-                channel->source->data.nix.path = path;
-                path = NULL;
-            } else if (STRPREFIX(type, "pty")) {
-                channel->source->type = VIR_DOMAIN_CHR_TYPE_PTY;
-                VIR_FREE(path);
-            } else {
-                goto cleanup;
-            }
-
-            channel->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL;
-            channel->targetType = VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_XEN;
-            channel->target.name = name;
-            name = NULL;
-
-            if (VIR_APPEND_ELEMENT(def->channels, def->nchannels, channel) < 0)
-                goto cleanup;
-
-        skipchannel:
-            list = list->next;
-        }
-    }
-
-    return 0;
-
- cleanup:
-    virDomainChrDefFree(channel);
-    VIR_FREE(path);
-    VIR_FREE(name);
-    return -1;
-}
-
-virDomainDefPtr
-xenParseXL(virConfPtr conf,
-           virCapsPtr caps,
-           virDomainXMLOptionPtr xmlopt)
-{
-    virDomainDefPtr def = NULL;
-
-    if (!(def = virDomainDefNew()))
-        return NULL;
-
-    def->virtType = VIR_DOMAIN_VIRT_XEN;
-    def->id = -1;
-
-    if (xenParseConfigCommon(conf, def, caps, XEN_CONFIG_FORMAT_XL,
-                             xmlopt) < 0)
-        goto cleanup;
-
-    if (xenParseXLOS(conf, def, caps) < 0)
-        goto cleanup;
-
-#ifdef LIBXL_HAVE_VNUMA
-    if (xenParseXLVnuma(conf, def) < 0)
-        goto cleanup;
-#endif
-
-#ifdef LIBXL_HAVE_BUILDINFO_GRANT_LIMITS
-    if (xenParseXLGntLimits(conf, def) < 0)
-        goto cleanup;
-#endif
-
-    if (xenParseXLCPUID(conf, def) < 0)
-        goto cleanup;
-
-    if (xenParseXLDisk(conf, def) < 0)
-        goto cleanup;
-
-    if (xenParseXLSpice(conf, def) < 0)
-        goto cleanup;
-
-    if (xenParseXLInputDevs(conf, def) < 0)
-        goto cleanup;
-
-    if (xenParseXLUSB(conf, def) < 0)
-        goto cleanup;
-
-    if (xenParseXLUSBController(conf, def) < 0)
-        goto cleanup;
-
-    if (xenParseXLChannel(conf, def) < 0)
-        goto cleanup;
-
-    if (virDomainDefPostParse(def, caps, VIR_DOMAIN_DEF_PARSE_ABI_UPDATE,
-                              xmlopt, NULL) < 0)
-        goto cleanup;
-
-    return def;
-
- cleanup:
-    virDomainDefFree(def);
-    return NULL;
-}
-
-
-static int
-xenFormatXLOS(virConfPtr conf, virDomainDefPtr def)
-{
-    size_t i;
-
-    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
-        char boot[VIR_DOMAIN_BOOT_LAST+1];
-        if (xenConfigSetString(conf, "builder", "hvm") < 0)
-            return -1;
-
-        if (def->os.loader &&
-            def->os.loader->type == VIR_DOMAIN_LOADER_TYPE_PFLASH) {
-            if (xenConfigSetString(conf, "bios", "ovmf") < 0)
-                return -1;
-        }
-
-#ifdef LIBXL_HAVE_BUILDINFO_KERNEL
-        if (def->os.kernel &&
-            xenConfigSetString(conf, "kernel", def->os.kernel) < 0)
-            return -1;
-
-        if (def->os.initrd &&
-            xenConfigSetString(conf, "ramdisk", def->os.initrd) < 0)
-            return -1;
-
-        if (def->os.cmdline &&
-            xenConfigSetString(conf, "cmdline", def->os.cmdline) < 0)
-            return -1;
-#endif
-
-        for (i = 0; i < def->os.nBootDevs; i++) {
-            switch (def->os.bootDevs[i]) {
-            case VIR_DOMAIN_BOOT_FLOPPY:
-                boot[i] = 'a';
-                break;
-            case VIR_DOMAIN_BOOT_CDROM:
-                boot[i] = 'd';
-                break;
-            case VIR_DOMAIN_BOOT_NET:
-                boot[i] = 'n';
-                break;
-            case VIR_DOMAIN_BOOT_DISK:
-            default:
-                boot[i] = 'c';
-                break;
-            }
-        }
-
-        if (!def->os.nBootDevs) {
-            boot[0] = 'c';
-            boot[1] = '\0';
-        } else {
-            boot[def->os.nBootDevs] = '\0';
-        }
-
-        if (xenConfigSetString(conf, "boot", boot) < 0)
-            return -1;
-
-        if (def->cpu &&
-            def->cpu->mode == VIR_CPU_MODE_HOST_PASSTHROUGH) {
-            bool hasHwVirt = true;
-
-            if (def->cpu->nfeatures) {
-                for (i = 0; i < def->cpu->nfeatures; i++) {
-
-                    switch (def->cpu->features[i].policy) {
-                        case VIR_CPU_FEATURE_DISABLE:
-                        case VIR_CPU_FEATURE_FORBID:
-                            if (STREQ(def->cpu->features[i].name, "vmx") ||
-                                STREQ(def->cpu->features[i].name, "svm"))
-                                hasHwVirt = false;
-                            break;
-
-                        case VIR_CPU_FEATURE_FORCE:
-                        case VIR_CPU_FEATURE_REQUIRE:
-                        case VIR_CPU_FEATURE_OPTIONAL:
-                        case VIR_CPU_FEATURE_LAST:
-                            break;
-                    }
-                }
-            }
-
-            if (xenConfigSetInt(conf, "nestedhvm", hasHwVirt) < 0)
-                return -1;
-        }
-
-        /* XXX floppy disks */
-    } else {
-        if (def->os.type == VIR_DOMAIN_OSTYPE_XENPVH) {
-            if (xenConfigSetString(conf, "type", "pvh") < 0)
-                return -1;
-        }
-
-        if (def->os.bootloader &&
-             xenConfigSetString(conf, "bootloader", def->os.bootloader) < 0)
-            return -1;
-
-         if (def->os.bootloaderArgs &&
-             xenConfigSetString(conf, "bootargs", def->os.bootloaderArgs) < 0)
-            return -1;
-
-         if (def->os.kernel &&
-             xenConfigSetString(conf, "kernel", def->os.kernel) < 0)
-            return -1;
-
-         if (def->os.initrd &&
-             xenConfigSetString(conf, "ramdisk", def->os.initrd) < 0)
-            return -1;
-
-         if (def->os.cmdline &&
-             xenConfigSetString(conf, "cmdline", def->os.cmdline) < 0)
-            return -1;
-     } /* !hvm */
-
-    return 0;
-}
-
-static int
-xenFormatXLCPUID(virConfPtr conf, virDomainDefPtr def)
-{
-    char **cpuid_pairs = NULL;
-    char *cpuid_string = NULL;
-    size_t i, j;
-    int ret = -1;
-
-    if (!def->cpu)
-        return 0;
-
-    if (def->cpu->mode != VIR_CPU_MODE_HOST_PASSTHROUGH) {
-        VIR_WARN("ignoring CPU mode '%s', only host-passthrough mode "
-                 "is supported", virCPUModeTypeToString(def->cpu->mode));
-        return 0;
-    }
-
-    /* "host" + all features + NULL */
-    if (VIR_ALLOC_N(cpuid_pairs, def->cpu->nfeatures + 2) < 0)
-        return -1;
-
-    if (VIR_STRDUP(cpuid_pairs[0], "host") < 0)
-        goto cleanup;
-
-    j = 1;
-    for (i = 0; i < def->cpu->nfeatures; i++) {
-        const char *feature_name = xenTranslateCPUFeature(
-                def->cpu->features[i].name,
-                false);
-        const char *policy = NULL;
-
-        if (STREQ(feature_name, "vmx") || STREQ(feature_name, "svm"))
-            /* ignore vmx/svm in cpuid option, translated into nestedhvm
-             * elsewhere */
-            continue;
-
-        switch (def->cpu->features[i].policy) {
-            case VIR_CPU_FEATURE_FORCE:
-            case VIR_CPU_FEATURE_REQUIRE:
-                policy = "1";
-                break;
-            case VIR_CPU_FEATURE_OPTIONAL:
-                policy = "x";
-                break;
-            case VIR_CPU_FEATURE_DISABLE:
-            case VIR_CPU_FEATURE_FORBID:
-                policy = "0";
-                break;
-        }
-        if (virAsprintf(&cpuid_pairs[j++], "%s=%s",
-                        feature_name,
-                        policy) < 0)
-            goto cleanup;
-    }
-    cpuid_pairs[j] = NULL;
-
-    if (j > 1) {
-        cpuid_string = virStringListJoin((const char **)cpuid_pairs, ",");
-        if (!cpuid_string)
-            goto cleanup;
-
-        if (xenConfigSetString(conf, "cpuid", cpuid_string) < 0)
-            goto cleanup;
-    }
-
-    ret = 0;
-
- cleanup:
-    virStringListFree(cpuid_pairs);
-    VIR_FREE(cpuid_string);
-    return ret;
-}
-
-#ifdef LIBXL_HAVE_VNUMA
-static int
-xenFormatXLVnode(virConfValuePtr list,
-                 virBufferPtr buf)
-{
-    int ret = -1;
-    virConfValuePtr numaPnode, tmp;
-
-    if (virBufferCheckError(buf) < 0)
-        goto cleanup;
-
-    if (VIR_ALLOC(numaPnode) < 0)
-        goto cleanup;
-
-    /* Place VNODE directive */
-    numaPnode->type = VIR_CONF_STRING;
-    numaPnode->str = virBufferContentAndReset(buf);
-
-    tmp = list->list;
-    while (tmp && tmp->next)
-        tmp = tmp->next;
-    if (tmp)
-        tmp->next = numaPnode;
-    else
-        list->list = numaPnode;
-    ret = 0;
-
- cleanup:
-    virBufferFreeAndReset(buf);
-    return ret;
-}
-
-static int
-xenFormatXLVnuma(virConfValuePtr list,
-                 virDomainNumaPtr numa,
-                 size_t node,
-                 size_t nr_nodes)
-{
-    int ret = -1;
-    size_t i;
-
-    virBuffer buf = VIR_BUFFER_INITIALIZER;
-    virConfValuePtr numaVnode, tmp;
-
-    size_t nodeSize = virDomainNumaGetNodeMemorySize(numa, node) / 1024;
-    char *nodeVcpus = virBitmapFormat(virDomainNumaGetNodeCpumask(numa, node));
-
-    if (VIR_ALLOC(numaVnode) < 0)
-        goto cleanup;
-
-    numaVnode->type = VIR_CONF_LIST;
-    numaVnode->list = NULL;
-
-    /* pnode */
-    virBufferAsprintf(&buf, "pnode=%zu", node);
-    xenFormatXLVnode(numaVnode, &buf);
-
-    /* size */
-    virBufferAsprintf(&buf, "size=%zu", nodeSize);
-    xenFormatXLVnode(numaVnode, &buf);
-
-    /* vcpus */
-    virBufferAsprintf(&buf, "vcpus=%s", nodeVcpus);
-    xenFormatXLVnode(numaVnode, &buf);
-
-    /* distances */
-    virBufferAddLit(&buf, "vdistances=");
-    for (i = 0; i < nr_nodes; i++) {
-        virBufferAsprintf(&buf, "%zu",
-            virDomainNumaGetNodeDistance(numa, node, i));
-        if ((nr_nodes - i) > 1)
-            virBufferAddLit(&buf, ",");
-    }
-    xenFormatXLVnode(numaVnode, &buf);
-
-    tmp = list->list;
-    while (tmp && tmp->next)
-        tmp = tmp->next;
-    if (tmp)
-        tmp->next = numaVnode;
-    else
-        list->list = numaVnode;
-    ret = 0;
-
- cleanup:
-    VIR_FREE(nodeVcpus);
-    return ret;
-}
-
-static int
-xenFormatXLDomainVnuma(virConfPtr conf,
-                       virDomainDefPtr def)
-{
-    virDomainNumaPtr numa = def->numa;
-    virConfValuePtr vnumaVal;
-    size_t i;
-    size_t nr_nodes;
-
-    if (numa == NULL)
-        return -1;
-
-    if (VIR_ALLOC(vnumaVal) < 0)
-        return -1;
-
-    vnumaVal->type = VIR_CONF_LIST;
-    vnumaVal->list = NULL;
-
-    nr_nodes = virDomainNumaGetNodeCount(numa);
-    for (i = 0; i < nr_nodes; i++) {
-        if (xenFormatXLVnuma(vnumaVal, numa, i, nr_nodes) < 0)
-            goto cleanup;
-    }
-
-    if (vnumaVal->list != NULL) {
-        int ret = virConfSetValue(conf, "vnuma", vnumaVal);
-            vnumaVal = NULL;
-            if (ret < 0)
-                return -1;
-    }
-    VIR_FREE(vnumaVal);
-
-    return 0;
-
- cleanup:
-    virConfFreeValue(vnumaVal);
-    return -1;
-}
-#endif
-
-#ifdef LIBXL_HAVE_BUILDINFO_GRANT_LIMITS
-static int
-xenFormatXLGntLimits(virConfPtr conf, virDomainDefPtr def)
-{
-    size_t i;
-
-    for (i = 0; i < def->ncontrollers; i++) {
-        if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_XENBUS &&
-            def->controllers[i]->opts.xenbusopts.maxGrantFrames > 0) {
-            if (xenConfigSetInt(conf, "max_grant_frames",
-                                def->controllers[i]->opts.xenbusopts.maxGrantFrames) < 0)
-                return -1;
-        }
-    }
-    return 0;
-}
-#endif
-
-static char *
-xenFormatXLDiskSrcNet(virStorageSourcePtr src)
-{
-    char *ret = NULL;
-    virBuffer buf = VIR_BUFFER_INITIALIZER;
-    size_t i;
-
-    switch ((virStorageNetProtocol) src->protocol) {
-    case VIR_STORAGE_NET_PROTOCOL_NBD:
-    case VIR_STORAGE_NET_PROTOCOL_HTTP:
-    case VIR_STORAGE_NET_PROTOCOL_HTTPS:
-    case VIR_STORAGE_NET_PROTOCOL_FTP:
-    case VIR_STORAGE_NET_PROTOCOL_FTPS:
-    case VIR_STORAGE_NET_PROTOCOL_TFTP:
-    case VIR_STORAGE_NET_PROTOCOL_ISCSI:
-    case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
-    case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG:
-    case VIR_STORAGE_NET_PROTOCOL_SSH:
-    case VIR_STORAGE_NET_PROTOCOL_VXHS:
-    case VIR_STORAGE_NET_PROTOCOL_LAST:
-    case VIR_STORAGE_NET_PROTOCOL_NONE:
-        virReportError(VIR_ERR_NO_SUPPORT,
-                       _("Unsupported network block protocol '%s'"),
-                       virStorageNetProtocolTypeToString(src->protocol));
-        goto cleanup;
-
-    case VIR_STORAGE_NET_PROTOCOL_RBD:
-        if (strchr(src->path, ':')) {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                           _("':' not allowed in RBD source volume name '%s'"),
-                           src->path);
-            goto cleanup;
-        }
-
-        virBufferStrcat(&buf, "rbd:", src->volume, "/", src->path, NULL);
-
-        virBufferAddLit(&buf, ":auth_supported=none");
-
-        if (src->nhosts > 0) {
-            virBufferAddLit(&buf, ":mon_host=");
-            for (i = 0; i < src->nhosts; i++) {
-                if (i)
-                    virBufferAddLit(&buf, "\\\\;");
-
-                /* assume host containing : is ipv6 */
-                if (strchr(src->hosts[i].name, ':'))
-                    virBufferEscape(&buf, '\\', ":", "[%s]",
-                                    src->hosts[i].name);
-                else
-                    virBufferAsprintf(&buf, "%s", src->hosts[i].name);
-
-                if (src->hosts[i].port)
-                    virBufferAsprintf(&buf, "\\\\:%u", src->hosts[i].port);
-            }
-        }
-
-        if (virBufferCheckError(&buf) < 0)
-            goto cleanup;
-
-        ret = virBufferContentAndReset(&buf);
-        break;
-    }
-
- cleanup:
-    virBufferFreeAndReset(&buf);
-
-    return ret;
-}
-
-
-static int
-xenFormatXLDiskSrc(virStorageSourcePtr src, char **srcstr)
-{
-    int actualType = virStorageSourceGetActualType(src);
-
-    *srcstr = NULL;
-
-    if (virStorageSourceIsEmpty(src))
-        return 0;
-
-    switch ((virStorageType)actualType) {
-    case VIR_STORAGE_TYPE_BLOCK:
-    case VIR_STORAGE_TYPE_FILE:
-    case VIR_STORAGE_TYPE_DIR:
-        if (VIR_STRDUP(*srcstr, src->path) < 0)
-            return -1;
-        break;
-
-    case VIR_STORAGE_TYPE_NETWORK:
-        if (!(*srcstr = xenFormatXLDiskSrcNet(src)))
-            return -1;
-        break;
-
-    case VIR_STORAGE_TYPE_VOLUME:
-    case VIR_STORAGE_TYPE_NONE:
-    case VIR_STORAGE_TYPE_LAST:
-        break;
-    }
-
-    return 0;
-}
-
-
-static int
-xenFormatXLDisk(virConfValuePtr list, virDomainDiskDefPtr disk)
-{
-    virBuffer buf = VIR_BUFFER_INITIALIZER;
-    virConfValuePtr val, tmp;
-    int format = virDomainDiskGetFormat(disk);
-    const char *driver = virDomainDiskGetDriver(disk);
-    char *target = NULL;
-    int ret = -1;
-
-    /* format */
-    virBufferAddLit(&buf, "format=");
-    switch (format) {
-        case VIR_STORAGE_FILE_RAW:
-            virBufferAddLit(&buf, "raw");
-            break;
-        case VIR_STORAGE_FILE_VHD:
-            virBufferAddLit(&buf, "xvhd");
-            break;
-        case VIR_STORAGE_FILE_QCOW:
-            virBufferAddLit(&buf, "qcow");
-            break;
-        case VIR_STORAGE_FILE_QCOW2:
-            virBufferAddLit(&buf, "qcow2");
-            break;
-        case VIR_STORAGE_FILE_QED:
-            virBufferAddLit(&buf, "qed");
-            break;
-      /* set default */
-        default:
-            virBufferAddLit(&buf, "raw");
-    }
-
-    /* device */
-    virBufferAsprintf(&buf, ",vdev=%s", disk->dst);
-
-    /* access */
-    virBufferAddLit(&buf, ",access=");
-    if (disk->src->readonly)
-        virBufferAddLit(&buf, "ro");
-    else if (disk->src->shared)
-        virBufferAddLit(&buf, "!");
-    else
-        virBufferAddLit(&buf, "rw");
-    if (disk->transient) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("transient disks not supported yet"));
-        goto cleanup;
-    }
-
-    /* backendtype */
-    if (driver) {
-        virBufferAddLit(&buf, ",backendtype=");
-        if (STREQ(driver, "qemu") || STREQ(driver, "file"))
-            virBufferAddLit(&buf, "qdisk");
-        else if (STREQ(driver, "tap"))
-            virBufferAddLit(&buf, "tap");
-        else if (STREQ(driver, "phy"))
-            virBufferAddLit(&buf, "phy");
-    }
-
-    /* devtype */
-    if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM)
-        virBufferAddLit(&buf, ",devtype=cdrom");
-
-    /*
-     * target
-     * From $xensrc/docs/misc/xl-disk-configuration.txt:
-     * When this parameter is specified by name, ie with the "target="
-     * syntax in the configuration file, it consumes the whole rest of the
-     * <diskspec> including trailing whitespaces.  Therefore in that case
-     * it must come last.
-     */
-    if (xenFormatXLDiskSrc(disk->src, &target) < 0)
-        goto cleanup;
-
-    if (target)
-        virBufferAsprintf(&buf, ",target=%s", target);
-
-    if (virBufferCheckError(&buf) < 0)
-        goto cleanup;
-
-    if (VIR_ALLOC(val) < 0)
-        goto cleanup;
-
-    val->type = VIR_CONF_STRING;
-    val->str = virBufferContentAndReset(&buf);
-    tmp = list->list;
-    while (tmp && tmp->next)
-        tmp = tmp->next;
-    if (tmp)
-        tmp->next = val;
-    else
-        list->list = val;
-    ret = 0;
-
- cleanup:
-    VIR_FREE(target);
-    virBufferFreeAndReset(&buf);
-    return ret;
-}
-
-
-static int
-xenFormatXLDomainDisks(virConfPtr conf, virDomainDefPtr def)
-{
-    virConfValuePtr diskVal;
-    size_t i;
-
-    if (VIR_ALLOC(diskVal) < 0)
-        return -1;
-
-    diskVal->type = VIR_CONF_LIST;
-    diskVal->list = NULL;
-
-    for (i = 0; i < def->ndisks; i++) {
-        if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY)
-            continue;
-
-        if (xenFormatXLDisk(diskVal, def->disks[i]) < 0)
-            goto cleanup;
-    }
-
-    if (diskVal->list != NULL) {
-        int ret = virConfSetValue(conf, "disk", diskVal);
-        diskVal = NULL;
-        if (ret < 0)
-            return -1;
-    }
-    VIR_FREE(diskVal);
-
-    return 0;
-
- cleanup:
-    virConfFreeValue(diskVal);
-    return -1;
-}
-
-
-static int
-xenFormatXLSpice(virConfPtr conf, virDomainDefPtr def)
-{
-    virDomainGraphicsListenDefPtr glisten;
-    virDomainGraphicsDefPtr graphics;
-
-    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM && def->graphics) {
-        graphics = def->graphics[0];
-
-        if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
-            /* set others to false but may not be necessary */
-            if (xenConfigSetInt(conf, "sdl", 0) < 0)
-                return -1;
-
-            if (xenConfigSetInt(conf, "vnc", 0) < 0)
-                return -1;
-
-            if (xenConfigSetInt(conf, "spice", 1) < 0)
-                return -1;
-
-            if ((glisten = virDomainGraphicsGetListen(graphics, 0)) &&
-                glisten->address &&
-                xenConfigSetString(conf, "spicehost", glisten->address) < 0)
-                return -1;
-
-            if (xenConfigSetInt(conf, "spiceport",
-                                graphics->data.spice.port) < 0)
-                return -1;
-
-            if (xenConfigSetInt(conf, "spicetls_port",
-                                graphics->data.spice.tlsPort) < 0)
-                return -1;
-
-            if (graphics->data.spice.auth.passwd) {
-                if (xenConfigSetInt(conf, "spicedisable_ticketing", 0) < 0)
-                    return -1;
-
-                if (xenConfigSetString(conf, "spicepasswd",
-                                       graphics->data.spice.auth.passwd) < 0)
-                    return -1;
-            } else {
-                if (xenConfigSetInt(conf, "spicedisable_ticketing", 1) < 0)
-                    return -1;
-            }
-
-            if (graphics->data.spice.mousemode) {
-                switch (graphics->data.spice.mousemode) {
-                case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_SERVER:
-                    if (xenConfigSetInt(conf, "spiceagent_mouse", 0) < 0)
-                        return -1;
-                    break;
-                case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_CLIENT:
-                    if (xenConfigSetInt(conf, "spiceagent_mouse", 1) < 0)
-                        return -1;
-                    /*
-                     * spicevdagent must be enabled if using client
-                     * mode mouse
-                     */
-                    if (xenConfigSetInt(conf, "spicevdagent", 1) < 0)
-                        return -1;
-                    break;
-                case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_DEFAULT:
-                    break;
-                case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_LAST:
-                default:
-                    virReportEnumRangeError(virDomainGraphicsSpiceMouseMode,
-                                            graphics->data.spice.mousemode);
-                    return -1;
-                }
-            }
-
-            if (graphics->data.spice.copypaste == VIR_TRISTATE_BOOL_YES) {
-                if (xenConfigSetInt(conf, "spice_clipboard_sharing", 1) < 0)
-                    return -1;
-                /*
-                 * spicevdagent must be enabled if spice_clipboard_sharing
-                 * is enabled
-                 */
-                if (xenConfigSetInt(conf, "spicevdagent", 1) < 0)
-                    return -1;
-            }
-        }
-    }
-
-    return 0;
-}
-
-static int
-xenFormatXLInputDevs(virConfPtr conf, virDomainDefPtr def)
-{
-    size_t i;
-    const char *devtype;
-    virConfValuePtr usbdevices = NULL, lastdev;
-
-    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
-        if (VIR_ALLOC(usbdevices) < 0)
-            goto error;
-
-        usbdevices->type = VIR_CONF_LIST;
-        usbdevices->list = NULL;
-        lastdev = NULL;
-        for (i = 0; i < def->ninputs; i++) {
-            if (def->inputs[i]->bus == VIR_DOMAIN_INPUT_BUS_USB) {
-                if (xenConfigSetInt(conf, "usb", 1) < 0)
-                    goto error;
-
-                switch (def->inputs[i]->type) {
-                    case VIR_DOMAIN_INPUT_TYPE_MOUSE:
-                        devtype = "mouse";
-                        break;
-                    case VIR_DOMAIN_INPUT_TYPE_TABLET:
-                        devtype = "tablet";
-                        break;
-                    case VIR_DOMAIN_INPUT_TYPE_KBD:
-                        devtype = "keyboard";
-                        break;
-                    default:
-                        continue;
-                }
-
-                if (lastdev == NULL) {
-                    if (VIR_ALLOC(lastdev) < 0)
-                        goto error;
-                    usbdevices->list = lastdev;
-                } else {
-                    if (VIR_ALLOC(lastdev->next) < 0)
-                        goto error;
-                    lastdev = lastdev->next;
-                }
-                lastdev->type = VIR_CONF_STRING;
-                if (VIR_STRDUP(lastdev->str, devtype) < 0)
-                    goto error;
-            }
-        }
-        if (usbdevices->list != NULL) {
-            if (usbdevices->list->next == NULL) {
-                /* for compatibility with Xen <= 4.2, use old syntax when
-                 * only one device present */
-                if (xenConfigSetString(conf, "usbdevice", usbdevices->list->str) < 0)
-                    goto error;
-                virConfFreeValue(usbdevices);
-            } else {
-                virConfSetValue(conf, "usbdevice", usbdevices);
-            }
-        } else {
-            VIR_FREE(usbdevices);
-        }
-    }
-
-    return 0;
- error:
-    virConfFreeValue(usbdevices);
-    return -1;
-}
-
-static int
-xenFormatXLUSBController(virConfPtr conf,
-                         virDomainDefPtr def)
-{
-    virConfValuePtr usbctrlVal = NULL;
-    int hasUSBCtrl = 0;
-    size_t i;
-
-    for (i = 0; i < def->ncontrollers; i++) {
-        if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_USB) {
-            hasUSBCtrl = 1;
-            break;
-        }
-    }
-
-    if (!hasUSBCtrl)
-        return 0;
-
-    if (VIR_ALLOC(usbctrlVal) < 0)
-        return -1;
-
-    usbctrlVal->type = VIR_CONF_LIST;
-    usbctrlVal->list = NULL;
-
-    for (i = 0; i < def->ncontrollers; i++) {
-        if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_USB) {
-            virConfValuePtr val, tmp;
-            virBuffer buf = VIR_BUFFER_INITIALIZER;
-
-            if (def->controllers[i]->model != -1) {
-                switch (def->controllers[i]->model) {
-                case VIR_DOMAIN_CONTROLLER_MODEL_USB_QUSB1:
-                    virBufferAddLit(&buf, "type=qusb,version=1,");
-                    break;
-
-                case VIR_DOMAIN_CONTROLLER_MODEL_USB_QUSB2:
-                    virBufferAddLit(&buf, "type=qusb,version=2,");
-                    break;
-
-                default:
-                    goto error;
-                }
-            }
-
-            if (def->controllers[i]->opts.usbopts.ports != -1)
-                virBufferAsprintf(&buf, "ports=%x",
-                                  def->controllers[i]->opts.usbopts.ports);
-
-            if (VIR_ALLOC(val) < 0) {
-                virBufferFreeAndReset(&buf);
-                goto error;
-            }
-            val->type = VIR_CONF_STRING;
-            val->str = virBufferContentAndReset(&buf);
-            tmp = usbctrlVal->list;
-            while (tmp && tmp->next)
-                tmp = tmp->next;
-            if (tmp)
-                tmp->next = val;
-            else
-                usbctrlVal->list = val;
-        }
-    }
-
-    if (usbctrlVal->list != NULL) {
-        int ret = virConfSetValue(conf, "usbctrl", usbctrlVal);
-        usbctrlVal = NULL;
-        if (ret < 0)
-            return -1;
-    }
-    VIR_FREE(usbctrlVal);
-
-    return 0;
-
- error:
-    virConfFreeValue(usbctrlVal);
-    return -1;
-}
-
-
-static int
-xenFormatXLUSB(virConfPtr conf,
-               virDomainDefPtr def)
-{
-    virConfValuePtr usbVal = NULL;
-    int hasUSB = 0;
-    size_t i;
-
-    for (i = 0; i < def->nhostdevs; i++) {
-        if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
-            def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
-            hasUSB = 1;
-            break;
-        }
-    }
-
-    if (!hasUSB)
-        return 0;
-
-    if (VIR_ALLOC(usbVal) < 0)
-        return -1;
-
-    usbVal->type = VIR_CONF_LIST;
-    usbVal->list = NULL;
-
-    for (i = 0; i < def->nhostdevs; i++) {
-        if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
-            def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
-            virConfValuePtr val, tmp;
-            char *buf;
-
-            if (virAsprintf(&buf, "hostbus=%x,hostaddr=%x",
-                            def->hostdevs[i]->source.subsys.u.usb.bus,
-                            def->hostdevs[i]->source.subsys.u.usb.device) < 0)
-                goto error;
-
-            if (VIR_ALLOC(val) < 0) {
-                VIR_FREE(buf);
-                goto error;
-            }
-            val->type = VIR_CONF_STRING;
-            val->str = buf;
-            tmp = usbVal->list;
-            while (tmp && tmp->next)
-                tmp = tmp->next;
-            if (tmp)
-                tmp->next = val;
-            else
-                usbVal->list = val;
-        }
-    }
-
-    if (usbVal->list != NULL) {
-        int ret = virConfSetValue(conf, "usbdev", usbVal);
-        usbVal = NULL;
-        if (ret < 0)
-            return -1;
-    }
-    VIR_FREE(usbVal);
-
-    return 0;
-
- error:
-    virConfFreeValue(usbVal);
-    return -1;
-}
-
-static int
-xenFormatXLChannel(virConfValuePtr list, virDomainChrDefPtr channel)
-{
-    virBuffer buf = VIR_BUFFER_INITIALIZER;
-    int sourceType = channel->source->type;
-    virConfValuePtr val, tmp;
-
-    /* connection */
-    virBufferAddLit(&buf, "connection=");
-    switch (sourceType) {
-        case VIR_DOMAIN_CHR_TYPE_PTY:
-            virBufferAddLit(&buf, "pty,");
-            break;
-        case VIR_DOMAIN_CHR_TYPE_UNIX:
-            virBufferAddLit(&buf, "socket,");
-            /* path */
-            if (channel->source->data.nix.path)
-                virBufferAsprintf(&buf, "path=%s,",
-                                  channel->source->data.nix.path);
-            break;
-        default:
-            goto cleanup;
-    }
-
-    /* name */
-    virBufferAsprintf(&buf, "name=%s", channel->target.name);
-
-    if (VIR_ALLOC(val) < 0)
-        goto cleanup;
-
-    val->type = VIR_CONF_STRING;
-    val->str = virBufferContentAndReset(&buf);
-    tmp = list->list;
-    while (tmp && tmp->next)
-        tmp = tmp->next;
-    if (tmp)
-        tmp->next = val;
-    else
-        list->list = val;
-    return 0;
-
- cleanup:
-    virBufferFreeAndReset(&buf);
-    return -1;
-}
-
-static int
-xenFormatXLDomainChannels(virConfPtr conf, virDomainDefPtr def)
-{
-    virConfValuePtr channelVal = NULL;
-    size_t i;
-
-    if (VIR_ALLOC(channelVal) < 0)
-        goto cleanup;
-
-    channelVal->type = VIR_CONF_LIST;
-    channelVal->list = NULL;
-
-    for (i = 0; i < def->nchannels; i++) {
-        virDomainChrDefPtr chr = def->channels[i];
-
-        if (chr->targetType != VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_XEN)
-            continue;
-
-        if (xenFormatXLChannel(channelVal, def->channels[i]) < 0)
-            goto cleanup;
-    }
-
-    if (channelVal->list != NULL) {
-        int ret = virConfSetValue(conf, "channel", channelVal);
-        channelVal = NULL;
-        if (ret < 0)
-            goto cleanup;
-    }
-
-    VIR_FREE(channelVal);
-    return 0;
-
- cleanup:
-    virConfFreeValue(channelVal);
-    return -1;
-}
-
-virConfPtr
-xenFormatXL(virDomainDefPtr def, virConnectPtr conn)
-{
-    virConfPtr conf = NULL;
-
-    if (!(conf = virConfNew()))
-        goto cleanup;
-
-    if (xenFormatConfigCommon(conf, def, conn, XEN_CONFIG_FORMAT_XL) < 0)
-        goto cleanup;
-
-    if (xenFormatXLOS(conf, def) < 0)
-        goto cleanup;
-
-    if (xenFormatXLCPUID(conf, def) < 0)
-        goto cleanup;
-
-#ifdef LIBXL_HAVE_VNUMA
-    if (xenFormatXLDomainVnuma(conf, def) < 0)
-        goto cleanup;
-#endif
-
-#ifdef LIBXL_HAVE_BUILDINFO_GRANT_LIMITS
-    if (xenFormatXLGntLimits(conf, def) < 0)
-        goto cleanup;
-#endif
-
-    if (xenFormatXLDomainDisks(conf, def) < 0)
-        goto cleanup;
-
-    if (xenFormatXLSpice(conf, def) < 0)
-        goto cleanup;
-
-    if (xenFormatXLInputDevs(conf, def) < 0)
-        goto cleanup;
-
-    if (xenFormatXLUSB(conf, def) < 0)
-        goto cleanup;
-
-    if (xenFormatXLUSBController(conf, def) < 0)
-        goto cleanup;
-
-    if (xenFormatXLDomainChannels(conf, def) < 0)
-        goto cleanup;
-
-    return conf;
-
- cleanup:
-    if (conf)
-        virConfFree(conf);
-    return NULL;
-}
diff --git a/src/xenconfig/xen_xl.h b/src/xenconfig/xen_xl.h
deleted file mode 100644 (file)
index 24f6470..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * xen_xl.h: Xen XL parsing functions
- *
- * Copyright (c) 2015 SUSE LINUX Products GmbH, Nuernberg, Germany.
- * Copyright (c) 2014 David Kiarie Kahurani
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library.  If not, see
- * <http://www.gnu.org/licenses/>.
- *
- */
-
-#pragma once
-
-#include "virconf.h"
-#include "domain_conf.h"
-#include "xen_common.h"
-
-virDomainDefPtr xenParseXL(virConfPtr conn,
-                           virCapsPtr caps,
-                           virDomainXMLOptionPtr xmlopt);
-
-virConfPtr xenFormatXL(virDomainDefPtr def, virConnectPtr);
-
-const char *xenTranslateCPUFeature(const char *feature_name, bool from_libxl);
diff --git a/src/xenconfig/xen_xm.c b/src/xenconfig/xen_xm.c
deleted file mode 100644 (file)
index b8dee09..0000000
+++ /dev/null
@@ -1,625 +0,0 @@
-/*
- * xen_xm.c: Xen XM parsing functions
- *
- * Copyright (C) 2006-2007, 2009-2014 Red Hat, Inc.
- * Copyright (C) 2011 Univention GmbH
- * Copyright (C) 2006 Daniel P. Berrange
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library.  If not, see
- * <http://www.gnu.org/licenses/>.
- */
-
-#include <config.h>
-
-#include "internal.h"
-#include "virerror.h"
-#include "virconf.h"
-#include "viralloc.h"
-#include "verify.h"
-#include "xenxs_private.h"
-#include "xen_xm.h"
-#include "domain_conf.h"
-#include "virstring.h"
-#include "xen_common.h"
-
-#define VIR_FROM_THIS VIR_FROM_XENXM
-
-static int
-xenParseXMOS(virConfPtr conf, virDomainDefPtr def)
-{
-    size_t i;
-
-    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
-        VIR_AUTOFREE(char *) boot = NULL;
-
-        if (VIR_ALLOC(def->os.loader) < 0 ||
-            xenConfigCopyString(conf, "kernel", &def->os.loader->path) < 0)
-            return -1;
-
-        if (xenConfigGetString(conf, "boot", &boot, "c") < 0)
-            return -1;
-
-        for (i = 0; i < VIR_DOMAIN_BOOT_LAST && boot[i]; i++) {
-            switch (boot[i]) {
-            case 'a':
-                def->os.bootDevs[i] = VIR_DOMAIN_BOOT_FLOPPY;
-                break;
-            case 'd':
-                def->os.bootDevs[i] = VIR_DOMAIN_BOOT_CDROM;
-                break;
-            case 'n':
-                def->os.bootDevs[i] = VIR_DOMAIN_BOOT_NET;
-                break;
-            case 'c':
-            default:
-                def->os.bootDevs[i] = VIR_DOMAIN_BOOT_DISK;
-                break;
-            }
-            def->os.nBootDevs++;
-        }
-    } else {
-        VIR_AUTOFREE(char *) extra = NULL;
-        VIR_AUTOFREE(char *) root = NULL;
-
-        if (xenConfigCopyStringOpt(conf, "bootloader", &def->os.bootloader) < 0)
-            return -1;
-        if (xenConfigCopyStringOpt(conf, "bootargs", &def->os.bootloaderArgs) < 0)
-            return -1;
-
-        if (xenConfigCopyStringOpt(conf, "kernel", &def->os.kernel) < 0)
-            return -1;
-
-        if (xenConfigCopyStringOpt(conf, "ramdisk", &def->os.initrd) < 0)
-            return -1;
-
-        if (xenConfigGetString(conf, "extra", &extra, NULL) < 0)
-            return -1;
-
-        if (xenConfigGetString(conf, "root", &root, NULL) < 0)
-            return -1;
-
-        if (root && extra) {
-            if (virAsprintf(&def->os.cmdline, "root=%s %s", root, extra) < 0)
-                return -1;
-        } else if (root) {
-            if (virAsprintf(&def->os.cmdline, "root=%s", root) < 0)
-                return -1;
-        } else if (extra) {
-            if (VIR_STRDUP(def->os.cmdline, extra) < 0)
-                return -1;
-        }
-    }
-
-    return 0;
-}
-
-
-static virDomainDiskDefPtr
-xenParseXMDisk(char *entry, int hvm)
-{
-    virDomainDiskDefPtr disk = NULL;
-    char *head;
-    char *offset;
-    char *tmp;
-    const char *src;
-
-    if (!(disk = virDomainDiskDefNew(NULL)))
-        return NULL;
-
-    head = entry;
-    /*
-     * Disks have 3 components, SOURCE,DEST-DEVICE,MODE
-     * eg, phy:/dev/HostVG/XenGuest1,xvda,w
-     * The SOURCE is usually prefixed with a driver type,
-     * and optionally driver sub-type
-     * The DEST-DEVICE is optionally post-fixed with disk type
-     */
-
-    /* Extract the source file path*/
-    if (!(offset = strchr(head, ',')))
-        goto error;
-
-    if (offset == head) {
-        /* No source file given, eg CDROM with no media */
-        ignore_value(virDomainDiskSetSource(disk, NULL));
-    } else {
-        if (VIR_STRNDUP(tmp, head, offset - head) < 0)
-            goto error;
-
-        if (virDomainDiskSetSource(disk, tmp) < 0) {
-            VIR_FREE(tmp);
-            goto error;
-        }
-        VIR_FREE(tmp);
-    }
-
-    head = offset + 1;
-    /* Remove legacy ioemu: junk */
-    if (STRPREFIX(head, "ioemu:"))
-        head = head + 6;
-
-    /* Extract the dest device name */
-    if (!(offset = strchr(head, ',')))
-        goto error;
-
-    if (VIR_ALLOC_N(disk->dst, (offset - head) + 1) < 0)
-        goto error;
-
-    if (virStrncpy(disk->dst, head, offset - head,
-                   (offset - head) + 1) < 0) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Dest file %s too big for destination"), head);
-        goto error;
-    }
-
-    head = offset + 1;
-    /* Extract source driver type */
-    src = virDomainDiskGetSource(disk);
-    if (src) {
-        size_t len;
-        /* The main type  phy:, file:, tap: ... */
-        if ((tmp = strchr(src, ':')) != NULL) {
-            len = tmp - src;
-            if (VIR_STRNDUP(tmp, src, len) < 0)
-                goto error;
-
-            if (virDomainDiskSetDriver(disk, tmp) < 0) {
-                VIR_FREE(tmp);
-                goto error;
-            }
-            VIR_FREE(tmp);
-
-            /* Strip the prefix we found off the source file name */
-            if (virDomainDiskSetSource(disk, src + len + 1) < 0)
-                goto error;
-
-            src = virDomainDiskGetSource(disk);
-        }
-
-        /* And the sub-type for tap:XXX: type */
-        if (STREQ_NULLABLE(virDomainDiskGetDriver(disk), "tap") ||
-            STREQ_NULLABLE(virDomainDiskGetDriver(disk), "tap2")) {
-            char *driverType;
-
-            if (!(tmp = strchr(src, ':')))
-                goto error;
-            len = tmp - src;
-
-            if (VIR_STRNDUP(driverType, src, len) < 0)
-                goto error;
-
-            if (STREQ(driverType, "aio"))
-                virDomainDiskSetFormat(disk, VIR_STORAGE_FILE_RAW);
-            else
-                virDomainDiskSetFormat(disk,
-                                       virStorageFileFormatTypeFromString(driverType));
-            VIR_FREE(driverType);
-            if (virDomainDiskGetFormat(disk) <= 0) {
-                virReportError(VIR_ERR_INTERNAL_ERROR,
-                               _("Unknown driver type %s"),
-                               src);
-                goto error;
-            }
-
-            /* Strip the prefix we found off the source file name */
-            if (virDomainDiskSetSource(disk, src + len + 1) < 0)
-                goto error;
-            src = virDomainDiskGetSource(disk);
-        }
-    }
-
-    /* No source, or driver name, so fix to phy: */
-    if (!virDomainDiskGetDriver(disk) &&
-        virDomainDiskSetDriver(disk, "phy") < 0)
-        goto error;
-
-    /* phy: type indicates a block device */
-    virDomainDiskSetType(disk,
-                         STREQ(virDomainDiskGetDriver(disk), "phy") ?
-                         VIR_STORAGE_TYPE_BLOCK :
-                         VIR_STORAGE_TYPE_FILE);
-
-    /* Check for a :cdrom/:disk postfix */
-    disk->device = VIR_DOMAIN_DISK_DEVICE_DISK;
-    if ((tmp = strchr(disk->dst, ':')) != NULL) {
-        if (STREQ(tmp, ":cdrom"))
-            disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
-        tmp[0] = '\0';
-    }
-
-    if (STRPREFIX(disk->dst, "xvd") || !hvm)
-        disk->bus = VIR_DOMAIN_DISK_BUS_XEN;
-    else if (STRPREFIX(disk->dst, "sd"))
-        disk->bus = VIR_DOMAIN_DISK_BUS_SCSI;
-    else
-        disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
-
-    if (STREQ(head, "r") || STREQ(head, "ro"))
-        disk->src->readonly = true;
-    else if (STREQ(head, "w!") || STREQ(head, "!"))
-        disk->src->shared = true;
-
-    return disk;
-
- error:
-    virDomainDiskDefFree(disk);
-    return NULL;
-}
-
-
-static int
-xenParseXMDiskList(virConfPtr conf, virDomainDefPtr def)
-{
-    char **disks = NULL, **entries;
-    int hvm = def->os.type == VIR_DOMAIN_OSTYPE_HVM;
-    int ret = -1;
-    int rc;
-
-    rc = virConfGetValueStringList(conf, "disk", false, &disks);
-    if (rc <= 0)
-        return rc;
-
-    for (entries = disks; *entries; entries++) {
-        virDomainDiskDefPtr disk;
-        char *entry = *entries;
-
-        if (!(disk = xenParseXMDisk(entry, hvm)))
-            continue;
-
-        /* Maintain list in sorted order according to target device name */
-        rc = VIR_APPEND_ELEMENT(def->disks, def->ndisks, disk);
-        virDomainDiskDefFree(disk);
-
-        if (rc < 0)
-            goto cleanup;
-    }
-
-    ret = 0;
-
- cleanup:
-    virStringListFree(disks);
-    return ret;
-}
-
-
-static int
-xenFormatXMDisk(virConfValuePtr list,
-                virDomainDiskDefPtr disk)
-{
-    virBuffer buf = VIR_BUFFER_INITIALIZER;
-    virConfValuePtr val, tmp;
-    const char *src = virDomainDiskGetSource(disk);
-    int format = virDomainDiskGetFormat(disk);
-    const char *driver = virDomainDiskGetDriver(disk);
-
-    if (src) {
-        if (format) {
-            const char *type;
-
-            if (format == VIR_STORAGE_FILE_RAW)
-                type = "aio";
-            else
-                type = virStorageFileFormatTypeToString(format);
-
-            if (driver) {
-                virBufferAsprintf(&buf, "%s:", driver);
-                if (STREQ(driver, "tap") || STREQ(driver, "tap2"))
-                    virBufferAsprintf(&buf, "%s:", type);
-            }
-        } else {
-            switch (virDomainDiskGetType(disk)) {
-            case VIR_STORAGE_TYPE_FILE:
-                virBufferAddLit(&buf, "file:");
-                break;
-            case VIR_STORAGE_TYPE_BLOCK:
-                virBufferAddLit(&buf, "phy:");
-                break;
-            default:
-                virReportError(VIR_ERR_INTERNAL_ERROR,
-                               _("unsupported disk type %s"),
-                               virStorageTypeToString(virDomainDiskGetType(disk)));
-                goto cleanup;
-            }
-        }
-        virBufferAdd(&buf, src, -1);
-    }
-    virBufferAddLit(&buf, ",");
-
-    virBufferAdd(&buf, disk->dst, -1);
-    if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM)
-        virBufferAddLit(&buf, ":cdrom");
-
-    if (disk->src->readonly)
-        virBufferAddLit(&buf, ",r");
-    else if (disk->src->shared)
-        virBufferAddLit(&buf, ",!");
-    else
-        virBufferAddLit(&buf, ",w");
-    if (disk->transient) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("transient disks not supported yet"));
-        return -1;
-    }
-
-    if (virBufferCheckError(&buf) < 0)
-        goto cleanup;
-
-    if (VIR_ALLOC(val) < 0)
-        goto cleanup;
-
-    val->type = VIR_CONF_STRING;
-    val->str = virBufferContentAndReset(&buf);
-    tmp = list->list;
-    while (tmp && tmp->next)
-        tmp = tmp->next;
-    if (tmp)
-        tmp->next = val;
-    else
-        list->list = val;
-
-    return 0;
-
- cleanup:
-    virBufferFreeAndReset(&buf);
-    return -1;
-}
-
-
-static int
-xenFormatXMDisks(virConfPtr conf, virDomainDefPtr def)
-{
-    virConfValuePtr diskVal = NULL;
-    size_t i = 0;
-
-    if (VIR_ALLOC(diskVal) < 0)
-        goto cleanup;
-
-    diskVal->type = VIR_CONF_LIST;
-    diskVal->list = NULL;
-
-    for (i = 0; i < def->ndisks; i++) {
-        if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY)
-            continue;
-
-        if (xenFormatXMDisk(diskVal, def->disks[i]) < 0)
-            goto cleanup;
-    }
-
-    if (diskVal->list != NULL) {
-        int ret = virConfSetValue(conf, "disk", diskVal);
-        diskVal = NULL;
-        if (ret < 0)
-            goto cleanup;
-    }
-    VIR_FREE(diskVal);
-
-    return 0;
-
- cleanup:
-    virConfFreeValue(diskVal);
-    return -1;
-}
-
-
-static int
-xenParseXMInputDevs(virConfPtr conf, virDomainDefPtr def)
-{
-    VIR_AUTOFREE(char *) str = NULL;
-
-    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
-        if (xenConfigGetString(conf, "usbdevice", &str, NULL) < 0)
-            return -1;
-        if (str &&
-                (STREQ(str, "tablet") ||
-                 STREQ(str, "mouse") ||
-                 STREQ(str, "keyboard"))) {
-            virDomainInputDefPtr input;
-            if (VIR_ALLOC(input) < 0)
-                return -1;
-
-            input->bus = VIR_DOMAIN_INPUT_BUS_USB;
-            if (STREQ(str, "mouse"))
-                input->type = VIR_DOMAIN_INPUT_TYPE_MOUSE;
-            else if (STREQ(str, "tablet"))
-                input->type = VIR_DOMAIN_INPUT_TYPE_TABLET;
-            else if (STREQ(str, "keyboard"))
-                input->type = VIR_DOMAIN_INPUT_TYPE_KBD;
-            if (VIR_APPEND_ELEMENT(def->inputs, def->ninputs, input) < 0) {
-                virDomainInputDefFree(input);
-                return -1;
-            }
-        }
-    }
-    return 0;
-}
-
-/*
- * Convert an XM config record into a virDomainDef object.
- */
-virDomainDefPtr
-xenParseXM(virConfPtr conf,
-           virCapsPtr caps,
-           virDomainXMLOptionPtr xmlopt)
-{
-    virDomainDefPtr def = NULL;
-
-    if (!(def = virDomainDefNew()))
-        return NULL;
-
-    def->virtType = VIR_DOMAIN_VIRT_XEN;
-    def->id = -1;
-
-    if (xenParseConfigCommon(conf, def, caps, XEN_CONFIG_FORMAT_XM,
-                             xmlopt) < 0)
-        goto cleanup;
-
-    if (xenParseXMOS(conf, def) < 0)
-         goto cleanup;
-
-    if (xenParseXMDiskList(conf, def) < 0)
-         goto cleanup;
-
-    if (xenParseXMInputDevs(conf, def) < 0)
-         goto cleanup;
-
-    if (virDomainDefPostParse(def, caps, VIR_DOMAIN_DEF_PARSE_ABI_UPDATE,
-                              xmlopt, NULL) < 0)
-        goto cleanup;
-
-    return def;
-
- cleanup:
-    virDomainDefFree(def);
-    return NULL;
-}
-
-static int
-xenFormatXMOS(virConfPtr conf, virDomainDefPtr def)
-{
-    size_t i;
-
-    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
-        char boot[VIR_DOMAIN_BOOT_LAST+1];
-        if (xenConfigSetString(conf, "builder", "hvm") < 0)
-            return -1;
-
-        if (def->os.loader && def->os.loader->path &&
-            xenConfigSetString(conf, "kernel", def->os.loader->path) < 0)
-            return -1;
-
-        for (i = 0; i < def->os.nBootDevs; i++) {
-            switch (def->os.bootDevs[i]) {
-            case VIR_DOMAIN_BOOT_FLOPPY:
-                boot[i] = 'a';
-                break;
-            case VIR_DOMAIN_BOOT_CDROM:
-                boot[i] = 'd';
-                break;
-            case VIR_DOMAIN_BOOT_NET:
-                boot[i] = 'n';
-                break;
-            case VIR_DOMAIN_BOOT_DISK:
-            default:
-                boot[i] = 'c';
-                break;
-            }
-        }
-
-        if (!def->os.nBootDevs) {
-            boot[0] = 'c';
-            boot[1] = '\0';
-        } else {
-            boot[def->os.nBootDevs] = '\0';
-        }
-
-        if (xenConfigSetString(conf, "boot", boot) < 0)
-            return -1;
-
-        /* XXX floppy disks */
-    } else {
-        if (def->os.bootloader &&
-             xenConfigSetString(conf, "bootloader", def->os.bootloader) < 0)
-            return -1;
-
-         if (def->os.bootloaderArgs &&
-             xenConfigSetString(conf, "bootargs", def->os.bootloaderArgs) < 0)
-            return -1;
-
-         if (def->os.kernel &&
-             xenConfigSetString(conf, "kernel", def->os.kernel) < 0)
-            return -1;
-
-         if (def->os.initrd &&
-             xenConfigSetString(conf, "ramdisk", def->os.initrd) < 0)
-            return -1;
-
-         if (def->os.cmdline &&
-             xenConfigSetString(conf, "extra", def->os.cmdline) < 0)
-            return -1;
-     } /* !hvm */
-
-    return 0;
-}
-
-
-static int
-xenFormatXMInputDevs(virConfPtr conf, virDomainDefPtr def)
-{
-    size_t i;
-    const char *devtype;
-
-    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
-        for (i = 0; i < def->ninputs; i++) {
-            if (def->inputs[i]->bus == VIR_DOMAIN_INPUT_BUS_USB) {
-                if (xenConfigSetInt(conf, "usb", 1) < 0)
-                    return -1;
-
-                switch (def->inputs[i]->type) {
-                    case VIR_DOMAIN_INPUT_TYPE_MOUSE:
-                        devtype = "mouse";
-                        break;
-                    case VIR_DOMAIN_INPUT_TYPE_TABLET:
-                        devtype = "tablet";
-                        break;
-                    case VIR_DOMAIN_INPUT_TYPE_KBD:
-                        devtype = "keyboard";
-                        break;
-                    default:
-                        continue;
-                }
-                if (xenConfigSetString(conf, "usbdevice", devtype) < 0)
-                    return -1;
-                break;
-            }
-        }
-    }
-    return 0;
-}
-
-
-/* Computing the vcpu_avail bitmask works because MAX_VIRT_CPUS is
-   either 32, or 64 on a platform where long is big enough.  */
-verify(MAX_VIRT_CPUS <= sizeof(1UL) * CHAR_BIT);
-
-/*
- * Convert a virDomainDef object into an XM config record.
- */
-virConfPtr
-xenFormatXM(virConnectPtr conn,
-            virDomainDefPtr def)
-{
-    virConfPtr conf = NULL;
-
-    if (!(conf = virConfNew()))
-        goto cleanup;
-
-    if (xenFormatConfigCommon(conf, def, conn, XEN_CONFIG_FORMAT_XM) < 0)
-        goto cleanup;
-
-    if (xenFormatXMOS(conf, def) < 0)
-        goto cleanup;
-
-    if (xenFormatXMDisks(conf, def) < 0)
-        goto cleanup;
-
-    if (xenFormatXMInputDevs(conf, def) < 0)
-        goto cleanup;
-
-    return conf;
-
- cleanup:
-    if (conf)
-        virConfFree(conf);
-    return NULL;
-}
diff --git a/src/xenconfig/xen_xm.h b/src/xenconfig/xen_xm.h
deleted file mode 100644 (file)
index 5546b2d..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * xen_xm.h: Xen XM parsing functions
- *
- * Copyright (C) 2011 Univention GmbH
- * Copyright (C) 2006-2007, 2009-2010 Red Hat, Inc.
- * Copyright (C) 2006 Daniel P. Berrange
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library.  If not, see
- * <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#include "internal.h"
-#include "virconf.h"
-#include "domain_conf.h"
-
-virConfPtr xenFormatXM(virConnectPtr conn, virDomainDefPtr def);
-
-virDomainDefPtr xenParseXM(virConfPtr conf,
-                           virCapsPtr caps, virDomainXMLOptionPtr xmlopt);
diff --git a/src/xenconfig/xenxs_private.h b/src/xenconfig/xenxs_private.h
deleted file mode 100644 (file)
index 2b0877d..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * xenxs_private.h: Private definitions for Xen parsing
- *
- * Copyright (C) 2007, 2010, 2012 Red Hat, Inc.
- * Copyright (C) 2011 Univention GmbH
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library.  If not, see
- * <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#include "internal.h"
-
-#include <xen/xen.h>
-
-/* xen-unstable changeset 19788 removed MAX_VIRT_CPUS from public
- * headers.  Its semantic was retained with XEN_LEGACY_MAX_VCPUS.
- * Ensure MAX_VIRT_CPUS is defined accordingly.
- */
-#if !defined(MAX_VIRT_CPUS) && defined(XEN_LEGACY_MAX_VCPUS)
-# define MAX_VIRT_CPUS XEN_LEGACY_MAX_VCPUS
-#endif
-
-#define MIN_XEN_GUEST_SIZE 64  /* 64 megabytes */
-
-#ifdef __sun
-# define DEFAULT_VIF_SCRIPT "vif-vnic"
-#else
-# define DEFAULT_VIF_SCRIPT "vif-bridge"
-#endif
index 59171606d1da1388163101b4b8b7bcd0e0d2dc78..ae0db712937364544932e038461fe8e077b5dd28 100644 (file)
@@ -27,7 +27,7 @@
 
 #include "internal.h"
 #include "datatypes.h"
-#include "xenconfig/xen_xl.h"
+#include "libxl/xen_xl.h"
 #include "viralloc.h"
 #include "virstring.h"
 #include "testutils.h"
index 1de3c33f69d70e84b1a09a00c3312868548f73a2..3137dc564cf9a5c47818e5bfa2ba37eaff5bc7d0 100644 (file)
@@ -25,7 +25,7 @@
 
 #include "internal.h"
 #include "datatypes.h"
-#include "xenconfig/xen_xm.h"
+#include "libxl/xen_xm.h"
 #include "testutils.h"
 #include "testutilsxen.h"
 #include "viralloc.h"