diff --git a/po/POTFILES.in b/po/POTFILES.in
index 2256cb29c79c490b2a3de3cd5da6fd3dfd8f1570..7fbbe8f370ebfa4e7c75bf53b9d61f618079d1c3 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -119,6 +119,7 @@ src/xen/xm_internal.c
src/xen/xs_internal.c
src/xenapi/xenapi_driver.c
src/xenapi/xenapi_utils.c
+src/xenxs/xen_sxpr.c
tools/console.c
tools/libvirt-guests.init.sh
tools/virsh.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 5c9b019c9b9918d338459edf4d7d528969bf492a..4a64eb1b2c945f5e49f9e2dee595127e11e55a16 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -423,6 +423,10 @@ CPU_SOURCES = \
VMX_SOURCES = \
vmx/vmx.c vmx/vmx.h
+XENXS_SOURCES = \
+ xenxs/xenxs_private.h \
+ xenxs/xen_sxpr.c xenxs/xen_sxpr.h
+
pkgdata_DATA = cpu/cpu_map.xml
EXTRA_DIST += $(pkgdata_DATA)
@@ -464,6 +468,14 @@ libvirt_vmx_la_CFLAGS = \
libvirt_vmx_la_SOURCES = $(VMX_SOURCES)
endif
+if WITH_XEN
+noinst_LTLIBRARIES += libvirt_xenxs.la
+libvirt_la_BUILT_LIBADD += libvirt_xenxs.la
+libvirt_xenxs_la_CFLAGS = \
+ -I@top_srcdir@/src/conf $(AM_CFLAGS)
+libvirt_xenxs_la_SOURCES = $(XENXS_SOURCES)
+endif
+
noinst_LTLIBRARIES += libvirt_driver.la
libvirt_la_BUILT_LIBADD += libvirt_driver.la
@@ -583,6 +595,7 @@ endif
libvirt_driver_xen_la_CFLAGS = \
$(XEN_CFLAGS) \
-I@top_srcdir@/src/conf \
+ -I@top_srcdir@/src/xenxs \
$(AM_CFLAGS)
libvirt_driver_xen_la_LDFLAGS = $(AM_LDFLAGS)
libvirt_driver_xen_la_LIBADD = $(XEN_LIBS)
@@ -995,7 +1008,8 @@ EXTRA_DIST += \
$(SECURITY_DRIVER_APPARMOR_SOURCES) \
$(SECRET_DRIVER_SOURCES) \
$(VBOX_DRIVER_EXTRA_DIST) \
- $(VMWARE_DRIVER_SOURCES)
+ $(VMWARE_DRIVER_SOURCES) \
+ $(XENXS_SOURCES)
check-local: augeas-check
diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c
index f6d281e49ae572c816d8ed2baf9ed3dd57d5f318..4bb549ae2c3babb749e0ebca2614c24473394196 100644
--- a/src/xen/xen_driver.c
+++ b/src/xen/xen_driver.c
@@ -33,6 +33,7 @@
#include "datatypes.h"
#include "xen_driver.h"
+#include "xen_sxpr.h"
#include "xen_hypervisor.h"
#include "xend_internal.h"
#include "xs_internal.h"
@@ -1198,6 +1199,9 @@ xenUnifiedDomainXMLFromNative(virConnectPtr conn,
virDomainDefPtr def = NULL;
char *ret = NULL;
virConfPtr conf = NULL;
+ int id;
+ char * tty;
+ int vncport;
GET_PRIVATE(conn);
if (STRNEQ(format, XEN_CONFIG_FORMAT_XM) &&
@@ -1214,7 +1218,13 @@ xenUnifiedDomainXMLFromNative(virConnectPtr conn,
def = xenXMDomainConfigParse(conn, conf);
} else if (STREQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
- def = xenDaemonParseSxprString(conn, config, priv->xendConfigVersion);
+ id = xenGetDomIdFromSxprString(config, priv->xendConfigVersion);
+ xenUnifiedLock(priv);
+ tty = xenStoreDomainGetConsolePath(conn, id);
+ vncport = xenStoreDomainGetVNCPort(conn, id);
+ xenUnifiedUnlock(priv);
+ def = xenDaemonParseSxprString(config, priv->xendConfigVersion, tty,
+ vncport);
}
if (!def)
goto cleanup;
diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c
index 346fb8f9a7537b29bb68f3ba5e3f56fe65182788..466c749ce8def34f2c7db96f5f76e8b8525e28c7 100644
--- a/src/xen/xend_internal.c
+++ b/src/xen/xend_internal.c
@@ -38,6 +38,7 @@
#include "driver.h"
#include "util.h"
#include "sexpr.h"
+#include "xen_sxpr.h"
#include "buf.h"
#include "uuid.h"
#include "xen_driver.h"
@@ -1040,1307 +1041,6 @@ xend_detect_config_version(virConnectPtr conn) {
}
-/*****************************************************************
- ******
- ****** Parsing of SEXPR into virDomainDef objects
- ******
- *****************************************************************/
-
-/**
- * xenDaemonParseSxprOS
- * @node: the root of the parsed S-Expression
- * @def: the domain config
- * @hvm: true or 1 if no contains HVM S-Expression
- * @bootloader: true or 1 if a bootloader is defined
- *
- * Parse the xend sexp for description of os and append it to buf.
- *
- * Returns 0 in case of success and -1 in case of error
- */
-static int
-xenDaemonParseSxprOS(const struct sexpr *node,
- virDomainDefPtr def,
- int hvm)
-{
- if (hvm) {
- if (sexpr_node_copy(node, "domain/image/hvm/loader", &def->os.loader) < 0)
- goto no_memory;
- if (def->os.loader == NULL) {
- if (sexpr_node_copy(node, "domain/image/hvm/kernel", &def->os.loader) < 0)
- goto no_memory;
-
- if (def->os.loader == NULL) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("domain information incomplete, missing HVM loader"));
- return(-1);
- }
- } else {
- if (sexpr_node_copy(node, "domain/image/hvm/kernel", &def->os.kernel) < 0)
- goto no_memory;
- if (sexpr_node_copy(node, "domain/image/hvm/ramdisk", &def->os.initrd) < 0)
- goto no_memory;
- if (sexpr_node_copy(node, "domain/image/hvm/args", &def->os.cmdline) < 0)
- goto no_memory;
- if (sexpr_node_copy(node, "domain/image/hvm/root", &def->os.root) < 0)
- goto no_memory;
- }
- } else {
- if (sexpr_node_copy(node, "domain/image/linux/kernel", &def->os.kernel) < 0)
- goto no_memory;
- if (sexpr_node_copy(node, "domain/image/linux/ramdisk", &def->os.initrd) < 0)
- goto no_memory;
- if (sexpr_node_copy(node, "domain/image/linux/args", &def->os.cmdline) < 0)
- goto no_memory;
- if (sexpr_node_copy(node, "domain/image/linux/root", &def->os.root) < 0)
- goto no_memory;
- }
-
- /* If HVM kenrel == loader, then old xend, so kill off kernel */
- if (hvm &&
- def->os.kernel &&
- STREQ(def->os.kernel, def->os.loader)) {
- VIR_FREE(def->os.kernel);
- }
-
- if (!def->os.kernel &&
- hvm) {
- const char *boot = sexpr_node(node, "domain/image/hvm/boot");
- if ((boot != NULL) && (boot[0] != 0)) {
- while (*boot &&
- def->os.nBootDevs < VIR_DOMAIN_BOOT_LAST) {
- if (*boot == 'a')
- def->os.bootDevs[def->os.nBootDevs++] = VIR_DOMAIN_BOOT_FLOPPY;
- else if (*boot == 'c')
- def->os.bootDevs[def->os.nBootDevs++] = VIR_DOMAIN_BOOT_DISK;
- else if (*boot == 'd')
- def->os.bootDevs[def->os.nBootDevs++] = VIR_DOMAIN_BOOT_CDROM;
- else if (*boot == 'n')
- def->os.bootDevs[def->os.nBootDevs++] = VIR_DOMAIN_BOOT_NET;
- boot++;
- }
- }
- }
-
- if (!hvm &&
- !def->os.kernel &&
- !def->os.bootloader) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("domain information incomplete, missing kernel & bootloader"));
- return -1;
- }
-
- return 0;
-
-no_memory:
- virReportOOMError();
- return -1;
-}
-
-virDomainChrDefPtr
-xenDaemonParseSxprChar(const char *value,
- const char *tty)
-{
- const char *prefix;
- char *tmp;
- virDomainChrDefPtr def;
-
- if (VIR_ALLOC(def) < 0) {
- virReportOOMError();
- return NULL;
- }
-
- prefix = value;
-
- if (value[0] == '/') {
- def->source.type = VIR_DOMAIN_CHR_TYPE_DEV;
- } 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) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- _("unknown chr device type '%s'"), prefix);
- goto error;
- }
- }
- }
-
- /* Compat with legacy syntax */
- switch (def->source.type) {
- case VIR_DOMAIN_CHR_TYPE_PTY:
- if (tty != NULL &&
- !(def->source.data.file.path = strdup(tty)))
- goto no_memory;
- break;
-
- case VIR_DOMAIN_CHR_TYPE_FILE:
- case VIR_DOMAIN_CHR_TYPE_PIPE:
- if (!(def->source.data.file.path = strdup(value)))
- goto no_memory;
- break;
-
- case VIR_DOMAIN_CHR_TYPE_TCP:
- {
- const char *offset = strchr(value, ':');
- const char *offset2;
-
- if (offset == NULL) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("malformed char device string"));
- goto error;
- }
-
- if (offset != value &&
- (def->source.data.tcp.host = strndup(value,
- offset - value)) == NULL)
- goto no_memory;
-
- offset2 = strchr(offset, ',');
- if (offset2 == NULL)
- def->source.data.tcp.service = strdup(offset+1);
- else
- def->source.data.tcp.service = strndup(offset+1,
- offset2-(offset+1));
- if (def->source.data.tcp.service == NULL)
- goto no_memory;
-
- 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) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("malformed char device string"));
- goto error;
- }
-
- if (offset != value &&
- (def->source.data.udp.connectHost
- = strndup(value, offset - value)) == NULL)
- goto no_memory;
-
- offset2 = strchr(offset, '@');
- if (offset2 != NULL) {
- if ((def->source.data.udp.connectService
- = strndup(offset + 1, offset2-(offset+1))) == NULL)
- goto no_memory;
-
- offset3 = strchr(offset2, ':');
- if (offset3 == NULL) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("malformed char device string"));
- goto error;
- }
-
- if (offset3 > (offset2 + 1) &&
- (def->source.data.udp.bindHost
- = strndup(offset2 + 1, offset3 - (offset2+1))) == NULL)
- goto no_memory;
-
- if ((def->source.data.udp.bindService
- = strdup(offset3 + 1)) == NULL)
- goto no_memory;
- } else {
- if ((def->source.data.udp.connectService
- = strdup(offset + 1)) == NULL)
- goto no_memory;
- }
- }
- break;
-
- case VIR_DOMAIN_CHR_TYPE_UNIX:
- {
- const char *offset = strchr(value, ',');
- if (offset)
- def->source.data.nix.path = strndup(value, (offset - value));
- else
- def->source.data.nix.path = strdup(value);
- if (def->source.data.nix.path == NULL)
- goto no_memory;
-
- if (offset != NULL &&
- strstr(offset, ",server") != NULL)
- def->source.data.nix.listen = true;
- }
- break;
- }
-
- return def;
-
-no_memory:
- virReportOOMError();
-error:
- virDomainChrDefFree(def);
- return NULL;
-}
-
-/**
- * xend_parse_sexp_desc_disks
- * @conn: connection
- * @root: root sexpr
- * @xendConfigVersion: version of xend
- *
- * This parses out block devices from the domain sexpr
- *
- * Returns 0 if successful or -1 if failed.
- */
-static int
-xenDaemonParseSxprDisks(virDomainDefPtr def,
- const struct sexpr *root,
- int hvm,
- int xendConfigVersion)
-{
- const struct sexpr *cur, *node;
- virDomainDiskDefPtr disk = NULL;
-
- for (cur = root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
- node = cur->u.s.car;
- /* Normally disks are in a (device (vbd ...)) block
- but blktap disks ended up in a differently named
- (device (tap ....)) block.... */
- if (sexpr_lookup(node, "device/vbd") ||
- sexpr_lookup(node, "device/tap") ||
- sexpr_lookup(node, "device/tap2")) {
- char *offset;
- const char *src = NULL;
- const char *dst = NULL;
- const char *mode = NULL;
-
- /* Again dealing with (vbd...) vs (tap ...) differences */
- if (sexpr_lookup(node, "device/vbd")) {
- src = sexpr_node(node, "device/vbd/uname");
- dst = sexpr_node(node, "device/vbd/dev");
- mode = sexpr_node(node, "device/vbd/mode");
- } else if (sexpr_lookup(node, "device/tap2")) {
- src = sexpr_node(node, "device/tap2/uname");
- dst = sexpr_node(node, "device/tap2/dev");
- mode = sexpr_node(node, "device/tap2/mode");
- } else {
- src = sexpr_node(node, "device/tap/uname");
- dst = sexpr_node(node, "device/tap/dev");
- mode = sexpr_node(node, "device/tap/mode");
- }
-
- if (VIR_ALLOC(disk) < 0)
- goto no_memory;
-
- if (dst == NULL) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("domain information incomplete, vbd has no dev"));
- goto error;
- }
-
- if (src == NULL) {
- /* There is a case without the uname to the CD-ROM device */
- offset = strchr(dst, ':');
- if (!offset ||
- !hvm ||
- STRNEQ(offset, ":cdrom")) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("domain information incomplete, vbd has no src"));
- goto error;
- }
- }
-
- if (src != NULL) {
- offset = strchr(src, ':');
- if (!offset) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("cannot parse vbd filename, missing driver name"));
- goto error;
- }
-
- if (VIR_ALLOC_N(disk->driverName, (offset-src)+1) < 0)
- goto no_memory;
- if (virStrncpy(disk->driverName, src, offset-src,
- (offset-src)+1) == NULL) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- _("Driver name %s too big for destination"),
- src);
- goto error;
- }
-
- src = offset + 1;
-
- if (STREQ (disk->driverName, "tap") ||
- STREQ (disk->driverName, "tap2")) {
- offset = strchr(src, ':');
- if (!offset) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("cannot parse vbd filename, missing driver type"));
- goto error;
- }
-
- if (VIR_ALLOC_N(disk->driverType, (offset-src)+1)< 0)
- goto no_memory;
- if (virStrncpy(disk->driverType, src, offset-src,
- (offset-src)+1) == NULL) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- _("Driver type %s too big for destination"),
- src);
- goto error;
- }
-
- src = offset + 1;
- /* Its possible to use blktap driver for block devs
- too, but kinda pointless because blkback is better,
- so we assume common case here. If blktap becomes
- omnipotent, we can revisit this, perhaps stat()'ing
- the src file in question */
- disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
- } else if (STREQ(disk->driverName, "phy")) {
- disk->type = VIR_DOMAIN_DISK_TYPE_BLOCK;
- } else if (STREQ(disk->driverName, "file")) {
- disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
- }
- } else {
- /* No CDROM media so can't really tell. We'll just
- call if a FILE for now and update when media
- is inserted later */
- disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
- }
-
- if (STREQLEN (dst, "ioemu:", 6))
- dst += 6;
-
- disk->device = VIR_DOMAIN_DISK_DEVICE_DISK;
- /* New style disk config from Xen >= 3.0.3 */
- if (xendConfigVersion > 1) {
- offset = strrchr(dst, ':');
- if (offset) {
- if (STREQ (offset, ":cdrom")) {
- disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
- } else if (STREQ (offset, ":disk")) {
- /* The default anyway */
- } else {
- /* Unknown, lets pretend its a disk too */
- }
- offset[0] = '\0';
- }
- }
-
- if (!(disk->dst = strdup(dst)))
- goto no_memory;
- if (src &&
- !(disk->src = strdup(src)))
- goto no_memory;
-
- if (STRPREFIX(disk->dst, "xvd"))
- disk->bus = VIR_DOMAIN_DISK_BUS_XEN;
- else if (STRPREFIX(disk->dst, "hd"))
- disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
- else if (STRPREFIX(disk->dst, "sd"))
- disk->bus = VIR_DOMAIN_DISK_BUS_SCSI;
- else
- disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
-
- if (mode &&
- strchr(mode, 'r'))
- disk->readonly = 1;
- if (mode &&
- strchr(mode, '!'))
- disk->shared = 1;
-
- if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0)
- goto no_memory;
-
- def->disks[def->ndisks++] = disk;
- disk = NULL;
- }
- }
-
- return 0;
-
-no_memory:
- virReportOOMError();
-
-error:
- virDomainDiskDefFree(disk);
- return -1;
-}
-
-
-static int
-xenDaemonParseSxprNets(virDomainDefPtr def,
- const struct sexpr *root)
-{
- virDomainNetDefPtr net = NULL;
- const struct sexpr *cur, *node;
- const char *tmp;
- int vif_index = 0;
-
- for (cur = root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
- node = cur->u.s.car;
- if (sexpr_lookup(node, "device/vif")) {
- const char *tmp2, *model, *type;
- char buf[50];
- tmp2 = sexpr_node(node, "device/vif/script");
- tmp = sexpr_node(node, "device/vif/bridge");
- model = sexpr_node(node, "device/vif/model");
- type = sexpr_node(node, "device/vif/type");
-
- if (VIR_ALLOC(net) < 0)
- goto no_memory;
-
- if (tmp != NULL ||
- (tmp2 != NULL && STREQ(tmp2, DEFAULT_VIF_SCRIPT))) {
- net->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
- /* XXX virtual network reverse resolve */
-
- if (tmp &&
- !(net->data.bridge.brname = strdup(tmp)))
- goto no_memory;
- if (tmp2 &&
- net->type == VIR_DOMAIN_NET_TYPE_BRIDGE &&
- !(net->data.bridge.script = strdup(tmp2)))
- goto no_memory;
- tmp = sexpr_node(node, "device/vif/ip");
- if (tmp &&
- !(net->data.bridge.ipaddr = strdup(tmp)))
- goto no_memory;
- } else {
- net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
- if (tmp2 &&
- !(net->data.ethernet.script = strdup(tmp2)))
- goto no_memory;
- tmp = sexpr_node(node, "device/vif/ip");
- if (tmp &&
- !(net->data.ethernet.ipaddr = strdup(tmp)))
- goto no_memory;
- }
-
- tmp = sexpr_node(node, "device/vif/vifname");
- if (!tmp) {
- snprintf(buf, sizeof(buf), "vif%d.%d", def->id, vif_index);
- tmp = buf;
- }
- if (!(net->ifname = strdup(tmp)))
- goto no_memory;
-
- tmp = sexpr_node(node, "device/vif/mac");
- if (tmp) {
- if (virParseMacAddr(tmp, net->mac) < 0) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- _("malformed mac address '%s'"), tmp);
- goto cleanup;
- }
- }
-
- if (model &&
- !(net->model = strdup(model)))
- goto no_memory;
-
- if (!model && type &&
- STREQ(type, "netfront") &&
- !(net->model = strdup("netfront")))
- goto no_memory;
-
- if (VIR_REALLOC_N(def->nets, def->nnets + 1) < 0)
- goto no_memory;
-
- def->nets[def->nnets++] = net;
- vif_index++;
- }
- }
-
- return 0;
-
-no_memory:
- virReportOOMError();
-cleanup:
- virDomainNetDefFree(net);
- return -1;
-}
-
-
-int
-xenDaemonParseSxprSound(virDomainDefPtr def,
- const char *str)
-{
- if (STREQ(str, "all")) {
- int i;
-
- /*
- * Special compatability code for Xen with a bogus
- * sound=all in config.
- *
- * NB delibrately, don't include all possible
- * sound models anymore, just the 2 that were
- * historically present in Xen's QEMU.
- *
- * ie just es1370 + sb16.
- *
- * Hence use of MODEL_ES1370 + 1, instead of MODEL_LAST
- */
-
- if (VIR_ALLOC_N(def->sounds,
- VIR_DOMAIN_SOUND_MODEL_ES1370 + 1) < 0)
- goto no_memory;
-
-
- for (i = 0 ; i < (VIR_DOMAIN_SOUND_MODEL_ES1370 + 1) ; i++) {
- virDomainSoundDefPtr sound;
- if (VIR_ALLOC(sound) < 0)
- goto no_memory;
- sound->model = i;
- def->sounds[def->nsounds++] = sound;
- }
- } else {
- char model[10];
- const char *offset = str, *offset2;
-
- do {
- int len;
- virDomainSoundDefPtr sound;
- offset2 = strchr(offset, ',');
- if (offset2)
- len = (offset2 - offset);
- else
- len = strlen(offset);
- if (virStrncpy(model, offset, len, sizeof(model)) == NULL) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- _("Sound model %s too big for destination"),
- offset);
- goto error;
- }
-
- if (VIR_ALLOC(sound) < 0)
- goto no_memory;
-
- if ((sound->model = virDomainSoundModelTypeFromString(model)) < 0) {
- VIR_FREE(sound);
- goto error;
- }
-
- if (VIR_REALLOC_N(def->sounds, def->nsounds+1) < 0) {
- virDomainSoundDefFree(sound);
- goto no_memory;
- }
-
- def->sounds[def->nsounds++] = sound;
- offset = offset2 ? offset2 + 1 : NULL;
- } while (offset);
- }
-
- return 0;
-
-no_memory:
- virReportOOMError();
-error:
- return -1;
-}
-
-
-static int
-xenDaemonParseSxprUSB(virDomainDefPtr def,
- const struct sexpr *root)
-{
- struct sexpr *cur, *node;
- const char *tmp;
-
- for (cur = sexpr_lookup(root, "domain/image/hvm"); cur && cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
- node = cur->u.s.car;
- if (sexpr_lookup(node, "usbdevice")) {
- tmp = sexpr_node(node, "usbdevice");
- if (tmp && *tmp) {
- if (STREQ(tmp, "tablet") ||
- STREQ(tmp, "mouse")) {
- virDomainInputDefPtr input;
- if (VIR_ALLOC(input) < 0)
- goto no_memory;
- input->bus = VIR_DOMAIN_INPUT_BUS_USB;
- if (STREQ(tmp, "tablet"))
- input->type = VIR_DOMAIN_INPUT_TYPE_TABLET;
- else
- input->type = VIR_DOMAIN_INPUT_TYPE_MOUSE;
-
- if (VIR_REALLOC_N(def->inputs, def->ninputs+1) < 0) {
- VIR_FREE(input);
- goto no_memory;
- }
- def->inputs[def->ninputs++] = input;
- } else {
- /* XXX Handle other non-input USB devices later */
- }
- }
- }
- }
- return 0;
-
-no_memory:
- virReportOOMError();
- return -1;
-}
-
-static int
-xenDaemonParseSxprGraphicsOld(virConnectPtr conn,
- virDomainDefPtr def,
- const struct sexpr *root,
- int hvm,
- int xendConfigVersion)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- const char *tmp;
- virDomainGraphicsDefPtr graphics = NULL;
-
- if ((tmp = sexpr_fmt_node(root, "domain/image/%s/vnc", hvm ? "hvm" : "linux")) &&
- tmp[0] == '1') {
- /* Graphics device (HVM, or old (pre-3.0.4) style PV VNC config) */
- int port;
- const char *listenAddr = sexpr_fmt_node(root, "domain/image/%s/vnclisten", hvm ? "hvm" : "linux");
- const char *vncPasswd = sexpr_fmt_node(root, "domain/image/%s/vncpasswd", hvm ? "hvm" : "linux");
- const char *keymap = sexpr_fmt_node(root, "domain/image/%s/keymap", hvm ? "hvm" : "linux");
- const char *unused = sexpr_fmt_node(root, "domain/image/%s/vncunused", hvm ? "hvm" : "linux");
-
- xenUnifiedLock(priv);
- port = xenStoreDomainGetVNCPort(conn, def->id);
- xenUnifiedUnlock(priv);
-
- if (VIR_ALLOC(graphics) < 0)
- goto no_memory;
-
- graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_VNC;
- /* For Xen >= 3.0.3, don't generate a fixed port mapping
- * because it will almost certainly be wrong ! Just leave
- * it as -1 which lets caller see that the VNC server isn't
- * present yet. Subsquent dumps of the XML will eventually
- * find the port in XenStore once VNC server has started
- */
- if (port == -1 && xendConfigVersion < 2)
- port = 5900 + def->id;
-
- if ((unused && STREQ(unused, "1")) || port == -1)
- graphics->data.vnc.autoport = 1;
- graphics->data.vnc.port = port;
-
- if (listenAddr &&
- !(graphics->data.vnc.listenAddr = strdup(listenAddr)))
- goto no_memory;
-
- if (vncPasswd &&
- !(graphics->data.vnc.auth.passwd = strdup(vncPasswd)))
- goto no_memory;
-
- if (keymap &&
- !(graphics->data.vnc.keymap = strdup(keymap)))
- goto no_memory;
-
- if (VIR_ALLOC_N(def->graphics, 1) < 0)
- goto no_memory;
- def->graphics[0] = graphics;
- def->ngraphics = 1;
- graphics = NULL;
- } else if ((tmp = sexpr_fmt_node(root, "domain/image/%s/sdl", hvm ? "hvm" : "linux")) &&
- tmp[0] == '1') {
- /* Graphics device (HVM, or old (pre-3.0.4) style PV sdl config) */
- const char *display = sexpr_fmt_node(root, "domain/image/%s/display", hvm ? "hvm" : "linux");
- const char *xauth = sexpr_fmt_node(root, "domain/image/%s/xauthority", hvm ? "hvm" : "linux");
-
- if (VIR_ALLOC(graphics) < 0)
- goto no_memory;
-
- graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_SDL;
- if (display &&
- !(graphics->data.sdl.display = strdup(display)))
- goto no_memory;
- if (xauth &&
- !(graphics->data.sdl.xauth = strdup(xauth)))
- goto no_memory;
-
- if (VIR_ALLOC_N(def->graphics, 1) < 0)
- goto no_memory;
- def->graphics[0] = graphics;
- def->ngraphics = 1;
- graphics = NULL;
- }
-
- return 0;
-
-no_memory:
- virReportOOMError();
- virDomainGraphicsDefFree(graphics);
- return -1;
-}
-
-
-static int
-xenDaemonParseSxprGraphicsNew(virConnectPtr conn,
- virDomainDefPtr def,
- const struct sexpr *root)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- virDomainGraphicsDefPtr graphics = NULL;
- const struct sexpr *cur, *node;
- const char *tmp;
-
- /* append network devices and framebuffer */
- for (cur = root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
- node = cur->u.s.car;
- if (sexpr_lookup(node, "device/vfb")) {
- /* New style graphics config for PV guests in >= 3.0.4,
- * or for HVM guests in >= 3.0.5 */
- if (sexpr_node(node, "device/vfb/type")) {
- tmp = sexpr_node(node, "device/vfb/type");
- } else if (sexpr_node(node, "device/vfb/vnc")) {
- tmp = "vnc";
- } else if (sexpr_node(node, "device/vfb/sdl")) {
- tmp = "sdl";
- } else {
- tmp = "unknown";
- }
-
- if (VIR_ALLOC(graphics) < 0)
- goto no_memory;
-
- if ((graphics->type = virDomainGraphicsTypeFromString(tmp)) < 0) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- _("unknown graphics type '%s'"), tmp);
- goto error;
- }
-
- if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
- const char *display = sexpr_node(node, "device/vfb/display");
- const char *xauth = sexpr_node(node, "device/vfb/xauthority");
- if (display &&
- !(graphics->data.sdl.display = strdup(display)))
- goto no_memory;
- if (xauth &&
- !(graphics->data.sdl.xauth = strdup(xauth)))
- goto no_memory;
- } else {
- int port;
- const char *listenAddr = sexpr_node(node, "device/vfb/vnclisten");
- const char *vncPasswd = sexpr_node(node, "device/vfb/vncpasswd");
- const char *keymap = sexpr_node(node, "device/vfb/keymap");
- const char *unused = sexpr_node(node, "device/vfb/vncunused");
-
- xenUnifiedLock(priv);
- port = xenStoreDomainGetVNCPort(conn, def->id);
- xenUnifiedUnlock(priv);
-
- /* Didn't find port entry in xenstore */
- if (port == -1) {
- const char *str = sexpr_node(node, "device/vfb/vncdisplay");
- int val;
- if (str != NULL && virStrToLong_i(str, NULL, 0, &val) == 0)
- port = val;
- }
-
- if ((unused && STREQ(unused, "1")) || port == -1)
- graphics->data.vnc.autoport = 1;
-
- if (port >= 0 && port < 5900)
- port += 5900;
- graphics->data.vnc.port = port;
-
- if (listenAddr &&
- !(graphics->data.vnc.listenAddr = strdup(listenAddr)))
- goto no_memory;
-
- if (vncPasswd &&
- !(graphics->data.vnc.auth.passwd = strdup(vncPasswd)))
- goto no_memory;
-
- if (keymap &&
- !(graphics->data.vnc.keymap = strdup(keymap)))
- goto no_memory;
- }
-
- if (VIR_ALLOC_N(def->graphics, 1) < 0)
- goto no_memory;
- def->graphics[0] = graphics;
- def->ngraphics = 1;
- graphics = NULL;
- break;
- }
- }
-
- return 0;
-
-no_memory:
- virReportOOMError();
-error:
- virDomainGraphicsDefFree(graphics);
- return -1;
-}
-
-/**
- * xenDaemonParseSxprPCI
- * @root: root sexpr
- *
- * This parses out block devices from the domain sexpr
- *
- * Returns 0 if successful or -1 if failed.
- */
-static int
-xenDaemonParseSxprPCI(virDomainDefPtr def,
- const struct sexpr *root)
-{
- const struct sexpr *cur, *tmp = NULL, *node;
- virDomainHostdevDefPtr dev = NULL;
-
- /*
- * With the (domain ...) block we have the following odd setup
- *
- * (device
- * (pci
- * (dev (domain 0x0000) (bus 0x00) (slot 0x1b) (func 0x0))
- * (dev (domain 0x0000) (bus 0x00) (slot 0x13) (func 0x0))
- * )
- * )
- *
- * Normally there is one (device ...) block per device, but in
- * wierd world of Xen PCI, once (device ...) covers multiple
- * devices.
- */
-
- for (cur = root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
- node = cur->u.s.car;
- if ((tmp = sexpr_lookup(node, "device/pci")) != NULL)
- break;
- }
-
- if (!tmp)
- return 0;
-
- for (cur = tmp; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
- const char *domain = NULL;
- const char *bus = NULL;
- const char *slot = NULL;
- const char *func = NULL;
- int domainID;
- int busID;
- int slotID;
- int funcID;
-
- node = cur->u.s.car;
- if (!sexpr_lookup(node, "dev"))
- continue;
-
- if (!(domain = sexpr_node(node, "dev/domain"))) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("missing PCI domain"));
- goto error;
- }
- if (!(bus = sexpr_node(node, "dev/bus"))) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("missing PCI bus"));
- goto error;
- }
- if (!(slot = sexpr_node(node, "dev/slot"))) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("missing PCI slot"));
- goto error;
- }
- if (!(func = sexpr_node(node, "dev/func"))) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("missing PCI func"));
- goto error;
- }
-
- if (virStrToLong_i(domain, NULL, 0, &domainID) < 0) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- _("cannot parse PCI domain '%s'"), domain);
- goto error;
- }
- if (virStrToLong_i(bus, NULL, 0, &busID) < 0) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- _("cannot parse PCI bus '%s'"), bus);
- goto error;
- }
- if (virStrToLong_i(slot, NULL, 0, &slotID) < 0) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- _("cannot parse PCI slot '%s'"), slot);
- goto error;
- }
- if (virStrToLong_i(func, NULL, 0, &funcID) < 0) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- _("cannot parse PCI func '%s'"), func);
- goto error;
- }
-
- if (VIR_ALLOC(dev) < 0)
- goto no_memory;
-
- dev->mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS;
- dev->managed = 0;
- dev->source.subsys.type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI;
- dev->source.subsys.u.pci.domain = domainID;
- dev->source.subsys.u.pci.bus = busID;
- dev->source.subsys.u.pci.slot = slotID;
- dev->source.subsys.u.pci.function = funcID;
-
- if (VIR_REALLOC_N(def->hostdevs, def->nhostdevs+1) < 0) {
- goto no_memory;
- }
-
- def->hostdevs[def->nhostdevs++] = dev;
- }
-
- return 0;
-
-no_memory:
- virReportOOMError();
-
-error:
- virDomainHostdevDefFree(dev);
- return -1;
-}
-
-
-/**
- * xenDaemonParseSxpr:
- * @conn: the connection associated with the XML
- * @root: the root of the parsed S-Expression
- * @xendConfigVersion: version of xend
- * @cpus: set of cpus the domain may be pinned to
- *
- * Parse the xend sexp description and turn it into the XML format similar
- * to the one unsed for creation.
- *
- * Returns the 0 terminated XML string or NULL in case of error.
- * the caller must free() the returned value.
- */
-static virDomainDefPtr
-xenDaemonParseSxpr(virConnectPtr conn,
- const struct sexpr *root,
- int xendConfigVersion,
- const char *cpus)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- const char *tmp;
- virDomainDefPtr def;
- int hvm = 0;
- char *tty = NULL;
-
- if (VIR_ALLOC(def) < 0)
- goto no_memory;
-
- tmp = sexpr_node(root, "domain/domid");
- if (tmp == NULL && xendConfigVersion < 3) { /* Old XenD, domid was mandatory */
- virXendError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("domain information incomplete, missing id"));
- goto error;
- }
- def->virtType = VIR_DOMAIN_VIRT_XEN;
- if (tmp)
- def->id = sexpr_int(root, "domain/domid");
- else
- def->id = -1;
-
- if (sexpr_node_copy(root, "domain/name", &def->name) < 0)
- goto no_memory;
- if (def->name == NULL) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("domain information incomplete, missing name"));
- goto error;
- }
-
- tmp = sexpr_node(root, "domain/uuid");
- if (tmp == NULL) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("domain information incomplete, missing name"));
- goto error;
- }
- virUUIDParse(tmp, def->uuid);
-
- if (sexpr_node_copy(root, "domain/description", &def->description) < 0)
- goto no_memory;
-
- hvm = sexpr_lookup(root, "domain/image/hvm") ? 1 : 0;
- if (!hvm) {
- if (sexpr_node_copy(root, "domain/bootloader",
- &def->os.bootloader) < 0)
- goto no_memory;
-
- if (!def->os.bootloader &&
- sexpr_has(root, "domain/bootloader") &&
- (def->os.bootloader = strdup("")) == NULL)
- goto no_memory;
-
- if (def->os.bootloader &&
- sexpr_node_copy(root, "domain/bootloader_args",
- &def->os.bootloaderArgs) < 0)
- goto no_memory;
- }
-
- if (!(def->os.type = strdup(hvm ? "hvm" : "linux")))
- goto no_memory;
-
- if (def->id != 0) {
- if (sexpr_lookup(root, "domain/image")) {
- if (xenDaemonParseSxprOS(root, def, hvm) < 0)
- goto error;
- }
- }
-
- def->mem.max_balloon = (unsigned long)
- (sexpr_u64(root, "domain/maxmem") << 10);
- def->mem.cur_balloon = (unsigned long)
- (sexpr_u64(root, "domain/memory") << 10);
- if (def->mem.cur_balloon > def->mem.max_balloon)
- def->mem.cur_balloon = def->mem.max_balloon;
-
- if (cpus != NULL) {
- def->cpumasklen = VIR_DOMAIN_CPUMASK_LEN;
- if (VIR_ALLOC_N(def->cpumask, def->cpumasklen) < 0) {
- virReportOOMError();
- goto error;
- }
-
- if (virDomainCpuSetParse(&cpus,
- 0, def->cpumask,
- def->cpumasklen) < 0) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- _("invalid CPU mask %s"), cpus);
- goto error;
- }
- }
-
- def->maxvcpus = sexpr_int(root, "domain/vcpus");
- def->vcpus = count_one_bits_l(sexpr_u64(root, "domain/vcpu_avail"));
- if (!def->vcpus || def->maxvcpus < def->vcpus)
- def->vcpus = def->maxvcpus;
-
- tmp = sexpr_node(root, "domain/on_poweroff");
- if (tmp != NULL) {
- if ((def->onPoweroff = virDomainLifecycleTypeFromString(tmp)) < 0) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- _("unknown lifecycle type %s"), tmp);
- goto error;
- }
- } else
- def->onPoweroff = VIR_DOMAIN_LIFECYCLE_DESTROY;
-
- tmp = sexpr_node(root, "domain/on_reboot");
- if (tmp != NULL) {
- if ((def->onReboot = virDomainLifecycleTypeFromString(tmp)) < 0) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- _("unknown lifecycle type %s"), tmp);
- goto error;
- }
- } else
- def->onReboot = VIR_DOMAIN_LIFECYCLE_RESTART;
-
- tmp = sexpr_node(root, "domain/on_crash");
- if (tmp != NULL) {
- if ((def->onCrash = virDomainLifecycleCrashTypeFromString(tmp)) < 0) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- _("unknown lifecycle type %s"), tmp);
- goto error;
- }
- } else
- def->onCrash = VIR_DOMAIN_LIFECYCLE_DESTROY;
-
- def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_UTC;
- if (hvm) {
- if (sexpr_int(root, "domain/image/hvm/acpi"))
- def->features |= (1 << VIR_DOMAIN_FEATURE_ACPI);
- if (sexpr_int(root, "domain/image/hvm/apic"))
- def->features |= (1 << VIR_DOMAIN_FEATURE_APIC);
- if (sexpr_int(root, "domain/image/hvm/pae"))
- def->features |= (1 << VIR_DOMAIN_FEATURE_PAE);
- if (sexpr_int(root, "domain/image/hvm/hap"))
- def->features |= (1 << VIR_DOMAIN_FEATURE_HAP);
-
- /* Old XenD only allows localtime here for HVM */
- if (sexpr_int(root, "domain/image/hvm/localtime"))
- def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME;
- }
-
- /* Current XenD allows localtime here, for PV and HVM */
- if (sexpr_int(root, "domain/localtime"))
- def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME;
-
- if (sexpr_node_copy(root, hvm ?
- "domain/image/hvm/device_model" :
- "domain/image/linux/device_model",
- &def->emulator) < 0)
- goto no_memory;
-
- /* append block devices */
- if (xenDaemonParseSxprDisks(def, root, hvm, xendConfigVersion) < 0)
- goto error;
-
- if (xenDaemonParseSxprNets(def, root) < 0)
- goto error;
-
- if (xenDaemonParseSxprPCI(def, root) < 0)
- goto error;
-
- /* New style graphics device config */
- if (xenDaemonParseSxprGraphicsNew(conn, def, root) < 0)
- goto error;
-
- /* Graphics device (HVM <= 3.0.4, or PV <= 3.0.3) vnc config */
- if ((def->ngraphics == 0) &&
- xenDaemonParseSxprGraphicsOld(conn, def, root, hvm, xendConfigVersion) < 0)
- goto error;
-
-
- /* Old style cdrom config from Xen <= 3.0.2 */
- if (hvm &&
- xendConfigVersion == 1) {
- tmp = sexpr_node(root, "domain/image/hvm/cdrom");
- if ((tmp != NULL) && (tmp[0] != 0)) {
- virDomainDiskDefPtr disk;
- if (VIR_ALLOC(disk) < 0)
- goto no_memory;
- if (!(disk->src = strdup(tmp))) {
- virDomainDiskDefFree(disk);
- goto no_memory;
- }
- disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
- disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
- if (!(disk->dst = strdup("hdc"))) {
- virDomainDiskDefFree(disk);
- goto no_memory;
- }
- if (!(disk->driverName = strdup("file"))) {
- virDomainDiskDefFree(disk);
- goto no_memory;
- }
- disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
- disk->readonly = 1;
-
- if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0) {
- virDomainDiskDefFree(disk);
- goto no_memory;
- }
- def->disks[def->ndisks++] = disk;
- }
- }
-
-
- /* Floppy disk config */
- if (hvm) {
- const char *const fds[] = { "fda", "fdb" };
- int i;
- for (i = 0 ; i < ARRAY_CARDINALITY(fds) ; i++) {
- tmp = sexpr_fmt_node(root, "domain/image/hvm/%s", fds[i]);
- if ((tmp != NULL) && (tmp[0] != 0)) {
- virDomainDiskDefPtr disk;
- if (VIR_ALLOC(disk) < 0)
- goto no_memory;
- if (!(disk->src = strdup(tmp))) {
- VIR_FREE(disk);
- goto no_memory;
- }
- disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
- disk->device = VIR_DOMAIN_DISK_DEVICE_FLOPPY;
- if (!(disk->dst = strdup(fds[i]))) {
- virDomainDiskDefFree(disk);
- goto no_memory;
- }
- if (!(disk->driverName = strdup("file"))) {
- virDomainDiskDefFree(disk);
- goto no_memory;
- }
- disk->bus = VIR_DOMAIN_DISK_BUS_FDC;
-
- if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0) {
- virDomainDiskDefFree(disk);
- goto no_memory;
- }
- def->disks[def->ndisks++] = disk;
- }
- }
- }
-
- /* in case of HVM we have USB device emulation */
- if (hvm &&
- xenDaemonParseSxprUSB(def, root) < 0)
- goto error;
-
- /* Character device config */
- xenUnifiedLock(priv);
- tty = xenStoreDomainGetConsolePath(conn, def->id);
- xenUnifiedUnlock(priv);
- if (hvm) {
- tmp = sexpr_node(root, "domain/image/hvm/serial");
- if (tmp && STRNEQ(tmp, "none")) {
- virDomainChrDefPtr chr;
- if ((chr = xenDaemonParseSxprChar(tmp, tty)) == NULL)
- goto error;
- if (VIR_REALLOC_N(def->serials, def->nserials+1) < 0) {
- virDomainChrDefFree(chr);
- goto no_memory;
- }
- chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL;
- def->serials[def->nserials++] = chr;
- }
- tmp = sexpr_node(root, "domain/image/hvm/parallel");
- if (tmp && STRNEQ(tmp, "none")) {
- virDomainChrDefPtr chr;
- /* XXX does XenD stuff parallel port tty info into xenstore somewhere ? */
- if ((chr = xenDaemonParseSxprChar(tmp, NULL)) == NULL)
- goto error;
- if (VIR_REALLOC_N(def->parallels, def->nparallels+1) < 0) {
- virDomainChrDefFree(chr);
- goto no_memory;
- }
- chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL;
- def->parallels[def->nparallels++] = chr;
- }
- } else {
- /* Fake a paravirt console, since that's not in the sexpr */
- if (!(def->console = xenDaemonParseSxprChar("pty", tty)))
- goto error;
- def->console->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE;
- def->console->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_XEN;
- }
- VIR_FREE(tty);
-
-
- /* Sound device config */
- if (hvm &&
- (tmp = sexpr_node(root, "domain/image/hvm/soundhw")) != NULL &&
- *tmp) {
- if (xenDaemonParseSxprSound(def, tmp) < 0)
- goto error;
- }
-
- return def;
-
-no_memory:
- virReportOOMError();
-error:
- VIR_FREE(tty);
- virDomainDefFree(def);
- return NULL;
-}
-
-virDomainDefPtr
-xenDaemonParseSxprString(virConnectPtr conn,
- const char *sexpr,
- int xendConfigVersion)
-{
- struct sexpr *root = string2sexpr(sexpr);
- virDomainDefPtr def;
-
- if (!root)
- return NULL;
-
- def = xenDaemonParseSxpr(conn, root, xendConfigVersion, NULL);
-
- sexpr_free(root);
-
- return def;
-}
-
-
/**
* sexpr_to_xend_domain_info:
* @root: an S-Expression describing a domain
@@ -3098,6 +1798,9 @@ xenDaemonDomainFetch(virConnectPtr conn,
struct sexpr *root;
xenUnifiedPrivatePtr priv;
virDomainDefPtr def;
+ int id;
+ char * tty;
+ int vncport;
if (name)
root = sexpr_get(conn, "/xend/domain/%s?detail=1", name);
@@ -3112,10 +1815,16 @@ xenDaemonDomainFetch(virConnectPtr conn,
priv = (xenUnifiedPrivatePtr) conn->privateData;
- if (!(def = xenDaemonParseSxpr(conn,
- root,
+ id = xenGetDomIdFromSxpr(root, priv->xendConfigVersion);
+ xenUnifiedLock(priv);
+ tty = xenStoreDomainGetConsolePath(conn, id);
+ vncport = xenStoreDomainGetVNCPort(conn, id);
+ xenUnifiedUnlock(priv);
+ if (!(def = xenDaemonParseSxpr(root,
priv->xendConfigVersion,
- cpus)))
+ cpus,
+ tty,
+ vncport)))
goto cleanup;
cleanup:
@@ -5043,6 +3752,9 @@ xenDaemonDomainBlockPeek (virDomainPtr domain, const char *path,
int fd = -1, ret = -1;
int found = 0, i;
virDomainDefPtr def;
+ int id;
+ char * tty;
+ int vncport;
priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
@@ -5068,7 +3780,14 @@ xenDaemonDomainBlockPeek (virDomainPtr domain, const char *path,
return -1;
}
- if (!(def = xenDaemonParseSxpr(domain->conn, root, priv->xendConfigVersion, NULL)))
+ id = xenGetDomIdFromSxpr(root, priv->xendConfigVersion);
+ xenUnifiedLock(priv);
+ tty = xenStoreDomainGetConsolePath(domain->conn, id);
+ vncport = xenStoreDomainGetVNCPort(domain->conn, id);
+ xenUnifiedUnlock(priv);
+
+ if (!(def = xenDaemonParseSxpr(root, priv->xendConfigVersion, NULL, tty,
+ vncport)))
goto cleanup;
for (i = 0 ; i < def->ndisks ; i++) {
diff --git a/src/xen/xend_internal.h b/src/xen/xend_internal.h
index 53f5d2c0be813883c684c967261f681ac68e2b29..8603a082ffe973667cf50c77c741b9788db84220 100644
--- a/src/xen/xend_internal.h
+++ b/src/xen/xend_internal.h
@@ -27,12 +27,6 @@
# include "driver.h"
# include "buf.h"
-# ifdef __sun
-# define DEFAULT_VIF_SCRIPT "vif-vnic"
-# else
-# define DEFAULT_VIF_SCRIPT "vif-bridge"
-# endif
-
int
xenDaemonOpen_unix(virConnectPtr conn, const char *path);
@@ -96,18 +90,6 @@ xenDaemonDomainFetch(virConnectPtr xend,
const char *name,
const char *cpus);
-virDomainDefPtr
-xenDaemonParseSxprString(virConnectPtr conn,
- const char *sexpr,
- int xendConfigVersion);
-
-int
-xenDaemonParseSxprSound(virDomainDefPtr def,
- const char *str);
-
-virDomainChrDefPtr
-xenDaemonParseSxprChar(const char *value,
- const char *tty);
int
xenDaemonFormatSxprChr(virDomainChrDefPtr def,
diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c
index bc304f077a284071b03eeda591df0151cb7dd146..ba30ffb9e818d4730d452978f496cf0e988ce0be 100644
--- a/src/xen/xm_internal.c
+++ b/src/xen/xm_internal.c
@@ -40,6 +40,7 @@
#include "xm_internal.h"
#include "xen_driver.h"
#include "xend_internal.h"
+#include "xen_sxpr.h"
#include "hash.h"
#include "buf.h"
#include "uuid.h"
diff --git a/src/xenxs/xen_sxpr.c b/src/xenxs/xen_sxpr.c
new file mode 100644
index 0000000000000000000000000000000000000000..edd0fb41b9fb1cf74a73dc0afef4676d61aa495d
--- /dev/null
+++ b/src/xenxs/xen_sxpr.c
@@ -0,0 +1,1351 @@
+/*
+ * xen_sxpr.c: Xen SEXPR parsing functions
+ *
+ * Copyright (C) 2011 Univention GmbH
+ * Copyright (C) 2010-2011 Red Hat, Inc.
+ * Copyright (C) 2005 Anthony Liguori
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Anthony Liguori
+ * Author: Daniel Veillard
+ * Author: Markus Groß
+ */
+
+#include
+
+#include "internal.h"
+#include "virterror_internal.h"
+#include "conf.h"
+#include "memory.h"
+#include "verify.h"
+#include "uuid.h"
+#include "logging.h"
+#include "count-one-bits.h"
+#include "xenxs_private.h"
+#include "xen_sxpr.h"
+
+/* Get a domain id from a sexpr string */
+int xenGetDomIdFromSxprString(const char *sexpr, int xendConfigVersion)
+{
+ struct sexpr *root = string2sexpr(sexpr);
+
+ if (!root)
+ return -1;
+
+ int id = xenGetDomIdFromSxpr(root, xendConfigVersion);
+ sexpr_free(root);
+ return id;
+}
+
+/* Get a domain id from a sexpr */
+int xenGetDomIdFromSxpr(const struct sexpr *root, int xendConfigVersion)
+{
+ int id = -1;
+ const char * tmp = sexpr_node(root, "domain/domid");
+ if (tmp == NULL && xendConfigVersion < 3) { /* Old XenD, domid was mandatory */
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("domain information incomplete, missing id"));
+ } else {
+ id = tmp ? sexpr_int(root, "domain/domid") : -1;
+ }
+ return id;
+}
+
+/*****************************************************************
+ ******
+ ****** Parsing of SEXPR into virDomainDef objects
+ ******
+ *****************************************************************/
+
+/**
+ * xenDaemonParseSxprOS
+ * @node: the root of the parsed S-Expression
+ * @def: the domain config
+ * @hvm: true or 1 if no contains HVM S-Expression
+ * @bootloader: true or 1 if a bootloader is defined
+ *
+ * Parse the xend sexp for description of os and append it to buf.
+ *
+ * Returns 0 in case of success and -1 in case of error
+ */
+static int
+xenDaemonParseSxprOS(const struct sexpr *node,
+ virDomainDefPtr def,
+ int hvm)
+{
+ if (hvm) {
+ if (sexpr_node_copy(node, "domain/image/hvm/loader", &def->os.loader) < 0)
+ goto no_memory;
+ if (def->os.loader == NULL) {
+ if (sexpr_node_copy(node, "domain/image/hvm/kernel", &def->os.loader) < 0)
+ goto no_memory;
+
+ if (def->os.loader == NULL) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("domain information incomplete, missing HVM loader"));
+ return(-1);
+ }
+ } else {
+ if (sexpr_node_copy(node, "domain/image/hvm/kernel", &def->os.kernel) < 0)
+ goto no_memory;
+ if (sexpr_node_copy(node, "domain/image/hvm/ramdisk", &def->os.initrd) < 0)
+ goto no_memory;
+ if (sexpr_node_copy(node, "domain/image/hvm/args", &def->os.cmdline) < 0)
+ goto no_memory;
+ if (sexpr_node_copy(node, "domain/image/hvm/root", &def->os.root) < 0)
+ goto no_memory;
+ }
+ } else {
+ if (sexpr_node_copy(node, "domain/image/linux/kernel", &def->os.kernel) < 0)
+ goto no_memory;
+ if (sexpr_node_copy(node, "domain/image/linux/ramdisk", &def->os.initrd) < 0)
+ goto no_memory;
+ if (sexpr_node_copy(node, "domain/image/linux/args", &def->os.cmdline) < 0)
+ goto no_memory;
+ if (sexpr_node_copy(node, "domain/image/linux/root", &def->os.root) < 0)
+ goto no_memory;
+ }
+
+ /* If HVM kenrel == loader, then old xend, so kill off kernel */
+ if (hvm &&
+ def->os.kernel &&
+ STREQ(def->os.kernel, def->os.loader)) {
+ VIR_FREE(def->os.kernel);
+ }
+
+ if (!def->os.kernel &&
+ hvm) {
+ const char *boot = sexpr_node(node, "domain/image/hvm/boot");
+ if ((boot != NULL) && (boot[0] != 0)) {
+ while (*boot &&
+ def->os.nBootDevs < VIR_DOMAIN_BOOT_LAST) {
+ if (*boot == 'a')
+ def->os.bootDevs[def->os.nBootDevs++] = VIR_DOMAIN_BOOT_FLOPPY;
+ else if (*boot == 'c')
+ def->os.bootDevs[def->os.nBootDevs++] = VIR_DOMAIN_BOOT_DISK;
+ else if (*boot == 'd')
+ def->os.bootDevs[def->os.nBootDevs++] = VIR_DOMAIN_BOOT_CDROM;
+ else if (*boot == 'n')
+ def->os.bootDevs[def->os.nBootDevs++] = VIR_DOMAIN_BOOT_NET;
+ boot++;
+ }
+ }
+ }
+
+ if (!hvm &&
+ !def->os.kernel &&
+ !def->os.bootloader) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("domain information incomplete, missing kernel & bootloader"));
+ return -1;
+ }
+
+ return 0;
+
+no_memory:
+ virReportOOMError();
+ return -1;
+}
+
+virDomainChrDefPtr
+xenDaemonParseSxprChar(const char *value,
+ const char *tty)
+{
+ const char *prefix;
+ char *tmp;
+ virDomainChrDefPtr def;
+
+ if (VIR_ALLOC(def) < 0) {
+ virReportOOMError();
+ return NULL;
+ }
+
+ prefix = value;
+
+ if (value[0] == '/') {
+ def->source.type = VIR_DOMAIN_CHR_TYPE_DEV;
+ } 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) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("unknown chr device type '%s'"), prefix);
+ goto error;
+ }
+ }
+ }
+
+ /* Compat with legacy syntax */
+ switch (def->source.type) {
+ case VIR_DOMAIN_CHR_TYPE_PTY:
+ if (tty != NULL &&
+ !(def->source.data.file.path = strdup(tty)))
+ goto no_memory;
+ break;
+
+ case VIR_DOMAIN_CHR_TYPE_FILE:
+ case VIR_DOMAIN_CHR_TYPE_PIPE:
+ if (!(def->source.data.file.path = strdup(value)))
+ goto no_memory;
+ break;
+
+ case VIR_DOMAIN_CHR_TYPE_TCP:
+ {
+ const char *offset = strchr(value, ':');
+ const char *offset2;
+
+ if (offset == NULL) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("malformed char device string"));
+ goto error;
+ }
+
+ if (offset != value &&
+ (def->source.data.tcp.host = strndup(value,
+ offset - value)) == NULL)
+ goto no_memory;
+
+ offset2 = strchr(offset, ',');
+ if (offset2 == NULL)
+ def->source.data.tcp.service = strdup(offset+1);
+ else
+ def->source.data.tcp.service = strndup(offset+1,
+ offset2-(offset+1));
+ if (def->source.data.tcp.service == NULL)
+ goto no_memory;
+
+ 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) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("malformed char device string"));
+ goto error;
+ }
+
+ if (offset != value &&
+ (def->source.data.udp.connectHost
+ = strndup(value, offset - value)) == NULL)
+ goto no_memory;
+
+ offset2 = strchr(offset, '@');
+ if (offset2 != NULL) {
+ if ((def->source.data.udp.connectService
+ = strndup(offset + 1, offset2-(offset+1))) == NULL)
+ goto no_memory;
+
+ offset3 = strchr(offset2, ':');
+ if (offset3 == NULL) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("malformed char device string"));
+ goto error;
+ }
+
+ if (offset3 > (offset2 + 1) &&
+ (def->source.data.udp.bindHost
+ = strndup(offset2 + 1, offset3 - (offset2+1))) == NULL)
+ goto no_memory;
+
+ if ((def->source.data.udp.bindService
+ = strdup(offset3 + 1)) == NULL)
+ goto no_memory;
+ } else {
+ if ((def->source.data.udp.connectService
+ = strdup(offset + 1)) == NULL)
+ goto no_memory;
+ }
+ }
+ break;
+
+ case VIR_DOMAIN_CHR_TYPE_UNIX:
+ {
+ const char *offset = strchr(value, ',');
+ if (offset)
+ def->source.data.nix.path = strndup(value, (offset - value));
+ else
+ def->source.data.nix.path = strdup(value);
+ if (def->source.data.nix.path == NULL)
+ goto no_memory;
+
+ if (offset != NULL &&
+ strstr(offset, ",server") != NULL)
+ def->source.data.nix.listen = true;
+ }
+ break;
+ }
+
+ return def;
+
+no_memory:
+ virReportOOMError();
+error:
+ virDomainChrDefFree(def);
+ return NULL;
+}
+
+/**
+ * xend_parse_sexp_desc_disks
+ * @conn: connection
+ * @root: root sexpr
+ * @xendConfigVersion: version of xend
+ *
+ * This parses out block devices from the domain sexpr
+ *
+ * Returns 0 if successful or -1 if failed.
+ */
+static int
+xenDaemonParseSxprDisks(virDomainDefPtr def,
+ const struct sexpr *root,
+ int hvm,
+ int xendConfigVersion)
+{
+ const struct sexpr *cur, *node;
+ virDomainDiskDefPtr disk = NULL;
+
+ for (cur = root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
+ node = cur->u.s.car;
+ /* Normally disks are in a (device (vbd ...)) block
+ but blktap disks ended up in a differently named
+ (device (tap ....)) block.... */
+ if (sexpr_lookup(node, "device/vbd") ||
+ sexpr_lookup(node, "device/tap") ||
+ sexpr_lookup(node, "device/tap2")) {
+ char *offset;
+ const char *src = NULL;
+ const char *dst = NULL;
+ const char *mode = NULL;
+
+ /* Again dealing with (vbd...) vs (tap ...) differences */
+ if (sexpr_lookup(node, "device/vbd")) {
+ src = sexpr_node(node, "device/vbd/uname");
+ dst = sexpr_node(node, "device/vbd/dev");
+ mode = sexpr_node(node, "device/vbd/mode");
+ } else if (sexpr_lookup(node, "device/tap2")) {
+ src = sexpr_node(node, "device/tap2/uname");
+ dst = sexpr_node(node, "device/tap2/dev");
+ mode = sexpr_node(node, "device/tap2/mode");
+ } else {
+ src = sexpr_node(node, "device/tap/uname");
+ dst = sexpr_node(node, "device/tap/dev");
+ mode = sexpr_node(node, "device/tap/mode");
+ }
+
+ if (VIR_ALLOC(disk) < 0)
+ goto no_memory;
+
+ if (dst == NULL) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("domain information incomplete, vbd has no dev"));
+ goto error;
+ }
+
+ if (src == NULL) {
+ /* There is a case without the uname to the CD-ROM device */
+ offset = strchr(dst, ':');
+ if (!offset ||
+ !hvm ||
+ STRNEQ(offset, ":cdrom")) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("domain information incomplete, vbd has no src"));
+ goto error;
+ }
+ }
+
+ if (src != NULL) {
+ offset = strchr(src, ':');
+ if (!offset) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("cannot parse vbd filename, missing driver name"));
+ goto error;
+ }
+
+ if (VIR_ALLOC_N(disk->driverName, (offset-src)+1) < 0)
+ goto no_memory;
+ if (virStrncpy(disk->driverName, src, offset-src,
+ (offset-src)+1) == NULL) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Driver name %s too big for destination"),
+ src);
+ goto error;
+ }
+
+ src = offset + 1;
+
+ if (STREQ (disk->driverName, "tap") ||
+ STREQ (disk->driverName, "tap2")) {
+ offset = strchr(src, ':');
+ if (!offset) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("cannot parse vbd filename, missing driver type"));
+ goto error;
+ }
+
+ if (VIR_ALLOC_N(disk->driverType, (offset-src)+1)< 0)
+ goto no_memory;
+ if (virStrncpy(disk->driverType, src, offset-src,
+ (offset-src)+1) == NULL) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Driver type %s too big for destination"),
+ src);
+ goto error;
+ }
+
+ src = offset + 1;
+ /* Its possible to use blktap driver for block devs
+ too, but kinda pointless because blkback is better,
+ so we assume common case here. If blktap becomes
+ omnipotent, we can revisit this, perhaps stat()'ing
+ the src file in question */
+ disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
+ } else if (STREQ(disk->driverName, "phy")) {
+ disk->type = VIR_DOMAIN_DISK_TYPE_BLOCK;
+ } else if (STREQ(disk->driverName, "file")) {
+ disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
+ }
+ } else {
+ /* No CDROM media so can't really tell. We'll just
+ call if a FILE for now and update when media
+ is inserted later */
+ disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
+ }
+
+ if (STREQLEN (dst, "ioemu:", 6))
+ dst += 6;
+
+ disk->device = VIR_DOMAIN_DISK_DEVICE_DISK;
+ /* New style disk config from Xen >= 3.0.3 */
+ if (xendConfigVersion > 1) {
+ offset = strrchr(dst, ':');
+ if (offset) {
+ if (STREQ (offset, ":cdrom")) {
+ disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
+ } else if (STREQ (offset, ":disk")) {
+ /* The default anyway */
+ } else {
+ /* Unknown, lets pretend its a disk too */
+ }
+ offset[0] = '\0';
+ }
+ }
+
+ if (!(disk->dst = strdup(dst)))
+ goto no_memory;
+ if (src &&
+ !(disk->src = strdup(src)))
+ goto no_memory;
+
+ if (STRPREFIX(disk->dst, "xvd"))
+ disk->bus = VIR_DOMAIN_DISK_BUS_XEN;
+ else if (STRPREFIX(disk->dst, "hd"))
+ disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
+ else if (STRPREFIX(disk->dst, "sd"))
+ disk->bus = VIR_DOMAIN_DISK_BUS_SCSI;
+ else
+ disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
+
+ if (mode &&
+ strchr(mode, 'r'))
+ disk->readonly = 1;
+ if (mode &&
+ strchr(mode, '!'))
+ disk->shared = 1;
+
+ if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0)
+ goto no_memory;
+
+ def->disks[def->ndisks++] = disk;
+ disk = NULL;
+ }
+ }
+
+ return 0;
+
+no_memory:
+ virReportOOMError();
+
+error:
+ virDomainDiskDefFree(disk);
+ return -1;
+}
+
+
+static int
+xenDaemonParseSxprNets(virDomainDefPtr def,
+ const struct sexpr *root)
+{
+ virDomainNetDefPtr net = NULL;
+ const struct sexpr *cur, *node;
+ const char *tmp;
+ int vif_index = 0;
+
+ for (cur = root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
+ node = cur->u.s.car;
+ if (sexpr_lookup(node, "device/vif")) {
+ const char *tmp2, *model, *type;
+ char buf[50];
+ tmp2 = sexpr_node(node, "device/vif/script");
+ tmp = sexpr_node(node, "device/vif/bridge");
+ model = sexpr_node(node, "device/vif/model");
+ type = sexpr_node(node, "device/vif/type");
+
+ if (VIR_ALLOC(net) < 0)
+ goto no_memory;
+
+ if (tmp != NULL ||
+ (tmp2 != NULL && STREQ(tmp2, DEFAULT_VIF_SCRIPT))) {
+ net->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
+ /* XXX virtual network reverse resolve */
+
+ if (tmp &&
+ !(net->data.bridge.brname = strdup(tmp)))
+ goto no_memory;
+ if (tmp2 &&
+ net->type == VIR_DOMAIN_NET_TYPE_BRIDGE &&
+ !(net->data.bridge.script = strdup(tmp2)))
+ goto no_memory;
+ tmp = sexpr_node(node, "device/vif/ip");
+ if (tmp &&
+ !(net->data.bridge.ipaddr = strdup(tmp)))
+ goto no_memory;
+ } else {
+ net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
+ if (tmp2 &&
+ !(net->data.ethernet.script = strdup(tmp2)))
+ goto no_memory;
+ tmp = sexpr_node(node, "device/vif/ip");
+ if (tmp &&
+ !(net->data.ethernet.ipaddr = strdup(tmp)))
+ goto no_memory;
+ }
+
+ tmp = sexpr_node(node, "device/vif/vifname");
+ if (!tmp) {
+ snprintf(buf, sizeof(buf), "vif%d.%d", def->id, vif_index);
+ tmp = buf;
+ }
+ if (!(net->ifname = strdup(tmp)))
+ goto no_memory;
+
+ tmp = sexpr_node(node, "device/vif/mac");
+ if (tmp) {
+ if (virParseMacAddr(tmp, net->mac) < 0) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("malformed mac address '%s'"), tmp);
+ goto cleanup;
+ }
+ }
+
+ if (model &&
+ !(net->model = strdup(model)))
+ goto no_memory;
+
+ if (!model && type &&
+ STREQ(type, "netfront") &&
+ !(net->model = strdup("netfront")))
+ goto no_memory;
+
+ if (VIR_REALLOC_N(def->nets, def->nnets + 1) < 0)
+ goto no_memory;
+
+ def->nets[def->nnets++] = net;
+ vif_index++;
+ }
+ }
+
+ return 0;
+
+no_memory:
+ virReportOOMError();
+cleanup:
+ virDomainNetDefFree(net);
+ return -1;
+}
+
+
+int
+xenDaemonParseSxprSound(virDomainDefPtr def,
+ const char *str)
+{
+ if (STREQ(str, "all")) {
+ int i;
+
+ /*
+ * Special compatability code for Xen with a bogus
+ * sound=all in config.
+ *
+ * NB delibrately, don't include all possible
+ * sound models anymore, just the 2 that were
+ * historically present in Xen's QEMU.
+ *
+ * ie just es1370 + sb16.
+ *
+ * Hence use of MODEL_ES1370 + 1, instead of MODEL_LAST
+ */
+
+ if (VIR_ALLOC_N(def->sounds,
+ VIR_DOMAIN_SOUND_MODEL_ES1370 + 1) < 0)
+ goto no_memory;
+
+
+ for (i = 0 ; i < (VIR_DOMAIN_SOUND_MODEL_ES1370 + 1) ; i++) {
+ virDomainSoundDefPtr sound;
+ if (VIR_ALLOC(sound) < 0)
+ goto no_memory;
+ sound->model = i;
+ def->sounds[def->nsounds++] = sound;
+ }
+ } else {
+ char model[10];
+ const char *offset = str, *offset2;
+
+ do {
+ int len;
+ virDomainSoundDefPtr sound;
+ offset2 = strchr(offset, ',');
+ if (offset2)
+ len = (offset2 - offset);
+ else
+ len = strlen(offset);
+ if (virStrncpy(model, offset, len, sizeof(model)) == NULL) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Sound model %s too big for destination"),
+ offset);
+ goto error;
+ }
+
+ if (VIR_ALLOC(sound) < 0)
+ goto no_memory;
+
+ if ((sound->model = virDomainSoundModelTypeFromString(model)) < 0) {
+ VIR_FREE(sound);
+ goto error;
+ }
+
+ if (VIR_REALLOC_N(def->sounds, def->nsounds+1) < 0) {
+ virDomainSoundDefFree(sound);
+ goto no_memory;
+ }
+
+ def->sounds[def->nsounds++] = sound;
+ offset = offset2 ? offset2 + 1 : NULL;
+ } while (offset);
+ }
+
+ return 0;
+
+no_memory:
+ virReportOOMError();
+error:
+ return -1;
+}
+
+
+static int
+xenDaemonParseSxprUSB(virDomainDefPtr def,
+ const struct sexpr *root)
+{
+ struct sexpr *cur, *node;
+ const char *tmp;
+
+ for (cur = sexpr_lookup(root, "domain/image/hvm"); cur && cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
+ node = cur->u.s.car;
+ if (sexpr_lookup(node, "usbdevice")) {
+ tmp = sexpr_node(node, "usbdevice");
+ if (tmp && *tmp) {
+ if (STREQ(tmp, "tablet") ||
+ STREQ(tmp, "mouse")) {
+ virDomainInputDefPtr input;
+ if (VIR_ALLOC(input) < 0)
+ goto no_memory;
+ input->bus = VIR_DOMAIN_INPUT_BUS_USB;
+ if (STREQ(tmp, "tablet"))
+ input->type = VIR_DOMAIN_INPUT_TYPE_TABLET;
+ else
+ input->type = VIR_DOMAIN_INPUT_TYPE_MOUSE;
+
+ if (VIR_REALLOC_N(def->inputs, def->ninputs+1) < 0) {
+ VIR_FREE(input);
+ goto no_memory;
+ }
+ def->inputs[def->ninputs++] = input;
+ } else {
+ /* XXX Handle other non-input USB devices later */
+ }
+ }
+ }
+ }
+ return 0;
+
+no_memory:
+ virReportOOMError();
+ return -1;
+}
+
+static int
+xenDaemonParseSxprGraphicsOld(virDomainDefPtr def,
+ const struct sexpr *root,
+ int hvm,
+ int xendConfigVersion, int vncport)
+{
+ const char *tmp;
+ virDomainGraphicsDefPtr graphics = NULL;
+
+ if ((tmp = sexpr_fmt_node(root, "domain/image/%s/vnc", hvm ? "hvm" : "linux")) &&
+ tmp[0] == '1') {
+ /* Graphics device (HVM, or old (pre-3.0.4) style PV VNC config) */
+ int port;
+ const char *listenAddr = sexpr_fmt_node(root, "domain/image/%s/vnclisten", hvm ? "hvm" : "linux");
+ const char *vncPasswd = sexpr_fmt_node(root, "domain/image/%s/vncpasswd", hvm ? "hvm" : "linux");
+ const char *keymap = sexpr_fmt_node(root, "domain/image/%s/keymap", hvm ? "hvm" : "linux");
+ const char *unused = sexpr_fmt_node(root, "domain/image/%s/vncunused", hvm ? "hvm" : "linux");
+
+ port = vncport;
+
+ if (VIR_ALLOC(graphics) < 0)
+ goto no_memory;
+
+ graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_VNC;
+ /* For Xen >= 3.0.3, don't generate a fixed port mapping
+ * because it will almost certainly be wrong ! Just leave
+ * it as -1 which lets caller see that the VNC server isn't
+ * present yet. Subsquent dumps of the XML will eventually
+ * find the port in XenStore once VNC server has started
+ */
+ if (port == -1 && xendConfigVersion < 2)
+ port = 5900 + def->id;
+
+ if ((unused && STREQ(unused, "1")) || port == -1)
+ graphics->data.vnc.autoport = 1;
+ graphics->data.vnc.port = port;
+
+ if (listenAddr &&
+ !(graphics->data.vnc.listenAddr = strdup(listenAddr)))
+ goto no_memory;
+
+ if (vncPasswd &&
+ !(graphics->data.vnc.auth.passwd = strdup(vncPasswd)))
+ goto no_memory;
+
+ if (keymap &&
+ !(graphics->data.vnc.keymap = strdup(keymap)))
+ goto no_memory;
+
+ if (VIR_ALLOC_N(def->graphics, 1) < 0)
+ goto no_memory;
+ def->graphics[0] = graphics;
+ def->ngraphics = 1;
+ graphics = NULL;
+ } else if ((tmp = sexpr_fmt_node(root, "domain/image/%s/sdl", hvm ? "hvm" : "linux")) &&
+ tmp[0] == '1') {
+ /* Graphics device (HVM, or old (pre-3.0.4) style PV sdl config) */
+ const char *display = sexpr_fmt_node(root, "domain/image/%s/display", hvm ? "hvm" : "linux");
+ const char *xauth = sexpr_fmt_node(root, "domain/image/%s/xauthority", hvm ? "hvm" : "linux");
+
+ if (VIR_ALLOC(graphics) < 0)
+ goto no_memory;
+
+ graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_SDL;
+ if (display &&
+ !(graphics->data.sdl.display = strdup(display)))
+ goto no_memory;
+ if (xauth &&
+ !(graphics->data.sdl.xauth = strdup(xauth)))
+ goto no_memory;
+
+ if (VIR_ALLOC_N(def->graphics, 1) < 0)
+ goto no_memory;
+ def->graphics[0] = graphics;
+ def->ngraphics = 1;
+ graphics = NULL;
+ }
+
+ return 0;
+
+no_memory:
+ virReportOOMError();
+ virDomainGraphicsDefFree(graphics);
+ return -1;
+}
+
+
+static int
+xenDaemonParseSxprGraphicsNew(virDomainDefPtr def,
+ const struct sexpr *root, int vncport)
+{
+ virDomainGraphicsDefPtr graphics = NULL;
+ const struct sexpr *cur, *node;
+ const char *tmp;
+
+ /* append network devices and framebuffer */
+ for (cur = root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
+ node = cur->u.s.car;
+ if (sexpr_lookup(node, "device/vfb")) {
+ /* New style graphics config for PV guests in >= 3.0.4,
+ * or for HVM guests in >= 3.0.5 */
+ if (sexpr_node(node, "device/vfb/type")) {
+ tmp = sexpr_node(node, "device/vfb/type");
+ } else if (sexpr_node(node, "device/vfb/vnc")) {
+ tmp = "vnc";
+ } else if (sexpr_node(node, "device/vfb/sdl")) {
+ tmp = "sdl";
+ } else {
+ tmp = "unknown";
+ }
+
+ if (VIR_ALLOC(graphics) < 0)
+ goto no_memory;
+
+ if ((graphics->type = virDomainGraphicsTypeFromString(tmp)) < 0) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("unknown graphics type '%s'"), tmp);
+ goto error;
+ }
+
+ if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
+ const char *display = sexpr_node(node, "device/vfb/display");
+ const char *xauth = sexpr_node(node, "device/vfb/xauthority");
+ if (display &&
+ !(graphics->data.sdl.display = strdup(display)))
+ goto no_memory;
+ if (xauth &&
+ !(graphics->data.sdl.xauth = strdup(xauth)))
+ goto no_memory;
+ } else {
+ int port;
+ const char *listenAddr = sexpr_node(node, "device/vfb/vnclisten");
+ const char *vncPasswd = sexpr_node(node, "device/vfb/vncpasswd");
+ const char *keymap = sexpr_node(node, "device/vfb/keymap");
+ const char *unused = sexpr_node(node, "device/vfb/vncunused");
+
+ port = vncport;
+
+ /* Didn't find port entry in xenstore */
+ if (port == -1) {
+ const char *str = sexpr_node(node, "device/vfb/vncdisplay");
+ int val;
+ if (str != NULL && virStrToLong_i(str, NULL, 0, &val) == 0)
+ port = val;
+ }
+
+ if ((unused && STREQ(unused, "1")) || port == -1)
+ graphics->data.vnc.autoport = 1;
+
+ if (port >= 0 && port < 5900)
+ port += 5900;
+ graphics->data.vnc.port = port;
+
+ if (listenAddr &&
+ !(graphics->data.vnc.listenAddr = strdup(listenAddr)))
+ goto no_memory;
+
+ if (vncPasswd &&
+ !(graphics->data.vnc.auth.passwd = strdup(vncPasswd)))
+ goto no_memory;
+
+ if (keymap &&
+ !(graphics->data.vnc.keymap = strdup(keymap)))
+ goto no_memory;
+ }
+
+ if (VIR_ALLOC_N(def->graphics, 1) < 0)
+ goto no_memory;
+ def->graphics[0] = graphics;
+ def->ngraphics = 1;
+ graphics = NULL;
+ break;
+ }
+ }
+
+ return 0;
+
+no_memory:
+ virReportOOMError();
+error:
+ virDomainGraphicsDefFree(graphics);
+ return -1;
+}
+
+/**
+ * xenDaemonParseSxprPCI
+ * @root: root sexpr
+ *
+ * This parses out block devices from the domain sexpr
+ *
+ * Returns 0 if successful or -1 if failed.
+ */
+static int
+xenDaemonParseSxprPCI(virDomainDefPtr def,
+ const struct sexpr *root)
+{
+ const struct sexpr *cur, *tmp = NULL, *node;
+ virDomainHostdevDefPtr dev = NULL;
+
+ /*
+ * With the (domain ...) block we have the following odd setup
+ *
+ * (device
+ * (pci
+ * (dev (domain 0x0000) (bus 0x00) (slot 0x1b) (func 0x0))
+ * (dev (domain 0x0000) (bus 0x00) (slot 0x13) (func 0x0))
+ * )
+ * )
+ *
+ * Normally there is one (device ...) block per device, but in
+ * wierd world of Xen PCI, once (device ...) covers multiple
+ * devices.
+ */
+
+ for (cur = root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
+ node = cur->u.s.car;
+ if ((tmp = sexpr_lookup(node, "device/pci")) != NULL)
+ break;
+ }
+
+ if (!tmp)
+ return 0;
+
+ for (cur = tmp; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
+ const char *domain = NULL;
+ const char *bus = NULL;
+ const char *slot = NULL;
+ const char *func = NULL;
+ int domainID;
+ int busID;
+ int slotID;
+ int funcID;
+
+ node = cur->u.s.car;
+ if (!sexpr_lookup(node, "dev"))
+ continue;
+
+ if (!(domain = sexpr_node(node, "dev/domain"))) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("missing PCI domain"));
+ goto error;
+ }
+ if (!(bus = sexpr_node(node, "dev/bus"))) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("missing PCI bus"));
+ goto error;
+ }
+ if (!(slot = sexpr_node(node, "dev/slot"))) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("missing PCI slot"));
+ goto error;
+ }
+ if (!(func = sexpr_node(node, "dev/func"))) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("missing PCI func"));
+ goto error;
+ }
+
+ if (virStrToLong_i(domain, NULL, 0, &domainID) < 0) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("cannot parse PCI domain '%s'"), domain);
+ goto error;
+ }
+ if (virStrToLong_i(bus, NULL, 0, &busID) < 0) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("cannot parse PCI bus '%s'"), bus);
+ goto error;
+ }
+ if (virStrToLong_i(slot, NULL, 0, &slotID) < 0) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("cannot parse PCI slot '%s'"), slot);
+ goto error;
+ }
+ if (virStrToLong_i(func, NULL, 0, &funcID) < 0) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("cannot parse PCI func '%s'"), func);
+ goto error;
+ }
+
+ if (VIR_ALLOC(dev) < 0)
+ goto no_memory;
+
+ dev->mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS;
+ dev->managed = 0;
+ dev->source.subsys.type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI;
+ dev->source.subsys.u.pci.domain = domainID;
+ dev->source.subsys.u.pci.bus = busID;
+ dev->source.subsys.u.pci.slot = slotID;
+ dev->source.subsys.u.pci.function = funcID;
+
+ if (VIR_REALLOC_N(def->hostdevs, def->nhostdevs+1) < 0) {
+ goto no_memory;
+ }
+
+ def->hostdevs[def->nhostdevs++] = dev;
+ }
+
+ return 0;
+
+no_memory:
+ virReportOOMError();
+
+error:
+ virDomainHostdevDefFree(dev);
+ return -1;
+}
+
+
+/**
+ * xenDaemonParseSxpr:
+ * @conn: the connection associated with the XML
+ * @root: the root of the parsed S-Expression
+ * @xendConfigVersion: version of xend
+ * @cpus: set of cpus the domain may be pinned to
+ *
+ * Parse the xend sexp description and turn it into the XML format similar
+ * to the one unsed for creation.
+ *
+ * Returns the 0 terminated XML string or NULL in case of error.
+ * the caller must free() the returned value.
+ */
+virDomainDefPtr
+xenDaemonParseSxpr(const struct sexpr *root,
+ int xendConfigVersion,
+ const char *cpus, char *tty, int vncport)
+{
+ const char *tmp;
+ virDomainDefPtr def;
+ int hvm = 0;
+
+ if (VIR_ALLOC(def) < 0)
+ goto no_memory;
+
+ tmp = sexpr_node(root, "domain/domid");
+ if (tmp == NULL && xendConfigVersion < 3) { /* Old XenD, domid was mandatory */
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("domain information incomplete, missing id"));
+ goto error;
+ }
+ def->virtType = VIR_DOMAIN_VIRT_XEN;
+ if (tmp)
+ def->id = sexpr_int(root, "domain/domid");
+ else
+ def->id = -1;
+
+ if (sexpr_node_copy(root, "domain/name", &def->name) < 0)
+ goto no_memory;
+ if (def->name == NULL) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("domain information incomplete, missing name"));
+ goto error;
+ }
+
+ tmp = sexpr_node(root, "domain/uuid");
+ if (tmp == NULL) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("domain information incomplete, missing name"));
+ goto error;
+ }
+ virUUIDParse(tmp, def->uuid);
+
+ if (sexpr_node_copy(root, "domain/description", &def->description) < 0)
+ goto no_memory;
+
+ hvm = sexpr_lookup(root, "domain/image/hvm") ? 1 : 0;
+ if (!hvm) {
+ if (sexpr_node_copy(root, "domain/bootloader",
+ &def->os.bootloader) < 0)
+ goto no_memory;
+
+ if (!def->os.bootloader &&
+ sexpr_has(root, "domain/bootloader") &&
+ (def->os.bootloader = strdup("")) == NULL)
+ goto no_memory;
+
+ if (def->os.bootloader &&
+ sexpr_node_copy(root, "domain/bootloader_args",
+ &def->os.bootloaderArgs) < 0)
+ goto no_memory;
+ }
+
+ if (!(def->os.type = strdup(hvm ? "hvm" : "linux")))
+ goto no_memory;
+
+ if (def->id != 0) {
+ if (sexpr_lookup(root, "domain/image")) {
+ if (xenDaemonParseSxprOS(root, def, hvm) < 0)
+ goto error;
+ }
+ }
+
+ def->mem.max_balloon = (unsigned long)
+ (sexpr_u64(root, "domain/maxmem") << 10);
+ def->mem.cur_balloon = (unsigned long)
+ (sexpr_u64(root, "domain/memory") << 10);
+ if (def->mem.cur_balloon > def->mem.max_balloon)
+ def->mem.cur_balloon = def->mem.max_balloon;
+
+ if (cpus != NULL) {
+ def->cpumasklen = VIR_DOMAIN_CPUMASK_LEN;
+ if (VIR_ALLOC_N(def->cpumask, def->cpumasklen) < 0) {
+ virReportOOMError();
+ goto error;
+ }
+
+ if (virDomainCpuSetParse(&cpus,
+ 0, def->cpumask,
+ def->cpumasklen) < 0) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("invalid CPU mask %s"), cpus);
+ goto error;
+ }
+ }
+
+ def->maxvcpus = sexpr_int(root, "domain/vcpus");
+ def->vcpus = count_one_bits_l(sexpr_u64(root, "domain/vcpu_avail"));
+ if (!def->vcpus || def->maxvcpus < def->vcpus)
+ def->vcpus = def->maxvcpus;
+
+ tmp = sexpr_node(root, "domain/on_poweroff");
+ if (tmp != NULL) {
+ if ((def->onPoweroff = virDomainLifecycleTypeFromString(tmp)) < 0) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("unknown lifecycle type %s"), tmp);
+ goto error;
+ }
+ } else
+ def->onPoweroff = VIR_DOMAIN_LIFECYCLE_DESTROY;
+
+ tmp = sexpr_node(root, "domain/on_reboot");
+ if (tmp != NULL) {
+ if ((def->onReboot = virDomainLifecycleTypeFromString(tmp)) < 0) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("unknown lifecycle type %s"), tmp);
+ goto error;
+ }
+ } else
+ def->onReboot = VIR_DOMAIN_LIFECYCLE_RESTART;
+
+ tmp = sexpr_node(root, "domain/on_crash");
+ if (tmp != NULL) {
+ if ((def->onCrash = virDomainLifecycleCrashTypeFromString(tmp)) < 0) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("unknown lifecycle type %s"), tmp);
+ goto error;
+ }
+ } else
+ def->onCrash = VIR_DOMAIN_LIFECYCLE_DESTROY;
+
+ def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_UTC;
+ if (hvm) {
+ if (sexpr_int(root, "domain/image/hvm/acpi"))
+ def->features |= (1 << VIR_DOMAIN_FEATURE_ACPI);
+ if (sexpr_int(root, "domain/image/hvm/apic"))
+ def->features |= (1 << VIR_DOMAIN_FEATURE_APIC);
+ if (sexpr_int(root, "domain/image/hvm/pae"))
+ def->features |= (1 << VIR_DOMAIN_FEATURE_PAE);
+ if (sexpr_int(root, "domain/image/hvm/hap"))
+ def->features |= (1 << VIR_DOMAIN_FEATURE_HAP);
+
+ /* Old XenD only allows localtime here for HVM */
+ if (sexpr_int(root, "domain/image/hvm/localtime"))
+ def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME;
+ }
+
+ /* Current XenD allows localtime here, for PV and HVM */
+ if (sexpr_int(root, "domain/localtime"))
+ def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME;
+
+ if (sexpr_node_copy(root, hvm ?
+ "domain/image/hvm/device_model" :
+ "domain/image/linux/device_model",
+ &def->emulator) < 0)
+ goto no_memory;
+
+ /* append block devices */
+ if (xenDaemonParseSxprDisks(def, root, hvm, xendConfigVersion) < 0)
+ goto error;
+
+ if (xenDaemonParseSxprNets(def, root) < 0)
+ goto error;
+
+ if (xenDaemonParseSxprPCI(def, root) < 0)
+ goto error;
+
+ /* New style graphics device config */
+ if (xenDaemonParseSxprGraphicsNew(def, root, vncport) < 0)
+ goto error;
+
+ /* Graphics device (HVM <= 3.0.4, or PV <= 3.0.3) vnc config */
+ if ((def->ngraphics == 0) &&
+ xenDaemonParseSxprGraphicsOld(def, root, hvm, xendConfigVersion,
+ vncport) < 0)
+ goto error;
+
+
+ /* Old style cdrom config from Xen <= 3.0.2 */
+ if (hvm &&
+ xendConfigVersion == 1) {
+ tmp = sexpr_node(root, "domain/image/hvm/cdrom");
+ if ((tmp != NULL) && (tmp[0] != 0)) {
+ virDomainDiskDefPtr disk;
+ if (VIR_ALLOC(disk) < 0)
+ goto no_memory;
+ if (!(disk->src = strdup(tmp))) {
+ virDomainDiskDefFree(disk);
+ goto no_memory;
+ }
+ disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
+ disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
+ if (!(disk->dst = strdup("hdc"))) {
+ virDomainDiskDefFree(disk);
+ goto no_memory;
+ }
+ if (!(disk->driverName = strdup("file"))) {
+ virDomainDiskDefFree(disk);
+ goto no_memory;
+ }
+ disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
+ disk->readonly = 1;
+
+ if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0) {
+ virDomainDiskDefFree(disk);
+ goto no_memory;
+ }
+ def->disks[def->ndisks++] = disk;
+ }
+ }
+
+
+ /* Floppy disk config */
+ if (hvm) {
+ const char *const fds[] = { "fda", "fdb" };
+ int i;
+ for (i = 0 ; i < ARRAY_CARDINALITY(fds) ; i++) {
+ tmp = sexpr_fmt_node(root, "domain/image/hvm/%s", fds[i]);
+ if ((tmp != NULL) && (tmp[0] != 0)) {
+ virDomainDiskDefPtr disk;
+ if (VIR_ALLOC(disk) < 0)
+ goto no_memory;
+ if (!(disk->src = strdup(tmp))) {
+ VIR_FREE(disk);
+ goto no_memory;
+ }
+ disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
+ disk->device = VIR_DOMAIN_DISK_DEVICE_FLOPPY;
+ if (!(disk->dst = strdup(fds[i]))) {
+ virDomainDiskDefFree(disk);
+ goto no_memory;
+ }
+ if (!(disk->driverName = strdup("file"))) {
+ virDomainDiskDefFree(disk);
+ goto no_memory;
+ }
+ disk->bus = VIR_DOMAIN_DISK_BUS_FDC;
+
+ if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0) {
+ virDomainDiskDefFree(disk);
+ goto no_memory;
+ }
+ def->disks[def->ndisks++] = disk;
+ }
+ }
+ }
+
+ /* in case of HVM we have USB device emulation */
+ if (hvm &&
+ xenDaemonParseSxprUSB(def, root) < 0)
+ goto error;
+
+ /* Character device config */
+ if (hvm) {
+ tmp = sexpr_node(root, "domain/image/hvm/serial");
+ if (tmp && STRNEQ(tmp, "none")) {
+ virDomainChrDefPtr chr;
+ if ((chr = xenDaemonParseSxprChar(tmp, tty)) == NULL)
+ goto error;
+ if (VIR_REALLOC_N(def->serials, def->nserials+1) < 0) {
+ virDomainChrDefFree(chr);
+ goto no_memory;
+ }
+ chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL;
+ def->serials[def->nserials++] = chr;
+ }
+ tmp = sexpr_node(root, "domain/image/hvm/parallel");
+ if (tmp && STRNEQ(tmp, "none")) {
+ virDomainChrDefPtr chr;
+ /* XXX does XenD stuff parallel port tty info into xenstore somewhere ? */
+ if ((chr = xenDaemonParseSxprChar(tmp, NULL)) == NULL)
+ goto error;
+ if (VIR_REALLOC_N(def->parallels, def->nparallels+1) < 0) {
+ virDomainChrDefFree(chr);
+ goto no_memory;
+ }
+ chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL;
+ def->parallels[def->nparallels++] = chr;
+ }
+ } else {
+ /* Fake a paravirt console, since that's not in the sexpr */
+ if (!(def->console = xenDaemonParseSxprChar("pty", tty)))
+ goto error;
+ def->console->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE;
+ def->console->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_XEN;
+ }
+ VIR_FREE(tty);
+
+
+ /* Sound device config */
+ if (hvm &&
+ (tmp = sexpr_node(root, "domain/image/hvm/soundhw")) != NULL &&
+ *tmp) {
+ if (xenDaemonParseSxprSound(def, tmp) < 0)
+ goto error;
+ }
+
+ return def;
+
+no_memory:
+ virReportOOMError();
+error:
+ VIR_FREE(tty);
+ virDomainDefFree(def);
+ return NULL;
+}
+
+virDomainDefPtr
+xenDaemonParseSxprString(const char *sexpr,
+ int xendConfigVersion, char *tty, int vncport)
+{
+ struct sexpr *root = string2sexpr(sexpr);
+ virDomainDefPtr def;
+
+ if (!root)
+ return NULL;
+
+ def = xenDaemonParseSxpr(root, xendConfigVersion, NULL, tty, vncport);
+
+ sexpr_free(root);
+
+ return def;
+}
\ No newline at end of file
diff --git a/src/xenxs/xen_sxpr.h b/src/xenxs/xen_sxpr.h
new file mode 100644
index 0000000000000000000000000000000000000000..c0c6a53b51cedb121b0031c9a9a633851aac8613
--- /dev/null
+++ b/src/xenxs/xen_sxpr.h
@@ -0,0 +1,62 @@
+/*
+ * xen_sxpr.h: Xen SEXPR parsing functions
+ *
+ * Copyright (C) 2011 Univention GmbH
+ * Copyright (C) 2006-2008, 2010 Red Hat, Inc.
+ * Copyright (C) 2005,2006
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Anthony Liguori
+ * Author: Daniel Veillard
+ * Author: Markus Groß
+ */
+
+#ifndef __VIR_XEN_SXPR_H__
+# define __VIR_XEN_SXPR_H__
+
+# include "internal.h"
+# include "conf.h"
+# include "domain_conf.h"
+# include "sexpr.h"
+
+# ifdef __sun
+# define DEFAULT_VIF_SCRIPT "vif-vnic"
+# else
+# define DEFAULT_VIF_SCRIPT "vif-bridge"
+# endif
+
+/* helper functions to get the dom id from a sexpr */
+int xenGetDomIdFromSxprString(const char *sexpr, int xendConfigVersion);
+int xenGetDomIdFromSxpr(const struct sexpr *root, int xendConfigVersion);
+
+virDomainDefPtr
+xenDaemonParseSxprString(const char *sexpr,
+ int xendConfigVersion, char *tty, int vncport);
+
+virDomainDefPtr
+xenDaemonParseSxpr(const struct sexpr *root,
+ int xendConfigVersion,
+ const char *cpus, char *tty, int vncport);
+
+int
+xenDaemonParseSxprSound(virDomainDefPtr def,
+ const char *str);
+
+virDomainChrDefPtr
+xenDaemonParseSxprChar(const char *value,
+ const char *tty);
+
+#endif /* __VIR_XEN_SXPR_H__ */
diff --git a/src/xenxs/xenxs_private.h b/src/xenxs/xenxs_private.h
new file mode 100644
index 0000000000000000000000000000000000000000..1acabfbcd8c92b877e798f6319c89a6cecc59f50
--- /dev/null
+++ b/src/xenxs/xenxs_private.h
@@ -0,0 +1,37 @@
+/*
+ * xenxs_private.h: Private definitions for Xen parsing
+ *
+ * Copyright (C) 2011 Univention GmbH
+ * Copyright (C) 2007, 2010 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Richard W.M. Jones
+ * Author: Markus Groß
+ */
+
+#ifndef __VIR_XENXS_PRIVATE_H__
+# define __VIR_XENXS_PRIVATE_H__
+
+# include "internal.h"
+
+
+# define VIR_FROM_THIS VIR_FROM_NONE
+
+# define XENXS_ERROR(code, ...) \
+ virReportErrorHelper(NULL, VIR_FROM_NONE, code, __FILE__, __FUNCTION__, \
+ __LINE__, __VA_ARGS__)
+
+#endif /* __VIR_XENXS_PRIVATE_H__ */
diff --git a/tests/sexpr2xmltest.c b/tests/sexpr2xmltest.c
index f100dd87ce52ed17ff52b55d0b7d51682db46461..cf3e5bcd3d9fc8b8b006c00548e8c39db8b86ba0 100644
--- a/tests/sexpr2xmltest.c
+++ b/tests/sexpr2xmltest.c
@@ -9,6 +9,7 @@
#include "datatypes.h"
#include "xen/xen_driver.h"
#include "xen/xend_internal.h"
+#include "xenxs/xen_sxpr.h"
#include "testutils.h"
#include "testutilsxen.h"
@@ -25,6 +26,9 @@ static int testCompareFiles(const char *xml, const char *sexpr,
char *gotxml = NULL;
char *xmlPtr = &(xmlData[0]);
char *sexprPtr = &(sexprData[0]);
+ int id;
+ char * tty;
+ int vncport;
int ret = -1;
virDomainDefPtr def = NULL;
virConnectPtr conn;
@@ -48,7 +52,14 @@ static int testCompareFiles(const char *xml, const char *sexpr,
if (virMutexInit(&priv.lock) < 0)
goto fail;
- if (!(def = xenDaemonParseSxprString(conn, sexprData, xendConfigVersion)))
+ id = xenGetDomIdFromSxprString(sexprData, xendConfigVersion);
+ xenUnifiedLock(&priv);
+ tty = xenStoreDomainGetConsolePath(conn, id);
+ vncport = xenStoreDomainGetVNCPort(conn, id);
+ xenUnifiedUnlock(&priv);
+
+ if (!(def = xenDaemonParseSxprString(sexprData, xendConfigVersion, tty,
+ vncport)))
goto fail;
if (!(gotxml = virDomainDefFormat(def, 0)))