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" \
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
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
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
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
+++ /dev/null
-#
-# 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:
# 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 \
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 = \
-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)
--- /dev/null
+/*
+ * 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", ¶llel, 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;
+}
--- /dev/null
+/*
+ * 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);
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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);
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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);
--- /dev/null
+/*
+ * 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
$(XENAPI_CFLAGS) \
$(CURL_CFLAGS) \
-I$(srcdir)/conf \
- -I$(srcdir)/xenconfig \
$(AM_CFLAGS) \
$(NULL)
libvirt_driver_xenapi_la_LDFLAGS = $(AM_LDFLAGS)
+++ /dev/null
-# 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
+++ /dev/null
-/*
- * 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", ¶llel, 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;
-}
+++ /dev/null
-/*
- * 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);
+++ /dev/null
-/*
- * 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;
-}
+++ /dev/null
-/*
- * 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);
+++ /dev/null
-/*
- * 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;
-}
+++ /dev/null
-/*
- * 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);
+++ /dev/null
-/*
- * 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
#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"
#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"