+Fri Jul 25 14:00:27 BST 2008 Daniel P. Berrange <berrange@redhat.com>
+
+ Convert XenD XML->SEXPR conversion to new domain XML APIs
+
+ * proxy/Makefile.am: no longer need to link xml.c
+ * proxy/libvirt_proxy.c: Adapt to use new domain XML
+ API contract
+ * src/xen_internal.c, src/xen_internal.h: Don't pass a
+ connection object when building capabilities.
+ * src/xen_unified.c, src/xen_unified.h: Initialize
+ a virCapsPtr object when opening the connection
+ * src/xend_internal.c, src/xend_internal.h: Add code
+ for converting from XML to SEXPR.
+ * src/xml.h, src/xml.c: Remove code for generating SXPR
+ * src/xm_intenral.c: Adapt to new SXPR generation
+ * tests/xml2sexprdata/*: Update to match new ordering
+ for XML / SXPR generation
+ * tests/xencapstest.c, tests/xml2sexprtest.c: Fix up
+ to work with new internal APIs
+ * src/domain_conf.c: Back compat workaround for Xen
+
Fri Jul 25 14:35:47 CEST 2008 Daniel Veillard <veillard@redhat.com>
* python/generator.py: skip generation for virDomainBlockPeek and
Fri Jul 25 11:45:27 BST 2008 Daniel P. Berrange <berrange@redhat.com>
- Convert XenD SEXPR->XML convesion to new domain XML APIs
+ Convert XenD SEXPR->XML conversion to new domain XML APIs
* proxy/Makefile.am: Link to domain XML formatting APIs
* src/domain_conf.c, src/domain_conf.h: Disable XML parsing
libvirt_proxy_SOURCES = libvirt_proxy.c @top_srcdir@/src/xend_internal.c \
@top_srcdir@/src/xen_internal.c @top_srcdir@/src/virterror.c \
- @top_srcdir@/src/sexpr.c @top_srcdir@/src/xml.c \
+ @top_srcdir@/src/sexpr.c \
@top_srcdir@/src/xs_internal.c @top_srcdir@/src/buf.c \
@top_srcdir@/src/capabilities.c \
@top_srcdir@/src/memory.c \
*/
static int
proxyReadClientSocket(int nr) {
+ virDomainDefPtr def;
virProxyFullPacket request;
virProxyPacketPtr req = (virProxyPacketPtr) &request;
int ret;
* rather hard to get from that code path. So proxy
* users won't see CPU pinning (last NULL arg)
*/
- xml = xenDaemonDomainDumpXMLByID(conn, request.data.arg, 0, NULL);
- if (!xml) {
+ def = xenDaemonDomainFetch(conn, request.data.arg, NULL, NULL);
+ if (!def) {
req->data.arg = -1;
req->len = sizeof(virProxyPacket);
} else {
- int xmllen = strlen(xml);
- if (xmllen > (int) sizeof(request.extra.str)) {
- req->data.arg = -2;
+ xml = virDomainDefFormat(conn, def, 0);
+ if (!xml) {
+ req->data.arg = -1;
req->len = sizeof(virProxyPacket);
} else {
- req->data.arg = 0;
- memmove(&request.extra.str[0], xml, xmllen);
- req->len = sizeof(virProxyPacket) + xmllen;
+ int xmllen = strlen(xml);
+ if (xmllen > (int) sizeof(request.extra.str)) {
+ req->data.arg = -2;
+ req->len = sizeof(virProxyPacket);
+ } else {
+ req->data.arg = 0;
+ memmove(&request.extra.str[0], xml, xmllen);
+ req->len = sizeof(virProxyPacket) + xmllen;
+ }
+ free(xml);
}
- free(xml);
}
+ virDomainDefFree(def);
break;
case VIR_PROXY_DOMAIN_OSTYPE:
if (req->len != sizeof(virProxyPacket))
(xmlStrEqual(cur->name, BAD_CAST "target"))) {
target = virXMLPropString(cur, "dev");
bus = virXMLPropString(cur, "bus");
+
+ /* HACK: Work around for compat with Xen
+ * driver in previous libvirt releases */
+ if (target &&
+ STRPREFIX(target, "ioemu:"))
+ memmove(target, target+6, strlen(target)-5);
} else if ((driverName == NULL) &&
(xmlStrEqual(cur->name, BAD_CAST "driver"))) {
driverName = virXMLPropString(cur, "name");
static virCapsPtr
-xenHypervisorBuildCapabilities(virConnectPtr conn,
- const char *hostmachine,
+xenHypervisorBuildCapabilities(const char *hostmachine,
int host_pae,
char *hvm_type,
struct guest_arch *guest_archs,
if (sys_interface_version >= 4) {
- if (xenDaemonNodeGetTopology(conn, caps) != 0) {
+ if (xenDaemonNodeGetTopology(NULL, caps) != 0) {
virCapabilitiesFree(caps);
return NULL;
}
*
* Return the capabilities of this hypervisor.
*/
-char *
-xenHypervisorMakeCapabilitiesXML(virConnectPtr conn,
- const char *hostmachine,
- FILE *cpuinfo, FILE *capabilities)
+virCapsPtr
+xenHypervisorMakeCapabilitiesInternal(const char *hostmachine,
+ FILE *cpuinfo, FILE *capabilities)
{
char line[1024], *str, *token;
regmatch_t subs[4];
int host_pae = 0;
struct guest_arch guest_archs[32];
int nr_guest_archs = 0;
-
- char *xml;
-
-
virCapsPtr caps = NULL;
memset(guest_archs, 0, sizeof(guest_archs));
}
}
- if ((caps = xenHypervisorBuildCapabilities(conn,
- hostmachine,
+ if ((caps = xenHypervisorBuildCapabilities(hostmachine,
host_pae,
hvm_type,
guest_archs,
nr_guest_archs)) == NULL)
goto no_memory;
- if ((xml = virCapabilitiesFormatXML(caps)) == NULL)
- goto no_memory;
- virCapabilitiesFree(caps);
- return xml;
+ return caps;
no_memory:
- virXenError(conn, VIR_ERR_NO_MEMORY, __FUNCTION__, 0);
+ virXenError(NULL, VIR_ERR_NO_MEMORY, __FUNCTION__, 0);
virCapabilitiesFree(caps);
return NULL;
}
/**
- * xenHypervisorGetCapabilities:
- * @conn: pointer to the connection block
+ * xenHypervisorMakeCapabilities:
*
* Return the capabilities of this hypervisor.
*/
-char *
-xenHypervisorGetCapabilities (virConnectPtr conn)
+virCapsPtr
+xenHypervisorMakeCapabilities(void)
{
- char *xml;
+ virCapsPtr caps;
FILE *cpuinfo, *capabilities;
struct utsname utsname;
cpuinfo = fopen ("/proc/cpuinfo", "r");
if (cpuinfo == NULL) {
if (errno != ENOENT) {
- virXenPerror (conn, "/proc/cpuinfo");
+ virXenPerror (NULL, "/proc/cpuinfo");
return NULL;
}
}
if (capabilities == NULL) {
if (errno != ENOENT) {
fclose(cpuinfo);
- virXenPerror (conn, "/sys/hypervisor/properties/capabilities");
+ virXenPerror (NULL, "/sys/hypervisor/properties/capabilities");
return NULL;
}
}
- xml = xenHypervisorMakeCapabilitiesXML(conn, utsname.machine, cpuinfo, capabilities);
+ caps = xenHypervisorMakeCapabilitiesInternal(utsname.machine, cpuinfo, capabilities);
if (cpuinfo)
fclose(cpuinfo);
if (capabilities)
fclose(capabilities);
+ return caps;
+}
+
+
+
+/**
+ * xenHypervisorGetCapabilities:
+ * @conn: pointer to the connection block
+ *
+ * Return the capabilities of this hypervisor.
+ */
+char *
+xenHypervisorGetCapabilities (virConnectPtr conn)
+{
+ xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
+ char *xml;
+
+ if (!(xml = virCapabilitiesFormatXML(priv->caps))) {
+ virXenError(conn, VIR_ERR_NO_MEMORY, NULL, 0);
+ return NULL;
+ }
+
return xml;
}
+
/**
* xenHypervisorNumOfDomains:
* @conn: pointer to the connection block
extern "C" {
#endif
+#include "internal.h"
+#include "capabilities.h"
+
extern struct xenUnifiedDriver xenHypervisorDriver;
int xenHypervisorInit (void);
+virCapsPtr xenHypervisorMakeCapabilities (void);
+
/* The following calls are made directly by the Xen proxy: */
virDomainPtr
int xenHypervisorClose (virConnectPtr conn);
int xenHypervisorGetVersion (virConnectPtr conn,
unsigned long *hvVer);
-char *
- xenHypervisorMakeCapabilitiesXML (virConnectPtr conn,
- const char *hostmachine,
- FILE *cpuinfo,
- FILE *capabilities);
+virCapsPtr
+ xenHypervisorMakeCapabilitiesInternal(const char *hostmachine,
+ FILE *cpuinfo,
+ FILE *capabilities);
char *
xenHypervisorGetCapabilities (virConnectPtr conn);
unsigned long
}
}
}
- res = virSaveCpuSet(dom->conn, cpulist, nb_cpu);
+ res = virDomainCpuSetFormat(dom->conn, cpulist, nb_cpu);
}
done:
}
}
+ if (!(priv->caps = xenHypervisorMakeCapabilities())) {
+ DEBUG0("Failed to make capabilities");
+ goto fail;
+ }
+
return VIR_DRV_OPEN_SUCCESS;
fail:
GET_PRIVATE(conn);
int i;
+ virCapabilitiesFree(priv->caps);
for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
if (priv->opened[i] && drivers[i]->close)
(void) drivers[i]->close (conn);
#define __VIR_XEN_UNIFIED_H__
#include "internal.h"
+#include "capabilities.h"
#ifndef HAVE_WINSOCK2_H
#include <sys/un.h>
* low-level drivers access parts of this structure.
*/
struct _xenUnifiedPrivate {
+ virCapsPtr caps;
#ifdef WITH_XEN
int handle; /* Xen hypervisor handle */
#include <libxml/uri.h>
#include <errno.h>
-#include "internal.h"
+#include "xend_internal.h"
#include "driver.h"
#include "util.h"
#include "sexpr.h"
-#include "xml.h"
#include "buf.h"
-#include "capabilities.h"
-#include "domain_conf.h"
#include "uuid.h"
#include "xen_unified.h"
-#include "xend_internal.h"
#include "xen_internal.h" /* for DOM0_INTERFACE_VERSION */
#include "xs_internal.h" /* To extract VNC port & Serial console TTY */
#include "memory.h"
};
+#ifndef PROXY
+static int
+xenDaemonFormatSxprDisk(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainDiskDefPtr def,
+ virBufferPtr buf,
+ int hvm,
+ int xendConfigVersion);
+static int
+xenDaemonFormatSxprNet(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainNetDefPtr def,
+ virBufferPtr buf,
+ int hvm,
+ int xendConfigVersion);
+static int
+virDomainXMLDevID(virDomainPtr domain,
+ virDomainDeviceDefPtr dev,
+ char *class,
+ char *ref,
+ int ref_len);
+#endif
+
static void virXendError(virConnectPtr conn, virErrorNumber error,
const char *fmt, ...)
ATTRIBUTE_FORMAT(printf,3,4);
for (cpu = 0; cpu < numCpus; cpu++)
cpuset[cpu] = 0;
} else {
- nb_cpus = virParseCpuSet(conn, &cur, 'n', cpuset, numCpus);
+ nb_cpus = virDomainCpuSetParse(conn, &cur, 'n', cpuset, numCpus);
if (nb_cpus < 0)
goto error;
}
#endif /* ! PROXY */
-/* XXX change proxy to use Name instead of ID, then
- dumpxml will work over proxy for inactive domains
- and this can be removed */
-char *
-xenDaemonDomainDumpXMLByID(virConnectPtr conn, int domid, int flags,
- const char *cpus)
-{
- char *ret = NULL;
- struct sexpr *root;
- xenUnifiedPrivatePtr priv;
- virDomainDefPtr def;
-
- root = sexpr_get(conn, "/xend/domain/%d?detail=1", domid);
- if (root == NULL) {
- virXendError (conn, VIR_ERR_XEN_CALL,
- _("xenDaemonDomainDumpXMLByID failed to"
- " find this domain"));
- return (NULL);
- }
-
- priv = (xenUnifiedPrivatePtr) conn->privateData;
-
- if (!(def = xenDaemonParseSxpr(conn, root, priv->xendConfigVersion,
- cpus)))
- goto cleanup;
-
- ret = virDomainDefFormat(conn, def, flags);
-
-cleanup:
- sexpr_free(root);
- virDomainDefFree(def);
-
- return (ret);
-}
-
-char *
-xenDaemonDomainDumpXMLByName(virConnectPtr conn, const char *name, int flags,
- const char *cpus)
+virDomainDefPtr
+xenDaemonDomainFetch(virConnectPtr conn,
+ int domid,
+ const char *name,
+ const char *cpus)
{
- char *ret = NULL;
struct sexpr *root;
xenUnifiedPrivatePtr priv;
virDomainDefPtr def;
- root = sexpr_get(conn, "/xend/domain/%s?detail=1", name);
+ if (name)
+ root = sexpr_get(conn, "/xend/domain/%s?detail=1", name);
+ else
+ root = sexpr_get(conn, "/xend/domain/%d?detail=1", domid);
if (root == NULL) {
virXendError (conn, VIR_ERR_XEN_CALL,
- _("xenDaemonDomainDumpXMLByName failed to"
+ _("xenDaemonDomainFetch failed to"
" find this domain"));
return (NULL);
}
priv = (xenUnifiedPrivatePtr) conn->privateData;
- if (!(def = xenDaemonParseSxpr(conn, root, priv->xendConfigVersion,
+ if (!(def = xenDaemonParseSxpr(conn,
+ root,
+ priv->xendConfigVersion,
cpus)))
goto cleanup;
- ret = virDomainDefFormat(conn, def, flags);
-
cleanup:
sexpr_free(root);
- virDomainDefFree(def);
- return (ret);
+ return (def);
}
xenDaemonDomainDumpXML(virDomainPtr domain, int flags, const char *cpus)
{
xenUnifiedPrivatePtr priv;
+ virDomainDefPtr def;
+ char *xml;
if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
return(NULL);
}
- if (domain->id < 0)
- return xenDaemonDomainDumpXMLByName(domain->conn, domain->name, flags,
- cpus);
- else
- return xenDaemonDomainDumpXMLByID(domain->conn, domain->id, flags,
- cpus);
+ if (!(def = xenDaemonDomainFetch(domain->conn,
+ domain->id,
+ domain->name,
+ cpus)))
+ return(NULL);
+
+ xml = virDomainDefFormat(domain->conn, def, flags);
+
+ virDomainDefFree(def);
+
+ return xml;
}
#endif /* !PROXY */
{
int ret;
char *sexpr;
- char *name = NULL;
virDomainPtr dom = NULL;
xenUnifiedPrivatePtr priv;
-
- if (!VIR_IS_CONNECT(conn)) {
- virXendError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
- return (NULL);
- }
- if (xmlDesc == NULL) {
- virXendError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
- return (NULL);
- }
+ virDomainDefPtr def;
priv = (xenUnifiedPrivatePtr) conn->privateData;
- sexpr = virDomainParseXMLDesc(conn, xmlDesc, &name, priv->xendConfigVersion);
- if ((sexpr == NULL) || (name == NULL)) {
- virXendError(conn, VIR_ERR_XML_ERROR,
- _("failed to parse domain description"));
- VIR_FREE(sexpr);
- VIR_FREE(name);
+ if (!(def = virDomainDefParseString(conn,
+ priv->caps,
+ xmlDesc)))
+ return (NULL);
+ if (!(sexpr = xenDaemonFormatSxpr(conn, def, priv->xendConfigVersion))) {
+ virXendError(conn, VIR_ERR_XML_ERROR,
+ "%s", _("failed to build sexpr"));
+ virDomainDefFree(def);
return (NULL);
}
/* This comes before wait_for_devices, to ensure that latter
cleanup will destroy the domain upon failure */
- if (!(dom = virDomainLookupByName(conn, name)))
+ if (!(dom = virDomainLookupByName(conn, def->name)))
goto error;
- if ((ret = xend_wait_for_devices(conn, name)) < 0)
+ if ((ret = xend_wait_for_devices(conn, def->name)) < 0)
goto error;
if ((ret = xenDaemonDomainResume(dom)) < 0)
goto error;
- VIR_FREE(name);
-
+ virDomainDefFree(def);
return (dom);
error:
xenDaemonDomainDestroy(dom);
virUnrefDomain(dom);
}
- VIR_FREE(name);
+ virDomainDefFree(def);
return (NULL);
}
static int
xenDaemonAttachDevice(virDomainPtr domain, const char *xml)
{
- char *sexpr, *conf, *str;
- int hvm = 0, ret;
xenUnifiedPrivatePtr priv;
+ char *sexpr = NULL;
+ int ret = -1;
+ virDomainDeviceDefPtr dev = NULL;
+ virDomainDefPtr def = NULL;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
char class[8], ref[80];
if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
__FUNCTION__);
- return (-1);
+ return -1;
}
priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
* avoid doing this on inactive guests
*/
if ((domain->id < 0) && (priv->xendConfigVersion < 3))
- return (-1);
+ return -1;
- str = virDomainGetOSType(domain);
- if (STREQ(str, "hvm"))
- hvm = 1;
- VIR_FREE(str);
- sexpr = virParseXMLDevice(domain->conn, xml, hvm, priv->xendConfigVersion);
- if (sexpr == NULL)
- return (-1);
- if (!memcmp(sexpr, "(device ", 8)) {
- conf = sexpr + 8;
- *(conf + strlen(conf) -1) = 0; /* suppress final ) */
+ if (!(def = xenDaemonDomainFetch(domain->conn,
+ domain->id,
+ domain->name,
+ NULL)))
+ goto cleanup;
+
+ if (!(dev = virDomainDeviceDefParse(domain->conn, def, xml)))
+ goto cleanup;
+
+
+ switch (dev->type) {
+ case VIR_DOMAIN_DEVICE_DISK:
+ if (xenDaemonFormatSxprDisk(domain->conn,
+ dev->data.disk,
+ &buf,
+ STREQ(def->os.type, "hvm") ? 1 : 0,
+ priv->xendConfigVersion) < 0)
+ goto cleanup;
+
+ case VIR_DOMAIN_DEVICE_NET:
+ if (xenDaemonFormatSxprNet(domain->conn,
+ dev->data.net,
+ &buf,
+ STREQ(def->os.type, "hvm") ? 1 : 0,
+ priv->xendConfigVersion) < 0)
+ goto cleanup;
+
+ default:
+ virXendError(domain->conn, VIR_ERR_NO_SUPPORT, "%s",
+ _("unsupported device type"));
+ goto cleanup;
}
- else conf = sexpr;
- if (virDomainXMLDevID(domain, xml, class, ref, sizeof(ref))) {
+
+ sexpr = virBufferContentAndReset(&buf);
+
+ if (virDomainXMLDevID(domain, dev, class, ref, sizeof(ref))) {
/* device doesn't exist, define it */
ret = xend_op(domain->conn, domain->name, "op", "device_create",
- "config", conf, NULL);
+ "config", sexpr, NULL);
}
else {
/* device exists, attempt to modify it */
ret = xend_op(domain->conn, domain->name, "op", "device_configure",
- "config", conf, "dev", ref, NULL);
+ "config", sexpr, "dev", ref, NULL);
}
+
+cleanup:
VIR_FREE(sexpr);
+ virDomainDefFree(def);
+ virDomainDeviceDefFree(dev);
return ret;
}
static int
xenDaemonDetachDevice(virDomainPtr domain, const char *xml)
{
+ xenUnifiedPrivatePtr priv;
char class[8], ref[80];
+ virDomainDeviceDefPtr dev = NULL;
+ virDomainDefPtr def = NULL;
+ int ret = -1;
if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
__FUNCTION__);
return (-1);
}
- if (virDomainXMLDevID(domain, xml, class, ref, sizeof(ref)))
- return (-1);
- return(xend_op(domain->conn, domain->name, "op", "device_destroy",
- "type", class, "dev", ref, "force", "0", "rm_cfg", "1", NULL));
+
+ priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+
+ /*
+ * on older Xen without the inactive guests management
+ * avoid doing this on inactive guests
+ */
+ if ((domain->id < 0) && (priv->xendConfigVersion < 3))
+ return -1;
+
+ if (!(def = xenDaemonDomainFetch(domain->conn,
+ domain->id,
+ domain->name,
+ NULL)))
+ goto cleanup;
+
+ if (!(dev = virDomainDeviceDefParse(domain->conn, def, xml)))
+ goto cleanup;
+
+ if (virDomainXMLDevID(domain, dev, class, ref, sizeof(ref)))
+ goto cleanup;
+
+ ret = xend_op(domain->conn, domain->name, "op", "device_destroy",
+ "type", class, "dev", ref, "force", "0", "rm_cfg", "1", NULL);
+
+cleanup:
+ virDomainDefFree(def);
+ virDomainDeviceDefFree(dev);
+
+ return ret;
}
int
char *name = NULL;
virDomainPtr dom;
xenUnifiedPrivatePtr priv;
-
- if (!VIR_IS_CONNECT(conn)) {
- virXendError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
- return (NULL);
- }
- if (xmlDesc == NULL) {
- virXendError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
- return (NULL);
- }
+ virDomainDefPtr def;
priv = (xenUnifiedPrivatePtr) conn->privateData;
if (priv->xendConfigVersion < 3)
return(NULL);
- sexpr = virDomainParseXMLDesc(conn, xmlDesc, &name, priv->xendConfigVersion);
- if ((sexpr == NULL) || (name == NULL)) {
+ if (!(def = virDomainDefParseString(conn, priv->caps, xmlDesc))) {
virXendError(conn, VIR_ERR_XML_ERROR,
_("failed to parse domain description"));
- VIR_FREE(sexpr);
- VIR_FREE(name);
-
return (NULL);
}
+ if (!(sexpr = xenDaemonFormatSxpr(conn, def, priv->xendConfigVersion))) {
+ virXendError(conn, VIR_ERR_XML_ERROR,
+ _("failed to build sexpr"));
+ goto error;
+ }
+
ret = xend_op(conn, "", "op", "new", "config", sexpr, NULL);
VIR_FREE(sexpr);
if (ret != 0) {
if (dom == NULL) {
goto error;
}
-
+ virDomainDefFree(def);
return (dom);
+
error:
- VIR_FREE(name);
+ virDomainDefFree(def);
return (NULL);
}
int xenDaemonDomainCreate(virDomainPtr domain)
xenDaemonSetSchedulerParameters, /* domainSetSchedulerParameters */
};
+/************************************************************************
+ * *
+ * Converter functions to go from the XML tree to an S-Expr for Xen *
+ * *
+ ************************************************************************/
+
+
+/**
+ * virtDomainParseXMLGraphicsDescVFB:
+ * @conn: pointer to the hypervisor connection
+ * @node: node containing graphics description
+ * @buf: a buffer for the result S-Expr
+ *
+ * Parse the graphics part of the XML description and add it to the S-Expr
+ * in buf. This is a temporary interface as the S-Expr interface will be
+ * replaced by XML-RPC in the future. However the XML format should stay
+ * valid over time.
+ *
+ * Returns 0 in case of success, -1 in case of error
+ */
+static int
+xenDaemonFormatSxprGraphicsNew(virConnectPtr conn,
+ virDomainGraphicsDefPtr def,
+ virBufferPtr buf)
+{
+ if (def->type != VIR_DOMAIN_GRAPHICS_TYPE_SDL &&
+ def->type != VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
+ virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("unexpected graphics type %d"),
+ def->type);
+ return -1;
+ }
+
+ virBufferAddLit(buf, "(device (vkbd))");
+ virBufferAddLit(buf, "(device (vfb ");
+
+ if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
+ virBufferAddLit(buf, "(type sdl)");
+ if (def->data.sdl.display)
+ virBufferVSprintf(buf, "(display '%s')", def->data.sdl.display);
+ if (def->data.sdl.xauth)
+ virBufferVSprintf(buf, "(xauthority '%s')", def->data.sdl.xauth);
+ } else if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
+ virBufferAddLit(buf, "(type vnc)");
+ if (def->data.vnc.autoport) {
+ virBufferAddLit(buf, "(vncunused 1)");
+ } else {
+ virBufferAddLit(buf, "(vncunused 0)");
+ virBufferVSprintf(buf, "(vncdisplay %d)", def->data.vnc.port-5900);
+ }
+
+ if (def->data.vnc.listenAddr)
+ virBufferVSprintf(buf, "(vnclisten '%s')", def->data.vnc.listenAddr);
+ if (def->data.vnc.passwd)
+ virBufferVSprintf(buf, "(vncpasswd '%s')", def->data.vnc.passwd);
+ if (def->data.vnc.keymap)
+ virBufferVSprintf(buf, "(keymap '%s')", def->data.vnc.keymap);
+ }
+
+ virBufferAddLit(buf, "))");
+
+ return 0;
+}
+
+
+static int
+xenDaemonFormatSxprGraphicsOld(virConnectPtr conn,
+ virDomainGraphicsDefPtr def,
+ virBufferPtr buf,
+ int xendConfigVersion)
+{
+ if (def->type != VIR_DOMAIN_GRAPHICS_TYPE_SDL &&
+ def->type != VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
+ virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("unexpected graphics type %d"),
+ def->type);
+ return -1;
+ }
+
+ if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
+ virBufferAddLit(buf, "(sdl 1)");
+ if (def->data.sdl.display)
+ virBufferVSprintf(buf, "(display '%s')", def->data.sdl.display);
+ if (def->data.sdl.xauth)
+ virBufferVSprintf(buf, "(xauthority '%s')", def->data.sdl.xauth);
+ } else if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
+ virBufferAddLit(buf, "(vnc 1)");
+ if (xendConfigVersion >= 2) {
+ if (def->data.vnc.autoport) {
+ virBufferAddLit(buf, "(vncunused 1)");
+ } else {
+ virBufferAddLit(buf, "(vncunused 0)");
+ virBufferVSprintf(buf, "(vncdisplay %d)", def->data.vnc.port-5900);
+ }
+
+ if (def->data.vnc.listenAddr)
+ virBufferVSprintf(buf, "(vnclisten '%s')", def->data.vnc.listenAddr);
+ if (def->data.vnc.passwd)
+ virBufferVSprintf(buf, "(vncpasswd '%s')", def->data.vnc.passwd);
+ if (def->data.vnc.keymap)
+ virBufferVSprintf(buf, "(keymap '%s')", def->data.vnc.keymap);
+
+ }
+ }
+
+ return 0;
+}
+
+static int
+xenDaemonFormatSxprChr(virConnectPtr conn,
+ virDomainChrDefPtr def,
+ virBufferPtr buf,
+ const char *name)
+{
+ const char *type = virDomainChrTypeToString(def->type);
+
+ if (!type) {
+ virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("unexpected chr device type"));
+ return -1;
+ }
+
+ switch (def->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:
+ virBufferVSprintf(buf, "(%s %s)", name, type);
+ break;
+
+ case VIR_DOMAIN_CHR_TYPE_FILE:
+ case VIR_DOMAIN_CHR_TYPE_PIPE:
+ virBufferVSprintf(buf, "(%s %s:%s)", name, type, def->data.file.path);
+ break;
+
+ case VIR_DOMAIN_CHR_TYPE_DEV:
+ virBufferVSprintf(buf, "(%s %s)", name, def->data.file.path);
+ break;
+
+ case VIR_DOMAIN_CHR_TYPE_TCP:
+ virBufferVSprintf(buf, "(%s %s:%s:%s%s)", name,
+ (def->data.tcp.protocol == VIR_DOMAIN_CHR_TCP_PROTOCOL_RAW ?
+ "tcp" : "telnet"),
+ (def->data.tcp.host ? def->data.tcp.host : ""),
+ (def->data.tcp.service ? def->data.tcp.service : ""),
+ (def->data.tcp.listen ? ",listen" : ""));
+ break;
+
+ case VIR_DOMAIN_CHR_TYPE_UDP:
+ virBufferVSprintf(buf, "(%s %s:%s:%s@%s:%s)", name, type,
+ (def->data.udp.connectHost ? def->data.udp.connectHost : ""),
+ (def->data.udp.connectService ? def->data.udp.connectService : ""),
+ (def->data.udp.bindHost ? def->data.udp.bindHost : ""),
+ (def->data.udp.bindService ? def->data.udp.bindService : ""));
+ break;
+
+ case VIR_DOMAIN_CHR_TYPE_UNIX:
+ virBufferVSprintf(buf, "(%s %s:%s%s)", name, type,
+ def->data.nix.path,
+ def->data.nix.listen ? ",listen" : "");
+ break;
+ }
+
+ return 0;
+}
+
+
+/**
+ * virDomainParseXMLDiskDesc:
+ * @node: node containing disk description
+ * @conn: pointer to the hypervisor connection
+ * @buf: a buffer for the result S-Expr
+ * @xendConfigVersion: xend configuration file format
+ *
+ * Parse the one disk in the XML description and add it to the S-Expr in buf
+ * This is a temporary interface as the S-Expr interface
+ * will be replaced by XML-RPC in the future. However the XML format should
+ * stay valid over time.
+ *
+ * Returns 0 in case of success, -1 in case of error.
+ */
+static int
+xenDaemonFormatSxprDisk(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainDiskDefPtr def,
+ virBufferPtr buf,
+ int hvm,
+ int xendConfigVersion)
+{
+ /* Xend (all versions) put the floppy device config
+ * under the hvm (image (os)) block
+ */
+ if (hvm &&
+ def->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY)
+ return 0;
+
+ /* Xend <= 3.0.2 doesn't include cdrom config here */
+ if (hvm &&
+ def->device == VIR_DOMAIN_DISK_DEVICE_CDROM &&
+ xendConfigVersion == 1)
+ return 0;
+
+ virBufferAddLit(buf, "(device ");
+ /* Normally disks are in a (device (vbd ...)) block
+ * but blktap disks ended up in a differently named
+ * (device (tap ....)) block.... */
+ if (def->driverName &&
+ STREQ(def->driverName, "tap")) {
+ virBufferAddLit(buf, "(tap ");
+ } else {
+ virBufferAddLit(buf, "(vbd ");
+ }
+
+ if (hvm) {
+ /* Xend <= 3.0.2 wants a ioemu: prefix on devices for HVM */
+ if (xendConfigVersion == 1)
+ virBufferVSprintf(buf, "(dev 'ioemu:%s')", def->dst);
+ else /* But newer does not */
+ virBufferVSprintf(buf, "(dev '%s:%s')", def->dst,
+ def->device == VIR_DOMAIN_DISK_DEVICE_CDROM ?
+ "cdrom" : "disk");
+ } else {
+ virBufferVSprintf(buf, "(dev '%s')", def->dst);
+ }
+
+ if (def->src) {
+ if (def->driverName) {
+ if (STREQ(def->driverName, "tap")) {
+ virBufferVSprintf(buf, "(uname '%s:%s:%s')",
+ def->driverName,
+ def->driverType ? def->driverType : "aio",
+ def->src);
+ } else {
+ virBufferVSprintf(buf, "(uname '%s:%s')",
+ def->driverName,
+ def->src);
+ }
+ } else {
+ if (def->type == VIR_DOMAIN_DISK_TYPE_FILE) {
+ virBufferVSprintf(buf, "(uname 'file:%s')", def->src);
+ } else {
+ if (def->src[0] == '/')
+ virBufferVSprintf(buf, "(uname 'phy:%s')", def->src);
+ else
+ virBufferVSprintf(buf, "(uname 'phy:/dev/%s')", def->src);
+ }
+ }
+ }
+
+ if (def->readonly)
+ virBufferAddLit(buf, "(mode 'r')");
+ else if (def->shared)
+ virBufferAddLit(buf, "(mode 'w!')");
+ else
+ virBufferAddLit(buf, "(mode 'w')");
+
+ virBufferAddLit(buf, "))");
+
+ return 0;
+}
+
+/**
+ * xenDaemonFormatSxprNet
+ * @conn: pointer to the hypervisor connection
+ * @node: node containing the interface description
+ * @buf: a buffer for the result S-Expr
+ * @xendConfigVersion: xend configuration file format
+ *
+ * Parse the one interface the XML description and add it to the S-Expr in buf
+ * This is a temporary interface as the S-Expr interface
+ * will be replaced by XML-RPC in the future. However the XML format should
+ * stay valid over time.
+ *
+ * Returns 0 in case of success, -1 in case of error.
+ */
+static int
+xenDaemonFormatSxprNet(virConnectPtr conn,
+ virDomainNetDefPtr def,
+ virBufferPtr buf,
+ int hvm,
+ int xendConfigVersion)
+{
+ if (def->type != VIR_DOMAIN_NET_TYPE_BRIDGE &&
+ def->type != VIR_DOMAIN_NET_TYPE_NETWORK &&
+ def->type != VIR_DOMAIN_NET_TYPE_ETHERNET) {
+ virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("unsupported network type %d"), def->type);
+ return -1;
+ }
+
+ virBufferAddLit(buf, "(device (vif ");
+
+ virBufferVSprintf(buf,
+ "(mac '%02x:%02x:%02x:%02x:%02x:%02x')",
+ def->mac[0], def->mac[1], def->mac[2],
+ def->mac[3], def->mac[4], def->mac[5]);
+
+ switch (def->type) {
+ case VIR_DOMAIN_NET_TYPE_BRIDGE:
+ virBufferVSprintf(buf, "(bridge '%s')", def->data.bridge.brname);
+ virBufferAddLit(buf, "(script 'vif-bridge')");
+ break;
+
+ case VIR_DOMAIN_NET_TYPE_NETWORK:
+ {
+ virNetworkPtr network =
+ virNetworkLookupByName(conn, def->data.network.name);
+ char *bridge;
+
+ if (!network) {
+ virXendError(conn, VIR_ERR_NO_SOURCE, "%s",
+ def->data.network.name);
+ return -1;
+ }
+
+ bridge = virNetworkGetBridgeName(network);
+ virNetworkFree(network);
+ if (!bridge) {
+ virXendError(conn, VIR_ERR_NO_SOURCE, "%s",
+ def->data.network.name);
+ return -1;
+ }
+ virBufferVSprintf(buf, "(bridge '%s')", bridge);
+ virBufferAddLit(buf, "(script 'vif-bridge')");
+ VIR_FREE(bridge);
+ }
+ break;
+
+ case VIR_DOMAIN_NET_TYPE_ETHERNET:
+ if (def->data.ethernet.script)
+ virBufferVSprintf(buf, "(script '%s')", def->data.ethernet.script);
+ if (def->data.ethernet.ipaddr != NULL)
+ virBufferVSprintf(buf, "(ip '%s')", def->data.ethernet.ipaddr);
+ break;
+ }
+
+ if (def->ifname != NULL &&
+ !STRPREFIX(def->ifname, "vif"))
+ virBufferVSprintf(buf, "(vifname '%s')", def->ifname);
+
+ if (def->model != NULL)
+ virBufferVSprintf(buf, "(model '%s')", def->model);
+
+ /*
+ * apparently (type ioemu) breaks paravirt drivers on HVM so skip this
+ * from Xen 3.1.0
+ */
+ if ((hvm) && (xendConfigVersion < 4))
+ virBufferAddLit(buf, "(type ioemu)");
+
+ virBufferAddLit(buf, "))");
+
+ return 0;
+}
+
+static int
+xenDaemonFormatSxprSound(virConnectPtr conn,
+ virDomainSoundDefPtr sound,
+ virBufferPtr buf)
+{
+ const char *str;
+ virDomainSoundDefPtr prev = NULL;
+ if (!sound)
+ return 0;
+
+ virBufferAddLit(buf, "(soundhw '");
+ while (sound) {
+ if (!(str = virDomainSoundModelTypeToString(sound->model))) {
+ virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("unexpected sound model %d"), sound->model);
+ return -1;
+ }
+ virBufferVSprintf(buf, "%s%s", prev ? "," : "", str);
+ prev = sound;
+ sound = sound->next;
+ }
+
+ virBufferAddLit(buf, "')");
+ return 0;
+}
+
+
+static int
+xenDaemonFormatSxprInput(virConnectPtr conn,
+ virDomainInputDefPtr input,
+ virBufferPtr buf)
+{
+ if (input->bus != VIR_DOMAIN_INPUT_BUS_USB)
+ return 0;
+
+ if (input->type != VIR_DOMAIN_INPUT_TYPE_MOUSE &&
+ input->type != VIR_DOMAIN_INPUT_TYPE_TABLET) {
+ virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("unexpected input type %d"), input->type);
+ return -1;
+ }
+
+ virBufferVSprintf(buf, "(usbdevice %s)",
+ input->type == VIR_DOMAIN_INPUT_TYPE_MOUSE ?
+ "mouse" : "tablet");
+
+ return 0;
+}
+
+
+/**
+ * xenDaemonFormatSxpr:
+ * @conn: pointer to the hypervisor connection
+ * @def: domain config definition
+ * @xendConfigVersion: xend configuration file format
+ *
+ * Generate an SEXPR representing the domain configuration.
+ *
+ * Returns the 0 terminatedi S-Expr string or NULL in case of error.
+ * the caller must free() the returned value.
+ */
+char *
+xenDaemonFormatSxpr(virConnectPtr conn,
+ virDomainDefPtr def,
+ int xendConfigVersion)
+{
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ const char *tmp;
+ int hvm = 0, i;
+ virDomainNetDefPtr net;
+ virDomainDiskDefPtr disk;
+ virDomainInputDefPtr input;
+
+ virBufferAddLit(&buf, "(vm ");
+ virBufferVSprintf(&buf, "(name '%s')", def->name);
+ virBufferVSprintf(&buf, "(memory %lu)(maxmem %lu)",
+ def->memory/1024, def->maxmem/1024);
+ virBufferVSprintf(&buf, "(vcpus %lu)", def->vcpus);
+
+ if (def->cpumask) {
+ char *ranges = virDomainCpuSetFormat(conn, def->cpumask, def->cpumasklen);
+ if (ranges == NULL)
+ goto error;
+ virBufferVSprintf(&buf, "(cpus '%s')", ranges);
+ VIR_FREE(ranges);
+ }
+
+ virUUIDFormat(def->uuid, uuidstr);
+ virBufferVSprintf(&buf, "(uuid '%s')", uuidstr);
+
+ if (def->os.bootloader) {
+ if (def->os.bootloader[0])
+ virBufferVSprintf(&buf, "(bootloader '%s')", def->os.bootloader);
+ else
+ virBufferAddLit(&buf, "(bootloader)");
+
+ if (def->os.bootloaderArgs)
+ virBufferVSprintf(&buf, "(bootloader_args '%s')", def->os.bootloaderArgs);
+ }
+
+ if (!(tmp = virDomainLifecycleTypeToString(def->onPoweroff))) {
+ virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("unexpected lifecycle value %d"), def->onPoweroff);
+ goto error;
+ }
+ virBufferVSprintf(&buf, "(on_poweroff '%s')", tmp);
+
+ if (!(tmp = virDomainLifecycleTypeToString(def->onReboot))) {
+ virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("unexpected lifecycle value %d"), def->onReboot);
+ goto error;
+ }
+ virBufferVSprintf(&buf, "(on_reboot '%s')", tmp);
+
+ if (!(tmp = virDomainLifecycleTypeToString(def->onCrash))) {
+ virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("unexpected lifecycle value %d"), def->onCrash);
+ goto error;
+ }
+ virBufferVSprintf(&buf, "(on_crash '%s')", tmp);
+
+ if (!def->os.bootloader) {
+ if (STREQ(def->os.type, "hvm"))
+ hvm = 1;
+
+ if (hvm)
+ virBufferAddLit(&buf, "(image (hvm ");
+ else
+ virBufferAddLit(&buf, "(image (linux ");
+
+ if (hvm &&
+ def->os.loader == NULL) {
+ virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+ "%s",_("no HVM domain loader"));
+ goto error;
+ }
+
+ if (def->os.kernel)
+ virBufferVSprintf(&buf, "(kernel '%s')", def->os.kernel);
+ if (def->os.initrd)
+ virBufferVSprintf(&buf, "(ramdisk '%s')", def->os.initrd);
+ if (def->os.root)
+ virBufferVSprintf(&buf, "(root '%s')", def->os.root);
+ if (def->os.cmdline)
+ virBufferVSprintf(&buf, "(args '%s')", def->os.cmdline);
+
+ if (hvm) {
+ char bootorder[VIR_DOMAIN_BOOT_LAST+1];
+ if (def->os.kernel)
+ virBufferVSprintf(&buf, "(loader '%s')", def->os.loader);
+ else
+ virBufferVSprintf(&buf, "(kernel '%s')", def->os.loader);
+
+ virBufferVSprintf(&buf, "(vcpus %lu)", def->vcpus);
+
+ for (i = 0 ; i < def->os.nBootDevs ; i++) {
+ switch (def->os.bootDevs[i]) {
+ case VIR_DOMAIN_BOOT_FLOPPY:
+ bootorder[i] = 'a';
+ break;
+ default:
+ case VIR_DOMAIN_BOOT_DISK:
+ bootorder[i] = 'c';
+ break;
+ case VIR_DOMAIN_BOOT_CDROM:
+ bootorder[i] = 'd';
+ break;
+ case VIR_DOMAIN_BOOT_NET:
+ bootorder[i] = 'n';
+ break;
+ }
+ }
+ if (def->os.nBootDevs == 0) {
+ bootorder[0] = 'c';
+ bootorder[1] = '\0';
+ } else {
+ bootorder[def->os.nBootDevs] = '\0';
+ }
+ virBufferVSprintf(&buf, "(boot %s)", bootorder);
+
+ /* get the cdrom device file */
+ /* Only XenD <= 3.0.2 wants cdrom config here */
+ if (xendConfigVersion == 1) {
+ disk = def->disks;
+ while (disk) {
+ if (disk->type == VIR_DOMAIN_DISK_DEVICE_CDROM &&
+ STREQ(disk->dst, "hdc") &&
+ disk->src) {
+ virBufferVSprintf(&buf, "(cdrom '%s')",
+ disk->src);
+ break;
+ }
+ disk = disk->next;
+ }
+ }
+
+ if (def->features & (1 << VIR_DOMAIN_FEATURE_ACPI))
+ virBufferAddLit(&buf, "(acpi 1)");
+ if (def->features & (1 << VIR_DOMAIN_FEATURE_APIC))
+ virBufferAddLit(&buf, "(apic 1)");
+ if (def->features & (1 << VIR_DOMAIN_FEATURE_PAE))
+ virBufferAddLit(&buf, "(pae 1)");
+
+ virBufferAddLit(&buf, "(usb 1)");
+
+ input = def->inputs;
+ while (input) {
+ if (xenDaemonFormatSxprInput(conn, input, &buf) < 0)
+ goto error;
+ input = input->next;
+ }
+
+ if (def->parallels) {
+ if (xenDaemonFormatSxprChr(conn, def->parallels, &buf, "parallel") < 0)
+ goto error;
+ } else {
+ virBufferAddLit(&buf, "(parallel none)");
+ }
+ if (def->serials) {
+ if (xenDaemonFormatSxprChr(conn, def->serials, &buf, "serial") < 0)
+ goto error;
+ } else {
+ virBufferAddLit(&buf, "(serial none)");
+ }
+
+ if (def->localtime)
+ virBufferAddLit(&buf, "(localtime 1)");
+
+ if (xenDaemonFormatSxprSound(conn, def->sounds, &buf) < 0)
+ goto error;
+ }
+
+ /* get the device emulation model */
+ if (def->emulator && (hvm || xendConfigVersion >= 3))
+ virBufferVSprintf(&buf, "(device_model '%s')", def->emulator);
+
+
+ /* PV graphics for xen <= 3.0.4, or HVM graphics for xen <= 3.1.0 */
+ if ((!hvm && xendConfigVersion < 3) ||
+ (hvm && xendConfigVersion < 4)) {
+ if (def->graphics &&
+ xenDaemonFormatSxprGraphicsOld(conn, def->graphics, &buf, xendConfigVersion) < 0)
+ goto error;
+ }
+
+ virBufferAddLit(&buf, "))");
+ }
+
+ disk = def->disks;
+ while (disk) {
+ if (xenDaemonFormatSxprDisk(conn, disk, &buf, hvm, xendConfigVersion) < 0)
+ goto error;
+ disk = disk->next;
+ }
+
+ net = def->nets;
+ while (net) {
+ if (xenDaemonFormatSxprNet(conn, net, &buf, hvm, xendConfigVersion) < 0)
+ goto error;
+ net = net->next;
+ }
+
+ /* New style PV graphics config xen >= 3.0.4,
+ * or HVM graphics config xen >= 3.0.5 */
+ if ((xendConfigVersion >= 3 && !hvm) ||
+ (xendConfigVersion >= 4 && hvm)) {
+ if (def->graphics &&
+ xenDaemonFormatSxprGraphicsNew(conn, def->graphics, &buf) < 0)
+ goto error;
+ }
+
+ virBufferAddLit(&buf, ")"); /* closes (vm */
+
+ return virBufferContentAndReset(&buf);
+
+error:
+ tmp = virBufferContentAndReset(&buf);
+ VIR_FREE(tmp);
+ return NULL;
+}
+
+
+/**
+ * virDomainXMLDevID:
+ * @domain: pointer to domain object
+ * @dev: pointer to device config object
+ * @class: Xen device class "vbd" or "vif" (OUT)
+ * @ref: Xen device reference (OUT)
+ *
+ * Set class according to XML root, and:
+ * - if disk, copy in ref the target name from description
+ * - if network, get MAC address from description, scan XenStore and
+ * copy in ref the corresponding vif number.
+ *
+ * Returns 0 in case of success, -1 in case of failure.
+ */
+static int
+virDomainXMLDevID(virDomainPtr domain,
+ virDomainDeviceDefPtr dev,
+ char *class,
+ char *ref,
+ int ref_len)
+{
+ char *xref;
+
+ if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
+ strcpy(class, "vbd");
+ if (dev->data.disk->dst == NULL)
+ return -1;
+ xref = xenStoreDomainGetDiskID(domain->conn, domain->id,
+ dev->data.disk->dst);
+ if (xref == NULL)
+ return -1;
+
+ strncpy(ref, xref, ref_len);
+ free(xref);
+ ref[ref_len - 1] = '\0';
+ } else if (dev->type == VIR_DOMAIN_DEVICE_NET) {
+ char mac[30];
+ virDomainNetDefPtr def = dev->data.net;
+ snprintf(mac, sizeof(mac), "%02x:%02x:%02x:%02x:%02x:%02x",
+ def->mac[0], def->mac[1], def->mac[2],
+ def->mac[3], def->mac[4], def->mac[5]);
+
+ strcpy(class, "vif");
+
+ xref = xenStoreDomainGetNetworkID(domain->conn, domain->id,
+ mac);
+ if (xref == NULL)
+ return -1;
+
+ strncpy(ref, xref, ref_len);
+ free(xref);
+ ref[ref_len - 1] = '\0';
+ } else {
+ virXendError(NULL, VIR_ERR_NO_SUPPORT,
+ _("hotplug of device type not supported"));
+ return -1;
+ }
+
+ return 0;
+}
+
#endif /* ! PROXY */
#endif /* WITH_XEN */
/*
- * libxend/xend.h -- Xend library
+ * xend_internal.h
*
* Copyright (C) 2005,2006
*
* Anthony Liguori <aliguori@us.ibm.com>
* Daniel Veillard <veillard@redhat.com>
*
+ * Copyright 2006-2008 Red Hat
+ *
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License. See the file COPYING in the main directory of this archive
* for more details.
*/
-#ifndef _LIBXEND_XEND_H_
-#define _LIBXEND_XEND_H_
+#ifndef __XEND_INTERNAL_H_
+#define __XEND_INTERNAL_H_
#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
-#include "libvirt/libvirt.h"
+#include "internal.h"
#include "capabilities.h"
#include "domain_conf.h"
#include "buf.h"
char **name, unsigned char *uuid);
-char *xenDaemonDomainDumpXMLByID(virConnectPtr xend,
- int domid,
- int flags,
- const char *cpus);
-
-char *xenDaemonDomainDumpXMLByName(virConnectPtr xend,
- const char *name,
- int flags,
- const char *cpus);
+virDomainDefPtr
+xenDaemonDomainFetch(virConnectPtr xend,
+ int domid,
+ const char *name,
+ const char *cpus);
int xend_parse_sexp_desc_char(virConnectPtr conn,
virBufferPtr buf,
xenDaemonParseSxprString(virConnectPtr conn,
const char *sexpr,
int xendConfigVersion);
+char *
+xenDaemonFormatSxpr(virConnectPtr conn,
+ virDomainDefPtr def,
+ int xendConfigVersion);
int is_sound_model_valid(const char *model);
int is_sound_model_conflict(const char *model, const char *soundstr);
int xenDaemonDomainBlockPeek (virDomainPtr domain, const char *path, unsigned long long offset, size_t size, void *buffer);
-#ifdef __cplusplus
-}
-#endif
-#endif
+#endif /* __XEND_INTERNAL_H_ */
int ret;
unsigned char uuid[VIR_UUID_BUFLEN];
xenUnifiedPrivatePtr priv;
-
- if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
- xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
- __FUNCTION__);
- return (-1);
- }
+ virDomainDefPtr def;
if (domain->id != -1)
return (-1);
- if (domain->conn->flags & VIR_CONNECT_RO)
- return (-1);
if (!(xml = xenXMDomainDumpXML(domain, 0)))
return (-1);
priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
- if (!(sexpr = virDomainParseXMLDesc(domain->conn, xml, NULL, priv->xendConfigVersion))) {
- VIR_FREE(xml);
+ if (!(def = virDomainDefParseString(domain->conn, priv->caps, xml))) {
+ xenXMError(domain->conn, VIR_ERR_XML_ERROR,
+ _("failed to parse domain description"));
return (-1);
}
VIR_FREE(xml);
+ if (!(sexpr = xenDaemonFormatSxpr(domain->conn, def, priv->xendConfigVersion))) {
+ virDomainDefFree(def);
+ xenXMError(domain->conn, VIR_ERR_XML_ERROR,
+ _("failed to build sexpr"));
+ return (-1);
+ }
+ virDomainDefFree(def);
+
ret = xenDaemonDomainCreateLinux(domain->conn, sexpr);
VIR_FREE(sexpr);
if (ret != 0) {
#include <string.h>
#include <stdarg.h>
#include <limits.h>
-#ifdef WITH_XEN
-#include <xs.h>
-#endif
#include <math.h> /* for isnan() */
#include "c-ctype.h"
#include "internal.h"
-#include "hash.h"
-#include "sexpr.h"
#include "xml.h"
#include "buf.h"
#include "util.h"
#include "memory.h"
-#include "xs_internal.h" /* for xenStoreDomainGetNetworkID */
-#include "xen_unified.h"
#include "xend_internal.h" /* for is_sound_* functions */
+
/**
* virXMLError:
* @conn: a connection if any
errmsg, info, NULL, value, 0, errmsg, info, value);
}
-/************************************************************************
- * *
- * Parser and converter for the CPUset strings used in libvirt *
- * *
- ************************************************************************/
-#if WITH_XEN || WITH_QEMU
-/**
- * parseCpuNumber:
- * @str: pointer to the char pointer used
- * @maxcpu: maximum CPU number allowed
- *
- * Parse a CPU number
- *
- * Returns the CPU number or -1 in case of error. @str will be
- * updated to skip the number.
- */
-static int
-parseCpuNumber(const char **str, int maxcpu)
-{
- int ret = 0;
- const char *cur = *str;
-
- if (!c_isdigit(*cur))
- return (-1);
-
- while (c_isdigit(*cur)) {
- ret = ret * 10 + (*cur - '0');
- if (ret >= maxcpu)
- return (-1);
- cur++;
- }
- *str = cur;
- return (ret);
-}
-
-/**
- * virSaveCpuSet:
- * @conn: connection
- * @cpuset: pointer to a char array for the CPU set
- * @maxcpu: number of elements available in @cpuset
- *
- * Serialize the cpuset to a string
- *
- * Returns the new string NULL in case of error. The string need to be
- * freed by the caller.
- */
-char *
-virSaveCpuSet(virConnectPtr conn, char *cpuset, int maxcpu)
-{
- virBuffer buf = VIR_BUFFER_INITIALIZER;
- int start, cur;
- int first = 1;
-
- if ((cpuset == NULL) || (maxcpu <= 0) || (maxcpu > 100000))
- return (NULL);
-
- cur = 0;
- start = -1;
- while (cur < maxcpu) {
- if (cpuset[cur]) {
- if (start == -1)
- start = cur;
- } else if (start != -1) {
- if (!first)
- virBufferAddLit(&buf, ",");
- else
- first = 0;
- if (cur == start + 1)
- virBufferVSprintf(&buf, "%d", start);
- else
- virBufferVSprintf(&buf, "%d-%d", start, cur - 1);
- start = -1;
- }
- cur++;
- }
- if (start != -1) {
- if (!first)
- virBufferAddLit(&buf, ",");
- if (maxcpu == start + 1)
- virBufferVSprintf(&buf, "%d", start);
- else
- virBufferVSprintf(&buf, "%d-%d", start, maxcpu - 1);
- }
-
- if (virBufferError(&buf)) {
- virXMLError(conn, VIR_ERR_NO_MEMORY, _("allocate buffer"), 1000);
- return NULL;
- }
-
- return virBufferContentAndReset(&buf);
-}
-
-/**
- * virParseCpuSet:
- * @conn: connection
- * @str: pointer to a CPU set string pointer
- * @sep: potential character used to mark the end of string if not 0
- * @cpuset: pointer to a char array for the CPU set
- * @maxcpu: number of elements available in @cpuset
- *
- * Parse the cpu set, it will set the value for enabled CPUs in the @cpuset
- * to 1, and 0 otherwise. The syntax allows coma separated entries each
- * can be either a CPU number, ^N to unset that CPU or N-M for ranges.
- *
- * Returns the number of CPU found in that set, or -1 in case of error.
- * @cpuset is modified accordingly to the value parsed.
- * @str is updated to the end of the part parsed
- */
-int
-virParseCpuSet(virConnectPtr conn, const char **str, char sep,
- char *cpuset, int maxcpu)
-{
- const char *cur;
- int ret = 0;
- int i, start, last;
- int neg = 0;
-
- if ((str == NULL) || (cpuset == NULL) || (maxcpu <= 0) ||
- (maxcpu > 100000))
- return (-1);
-
- cur = *str;
- virSkipSpaces(&cur);
- if (*cur == 0)
- goto parse_error;
-
- /* initialize cpumap to all 0s */
- for (i = 0; i < maxcpu; i++)
- cpuset[i] = 0;
- ret = 0;
-
- while ((*cur != 0) && (*cur != sep)) {
- /*
- * 3 constructs are allowed:
- * - N : a single CPU number
- * - N-M : a range of CPU numbers with N < M
- * - ^N : remove a single CPU number from the current set
- */
- if (*cur == '^') {
- cur++;
- neg = 1;
- }
-
- if (!c_isdigit(*cur))
- goto parse_error;
- start = parseCpuNumber(&cur, maxcpu);
- if (start < 0)
- goto parse_error;
- virSkipSpaces(&cur);
- if ((*cur == ',') || (*cur == 0) || (*cur == sep)) {
- if (neg) {
- if (cpuset[start] == 1) {
- cpuset[start] = 0;
- ret--;
- }
- } else {
- if (cpuset[start] == 0) {
- cpuset[start] = 1;
- ret++;
- }
- }
- } else if (*cur == '-') {
- if (neg)
- goto parse_error;
- cur++;
- virSkipSpaces(&cur);
- last = parseCpuNumber(&cur, maxcpu);
- if (last < start)
- goto parse_error;
- for (i = start; i <= last; i++) {
- if (cpuset[i] == 0) {
- cpuset[i] = 1;
- ret++;
- }
- }
- virSkipSpaces(&cur);
- }
- if (*cur == ',') {
- cur++;
- virSkipSpaces(&cur);
- neg = 0;
- } else if ((*cur == 0) || (*cur == sep)) {
- break;
- } else
- goto parse_error;
- }
- *str = cur;
- return (ret);
-
- parse_error:
- virXMLError(conn, VIR_ERR_XEN_CALL,
- _("topology cpuset syntax error"), 0);
- return (-1);
-}
-#endif
-
-#if WITH_XEN
-/**
- * virConvertCpuSet:
- * @conn: connection
- * @str: pointer to a Xen or user provided CPU set string pointer
- * @maxcpu: number of CPUs on the node, if 0 4096 will be used
- *
- * Parse the given CPU set string and convert it to a range based
- * string.
- *
- * Returns a new string which must be freed by the caller or NULL in
- * case of error.
- */
-char *
-virConvertCpuSet(virConnectPtr conn, const char *str, int maxcpu) {
- int ret;
- char *res, *cpuset;
- const char *cur = str;
-
- if (str == NULL)
- return(NULL);
-
- if (maxcpu <= 0)
- maxcpu = 4096;
-
- if (VIR_ALLOC_N(cpuset, maxcpu) < 0) {
- virXMLError(conn, VIR_ERR_NO_MEMORY, _("allocate buffer"), 0);
- return(NULL);
- }
-
- ret = virParseCpuSet(conn, &cur, 0, cpuset, maxcpu);
- if (ret < 0) {
- VIR_FREE(cpuset);
- return(NULL);
- }
- res = virSaveCpuSet(conn, cpuset, maxcpu);
- VIR_FREE(cpuset);
- return (res);
-}
-
-#ifndef PROXY
-/**
- * virBuildSoundStringFromXML
- * @sound buffer to populate
- * @len size of preallocated buffer 'sound'
- * @ctxt xml context to pull sound info from
- *
- * Builds a string of the form m1,m2,m3 from the different sound models
- * in the xml. String must be free'd by caller.
- *
- * Returns string on success, NULL on error
- */
-char * virBuildSoundStringFromXML(virConnectPtr conn,
- xmlXPathContextPtr ctxt) {
-
- int nb_nodes, size = 256;
- char *sound;
- xmlNodePtr *nodes = NULL;
-
- if (VIR_ALLOC_N(sound, size + 1) < 0) {
- virXMLError(conn, VIR_ERR_NO_MEMORY,
- _("failed to allocate sound string"), 0);
- return NULL;
- }
-
- nb_nodes = virXPathNodeSet("/domain/devices/sound", ctxt, &nodes);
- if (nb_nodes > 0) {
- int i;
- for (i = 0; i < nb_nodes && size > 0; i++) {
- char *model = NULL;
- int collision = 0;
-
- model = (char *) xmlGetProp(nodes[i], (xmlChar *) "model");
- if (!model) {
- virXMLError(conn, VIR_ERR_XML_ERROR,
- _("no model for sound device"), 0);
- goto error;
- }
-
- if (!is_sound_model_valid(model)) {
- virXMLError(conn, VIR_ERR_XML_ERROR,
- _("unknown sound model type"), 0);
- VIR_FREE(model);
- goto error;
- }
-
- // Check for duplicates in currently built string
- if (*sound)
- collision = is_sound_model_conflict(model, sound);
-
- // If no collision, add to string
- if (!collision) {
- if (*sound && (size >= (strlen(model) + 1))) {
- strncat(sound, ",", size--);
- } else if (*sound || size < strlen(model)) {
- VIR_FREE(model);
- continue;
- }
- strncat(sound, model, size);
- size -= strlen(model);
- }
-
- VIR_FREE(model);
- }
- }
- VIR_FREE(nodes);
- return sound;
-
- error:
- VIR_FREE(nodes);
- return NULL;
-}
-#endif /* !PROXY */
-#endif /* WITH_XEN */
-#ifndef PROXY
/************************************************************************
* *
return (ret);
}
-/************************************************************************
- * *
- * Converter functions to go from the XML tree to an S-Expr for Xen *
- * *
- ************************************************************************/
#if WITH_XEN
+#ifndef PROXY
/**
- * virtDomainParseXMLGraphicsDescImage:
- * @conn: pointer to the hypervisor connection
- * @node: node containing graphics description
- * @buf: a buffer for the result S-Expr
- * @xendConfigVersion: xend configuration file format
+ * virConvertCpuSet:
+ * @conn: connection
+ * @str: pointer to a Xen or user provided CPU set string pointer
+ * @maxcpu: number of CPUs on the node, if 0 4096 will be used
*
- * Parse the graphics part of the XML description and add it to the S-Expr
- * in buf. This is a temporary interface as the S-Expr interface will be
- * replaced by XML-RPC in the future. However the XML format should stay
- * valid over time.
+ * Parse the given CPU set string and convert it to a range based
+ * string.
*
- * Returns 0 in case of success, -1 in case of error
+ * Returns a new string which must be freed by the caller or NULL in
+ * case of error.
*/
-static int
-virDomainParseXMLGraphicsDescImage(virConnectPtr conn ATTRIBUTE_UNUSED,
- xmlNodePtr node, virBufferPtr buf,
- int xendConfigVersion)
-{
- xmlChar *graphics_type = NULL;
-
- graphics_type = xmlGetProp(node, BAD_CAST "type");
- if (graphics_type != NULL) {
- if (xmlStrEqual(graphics_type, BAD_CAST "sdl")) {
- virBufferAddLit(buf, "(sdl 1)");
- /* TODO:
- * Need to understand sdl options
- *
- *virBufferAddLit(buf, "(display localhost:10.0)");
- *virBufferAddLit(buf, "(xauthority /root/.Xauthority)");
- */
- } else if (xmlStrEqual(graphics_type, BAD_CAST "vnc")) {
- virBufferAddLit(buf, "(vnc 1)");
- if (xendConfigVersion >= 2) {
- xmlChar *vncport = xmlGetProp(node, BAD_CAST "port");
- xmlChar *vnclisten = xmlGetProp(node, BAD_CAST "listen");
- xmlChar *vncpasswd = xmlGetProp(node, BAD_CAST "passwd");
- xmlChar *keymap = xmlGetProp(node, BAD_CAST "keymap");
-
- if (vncport != NULL) {
- long port = strtol((const char *) vncport, NULL, 10);
-
- if (port == -1)
- virBufferAddLit(buf, "(vncunused 1)");
- else if (port >= 5900)
- virBufferVSprintf(buf, "(vncdisplay %ld)",
- port - 5900);
- xmlFree(vncport);
- }
- if (vnclisten != NULL) {
- virBufferVSprintf(buf, "(vnclisten %s)", vnclisten);
- xmlFree(vnclisten);
- }
- if (vncpasswd != NULL) {
- virBufferVSprintf(buf, "(vncpasswd %s)", vncpasswd);
- xmlFree(vncpasswd);
- }
- if (keymap != NULL) {
- virBufferVSprintf(buf, "(keymap %s)", keymap);
- xmlFree(keymap);
- }
- }
- }
- xmlFree(graphics_type);
+char *
+virConvertCpuSet(virConnectPtr conn, const char *str, int maxcpu) {
+ int ret;
+ char *res, *cpuset;
+ const char *cur = str;
+
+ if (str == NULL)
+ return(NULL);
+
+ if (maxcpu <= 0)
+ maxcpu = 4096;
+
+ if (VIR_ALLOC_N(cpuset, maxcpu) < 0) {
+ virXMLError(conn, VIR_ERR_NO_MEMORY, _("allocate buffer"), 0);
+ return(NULL);
}
- return 0;
+
+ ret = virDomainCpuSetParse(conn, &cur, 0, cpuset, maxcpu);
+ if (ret < 0) {
+ VIR_FREE(cpuset);
+ return(NULL);
+ }
+ res = virDomainCpuSetFormat(conn, cpuset, maxcpu);
+ VIR_FREE(cpuset);
+ return (res);
}
/**
- * virtDomainParseXMLGraphicsDescVFB:
- * @conn: pointer to the hypervisor connection
- * @node: node containing graphics description
- * @buf: a buffer for the result S-Expr
+ * virBuildSoundStringFromXML
+ * @sound buffer to populate
+ * @len size of preallocated buffer 'sound'
+ * @ctxt xml context to pull sound info from
*
- * Parse the graphics part of the XML description and add it to the S-Expr
- * in buf. This is a temporary interface as the S-Expr interface will be
- * replaced by XML-RPC in the future. However the XML format should stay
- * valid over time.
+ * Builds a string of the form m1,m2,m3 from the different sound models
+ * in the xml. String must be free'd by caller.
*
- * Returns 0 in case of success, -1 in case of error
+ * Returns string on success, NULL on error
*/
-static int
-virDomainParseXMLGraphicsDescVFB(virConnectPtr conn ATTRIBUTE_UNUSED,
- xmlNodePtr node, virBufferPtr buf)
-{
- xmlChar *graphics_type = NULL;
-
- graphics_type = xmlGetProp(node, BAD_CAST "type");
- if (graphics_type != NULL) {
- virBufferAddLit(buf, "(device (vkbd))");
- virBufferAddLit(buf, "(device (vfb ");
- if (xmlStrEqual(graphics_type, BAD_CAST "sdl")) {
- virBufferAddLit(buf, "(type sdl)");
- /* TODO:
- * Need to understand sdl options
- *
- *virBufferAddLit(buf, "(display localhost:10.0)");
- *virBufferAddLit(buf, "(xauthority /root/.Xauthority)");
- */
- } else if (xmlStrEqual(graphics_type, BAD_CAST "vnc")) {
- virBufferAddLit(buf, "(type vnc)");
- xmlChar *vncport = xmlGetProp(node, BAD_CAST "port");
- xmlChar *vnclisten = xmlGetProp(node, BAD_CAST "listen");
- xmlChar *vncpasswd = xmlGetProp(node, BAD_CAST "passwd");
- xmlChar *keymap = xmlGetProp(node, BAD_CAST "keymap");
-
- if (vncport != NULL) {
- long port = strtol((const char *) vncport, NULL, 10);
-
- if (port == -1)
- virBufferAddLit(buf, "(vncunused 1)");
- else if (port >= 5900)
- virBufferVSprintf(buf, "(vncdisplay %ld)",
- port - 5900);
- xmlFree(vncport);
- }
- if (vnclisten != NULL) {
- virBufferVSprintf(buf, "(vnclisten %s)", vnclisten);
- xmlFree(vnclisten);
- }
- if (vncpasswd != NULL) {
- virBufferVSprintf(buf, "(vncpasswd %s)", vncpasswd);
- xmlFree(vncpasswd);
- }
- if (keymap != NULL) {
- virBufferVSprintf(buf, "(keymap %s)", keymap);
- xmlFree(keymap);
- }
- }
- virBufferAddLit(buf, "))");
- xmlFree(graphics_type);
+char * virBuildSoundStringFromXML(virConnectPtr conn,
+ xmlXPathContextPtr ctxt) {
+
+ int nb_nodes, size = 256;
+ char *sound;
+ xmlNodePtr *nodes = NULL;
+
+ if (VIR_ALLOC_N(sound, size + 1) < 0) {
+ virXMLError(conn, VIR_ERR_NO_MEMORY,
+ _("failed to allocate sound string"), 0);
+ return NULL;
}
- return 0;
-}
+ nb_nodes = virXPathNodeSet("/domain/devices/sound", ctxt, &nodes);
+ if (nb_nodes > 0) {
+ int i;
+ for (i = 0; i < nb_nodes && size > 0; i++) {
+ char *model = NULL;
+ int collision = 0;
-int
-virDomainParseXMLOSDescHVMChar(virConnectPtr conn,
- char *buf,
- size_t buflen,
- xmlNodePtr node)
-{
+ model = (char *) xmlGetProp(nodes[i], (xmlChar *) "model");
+ if (!model) {
+ virXMLError(conn, VIR_ERR_XML_ERROR,
+ _("no model for sound device"), 0);
+ goto error;
+ }
+
+ if (!is_sound_model_valid(model)) {
+ virXMLError(conn, VIR_ERR_XML_ERROR,
+ _("unknown sound model type"), 0);
+ VIR_FREE(model);
+ goto error;
+ }
+
+ // Check for duplicates in currently built string
+ if (*sound)
+ collision = is_sound_model_conflict(model, sound);
+
+ // If no collision, add to string
+ if (!collision) {
+ if (*sound && (size >= (strlen(model) + 1))) {
+ strncat(sound, ",", size--);
+ } else if (*sound || size < strlen(model)) {
+ VIR_FREE(model);
+ continue;
+ }
+ strncat(sound, model, size);
+ size -= strlen(model);
+ }
+
+ VIR_FREE(model);
+ }
+ }
+ VIR_FREE(nodes);
+ return sound;
+ error:
+ VIR_FREE(nodes);
+ return NULL;
+}
+
+int
+virDomainParseXMLOSDescHVMChar(virConnectPtr conn,
+ char *buf,
+ size_t buflen,
+ xmlNodePtr node)
+{
xmlChar *type = NULL;
xmlChar *path = NULL;
xmlChar *bindHost = NULL;
return -1;
}
-/**
- * virDomainParseXMLOSDescHVM:
- * @conn: pointer to the hypervisor connection
- * @node: node containing HVM OS description
- * @buf: a buffer for the result S-Expr
- * @ctxt: a path context representing the XML description
- * @vcpus: number of virtual CPUs to configure
- * @xendConfigVersion: xend configuration file format
- * @hasKernel: whether the domain is booting from a kernel
- *
- * Parse the OS part of the XML description for a HVM domain
- * and add it to the S-Expr in buf.
- *
- * Returns 0 in case of success, -1 in case of error.
- */
-static int
-virDomainParseXMLOSDescHVM(virConnectPtr conn, xmlNodePtr node,
- virBufferPtr buf, xmlXPathContextPtr ctxt,
- int vcpus, int xendConfigVersion,
- int hasKernel)
-{
- xmlNodePtr cur, txt;
- xmlNodePtr *nodes = NULL;
- xmlChar *loader = NULL;
- char bootorder[5];
- int nbootorder = 0;
- int res, nb_nodes;
- char *str;
-
- cur = node->children;
- while (cur != NULL) {
- if (cur->type == XML_ELEMENT_NODE) {
- if ((loader == NULL) &&
- (xmlStrEqual(cur->name, BAD_CAST "loader"))) {
- txt = cur->children;
- if ((txt != NULL) && (txt->type == XML_TEXT_NODE) &&
- (txt->next == NULL))
- loader = txt->content;
- } else if ((xmlStrEqual(cur->name, BAD_CAST "boot"))) {
- xmlChar *boot_dev = xmlGetProp(cur, BAD_CAST "dev");
-
- if (nbootorder ==
- ((sizeof(bootorder) / sizeof(bootorder[0])) - 1)) {
- virXMLError(conn, VIR_ERR_XML_ERROR,
- _("too many boot devices"), 0);
- return (-1);
- }
- if (xmlStrEqual(boot_dev, BAD_CAST "fd")) {
- bootorder[nbootorder++] = 'a';
- } else if (xmlStrEqual(boot_dev, BAD_CAST "cdrom")) {
- bootorder[nbootorder++] = 'd';
- } else if (xmlStrEqual(boot_dev, BAD_CAST "network")) {
- bootorder[nbootorder++] = 'n';
- } else if (xmlStrEqual(boot_dev, BAD_CAST "hd")) {
- bootorder[nbootorder++] = 'c';
- } else {
- xmlFree(boot_dev);
- /* Any other type of boot dev is unsupported right now */
- virXMLError(conn, VIR_ERR_XML_ERROR, NULL, 0);
- return (-1);
- }
- xmlFree(boot_dev);
- }
- }
- cur = cur->next;
- }
- /*
- * XenD always needs boot order defined for HVM, even if
- * booting off a kernel + initrd, so force to 'c' if nothing
- * else is specified
- */
- if (nbootorder == 0)
- bootorder[nbootorder++] = 'c';
- bootorder[nbootorder] = '\0';
-
- if (loader == NULL) {
- virXMLError(conn, VIR_ERR_INTERNAL_ERROR, _("no HVM domain loader"), 0);
- return -1;
- }
-
- /*
- * Originally XenD abused the 'kernel' parameter for the HVM
- * firmware. New XenD allows HVM guests to boot from a kernel
- * and if this is enabled, the HVM firmware must use the new
- * 'loader' parameter
- */
- if (hasKernel) {
- virBufferVSprintf(buf, "(loader '%s')", (const char *) loader);
- } else {
- virBufferVSprintf(buf, "(kernel '%s')", (const char *) loader);
- }
-
- virBufferVSprintf(buf, "(vcpus %d)", vcpus);
-
- if (nbootorder)
- virBufferVSprintf(buf, "(boot %s)", bootorder);
-
- /* get the 1st floppy device file */
- cur = virXPathNode(
- "/domain/devices/disk[@device='floppy' and target/@dev='fda']/source",
- ctxt);
- if (cur != NULL) {
- xmlChar *fdfile;
-
- fdfile = xmlGetProp(cur, BAD_CAST "file");
- if (fdfile != NULL) {
- virBufferVSprintf(buf, "(fda '%s')", fdfile);
- VIR_FREE(fdfile);
- }
- }
-
- /* get the 2nd floppy device file */
- cur = virXPathNode(
- "/domain/devices/disk[@device='floppy' and target/@dev='fdb']/source",
- ctxt);
- if (cur != NULL) {
- xmlChar *fdfile;
-
- fdfile = xmlGetProp(cur, BAD_CAST "file");
- if (fdfile != NULL) {
- virBufferVSprintf(buf, "(fdb '%s')", fdfile);
- VIR_FREE(fdfile);
- }
- }
-
- /* get the cdrom device file */
- /* Only XenD <= 3.0.2 wants cdrom config here */
- if (xendConfigVersion == 1) {
- cur = virXPathNode(
- "/domain/devices/disk[@device='cdrom' and target/@dev='hdc']/source",
- ctxt);
- if (cur != NULL) {
- xmlChar *cdfile;
-
- cdfile = xmlGetProp(cur, BAD_CAST "file");
- if (cdfile != NULL) {
- virBufferVSprintf(buf, "(cdrom '%s')",
- (const char *) cdfile);
- xmlFree(cdfile);
- }
- }
- }
-
- if (virXPathNode("/domain/features/acpi", ctxt) != NULL)
- virBufferAddLit(buf, "(acpi 1)");
- if (virXPathNode("/domain/features/apic", ctxt) != NULL)
- virBufferAddLit(buf, "(apic 1)");
- if (virXPathNode("/domain/features/pae", ctxt) != NULL)
- virBufferAddLit(buf, "(pae 1)");
-
- virBufferAddLit(buf, "(usb 1)");
- nb_nodes = virXPathNodeSet("/domain/devices/input", ctxt, &nodes);
- if (nb_nodes > 0) {
- int i;
-
- for (i = 0; i < nb_nodes; i++) {
- xmlChar *itype = NULL, *bus = NULL;
- int isMouse = 1;
-
- itype = xmlGetProp(nodes[i], (xmlChar *) "type");
-
- if (!itype) {
- goto error;
- }
- if (STREQ((const char *) itype, "tablet"))
- isMouse = 0;
- else if (STRNEQ((const char *) itype, "mouse")) {
- xmlFree(itype);
- virXMLError(conn, VIR_ERR_XML_ERROR,
- _("invalid input device"), 0);
- goto error;
- }
- xmlFree(itype);
-
- bus = xmlGetProp(nodes[i], (xmlChar *) "bus");
- if (!bus) {
- if (!isMouse) {
- /* Nothing - implicit ps2 */
- } else {
- virBufferAddLit(buf, "(usbdevice tablet)");
- }
- } else {
- if (STREQ((const char *) bus, "ps2")) {
- if (!isMouse) {
- xmlFree(bus);
- virXMLError(conn, VIR_ERR_XML_ERROR,
- _("invalid input device"), 0);
- goto error;
- }
- /* Nothing - implicit ps2 */
- } else if (STREQ((const char *) bus, "usb")) {
- if (isMouse)
- virBufferAddLit(buf, "(usbdevice mouse)");
- else
- virBufferAddLit(buf, "(usbdevice tablet)");
- }
- }
- xmlFree(bus);
- }
- VIR_FREE(nodes);
- nodes = NULL;
- }
-
- cur = virXPathNode("/domain/devices/parallel[1]", ctxt);
- if (cur != NULL) {
- char scratch[PATH_MAX];
- if (virDomainParseXMLOSDescHVMChar(conn, scratch, sizeof(scratch), cur) < 0)
- goto error;
- virBufferVSprintf(buf, "(parallel %s)", scratch);
- } else {
- virBufferAddLit(buf, "(parallel none)");
- }
-
- cur = virXPathNode("/domain/devices/serial[1]", ctxt);
- if (cur != NULL) {
- char scratch[PATH_MAX];
- if (virDomainParseXMLOSDescHVMChar(conn, scratch, sizeof(scratch), cur) < 0)
- goto error;
- virBufferVSprintf(buf, "(serial %s)", scratch);
- } else {
- res = virXPathBoolean("count(/domain/devices/console) > 0", ctxt);
- if (res < 0) {
- virXMLError(conn, VIR_ERR_XML_ERROR, NULL, 0);
- goto error;
- }
- if (res) {
- virBufferAddLit(buf, "(serial pty)");
- } else {
- virBufferAddLit(buf, "(serial none)");
- }
- }
-
- cur = virXPathNode("/domain/devices/sound", ctxt);
- if (cur) {
- char *soundstr;
- if (!(soundstr = virBuildSoundStringFromXML(conn, ctxt)))
- goto error;
- virBufferVSprintf(buf, "(soundhw '%s')", soundstr);
- VIR_FREE(soundstr);
- }
-
- str = virXPathString("string(/domain/clock/@offset)", ctxt);
- if (str != NULL && STREQ(str, "localtime")) {
- virBufferAddLit(buf, "(localtime 1)");
- }
- VIR_FREE(str);
-
- return (0);
-
- error:
- VIR_FREE(nodes);
- return (-1);
-}
-
-
-/**
- * virDomainParseXMLOSDescKernel:
- * @conn: pointer to the hypervisor connection
- * @node: node containing PV OS description
- * @buf: a buffer for the result S-Expr
- *
- * Parse the OS part of the XML description for a domain using a direct
- * kernel and initrd to boot.
- *
- * Returns 0 in case of success, -1 in case of error.
- */
-static int
-virDomainParseXMLOSDescKernel(virConnectPtr conn ATTRIBUTE_UNUSED,
- xmlNodePtr node,
- virBufferPtr buf)
-{
- xmlNodePtr cur, txt;
- const xmlChar *root = NULL;
- const xmlChar *kernel = NULL;
- const xmlChar *initrd = NULL;
- const xmlChar *cmdline = NULL;
-
- cur = node->children;
- while (cur != NULL) {
- if (cur->type == XML_ELEMENT_NODE) {
- if ((kernel == NULL) &&
- (xmlStrEqual(cur->name, BAD_CAST "kernel"))) {
- txt = cur->children;
- if ((txt != NULL) && (txt->type == XML_TEXT_NODE) &&
- (txt->next == NULL))
- kernel = txt->content;
- } else if ((root == NULL) &&
- (xmlStrEqual(cur->name, BAD_CAST "root"))) {
- txt = cur->children;
- if ((txt != NULL) && (txt->type == XML_TEXT_NODE) &&
- (txt->next == NULL))
- root = txt->content;
- } else if ((initrd == NULL) &&
- (xmlStrEqual(cur->name, BAD_CAST "initrd"))) {
- txt = cur->children;
- if ((txt != NULL) && (txt->type == XML_TEXT_NODE) &&
- (txt->next == NULL))
- initrd = txt->content;
- } else if ((cmdline == NULL) &&
- (xmlStrEqual(cur->name, BAD_CAST "cmdline"))) {
- txt = cur->children;
- if ((txt != NULL) && (txt->type == XML_TEXT_NODE) &&
- (txt->next == NULL))
- cmdline = txt->content;
- }
- }
- cur = cur->next;
- }
-
- virBufferVSprintf(buf, "(kernel '%s')", (const char *) kernel);
-
- if (initrd != NULL)
- virBufferVSprintf(buf, "(ramdisk '%s')", (const char *) initrd);
- if (root != NULL)
- virBufferVSprintf(buf, "(root '%s')", (const char *) root);
- if (cmdline != NULL)
- virBufferVSprintf(buf, "(args '%s')", (const char *) cmdline);
-
- return (0);
-}
-
-/**
- * virCatchXMLParseError:
- * @ctx: the context
- * @msg: the error message
- * @...: extra arguments
- *
- * SAX callback on parsing errors, act as a gate for libvirt own
- * error reporting.
- */
-static void
-virCatchXMLParseError(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
-{
- xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-
- if ((ctxt != NULL) &&
- (ctxt->lastError.level == XML_ERR_FATAL) &&
- (ctxt->lastError.message != NULL)) {
- virXMLError(NULL, VIR_ERR_XML_DETAIL, ctxt->lastError.message,
- ctxt->lastError.line);
- }
-}
-
-/**
- * virDomainParseXMLDiskDesc:
- * @node: node containing disk description
- * @conn: pointer to the hypervisor connection
- * @buf: a buffer for the result S-Expr
- * @xendConfigVersion: xend configuration file format
- *
- * Parse the one disk in the XML description and add it to the S-Expr in buf
- * This is a temporary interface as the S-Expr interface
- * will be replaced by XML-RPC in the future. However the XML format should
- * stay valid over time.
- *
- * Returns 0 in case of success, -1 in case of error.
- */
-static int
-virDomainParseXMLDiskDesc(virConnectPtr conn, xmlNodePtr node,
- virBufferPtr buf, int hvm, int xendConfigVersion)
-{
- xmlNodePtr cur;
- xmlChar *type = NULL;
- xmlChar *device = NULL;
- xmlChar *source = NULL;
- xmlChar *target = NULL;
- xmlChar *drvName = NULL;
- xmlChar *drvType = NULL;
- int ro = 0;
- int shareable = 0;
- int typ = 0;
- int cdrom = 0;
- int isNoSrcCdrom = 0;
- int ret = 0;
-
- type = xmlGetProp(node, BAD_CAST "type");
- if (type != NULL) {
- if (xmlStrEqual(type, BAD_CAST "file"))
- typ = 0;
- else if (xmlStrEqual(type, BAD_CAST "block"))
- typ = 1;
- xmlFree(type);
- }
- device = xmlGetProp(node, BAD_CAST "device");
-
- cur = node->children;
- while (cur != NULL) {
- if (cur->type == XML_ELEMENT_NODE) {
- if ((source == NULL) &&
- (xmlStrEqual(cur->name, BAD_CAST "source"))) {
-
- if (typ == 0)
- source = xmlGetProp(cur, BAD_CAST "file");
- else
- source = xmlGetProp(cur, BAD_CAST "dev");
- } else if ((target == NULL) &&
- (xmlStrEqual(cur->name, BAD_CAST "target"))) {
- target = xmlGetProp(cur, BAD_CAST "dev");
- } else if ((drvName == NULL) &&
- (xmlStrEqual(cur->name, BAD_CAST "driver"))) {
- drvName = xmlGetProp(cur, BAD_CAST "name");
- if (drvName && STREQ((const char *) drvName, "tap"))
- drvType = xmlGetProp(cur, BAD_CAST "type");
- } else if (xmlStrEqual(cur->name, BAD_CAST "readonly")) {
- ro = 1;
- } else if (xmlStrEqual(cur->name, BAD_CAST "shareable")) {
- shareable = 1;
- }
- }
- cur = cur->next;
- }
-
- if (source == NULL) {
- /* There is a case without the source
- * to the CD-ROM device
- */
- if (hvm && device && STREQ((const char *) device, "cdrom")) {
- isNoSrcCdrom = 1;
- }
- if (!isNoSrcCdrom) {
- virXMLError(conn, VIR_ERR_NO_SOURCE, (const char *) target, 0);
- ret = -1;
- goto cleanup;
- }
- }
- if (target == NULL) {
- virXMLError(conn, VIR_ERR_NO_TARGET, (const char *) source, 0);
- ret = -1;
- goto cleanup;
- }
-
- /* Xend (all versions) put the floppy device config
- * under the hvm (image (os)) block
- */
- if (hvm && device && STREQ((const char *) device, "floppy")) {
- goto cleanup;
- }
-
- /* Xend <= 3.0.2 doesn't include cdrom config here */
- if (hvm && device && STREQ((const char *) device, "cdrom")) {
- if (xendConfigVersion == 1)
- goto cleanup;
- else
- cdrom = 1;
- }
-
-
- virBufferAddLit(buf, "(device ");
- /* Normally disks are in a (device (vbd ...)) block
- * but blktap disks ended up in a differently named
- * (device (tap ....)) block.... */
- if (drvName && STREQ((const char *) drvName, "tap")) {
- virBufferAddLit(buf, "(tap ");
- } else {
- virBufferAddLit(buf, "(vbd ");
- }
-
- if (hvm) {
- char *tmp = (char *) target;
-
- /* Just in case user mistakenly still puts ioemu: in their XML */
- if (STRPREFIX((const char *) tmp, "ioemu:"))
- tmp += 6;
-
- /* Xend <= 3.0.2 wants a ioemu: prefix on devices for HVM */
- if (xendConfigVersion == 1)
- virBufferVSprintf(buf, "(dev 'ioemu:%s')", (const char *) tmp);
- else /* But newer does not */
- virBufferVSprintf(buf, "(dev '%s%s')", (const char *) tmp,
- cdrom ? ":cdrom" : ":disk");
- } else
- virBufferVSprintf(buf, "(dev '%s')", (const char *) target);
-
- if (drvName && !isNoSrcCdrom) {
- if (STREQ((const char *) drvName, "tap")) {
- virBufferVSprintf(buf, "(uname '%s:%s:%s')",
- (const char *) drvName,
- (drvType ? (const char *) drvType : "aio"),
- (const char *) source);
- } else {
- virBufferVSprintf(buf, "(uname '%s:%s')",
- (const char *) drvName,
- (const char *) source);
- }
- } else if (!isNoSrcCdrom) {
- if (typ == 0)
- virBufferVSprintf(buf, "(uname 'file:%s')", source);
- else if (typ == 1) {
- if (source[0] == '/')
- virBufferVSprintf(buf, "(uname 'phy:%s')", source);
- else
- virBufferVSprintf(buf, "(uname 'phy:/dev/%s')", source);
- }
- }
- if (ro == 1)
- virBufferAddLit(buf, "(mode 'r')");
- else if (shareable == 1)
- virBufferAddLit(buf, "(mode 'w!')");
- else
- virBufferAddLit(buf, "(mode 'w')");
-
- virBufferAddLit(buf, ")");
- virBufferAddLit(buf, ")");
-
- cleanup:
- xmlFree(drvType);
- xmlFree(drvName);
- xmlFree(device);
- xmlFree(target);
- xmlFree(source);
- return (ret);
-}
-
-/**
- * virDomainParseXMLIfDesc:
- * @conn: pointer to the hypervisor connection
- * @node: node containing the interface description
- * @buf: a buffer for the result S-Expr
- * @xendConfigVersion: xend configuration file format
- *
- * Parse the one interface the XML description and add it to the S-Expr in buf
- * This is a temporary interface as the S-Expr interface
- * will be replaced by XML-RPC in the future. However the XML format should
- * stay valid over time.
- *
- * Returns 0 in case of success, -1 in case of error.
- */
-static int
-virDomainParseXMLIfDesc(virConnectPtr conn ATTRIBUTE_UNUSED,
- xmlNodePtr node, virBufferPtr buf, int hvm,
- int xendConfigVersion)
-{
- xmlNodePtr cur;
- xmlChar *type = NULL;
- xmlChar *source = NULL;
- xmlChar *mac = NULL;
- xmlChar *script = NULL;
- xmlChar *model = NULL;
- xmlChar *ip = NULL;
- int typ = 0;
- int ret = -1;
-
- type = xmlGetProp(node, BAD_CAST "type");
- if (type != NULL) {
- if (xmlStrEqual(type, BAD_CAST "bridge"))
- typ = 0;
- else if (xmlStrEqual(type, BAD_CAST "ethernet"))
- typ = 1;
- else if (xmlStrEqual(type, BAD_CAST "network"))
- typ = 2;
- xmlFree(type);
- }
- cur = node->children;
- while (cur != NULL) {
- if (cur->type == XML_ELEMENT_NODE) {
- if ((source == NULL) &&
- (xmlStrEqual(cur->name, BAD_CAST "source"))) {
- if (typ == 0)
- source = xmlGetProp(cur, BAD_CAST "bridge");
- else if (typ == 1)
- source = xmlGetProp(cur, BAD_CAST "dev");
- else
- source = xmlGetProp(cur, BAD_CAST "network");
- } else if ((mac == NULL) &&
- (xmlStrEqual(cur->name, BAD_CAST "mac"))) {
- mac = xmlGetProp(cur, BAD_CAST "address");
- } else if ((script == NULL) &&
- (xmlStrEqual(cur->name, BAD_CAST "script"))) {
- script = xmlGetProp(cur, BAD_CAST "path");
- } else if ((model == NULL) &&
- (xmlStrEqual(cur->name, BAD_CAST "model"))) {
- model = xmlGetProp(cur, BAD_CAST "type");
- } else if ((ip == NULL) &&
- (xmlStrEqual(cur->name, BAD_CAST "ip"))) {
- /* XXX in future expect to need to have > 1 ip
- * address element - eg ipv4 & ipv6. For now
- * xen only supports a single address though
- * so lets ignore that complication */
- ip = xmlGetProp(cur, BAD_CAST "address");
- }
- }
- cur = cur->next;
- }
-
- virBufferAddLit(buf, "(vif ");
- if (mac != NULL) {
- unsigned char addr[6];
- if (virParseMacAddr((const char*) mac, addr) == -1) {
- virXMLError(conn, VIR_ERR_INVALID_MAC, (const char *) mac, 0);
- goto error;
- }
- virBufferVSprintf(buf, "(mac '%s')", (const char *) mac);
- }
- if (source != NULL) {
- if (typ == 0)
- virBufferVSprintf(buf, "(bridge '%s')", (const char *) source);
- else if (typ == 1) /* TODO does that work like that ? */
- virBufferVSprintf(buf, "(dev '%s')", (const char *) source);
- else {
- virNetworkPtr network =
- virNetworkLookupByName(conn, (const char *) source);
- char *bridge;
-
- if (!network || !(bridge = virNetworkGetBridgeName(network))) {
- if (network)
- virNetworkFree(network);
- virXMLError(conn, VIR_ERR_NO_SOURCE, (const char *) source,
- 0);
- goto error;
- }
- virNetworkFree(network);
- virBufferVSprintf(buf, "(bridge '%s')", bridge);
- VIR_FREE(bridge);
- }
- }
- if (script != NULL)
- virBufferVSprintf(buf, "(script '%s')", script);
- if (model != NULL)
- virBufferVSprintf(buf, "(model '%s')", model);
- if (ip != NULL)
- virBufferVSprintf(buf, "(ip '%s')", ip);
- /*
- * apparently (type ioemu) breaks paravirt drivers on HVM so skip this
- * from Xen 3.1.0
- */
- if ((hvm) && (xendConfigVersion < 4))
- virBufferAddLit(buf, "(type ioemu)");
-
- virBufferAddLit(buf, ")");
- ret = 0;
- error:
- xmlFree(mac);
- xmlFree(source);
- xmlFree(script);
- xmlFree(ip);
- xmlFree(model);
- return (ret);
-}
-
-/**
- * virDomainParseXMLDesc:
- * @conn: pointer to the hypervisor connection
- * @xmldesc: string with the XML description
- * @xendConfigVersion: xend configuration file format
- *
- * Parse the XML description and turn it into the xend sexp needed to
- * create the domain. This is a temporary interface as the S-Expr interface
- * will be replaced by XML-RPC in the future. However the XML format should
- * stay valid over time.
- *
- * Returns the 0 terminatedi S-Expr string or NULL in case of error.
- * the caller must free() the returned value.
- */
-char *
-virDomainParseXMLDesc(virConnectPtr conn, const char *xmldesc, char **name,
- int xendConfigVersion)
-{
- xmlDocPtr xml = NULL;
- xmlNodePtr node;
- char *nam = NULL, *tmp;
- virBuffer buf = VIR_BUFFER_INITIALIZER;
- xmlChar *prop;
- xmlParserCtxtPtr pctxt;
- xmlXPathContextPtr ctxt = NULL;
- int i, res;
- int bootloader = 0;
- int hvm = 0;
- unsigned int vcpus = 1;
- unsigned long mem = 0, max_mem = 0;
- char *str;
- double f;
- xmlNodePtr *nodes;
- int nb_nodes;
-
- if (name != NULL)
- *name = NULL;
-
- pctxt = xmlNewParserCtxt();
- if ((pctxt == NULL) || (pctxt->sax == NULL)) {
- goto error;
- }
-
- /* TODO pass the connection point to the error handler:
- * pctxt->userData = virConnectPtr;
- */
- pctxt->sax->error = virCatchXMLParseError;
-
- xml = xmlCtxtReadDoc(pctxt, (const xmlChar *) xmldesc, "domain.xml",
- NULL, XML_PARSE_NOENT | XML_PARSE_NONET |
- XML_PARSE_NOWARNING);
- if (xml == NULL) {
- goto error;
- }
- node = xmlDocGetRootElement(xml);
- if ((node == NULL) || (!xmlStrEqual(node->name, BAD_CAST "domain")))
- goto error;
-
- prop = xmlGetProp(node, BAD_CAST "type");
- if (prop != NULL) {
- if (!xmlStrEqual(prop, BAD_CAST "xen")) {
- xmlFree(prop);
- goto error;
- }
- xmlFree(prop);
- }
- virBufferAddLit(&buf, "(vm ");
- ctxt = xmlXPathNewContext(xml);
- if (ctxt == NULL) {
- goto error;
- }
- /*
- * extract some of the basics, name, memory, cpus ...
- */
- nam = virXPathString("string(/domain/name[1])", ctxt);
- if (nam == NULL) {
- virXMLError(conn, VIR_ERR_NO_NAME, xmldesc, 0);
- goto error;
- }
- virBufferVSprintf(&buf, "(name '%s')", nam);
-
- if ((virXPathNumber("number(/domain/memory[1])", ctxt, &f) < 0) ||
- (f < MIN_XEN_GUEST_SIZE * 1024)) {
- max_mem = 128;
- } else {
- max_mem = (f / 1024);
- }
-
- if ((virXPathNumber("number(/domain/currentMemory[1])", ctxt, &f) < 0)
- || (f < MIN_XEN_GUEST_SIZE * 1024)) {
- mem = max_mem;
- } else {
- mem = (f / 1024);
- if (mem > max_mem) {
- max_mem = mem;
- }
- }
- virBufferVSprintf(&buf, "(memory %lu)(maxmem %lu)", mem, max_mem);
-
- if ((virXPathNumber("number(/domain/vcpu[1])", ctxt, &f) == 0) &&
- (f > 0)) {
- vcpus = (unsigned int) f;
- }
- virBufferVSprintf(&buf, "(vcpus %u)", vcpus);
-
- str = virXPathString("string(/domain/vcpu/@cpuset)", ctxt);
- if (str != NULL) {
- int maxcpu = xenNbCpus(conn);
- char *cpuset = NULL;
- char *ranges = NULL;
- const char *cur = str;
-
- /*
- * Parse the CPUset attribute given in libvirt format and reserialize
- * it in a range format guaranteed to be understood by Xen.
- */
- if (maxcpu > 0) {
- if (VIR_ALLOC_N(cpuset, maxcpu) < 0) {
- virXMLError(conn, VIR_ERR_NO_MEMORY, xmldesc, 0);
- goto error;
- }
- res = virParseCpuSet(conn, &cur, 0, cpuset, maxcpu);
- if (res > 0) {
- ranges = virSaveCpuSet(conn, cpuset, maxcpu);
- if (ranges != NULL) {
- virBufferVSprintf(&buf, "(cpus '%s')", ranges);
- VIR_FREE(ranges);
- }
- }
- VIR_FREE(cpuset);
- if (res < 0)
- goto error;
- }
- VIR_FREE(str);
- }
-
- str = virXPathString("string(/domain/uuid[1])", ctxt);
- if (str != NULL) {
- virBufferVSprintf(&buf, "(uuid '%s')", str);
- VIR_FREE(str);
- }
-
- str = virXPathString("string(/domain/bootloader[1])", ctxt);
- if (str != NULL) {
- virBufferVSprintf(&buf, "(bootloader '%s')", str);
- /*
- * if using a bootloader, the kernel and initrd strings are not
- * significant and should be discarded
- */
- bootloader = 1;
- VIR_FREE(str);
- } else if (virXPathNumber("count(/domain/bootloader)", ctxt, &f) == 0
- && (f > 0)) {
- virBufferAddLit(&buf, "(bootloader)");
- /*
- * if using a bootloader, the kernel and initrd strings are not
- * significant and should be discarded
- */
- bootloader = 1;
- }
-
- str = virXPathString("string(/domain/bootloader_args[1])", ctxt);
- if (str != NULL && bootloader) {
- /*
- * ignore the bootloader_args value unless a bootloader was specified
- */
- virBufferVSprintf(&buf, "(bootloader_args '%s')", str);
- VIR_FREE(str);
- }
-
- str = virXPathString("string(/domain/on_poweroff[1])", ctxt);
- if (str != NULL) {
- virBufferVSprintf(&buf, "(on_poweroff '%s')", str);
- VIR_FREE(str);
- }
-
- str = virXPathString("string(/domain/on_reboot[1])", ctxt);
- if (str != NULL) {
- virBufferVSprintf(&buf, "(on_reboot '%s')", str);
- VIR_FREE(str);
- }
-
- str = virXPathString("string(/domain/on_crash[1])", ctxt);
- if (str != NULL) {
- virBufferVSprintf(&buf, "(on_crash '%s')", str);
- VIR_FREE(str);
- }
-
- if (!bootloader) {
- if ((node = virXPathNode("/domain/os[1]", ctxt)) != NULL) {
- int has_kernel = 0;
-
- /* Analyze of the os description, based on HVM or PV. */
- str = virXPathString("string(/domain/os/type[1])", ctxt);
- if ((str != NULL) && STREQ(str, "hvm"))
- hvm = 1;
- xmlFree(str);
- str = NULL;
-
- if (hvm)
- virBufferAddLit(&buf, "(image (hvm ");
- else
- virBufferAddLit(&buf, "(image (linux ");
-
- if (virXPathBoolean("count(/domain/os/kernel) > 0", ctxt)) {
- if (virDomainParseXMLOSDescKernel(conn, node,
- &buf) != 0)
- goto error;
- has_kernel = 1;
- }
-
- if (hvm &&
- virDomainParseXMLOSDescHVM(conn, node,
- &buf, ctxt, vcpus,
- xendConfigVersion,
- has_kernel) != 0)
- goto error;
-
- /* get the device emulation model */
- str = virXPathString("string(/domain/devices/emulator[1])", ctxt);
- if (str != NULL) {
- virBufferVSprintf(&buf, "(device_model '%s')", str);
- xmlFree(str);
- str = NULL;
- }
-
- /* PV graphics for xen <= 3.0.4, or HVM graphics for xen <= 3.1.0 */
- if ((!hvm && xendConfigVersion < 3) ||
- (hvm && xendConfigVersion < 4)) {
- xmlNodePtr cur;
- cur = virXPathNode("/domain/devices/graphics[1]", ctxt);
- if (cur != NULL &&
- virDomainParseXMLGraphicsDescImage(conn, cur, &buf,
- xendConfigVersion) != 0)
- goto error;
- }
-
- virBufferAddLit(&buf, "))");
- } else {
- virXMLError(conn, VIR_ERR_NO_OS, nam, 0);
- goto error;
- }
- }
-
- /* analyze of the devices */
- nb_nodes = virXPathNodeSet("/domain/devices/disk", ctxt, &nodes);
- if (nb_nodes > 0) {
- for (i = 0; i < nb_nodes; i++) {
- res = virDomainParseXMLDiskDesc(conn, nodes[i], &buf,
- hvm, xendConfigVersion);
- if (res != 0) {
- VIR_FREE(nodes);
- goto error;
- }
- }
- VIR_FREE(nodes);
- }
-
- nb_nodes = virXPathNodeSet("/domain/devices/interface", ctxt, &nodes);
- if (nb_nodes > 0) {
- for (i = 0; i < nb_nodes; i++) {
- virBufferAddLit(&buf, "(device ");
- res =
- virDomainParseXMLIfDesc(conn, nodes[i], &buf, hvm,
- xendConfigVersion);
- if (res != 0) {
- VIR_FREE(nodes);
- goto error;
- }
- virBufferAddLit(&buf, ")");
- }
- VIR_FREE(nodes);
- }
-
- /* New style PV graphics config xen >= 3.0.4,
- * or HVM graphics config xen >= 3.0.5 */
- if ((xendConfigVersion >= 3 && !hvm) ||
- (xendConfigVersion >= 4 && hvm)) {
- nb_nodes = virXPathNodeSet("/domain/devices/graphics", ctxt, &nodes);
- if (nb_nodes > 0) {
- for (i = 0; i < nb_nodes; i++) {
- res = virDomainParseXMLGraphicsDescVFB(conn, nodes[i], &buf);
- if (res != 0) {
- VIR_FREE(nodes);
- goto error;
- }
- }
- VIR_FREE(nodes);
- }
- }
-
-
- virBufferAddLit(&buf, ")"); /* closes (vm */
-
- xmlXPathFreeContext(ctxt);
- xmlFreeDoc(xml);
- xmlFreeParserCtxt(pctxt);
-
- if (name != NULL)
- *name = nam;
- else
- VIR_FREE(nam);
-
- if (virBufferError(&buf)) {
- virXMLError(conn, VIR_ERR_NO_MEMORY, _("allocate buffer"), 0);
- return NULL;
- }
-
- return virBufferContentAndReset(&buf);
-
- error:
- VIR_FREE(nam);
- if (name != NULL)
- *name = NULL;
- xmlXPathFreeContext(ctxt);
- if (xml != NULL)
- xmlFreeDoc(xml);
- if (pctxt != NULL)
- xmlFreeParserCtxt(pctxt);
- tmp = virBufferContentAndReset(&buf);
- VIR_FREE(tmp);
- return (NULL);
-}
-
-/**
- * virParseXMLDevice:
- * @conn: pointer to the hypervisor connection
- * @xmldesc: string with the XML description
- * @hvm: 1 for fully virtualized guest, 0 for paravirtualized
- * @xendConfigVersion: xend configuration file format
- *
- * Parse the XML description and turn it into the xend sexp needed to
- * create the device. This is a temporary interface as the S-Expr interface
- * will be replaced by XML-RPC in the future. However the XML format should
- * stay valid over time.
- *
- * Returns the 0-terminated S-Expr string, or NULL in case of error.
- * the caller must free() the returned value.
- */
-char *
-virParseXMLDevice(virConnectPtr conn, const char *xmldesc, int hvm,
- int xendConfigVersion)
-{
- xmlDocPtr xml = NULL;
- xmlNodePtr node;
- virBuffer buf = VIR_BUFFER_INITIALIZER;
-
- xml = xmlReadDoc((const xmlChar *) xmldesc, "device.xml", NULL,
- XML_PARSE_NOENT | XML_PARSE_NONET |
- XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
- if (xml == NULL) {
- virXMLError(conn, VIR_ERR_XML_ERROR, NULL, 0);
- goto error;
- }
- node = xmlDocGetRootElement(xml);
- if (node == NULL)
- goto error;
- if (xmlStrEqual(node->name, BAD_CAST "disk")) {
- if (virDomainParseXMLDiskDesc(conn, node, &buf, hvm,
- xendConfigVersion) != 0)
- goto error;
- } else if (xmlStrEqual(node->name, BAD_CAST "interface")) {
- if (virDomainParseXMLIfDesc(conn, node, &buf, hvm,
- xendConfigVersion) != 0)
- goto error;
- } else {
- virXMLError(conn, VIR_ERR_XML_ERROR, (const char *) node->name, 0);
- goto error;
- }
-
- xmlFreeDoc(xml);
-
- if (virBufferError(&buf)) {
- virXMLError(conn, VIR_ERR_NO_MEMORY, _("allocate buffer"), 0);
- return NULL;
- }
-
- return virBufferContentAndReset(&buf);
-
- error:
- free(virBufferContentAndReset(&buf));
- xmlFreeDoc(xml);
- return NULL;
-}
-
-
-/**
- * virDomainXMLDevID:
- * @domain: pointer to domain object
- * @xmldesc: string with the XML description
- * @class: Xen device class "vbd" or "vif" (OUT)
- * @ref: Xen device reference (OUT)
- *
- * Set class according to XML root, and:
- * - if disk, copy in ref the target name from description
- * - if network, get MAC address from description, scan XenStore and
- * copy in ref the corresponding vif number.
- *
- * Returns 0 in case of success, -1 in case of failure.
- */
-int
-virDomainXMLDevID(virDomainPtr domain, const char *xmldesc, char *class,
- char *ref, int ref_len)
-{
- xmlDocPtr xml = NULL;
- xmlNodePtr node, cur;
- xmlChar *attr = NULL;
-
- char *xref;
- int ret = 0;
-
- xml = xmlReadDoc((const xmlChar *) xmldesc, "device.xml", NULL,
- XML_PARSE_NOENT | XML_PARSE_NONET |
- XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
- if (xml == NULL) {
- virXMLError(NULL, VIR_ERR_XML_ERROR, NULL, 0);
- goto error;
- }
- node = xmlDocGetRootElement(xml);
- if (node == NULL)
- goto error;
- if (xmlStrEqual(node->name, BAD_CAST "disk")) {
- strcpy(class, "vbd");
- for (cur = node->children; cur != NULL; cur = cur->next) {
- if ((cur->type != XML_ELEMENT_NODE) ||
- (!xmlStrEqual(cur->name, BAD_CAST "target")))
- continue;
- attr = xmlGetProp(cur, BAD_CAST "dev");
- if (attr == NULL)
- goto error;
- xref = xenStoreDomainGetDiskID(domain->conn, domain->id,
- (char *) attr);
- if (xref != NULL) {
- strncpy(ref, xref, ref_len);
- free(xref);
- ref[ref_len - 1] = '\0';
- goto cleanup;
- }
- /* hack to avoid the warning that domain is unused */
- if (domain->id < 0)
- ret = -1;
-
- goto error;
- }
- } else if (xmlStrEqual(node->name, BAD_CAST "interface")) {
- strcpy(class, "vif");
- for (cur = node->children; cur != NULL; cur = cur->next) {
- if ((cur->type != XML_ELEMENT_NODE) ||
- (!xmlStrEqual(cur->name, BAD_CAST "mac")))
- continue;
- attr = xmlGetProp(cur, BAD_CAST "address");
- if (attr == NULL)
- goto error;
-
- xref = xenStoreDomainGetNetworkID(domain->conn, domain->id,
- (char *) attr);
- if (xref != NULL) {
- strncpy(ref, xref, ref_len);
- free(xref);
- ref[ref_len - 1] = '\0';
- goto cleanup;
- }
- /* hack to avoid the warning that domain is unused */
- if (domain->id < 0)
- ret = -1;
+#endif /* !PROXY */
- goto error;
- }
- } else {
- virXMLError(NULL, VIR_ERR_XML_ERROR, (const char *) node->name, 0);
- }
- error:
- ret = -1;
- cleanup:
- if (xml != NULL)
- xmlFreeDoc(xml);
- xmlFree(attr);
- return ret;
-}
#endif /* WITH_XEN */
-#endif /* !PROXY */
#ifndef __VIR_XML_H__
#define __VIR_XML_H__
-#include "libvirt/libvirt.h"
#include "internal.h"
-#include "buf.h"
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxml/xpath.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
int virXPathBoolean (const char *xpath,
xmlXPathContextPtr ctxt);
char * virXMLPropString(xmlNodePtr node,
const char *name);
+char *
+virConvertCpuSet(virConnectPtr conn, const char *str, int maxcpu);
-#if WITH_XEN || WITH_QEMU
-int virParseCpuSet (virConnectPtr conn,
- const char **str,
- char sep,
- char *cpuset,
- int maxcpu);
-char * virSaveCpuSet (virConnectPtr conn,
- char *cpuset,
- int maxcpu);
-#endif
-#if WITH_XEN
-char * virConvertCpuSet(virConnectPtr conn,
- const char *str,
- int maxcpu);
-int virDomainParseXMLOSDescHVMChar(virConnectPtr conn,
- char *buf,
- size_t buflen,
- xmlNodePtr node);
-char * virDomainParseXMLDesc(virConnectPtr conn,
- const char *xmldesc,
- char **name,
- int xendConfigVersion);
-char * virParseXMLDevice(virConnectPtr conn,
- const char *xmldesc,
- int hvm,
- int xendConfigVersion);
-int virDomainXMLDevID(virDomainPtr domain,
- const char *xmldesc,
- char *class,
- char *ref,
- int ref_len);
char * virBuildSoundStringFromXML(virConnectPtr conn,
xmlXPathContextPtr ctxt);
-#endif
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
+int
+virDomainParseXMLOSDescHVMChar(virConnectPtr conn,
+ char *buf,
+ size_t buflen,
+ xmlNodePtr node);
+
#endif /* __VIR_XML_H__ */
xmlrpctest_LDADD = $(LDADDS)
xml2sexprtest_SOURCES = \
- xml2sexprtest.c \
+ xml2sexprtest.c testutilsxen.c testutilsxen.h \
testutils.c testutils.h
xml2sexprtest_LDADD = $(LDADDS)
--- /dev/null
+#include <config.h>
+
+#include <sys/utsname.h>
+#include <stdlib.h>
+
+#include "testutilsxen.h"
+
+virCapsPtr testXenCapsInit(void) {
+ struct utsname utsname;
+ virCapsPtr caps;
+ virCapsGuestPtr guest;
+ static const char *const x86_machines[] = {
+ "xenfv"
+ };
+ static const char *const xen_machines[] = {
+ "xenpv"
+ };
+
+ uname (&utsname);
+ if ((caps = virCapabilitiesNew(utsname.machine,
+ 0, 0)) == NULL)
+ return NULL;
+
+ if ((guest = virCapabilitiesAddGuest(caps, "hvm", "i686", 32,
+ "/usr/lib/xen/bin/qemu-dm", NULL,
+ 1, x86_machines)) == NULL)
+ goto cleanup;
+ if (virCapabilitiesAddGuestDomain(guest,
+ "xen",
+ NULL,
+ NULL,
+ 0,
+ NULL) == NULL)
+ goto cleanup;
+
+ if ((guest = virCapabilitiesAddGuest(caps, "xen", "i686", 32,
+ "/usr/lib/xen/bin/qemu-dm", NULL,
+ 1, xen_machines)) == NULL)
+ goto cleanup;
+ if (virCapabilitiesAddGuestDomain(guest,
+ "xen",
+ NULL,
+ NULL,
+ 0,
+ NULL) == NULL)
+ goto cleanup;
+
+ return caps;
+
+cleanup:
+ virCapabilitiesFree(caps);
+ return NULL;
+}
--- /dev/null
+
+#include "capabilities.h"
+
+virCapsPtr testXenCapsInit(void);
+
char *expectxml = &(xmlData[0]);
char *actualxml = NULL;
FILE *fp1 = NULL, *fp2 = NULL;
+ virCapsPtr caps = NULL;
int ret = -1;
abs_srcdir, capabilities_rel);
if (virtTestLoadFile(xml, &expectxml, MAX_FILE) < 0)
- goto fail;
+ goto fail;
if (!(fp1 = fopen(cpuinfo, "r")))
- goto fail;
+ goto fail;
if (!(fp2 = fopen(capabilities, "r")))
- goto fail;
+ goto fail;
- if (!(actualxml = xenHypervisorMakeCapabilitiesXML(NULL, hostmachine, fp1, fp2)))
- goto fail;
+ if (!(caps = xenHypervisorMakeCapabilitiesInternal(hostmachine, fp1, fp2)))
+ goto fail;
+
+ if (!(actualxml = virCapabilitiesFormatXML(caps)))
+ goto fail;
if (STRNEQ(expectxml, actualxml)) {
virtTestDifference(stderr, expectxml, actualxml);
if (fp2)
fclose(fp2);
+ virCapabilitiesFree(caps);
return ret;
}
-(vm (name 'rhel5')(memory 175)(maxmem 385)(vcpus 1)(uuid '4f77abd2301958e83bab6fbf2118f880')(bootloader '/usr/bin/pygrub')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(device (tap (dev 'xvda:disk')(uname 'tap:aio:/xen/rhel5.img')(mode 'w')))(device (vif (mac '00:16:3e:1d:06:15')(bridge 'xenbr0')(script 'vif-bridge'))))
\ No newline at end of file
+(vm (name 'rhel5')(memory 175)(maxmem 385)(vcpus 1)(uuid '4f77abd2-3019-58e8-3bab-6fbf2118f880')(bootloader '/usr/bin/pygrub')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(device (tap (dev 'xvda:disk')(uname 'tap:aio:/xen/rhel5.img')(mode 'w')))(device (vif (mac '00:16:3e:1d:06:15')(bridge 'xenbr0')(script 'vif-bridge'))))
\ No newline at end of file
-(vm (name 'pvtest')(memory 384)(maxmem 512)(vcpus 1)(uuid '49a0c6ffc066539264983632d093c2e7')(bootloader '/usr/bin/pygrub')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(device (tap (dev 'xvda')(uname 'tap:aio:/var/lib/xen/images/rhel5pv.img')(mode 'w!')))(device (vif (mac '00:16:3e:23:9e:eb')(bridge 'xenbr0')(script 'vif-bridge'))))
\ No newline at end of file
+(vm (name 'pvtest')(memory 384)(maxmem 512)(vcpus 1)(uuid '49a0c6ff-c066-5392-6498-3632d093c2e7')(bootloader '/usr/bin/pygrub')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(device (tap (dev 'xvda')(uname 'tap:aio:/var/lib/xen/images/rhel5pv.img')(mode 'w!')))(device (vif (mac '00:16:3e:23:9e:eb')(bridge 'xenbr0')(script 'vif-bridge'))))
\ No newline at end of file
-(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os ')))(device (vbd (dev 'xvda')(uname 'phy:/dev/MainVG/GuestLV')(mode 'w'))))
\ No newline at end of file
+(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os ')))(device (vbd (dev 'xvda')(uname 'phy:/dev/MainVG/GuestLV')(mode 'w'))))
\ No newline at end of file
-(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os ')))(device (vbd (dev 'xvda')(uname 'phy:/dev/MainVG/GuestLV')(mode 'w'))))
\ No newline at end of file
+(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os ')))(device (vbd (dev 'xvda')(uname 'phy:/dev/MainVG/GuestLV')(mode 'w'))))
\ No newline at end of file
-(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os ')))(device (tap (dev 'xvda')(uname 'tap:qcow:/root/some.img')(mode 'w'))))
\ No newline at end of file
+(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os ')))(device (tap (dev 'xvda')(uname 'tap:qcow:/root/some.img')(mode 'w'))))
\ No newline at end of file
-(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os ')))(device (tap (dev 'xvda')(uname 'tap:aio:/root/some.img')(mode 'w'))))
\ No newline at end of file
+(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os ')))(device (tap (dev 'xvda')(uname 'tap:aio:/root/some.img')(mode 'w'))))
\ No newline at end of file
-(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os ')))(device (tap (dev 'xvda')(uname 'tap:aio:/root/some.img')(mode 'w'))))
\ No newline at end of file
+(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os ')))(device (tap (dev 'xvda')(uname 'tap:aio:/root/some.img')(mode 'w'))))
\ No newline at end of file
-(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w'))))
\ No newline at end of file
+(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w'))))
\ No newline at end of file
-(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w'))))
\ No newline at end of file
+(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w'))))
\ No newline at end of file
-(vm (name 'fvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (hvm (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os ')(loader '/usr/lib/xen/boot/hvmloader')(vcpus 2)(boot c)(usb 1)(parallel none)(serial pty)))(device (vbd (dev 'ioemu:xvda')(uname 'file:/root/some.img')(mode 'w'))))
\ No newline at end of file
+(vm (name 'fvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (hvm (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os ')(loader '/usr/lib/xen/boot/hvmloader')(vcpus 2)(boot c)(usb 1)(parallel none)(serial pty)(device_model '/usr/lib/xen/bin/qemu-dm')))(device (vbd (dev 'ioemu:xvda')(uname 'file:/root/some.img')(mode 'w'))))
\ No newline at end of file
-(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial none)(localtime 1)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
+(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial none)(localtime 1)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
-(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel tcp:localhost:9999)(serial none)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
+(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel tcp:localhost:9999)(serial none)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
-(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial file:/tmp/serial.log)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
+(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial file:/tmp/serial.log)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
-(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial null)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
+(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial null)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
-(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial pipe:/tmp/serial.pipe)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
+(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial pipe:/tmp/serial.pipe)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
-(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial pty)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
+(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial pty)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
-(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial stdio)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
+(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial stdio)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
-(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial telnet:localhost:9999,listen)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
+(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial telnet:localhost:9999,listen)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
-(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial tcp:localhost:9999,listen)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
+(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial tcp:localhost:9999,listen)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
-(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial udp:localhost:9998@localhost:9999)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
+(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial udp:localhost:9998@localhost:9999)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
-(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial unix:/tmp/serial.sock,listen)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
+(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial unix:/tmp/serial.sock,listen)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
-(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial none)(soundhw 'sb16,es1370')(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
+(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial none)(soundhw 'sb16,es1370')(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
-(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(usbdevice mouse)(parallel none)(serial none)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
+(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(usbdevice mouse)(parallel none)(serial none)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
-(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(usbdevice tablet)(parallel none)(serial none)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
+(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(usbdevice tablet)(parallel none)(serial none)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
-(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial none)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
+(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial none)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
-(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(acpi 1)(usb 1)(parallel none)(serial none)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)(vncdisplay 17)(keymap ja)))(device (vbd (dev 'hdc:cdrom')(uname 'file:/root/boot.iso')(mode 'r')))(device (vbd (dev 'hda:disk')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
+(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(acpi 1)(usb 1)(parallel none)(serial none)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)(vncunused 0)(vncdisplay 17)(keymap 'ja')))(device (vbd (dev 'hdc:cdrom')(uname 'file:/root/boot.iso')(mode 'r')))(device (vbd (dev 'hda:disk')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
-(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(acpi 1)(usb 1)(parallel none)(serial none)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)(vncunused 1)(keymap ja)))(device (vbd (dev 'hdc:cdrom')(uname 'file:/root/boot.iso')(mode 'r')))(device (vbd (dev 'hda:disk')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
+(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(acpi 1)(usb 1)(parallel none)(serial none)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)(vncunused 1)(keymap 'ja')))(device (vbd (dev 'hdc:cdrom')(uname 'file:/root/boot.iso')(mode 'r')))(device (vbd (dev 'hda:disk')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
-(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial none)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
+(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial none)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
-(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))(device (vif (mac '00:11:22:33:44:55')(bridge 'xenbr2')(script 'vif-bridge'))))
\ No newline at end of file
+(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))(device (vif (mac '00:11:22:33:44:55')(bridge 'xenbr2')(script 'vif-bridge'))))
\ No newline at end of file
-(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))(device (vif (mac '00:11:22:33:44:55')(bridge 'xenbr2')(script 'vif-bridge')(model 'e1000'))))
\ No newline at end of file
+(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))(device (vif (mac '00:11:22:33:44:55')(bridge 'xenbr2')(script 'vif-bridge')(model 'e1000'))))
\ No newline at end of file
-(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))(device (vif (mac '00:11:22:33:44:55')(dev 'eth3')(script 'vif-routed')(ip '172.14.5.6'))))
\ No newline at end of file
+(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))(device (vif (mac '00:11:22:33:44:55')(script 'vif-routed')(ip '172.14.5.6'))))
\ No newline at end of file
-(vm (name 'test')(memory 350)(maxmem 382)(vcpus 1)(uuid 'cc2315e7d26a307a438c6d188ec4c09c')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(acpi 1)(apic 1)(pae 1)(usb 1)(parallel none)(serial none)(device_model '/usr/lib/xen/bin/qemu-dm')(vnc 1)(vncdisplay 6)))(device (vbd (dev 'hda:disk:disk')(uname 'phy:/dev/sda8')(mode 'w')))(device (vbd (dev 'hdc:cdrom')(mode 'r')))(device (vif (mac '00:16:3e:0a:7b:39')(type ioemu))))
\ No newline at end of file
+(vm (name 'test')(memory 350)(maxmem 382)(vcpus 1)(uuid 'cc2315e7-d26a-307a-438c-6d188ec4c09c')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(acpi 1)(apic 1)(pae 1)(usb 1)(parallel none)(serial none)(device_model '/usr/lib/xen/bin/qemu-dm')(vnc 1)(vncunused 0)(vncdisplay 6)))(device (vbd (dev 'hda:disk')(uname 'phy:/dev/sda8')(mode 'w')))(device (vbd (dev 'hdc:cdrom')(mode 'r')))(device (vif (mac '00:16:3e:0a:7b:39')(type ioemu))))
\ No newline at end of file
<disk type='block' device='disk'>
<driver name='phy'/>
<source dev='/dev/sda8'/>
- <target dev='hda:disk'/>
+ <target dev='hda'/>
</disk>
<disk device='cdrom'>
<target dev='hdc'/>
-(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(bootloader '/usr/bin/pypxeboot')(bootloader_args 'mac=AA:00:86:e2:35:72')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w'))))
\ No newline at end of file
+(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(bootloader '/usr/bin/pypxeboot')(bootloader_args 'mac=AA:00:86:e2:35:72')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w'))))
\ No newline at end of file
-(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))(device (vkbd))(device (vfb (type vnc)(vncdisplay 6)(vnclisten 127.0.0.1)(vncpasswd 123456)(keymap ja))))
\ No newline at end of file
+(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os ')(device_model '/usr/lib/xen/bin/qemu-dm')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))(device (vkbd))(device (vfb (type vnc)(vncunused 0)(vncdisplay 6)(vnclisten '127.0.0.1')(vncpasswd '123456')(keymap 'ja'))))
\ No newline at end of file
-(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os ')(vnc 1)(vncdisplay 6)(vnclisten 127.0.0.1)(vncpasswd 123456)(keymap ja)))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w'))))
\ No newline at end of file
+(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os ')(vnc 1)(vncunused 0)(vncdisplay 6)(vnclisten '127.0.0.1')(vncpasswd '123456')(keymap 'ja')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w'))))
\ No newline at end of file
-(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w'))))
\ No newline at end of file
+(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w'))))
\ No newline at end of file
#if WITH_XEN
#include "internal.h"
-#include "xml.h"
+#include "xend_internal.h"
#include "testutils.h"
+#include "testutilsxen.h"
static char *progname;
static char *abs_srcdir;
+static virCapsPtr caps;
#define MAX_FILE 4096
static int testCompareFiles(const char *xml, const char *sexpr,
- const char *name, int xendConfigVersion) {
+ int xendConfigVersion) {
char xmlData[MAX_FILE];
char sexprData[MAX_FILE];
- char *gotname = NULL;
char *gotsexpr = NULL;
char *xmlPtr = &(xmlData[0]);
char *sexprPtr = &(sexprData[0]);
int ret = -1;
+ virDomainDefPtr def = NULL;
if (virtTestLoadFile(xml, &xmlPtr, MAX_FILE) < 0)
- goto fail;
+ goto fail;
if (virtTestLoadFile(sexpr, &sexprPtr, MAX_FILE) < 0)
- goto fail;
+ goto fail;
- if (!(gotsexpr = virDomainParseXMLDesc(NULL, xmlData, &gotname, xendConfigVersion)))
- goto fail;
+ if (!(def = virDomainDefParseString(NULL, caps, xmlData)))
+ goto fail;
- if (STRNEQ(sexprData, gotsexpr)) {
- virtTestDifference(stderr, sexprData, gotsexpr);
+ if (!(gotsexpr = xenDaemonFormatSxpr(NULL, def, xendConfigVersion)))
goto fail;
- }
- if (STRNEQ(name, gotname)) {
- printf("Got wrong name: expected %s, got %s\n", name, gotname);
+ if (STRNEQ(sexprData, gotsexpr)) {
+ virtTestDifference(stderr, sexprData, gotsexpr);
goto fail;
}
ret = 0;
fail:
-
- free(gotname);
+ virDomainDefFree(def);
free(gotsexpr);
return ret;
abs_srcdir, info->input);
snprintf(args, PATH_MAX, "%s/xml2sexprdata/xml2sexpr-%s.sexpr",
abs_srcdir, info->output);
- return testCompareFiles(xml, args, info->name, info->version);
+ return testCompareFiles(xml, args, info->version);
}
ret = -1; \
} while (0)
+ if (!(caps = testXenCapsInit()))
+ return(EXIT_FAILURE);
+
DO_TEST("pv", "pv", "pvtest", 1);
DO_TEST("fv", "fv", "fvtest", 1);
DO_TEST("pv", "pv", "pvtest", 2);
DO_TEST("fv-sound", "fv-sound", "fvtest", 1);
+ virCapabilitiesFree(caps);
+
return(ret==0 ? EXIT_SUCCESS : EXIT_FAILURE);
}