#define XEN_SCHED_SEDF_NPARAM 6
#define XEN_SCHED_CRED_NPARAM 2
-#ifdef WITH_RHEL5_API
-# define XEND_CONFIG_MAX_VERS_NET_TYPE_IOEMU 0
-# define XEND_CONFIG_MIN_VERS_PVFB_NEWCONF 2
-#else
-# define XEND_CONFIG_MAX_VERS_NET_TYPE_IOEMU 3
-# define XEND_CONFIG_MIN_VERS_PVFB_NEWCONF 3
-#endif
-
#define XEND_RCV_BUF_MAX_LEN 65536
-static int
-xenDaemonFormatSxprDisk(virConnectPtr conn ATTRIBUTE_UNUSED,
- virDomainDiskDefPtr def,
- virBufferPtr buf,
- int hvm,
- int xendConfigVersion,
- int isAttach);
-static int
-xenDaemonFormatSxprNet(virConnectPtr conn ATTRIBUTE_UNUSED,
- virDomainNetDefPtr def,
- virBufferPtr buf,
- int hvm,
- int xendConfigVersion,
- int isAttach);
-static int
-xenDaemonFormatSxprOnePCI(virDomainHostdevDefPtr def,
- virBufferPtr buf,
- int detach);
-
static int
virDomainXMLDevID(virDomainPtr domain,
virDomainDeviceDefPtr dev,
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(virDomainGraphicsDefPtr def,
- virBufferPtr buf)
-{
- if (def->type != VIR_DOMAIN_GRAPHICS_TYPE_SDL &&
- def->type != VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
- virXendError(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.auth.passwd)
- virBufferVSprintf(buf, "(vncpasswd '%s')", def->data.vnc.auth.passwd);
- if (def->data.vnc.keymap)
- virBufferVSprintf(buf, "(keymap '%s')", def->data.vnc.keymap);
- }
-
- virBufferAddLit(buf, "))");
-
- return 0;
-}
-
-
-static int
-xenDaemonFormatSxprGraphicsOld(virDomainGraphicsDefPtr def,
- virBufferPtr buf,
- int xendConfigVersion)
-{
- if (def->type != VIR_DOMAIN_GRAPHICS_TYPE_SDL &&
- def->type != VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
- virXendError(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.auth.passwd)
- virBufferVSprintf(buf, "(vncpasswd '%s')", def->data.vnc.auth.passwd);
- if (def->data.vnc.keymap)
- virBufferVSprintf(buf, "(keymap '%s')", def->data.vnc.keymap);
-
- }
- }
-
- return 0;
-}
-
-int
-xenDaemonFormatSxprChr(virDomainChrDefPtr def,
- virBufferPtr buf)
-{
- const char *type = virDomainChrTypeToString(def->source.type);
-
- if (!type) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("unexpected chr device type"));
- return -1;
- }
-
- switch (def->source.type) {
- case VIR_DOMAIN_CHR_TYPE_NULL:
- case VIR_DOMAIN_CHR_TYPE_STDIO:
- case VIR_DOMAIN_CHR_TYPE_VC:
- case VIR_DOMAIN_CHR_TYPE_PTY:
- virBufferVSprintf(buf, "%s", type);
- break;
-
- case VIR_DOMAIN_CHR_TYPE_FILE:
- case VIR_DOMAIN_CHR_TYPE_PIPE:
- virBufferVSprintf(buf, "%s:", type);
- virBufferEscapeSexpr(buf, "%s", def->source.data.file.path);
- break;
-
- case VIR_DOMAIN_CHR_TYPE_DEV:
- virBufferEscapeSexpr(buf, "%s", def->source.data.file.path);
- break;
-
- case VIR_DOMAIN_CHR_TYPE_TCP:
- virBufferVSprintf(buf, "%s:%s:%s%s",
- (def->source.data.tcp.protocol
- == VIR_DOMAIN_CHR_TCP_PROTOCOL_RAW ?
- "tcp" : "telnet"),
- (def->source.data.tcp.host ?
- def->source.data.tcp.host : ""),
- (def->source.data.tcp.service ?
- def->source.data.tcp.service : ""),
- (def->source.data.tcp.listen ?
- ",server,nowait" : ""));
- break;
-
- case VIR_DOMAIN_CHR_TYPE_UDP:
- virBufferVSprintf(buf, "%s:%s:%s@%s:%s", type,
- (def->source.data.udp.connectHost ?
- def->source.data.udp.connectHost : ""),
- (def->source.data.udp.connectService ?
- def->source.data.udp.connectService : ""),
- (def->source.data.udp.bindHost ?
- def->source.data.udp.bindHost : ""),
- (def->source.data.udp.bindService ?
- def->source.data.udp.bindService : ""));
- break;
-
- case VIR_DOMAIN_CHR_TYPE_UNIX:
- virBufferVSprintf(buf, "%s:", type);
- virBufferEscapeSexpr(buf, "%s", def->source.data.nix.path);
- if (def->source.data.nix.listen)
- virBufferAddLit(buf, ",server,nowait");
- break;
- }
-
- if (virBufferError(buf)) {
- virReportOOMError();
- return -1;
- }
-
- 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,
- int isAttach)
-{
- /* Xend (all versions) put the floppy device config
- * under the hvm (image (os)) block
- */
- if (hvm &&
- def->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
- if (isAttach) {
- virXendError(VIR_ERR_INVALID_ARG,
- _("Cannot directly attach floppy %s"), def->src);
- return -1;
- }
- return 0;
- }
-
- /* Xend <= 3.0.2 doesn't include cdrom config here */
- if (hvm &&
- def->device == VIR_DOMAIN_DISK_DEVICE_CDROM &&
- xendConfigVersion == 1) {
- if (isAttach) {
- virXendError(VIR_ERR_INVALID_ARG,
- _("Cannot directly attach CDROM %s"), def->src);
- return -1;
- }
- return 0;
- }
-
- if (!isAttach)
- 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 if (def->driverName && STREQ(def->driverName, "tap2")) {
- virBufferAddLit(buf, "(tap2 ");
- } else {
- virBufferAddLit(buf, "(vbd ");
- }
-
- if (hvm) {
- /* Xend <= 3.0.2 wants a ioemu: prefix on devices for HVM */
- if (xendConfigVersion == 1) {
- virBufferEscapeSexpr(buf, "(dev 'ioemu:%s')", def->dst);
- } else {
- /* But newer does not */
- virBufferEscapeSexpr(buf, "(dev '%s:", def->dst);
- virBufferVSprintf(buf, "%s')",
- def->device == VIR_DOMAIN_DISK_DEVICE_CDROM ?
- "cdrom" : "disk");
- }
- } else if (def->device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
- virBufferEscapeSexpr(buf, "(dev '%s:cdrom')", def->dst);
- } else {
- virBufferEscapeSexpr(buf, "(dev '%s')", def->dst);
- }
-
- if (def->src) {
- if (def->driverName) {
- if (STREQ(def->driverName, "tap") ||
- STREQ(def->driverName, "tap2")) {
- virBufferEscapeSexpr(buf, "(uname '%s:", def->driverName);
- virBufferEscapeSexpr(buf, "%s:",
- def->driverType ? def->driverType : "aio");
- virBufferEscapeSexpr(buf, "%s')", def->src);
- } else {
- virBufferEscapeSexpr(buf, "(uname '%s:", def->driverName);
- virBufferEscapeSexpr(buf, "%s')", def->src);
- }
- } else {
- if (def->type == VIR_DOMAIN_DISK_TYPE_FILE) {
- virBufferEscapeSexpr(buf, "(uname 'file:%s')", def->src);
- } else if (def->type == VIR_DOMAIN_DISK_TYPE_BLOCK) {
- if (def->src[0] == '/')
- virBufferEscapeSexpr(buf, "(uname 'phy:%s')", def->src);
- else
- virBufferEscapeSexpr(buf, "(uname 'phy:/dev/%s')",
- def->src);
- } else {
- virXendError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("unsupported disk type %s"),
- virDomainDiskTypeToString(def->type));
- return -1;
- }
- }
- }
-
- if (def->readonly)
- virBufferAddLit(buf, "(mode 'r')");
- else if (def->shared)
- virBufferAddLit(buf, "(mode 'w!')");
- else
- virBufferAddLit(buf, "(mode 'w')");
-
- if (!isAttach)
- virBufferAddLit(buf, ")");
-
- 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,
- int isAttach)
-{
- const char *script = DEFAULT_VIF_SCRIPT;
-
- if (def->type != VIR_DOMAIN_NET_TYPE_BRIDGE &&
- def->type != VIR_DOMAIN_NET_TYPE_NETWORK &&
- def->type != VIR_DOMAIN_NET_TYPE_ETHERNET) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- _("unsupported network type %d"), def->type);
- return -1;
- }
-
- if (!isAttach)
- virBufferAddLit(buf, "(device ");
-
- virBufferAddLit(buf, "(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:
- virBufferEscapeSexpr(buf, "(bridge '%s')", def->data.bridge.brname);
- if (def->data.bridge.script)
- script = def->data.bridge.script;
-
- virBufferEscapeSexpr(buf, "(script '%s')", script);
- if (def->data.bridge.ipaddr != NULL)
- virBufferEscapeSexpr(buf, "(ip '%s')", def->data.bridge.ipaddr);
- break;
-
- case VIR_DOMAIN_NET_TYPE_NETWORK:
- {
- virNetworkPtr network =
- virNetworkLookupByName(conn, def->data.network.name);
- char *bridge;
-
- if (!network) {
- virXendError(VIR_ERR_NO_NETWORK, "%s",
- def->data.network.name);
- return -1;
- }
-
- bridge = virNetworkGetBridgeName(network);
- virNetworkFree(network);
- if (!bridge) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- _("network %s is not active"),
- def->data.network.name);
- return -1;
- }
- virBufferEscapeSexpr(buf, "(bridge '%s')", bridge);
- virBufferEscapeSexpr(buf, "(script '%s')", script);
- VIR_FREE(bridge);
- }
- break;
-
- case VIR_DOMAIN_NET_TYPE_ETHERNET:
- if (def->data.ethernet.script)
- virBufferEscapeSexpr(buf, "(script '%s')",
- def->data.ethernet.script);
- if (def->data.ethernet.ipaddr != NULL)
- virBufferEscapeSexpr(buf, "(ip '%s')", def->data.ethernet.ipaddr);
- break;
-
- case VIR_DOMAIN_NET_TYPE_USER:
- case VIR_DOMAIN_NET_TYPE_SERVER:
- case VIR_DOMAIN_NET_TYPE_CLIENT:
- case VIR_DOMAIN_NET_TYPE_MCAST:
- case VIR_DOMAIN_NET_TYPE_INTERNAL:
- case VIR_DOMAIN_NET_TYPE_DIRECT:
- case VIR_DOMAIN_NET_TYPE_LAST:
- break;
- }
-
- if (def->ifname != NULL &&
- !STRPREFIX(def->ifname, "vif"))
- virBufferEscapeSexpr(buf, "(vifname '%s')", def->ifname);
-
- if (!hvm) {
- if (def->model != NULL)
- virBufferEscapeSexpr(buf, "(model '%s')", def->model);
- }
- else if (def->model == NULL) {
- /*
- * apparently (type ioemu) breaks paravirt drivers on HVM so skip
- * this from XEND_CONFIG_MAX_VERS_NET_TYPE_IOEMU
- */
- if (xendConfigVersion <= XEND_CONFIG_MAX_VERS_NET_TYPE_IOEMU)
- virBufferAddLit(buf, "(type ioemu)");
- }
- else if (STREQ(def->model, "netfront")) {
- virBufferAddLit(buf, "(type netfront)");
- }
- else {
- virBufferEscapeSexpr(buf, "(model '%s')", def->model);
- virBufferAddLit(buf, "(type ioemu)");
- }
-
- if (!isAttach)
- virBufferAddLit(buf, ")");
-
- virBufferAddLit(buf, ")");
-
- return 0;
-}
-
-
-static void
-xenDaemonFormatSxprPCI(virDomainHostdevDefPtr def,
- virBufferPtr buf)
-{
- virBufferVSprintf(buf, "(dev (domain 0x%04x)(bus 0x%02x)(slot 0x%02x)(func 0x%x))",
- def->source.subsys.u.pci.domain,
- def->source.subsys.u.pci.bus,
- def->source.subsys.u.pci.slot,
- def->source.subsys.u.pci.function);
-}
-
-static int
-xenDaemonFormatSxprOnePCI(virDomainHostdevDefPtr def,
- virBufferPtr buf,
- int detach)
-{
- if (def->managed) {
- virXendError(VIR_ERR_NO_SUPPORT, "%s",
- _("managed PCI devices not supported with XenD"));
- return -1;
- }
-
- virBufferAddLit(buf, "(pci ");
- xenDaemonFormatSxprPCI(def, buf);
- if (detach)
- virBufferAddLit(buf, "(state 'Closing')");
- else
- virBufferAddLit(buf, "(state 'Initialising')");
- virBufferAddLit(buf, ")");
-
- return 0;
-}
-
-static int
-xenDaemonFormatSxprAllPCI(virDomainDefPtr def,
- virBufferPtr buf)
-{
- int hasPCI = 0;
- int i;
-
- for (i = 0 ; i < def->nhostdevs ; i++)
- if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
- def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
- hasPCI = 1;
-
- if (!hasPCI)
- return 0;
-
- /*
- * With the (domain ...) block we have the following odd setup
- *
- * (device
- * (pci
- * (dev (domain 0x0000) (bus 0x00) (slot 0x1b) (func 0x0))
- * (dev (domain 0x0000) (bus 0x00) (slot 0x13) (func 0x0))
- * )
- * )
- *
- * Normally there is one (device ...) block per device, but in the
- * weird world of Xen PCI, one (device ...) covers multiple devices.
- */
-
- virBufferAddLit(buf, "(device (pci ");
- for (i = 0 ; i < def->nhostdevs ; i++) {
- if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
- def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
- if (def->hostdevs[i]->managed) {
- virXendError(VIR_ERR_NO_SUPPORT, "%s",
- _("managed PCI devices not supported with XenD"));
- return -1;
- }
-
- xenDaemonFormatSxprPCI(def->hostdevs[i], buf);
- }
- }
- virBufferAddLit(buf, "))");
-
- return 0;
-}
-
-int
-xenDaemonFormatSxprSound(virDomainDefPtr def,
- virBufferPtr buf)
-{
- const char *str;
- int i;
-
- for (i = 0 ; i < def->nsounds ; i++) {
- if (!(str = virDomainSoundModelTypeToString(def->sounds[i]->model))) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- _("unexpected sound model %d"),
- def->sounds[i]->model);
- return -1;
- }
- if (i)
- virBufferAddChar(buf, ',');
- virBufferEscapeSexpr(buf, "%s", str);
- }
-
- if (virBufferError(buf)) {
- virReportOOMError();
- return -1;
- }
-
- return 0;
-}
-
-
-static int
-xenDaemonFormatSxprInput(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(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;
-}
-
-
-/* Computing the vcpu_avail bitmask works because MAX_VIRT_CPUS is
- either 32, or 64 on a platform where long is big enough. */
-verify(MAX_VIRT_CPUS <= sizeof(1UL) * CHAR_BIT);
-
-/**
- * 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 terminated 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;
- char *bufout;
- int hvm = 0, i;
-
- VIR_DEBUG0("Formatting domain sexpr");
-
- virBufferAddLit(&buf, "(vm ");
- virBufferEscapeSexpr(&buf, "(name '%s')", def->name);
- virBufferVSprintf(&buf, "(memory %lu)(maxmem %lu)",
- VIR_DIV_UP(def->mem.cur_balloon, 1024),
- VIR_DIV_UP(def->mem.max_balloon, 1024));
- virBufferVSprintf(&buf, "(vcpus %u)", def->maxvcpus);
- /* Computing the vcpu_avail bitmask works because MAX_VIRT_CPUS is
- either 32, or 64 on a platform where long is big enough. */
- if (def->vcpus < def->maxvcpus)
- virBufferVSprintf(&buf, "(vcpu_avail %lu)", (1UL << def->vcpus) - 1);
-
- if (def->cpumask) {
- char *ranges = virDomainCpuSetFormat(def->cpumask, def->cpumasklen);
- if (ranges == NULL)
- goto error;
- virBufferEscapeSexpr(&buf, "(cpus '%s')", ranges);
- VIR_FREE(ranges);
- }
-
- virUUIDFormat(def->uuid, uuidstr);
- virBufferVSprintf(&buf, "(uuid '%s')", uuidstr);
-
- if (def->description)
- virBufferEscapeSexpr(&buf, "(description '%s')", def->description);
-
- if (def->os.bootloader) {
- if (def->os.bootloader[0])
- virBufferEscapeSexpr(&buf, "(bootloader '%s')", def->os.bootloader);
- else
- virBufferAddLit(&buf, "(bootloader)");
-
- if (def->os.bootloaderArgs)
- virBufferEscapeSexpr(&buf, "(bootloader_args '%s')", def->os.bootloaderArgs);
- }
-
- if (!(tmp = virDomainLifecycleTypeToString(def->onPoweroff))) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- _("unexpected lifecycle value %d"), def->onPoweroff);
- goto error;
- }
- virBufferVSprintf(&buf, "(on_poweroff '%s')", tmp);
-
- if (!(tmp = virDomainLifecycleTypeToString(def->onReboot))) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- _("unexpected lifecycle value %d"), def->onReboot);
- goto error;
- }
- virBufferVSprintf(&buf, "(on_reboot '%s')", tmp);
-
- if (!(tmp = virDomainLifecycleCrashTypeToString(def->onCrash))) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- _("unexpected lifecycle value %d"), def->onCrash);
- goto error;
- }
- virBufferVSprintf(&buf, "(on_crash '%s')", tmp);
-
- /* Set localtime here for current XenD (both PV & HVM) */
- if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME) {
- if (def->clock.data.timezone) {
- virXendError(VIR_ERR_CONFIG_UNSUPPORTED,
- "%s", _("configurable timezones are not supported"));
- goto error;
- }
-
- virBufferAddLit(&buf, "(localtime 1)");
- } else if (def->clock.offset != VIR_DOMAIN_CLOCK_OFFSET_UTC) {
- virXendError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("unsupported clock offset '%s'"),
- virDomainClockOffsetTypeToString(def->clock.offset));
- goto error;
- }
-
- 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(VIR_ERR_INTERNAL_ERROR,
- "%s",_("no HVM domain loader"));
- goto error;
- }
-
- if (def->os.kernel)
- virBufferEscapeSexpr(&buf, "(kernel '%s')", def->os.kernel);
- if (def->os.initrd)
- virBufferEscapeSexpr(&buf, "(ramdisk '%s')", def->os.initrd);
- if (def->os.root)
- virBufferEscapeSexpr(&buf, "(root '%s')", def->os.root);
- if (def->os.cmdline)
- virBufferEscapeSexpr(&buf, "(args '%s')", def->os.cmdline);
-
- if (hvm) {
- char bootorder[VIR_DOMAIN_BOOT_LAST+1];
- if (def->os.kernel)
- virBufferEscapeSexpr(&buf, "(loader '%s')", def->os.loader);
- else
- virBufferEscapeSexpr(&buf, "(kernel '%s')", def->os.loader);
-
- virBufferVSprintf(&buf, "(vcpus %u)", def->maxvcpus);
- if (def->vcpus < def->maxvcpus)
- virBufferVSprintf(&buf, "(vcpu_avail %lu)",
- (1UL << def->vcpus) - 1);
-
- 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);
-
- /* some disk devices are defined here */
- for (i = 0 ; i < def->ndisks ; i++) {
- switch (def->disks[i]->device) {
- case VIR_DOMAIN_DISK_DEVICE_CDROM:
- /* Only xend <= 3.0.2 wants cdrom config here */
- if (xendConfigVersion != 1)
- break;
- if (!STREQ(def->disks[i]->dst, "hdc") ||
- def->disks[i]->src == NULL)
- break;
-
- virBufferEscapeSexpr(&buf, "(cdrom '%s')",
- def->disks[i]->src);
- break;
-
- case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
- /* all xend versions define floppies here */
- virBufferEscapeSexpr(&buf, "(%s ", def->disks[i]->dst);
- virBufferEscapeSexpr(&buf, "'%s')", def->disks[i]->src);
- break;
-
- default:
- break;
- }
- }
-
- 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)");
- if (def->features & (1 << VIR_DOMAIN_FEATURE_HAP))
- virBufferAddLit(&buf, "(hap 1)");
-
- virBufferAddLit(&buf, "(usb 1)");
-
- for (i = 0 ; i < def->ninputs ; i++)
- if (xenDaemonFormatSxprInput(def->inputs[i], &buf) < 0)
- goto error;
-
- if (def->parallels) {
- virBufferAddLit(&buf, "(parallel ");
- if (xenDaemonFormatSxprChr(def->parallels[0], &buf) < 0)
- goto error;
- virBufferAddLit(&buf, ")");
- } else {
- virBufferAddLit(&buf, "(parallel none)");
- }
- if (def->serials) {
- virBufferAddLit(&buf, "(serial ");
- if (xenDaemonFormatSxprChr(def->serials[0], &buf) < 0)
- goto error;
- virBufferAddLit(&buf, ")");
- } else {
- virBufferAddLit(&buf, "(serial none)");
- }
-
- /* Set localtime here to keep old XenD happy for HVM */
- if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME)
- virBufferAddLit(&buf, "(localtime 1)");
-
- if (def->sounds) {
- virBufferAddLit(&buf, "(soundhw '");
- if (xenDaemonFormatSxprSound(def, &buf) < 0)
- goto error;
- virBufferAddLit(&buf, "')");
- }
- }
-
- /* get the device emulation model */
- if (def->emulator && (hvm || xendConfigVersion >= 3))
- virBufferEscapeSexpr(&buf, "(device_model '%s')", def->emulator);
-
-
- /* PV graphics for xen <= 3.0.4, or HVM graphics for xen <= 3.1.0 */
- if ((!hvm && xendConfigVersion < XEND_CONFIG_MIN_VERS_PVFB_NEWCONF) ||
- (hvm && xendConfigVersion < 4)) {
- if ((def->ngraphics == 1) &&
- xenDaemonFormatSxprGraphicsOld(def->graphics[0],
- &buf, xendConfigVersion) < 0)
- goto error;
- }
-
- virBufferAddLit(&buf, "))");
- }
-
- for (i = 0 ; i < def->ndisks ; i++)
- if (xenDaemonFormatSxprDisk(conn, def->disks[i],
- &buf, hvm, xendConfigVersion, 0) < 0)
- goto error;
-
- for (i = 0 ; i < def->nnets ; i++)
- if (xenDaemonFormatSxprNet(conn, def->nets[i],
- &buf, hvm, xendConfigVersion, 0) < 0)
- goto error;
-
- if (xenDaemonFormatSxprAllPCI(def, &buf) < 0)
- goto error;
-
- /* New style PV graphics config xen >= 3.0.4,
- * or HVM graphics config xen >= 3.0.5 */
- if ((xendConfigVersion >= XEND_CONFIG_MIN_VERS_PVFB_NEWCONF && !hvm) ||
- (xendConfigVersion >= 4 && hvm)) {
- if ((def->ngraphics == 1) &&
- xenDaemonFormatSxprGraphicsNew(def->graphics[0], &buf) < 0)
- goto error;
- }
-
- virBufferAddLit(&buf, ")"); /* closes (vm */
-
- if (virBufferError(&buf)) {
- virReportOOMError();
- goto error;
- }
-
- bufout = virBufferContentAndReset(&buf);
- VIR_DEBUG("Formatted sexpr: \n%s", bufout);
- return bufout;
-
-error:
- virBufferFreeAndReset(&buf);
- return NULL;
-}
-
/**
* virDomainXMLDevID:
const char *cpus);
-int
-xenDaemonFormatSxprChr(virDomainChrDefPtr def,
- virBufferPtr buf);
-int
-xenDaemonFormatSxprSound(virDomainDefPtr def,
- virBufferPtr buf);
-
-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);
sexpr_free(root);
return def;
-}
\ No newline at end of file
+}
+
+/************************************************************************
+ * *
+ * 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(virDomainGraphicsDefPtr def,
+ virBufferPtr buf)
+{
+ if (def->type != VIR_DOMAIN_GRAPHICS_TYPE_SDL &&
+ def->type != VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
+ XENXS_ERROR(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.auth.passwd)
+ virBufferVSprintf(buf, "(vncpasswd '%s')", def->data.vnc.auth.passwd);
+ if (def->data.vnc.keymap)
+ virBufferVSprintf(buf, "(keymap '%s')", def->data.vnc.keymap);
+ }
+
+ virBufferAddLit(buf, "))");
+
+ return 0;
+}
+
+
+static int
+xenDaemonFormatSxprGraphicsOld(virDomainGraphicsDefPtr def,
+ virBufferPtr buf,
+ int xendConfigVersion)
+{
+ if (def->type != VIR_DOMAIN_GRAPHICS_TYPE_SDL &&
+ def->type != VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
+ XENXS_ERROR(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.auth.passwd)
+ virBufferVSprintf(buf, "(vncpasswd '%s')", def->data.vnc.auth.passwd);
+ if (def->data.vnc.keymap)
+ virBufferVSprintf(buf, "(keymap '%s')", def->data.vnc.keymap);
+
+ }
+ }
+
+ return 0;
+}
+
+int
+xenDaemonFormatSxprChr(virDomainChrDefPtr def,
+ virBufferPtr buf)
+{
+ const char *type = virDomainChrTypeToString(def->source.type);
+
+ if (!type) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("unexpected chr device type"));
+ return -1;
+ }
+
+ switch (def->source.type) {
+ case VIR_DOMAIN_CHR_TYPE_NULL:
+ case VIR_DOMAIN_CHR_TYPE_STDIO:
+ case VIR_DOMAIN_CHR_TYPE_VC:
+ case VIR_DOMAIN_CHR_TYPE_PTY:
+ virBufferVSprintf(buf, "%s", type);
+ break;
+
+ case VIR_DOMAIN_CHR_TYPE_FILE:
+ case VIR_DOMAIN_CHR_TYPE_PIPE:
+ virBufferVSprintf(buf, "%s:", type);
+ virBufferEscapeSexpr(buf, "%s", def->source.data.file.path);
+ break;
+
+ case VIR_DOMAIN_CHR_TYPE_DEV:
+ virBufferEscapeSexpr(buf, "%s", def->source.data.file.path);
+ break;
+
+ case VIR_DOMAIN_CHR_TYPE_TCP:
+ virBufferVSprintf(buf, "%s:%s:%s%s",
+ (def->source.data.tcp.protocol
+ == VIR_DOMAIN_CHR_TCP_PROTOCOL_RAW ?
+ "tcp" : "telnet"),
+ (def->source.data.tcp.host ?
+ def->source.data.tcp.host : ""),
+ (def->source.data.tcp.service ?
+ def->source.data.tcp.service : ""),
+ (def->source.data.tcp.listen ?
+ ",server,nowait" : ""));
+ break;
+
+ case VIR_DOMAIN_CHR_TYPE_UDP:
+ virBufferVSprintf(buf, "%s:%s:%s@%s:%s", type,
+ (def->source.data.udp.connectHost ?
+ def->source.data.udp.connectHost : ""),
+ (def->source.data.udp.connectService ?
+ def->source.data.udp.connectService : ""),
+ (def->source.data.udp.bindHost ?
+ def->source.data.udp.bindHost : ""),
+ (def->source.data.udp.bindService ?
+ def->source.data.udp.bindService : ""));
+ break;
+
+ case VIR_DOMAIN_CHR_TYPE_UNIX:
+ virBufferVSprintf(buf, "%s:", type);
+ virBufferEscapeSexpr(buf, "%s", def->source.data.nix.path);
+ if (def->source.data.nix.listen)
+ virBufferAddLit(buf, ",server,nowait");
+ break;
+ }
+
+ if (virBufferError(buf)) {
+ virReportOOMError();
+ return -1;
+ }
+
+ 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.
+ */
+int
+xenDaemonFormatSxprDisk(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainDiskDefPtr def,
+ virBufferPtr buf,
+ int hvm,
+ int xendConfigVersion,
+ int isAttach)
+{
+ /* Xend (all versions) put the floppy device config
+ * under the hvm (image (os)) block
+ */
+ if (hvm &&
+ def->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
+ if (isAttach) {
+ XENXS_ERROR(VIR_ERR_INVALID_ARG,
+ _("Cannot directly attach floppy %s"), def->src);
+ return -1;
+ }
+ return 0;
+ }
+
+ /* Xend <= 3.0.2 doesn't include cdrom config here */
+ if (hvm &&
+ def->device == VIR_DOMAIN_DISK_DEVICE_CDROM &&
+ xendConfigVersion == 1) {
+ if (isAttach) {
+ XENXS_ERROR(VIR_ERR_INVALID_ARG,
+ _("Cannot directly attach CDROM %s"), def->src);
+ return -1;
+ }
+ return 0;
+ }
+
+ if (!isAttach)
+ 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 if (def->driverName && STREQ(def->driverName, "tap2")) {
+ virBufferAddLit(buf, "(tap2 ");
+ } else {
+ virBufferAddLit(buf, "(vbd ");
+ }
+
+ if (hvm) {
+ /* Xend <= 3.0.2 wants a ioemu: prefix on devices for HVM */
+ if (xendConfigVersion == 1) {
+ virBufferEscapeSexpr(buf, "(dev 'ioemu:%s')", def->dst);
+ } else {
+ /* But newer does not */
+ virBufferEscapeSexpr(buf, "(dev '%s:", def->dst);
+ virBufferVSprintf(buf, "%s')",
+ def->device == VIR_DOMAIN_DISK_DEVICE_CDROM ?
+ "cdrom" : "disk");
+ }
+ } else if (def->device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
+ virBufferEscapeSexpr(buf, "(dev '%s:cdrom')", def->dst);
+ } else {
+ virBufferEscapeSexpr(buf, "(dev '%s')", def->dst);
+ }
+
+ if (def->src) {
+ if (def->driverName) {
+ if (STREQ(def->driverName, "tap") ||
+ STREQ(def->driverName, "tap2")) {
+ virBufferEscapeSexpr(buf, "(uname '%s:", def->driverName);
+ virBufferEscapeSexpr(buf, "%s:",
+ def->driverType ? def->driverType : "aio");
+ virBufferEscapeSexpr(buf, "%s')", def->src);
+ } else {
+ virBufferEscapeSexpr(buf, "(uname '%s:", def->driverName);
+ virBufferEscapeSexpr(buf, "%s')", def->src);
+ }
+ } else {
+ if (def->type == VIR_DOMAIN_DISK_TYPE_FILE) {
+ virBufferEscapeSexpr(buf, "(uname 'file:%s')", def->src);
+ } else if (def->type == VIR_DOMAIN_DISK_TYPE_BLOCK) {
+ if (def->src[0] == '/')
+ virBufferEscapeSexpr(buf, "(uname 'phy:%s')", def->src);
+ else
+ virBufferEscapeSexpr(buf, "(uname 'phy:/dev/%s')",
+ def->src);
+ } else {
+ XENXS_ERROR(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unsupported disk type %s"),
+ virDomainDiskTypeToString(def->type));
+ return -1;
+ }
+ }
+ }
+
+ if (def->readonly)
+ virBufferAddLit(buf, "(mode 'r')");
+ else if (def->shared)
+ virBufferAddLit(buf, "(mode 'w!')");
+ else
+ virBufferAddLit(buf, "(mode 'w')");
+
+ if (!isAttach)
+ virBufferAddLit(buf, ")");
+
+ 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.
+ */
+int
+xenDaemonFormatSxprNet(virConnectPtr conn,
+ virDomainNetDefPtr def,
+ virBufferPtr buf,
+ int hvm,
+ int xendConfigVersion,
+ int isAttach)
+{
+ const char *script = DEFAULT_VIF_SCRIPT;
+
+ if (def->type != VIR_DOMAIN_NET_TYPE_BRIDGE &&
+ def->type != VIR_DOMAIN_NET_TYPE_NETWORK &&
+ def->type != VIR_DOMAIN_NET_TYPE_ETHERNET) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("unsupported network type %d"), def->type);
+ return -1;
+ }
+
+ if (!isAttach)
+ virBufferAddLit(buf, "(device ");
+
+ virBufferAddLit(buf, "(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:
+ virBufferEscapeSexpr(buf, "(bridge '%s')", def->data.bridge.brname);
+ if (def->data.bridge.script)
+ script = def->data.bridge.script;
+
+ virBufferEscapeSexpr(buf, "(script '%s')", script);
+ if (def->data.bridge.ipaddr != NULL)
+ virBufferEscapeSexpr(buf, "(ip '%s')", def->data.bridge.ipaddr);
+ break;
+
+ case VIR_DOMAIN_NET_TYPE_NETWORK:
+ {
+ virNetworkPtr network =
+ virNetworkLookupByName(conn, def->data.network.name);
+ char *bridge;
+
+ if (!network) {
+ XENXS_ERROR(VIR_ERR_NO_NETWORK, "%s",
+ def->data.network.name);
+ return -1;
+ }
+
+ bridge = virNetworkGetBridgeName(network);
+ virNetworkFree(network);
+ if (!bridge) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("network %s is not active"),
+ def->data.network.name);
+ return -1;
+ }
+ virBufferEscapeSexpr(buf, "(bridge '%s')", bridge);
+ virBufferEscapeSexpr(buf, "(script '%s')", script);
+ VIR_FREE(bridge);
+ }
+ break;
+
+ case VIR_DOMAIN_NET_TYPE_ETHERNET:
+ if (def->data.ethernet.script)
+ virBufferEscapeSexpr(buf, "(script '%s')",
+ def->data.ethernet.script);
+ if (def->data.ethernet.ipaddr != NULL)
+ virBufferEscapeSexpr(buf, "(ip '%s')", def->data.ethernet.ipaddr);
+ break;
+
+ case VIR_DOMAIN_NET_TYPE_USER:
+ case VIR_DOMAIN_NET_TYPE_SERVER:
+ case VIR_DOMAIN_NET_TYPE_CLIENT:
+ case VIR_DOMAIN_NET_TYPE_MCAST:
+ case VIR_DOMAIN_NET_TYPE_INTERNAL:
+ case VIR_DOMAIN_NET_TYPE_DIRECT:
+ case VIR_DOMAIN_NET_TYPE_LAST:
+ break;
+ }
+
+ if (def->ifname != NULL &&
+ !STRPREFIX(def->ifname, "vif"))
+ virBufferEscapeSexpr(buf, "(vifname '%s')", def->ifname);
+
+ if (!hvm) {
+ if (def->model != NULL)
+ virBufferEscapeSexpr(buf, "(model '%s')", def->model);
+ }
+ else if (def->model == NULL) {
+ /*
+ * apparently (type ioemu) breaks paravirt drivers on HVM so skip
+ * this from XEND_CONFIG_MAX_VERS_NET_TYPE_IOEMU
+ */
+ if (xendConfigVersion <= XEND_CONFIG_MAX_VERS_NET_TYPE_IOEMU)
+ virBufferAddLit(buf, "(type ioemu)");
+ }
+ else if (STREQ(def->model, "netfront")) {
+ virBufferAddLit(buf, "(type netfront)");
+ }
+ else {
+ virBufferEscapeSexpr(buf, "(model '%s')", def->model);
+ virBufferAddLit(buf, "(type ioemu)");
+ }
+
+ if (!isAttach)
+ virBufferAddLit(buf, ")");
+
+ virBufferAddLit(buf, ")");
+
+ return 0;
+}
+
+
+static void
+xenDaemonFormatSxprPCI(virDomainHostdevDefPtr def,
+ virBufferPtr buf)
+{
+ virBufferVSprintf(buf, "(dev (domain 0x%04x)(bus 0x%02x)(slot 0x%02x)(func 0x%x))",
+ def->source.subsys.u.pci.domain,
+ def->source.subsys.u.pci.bus,
+ def->source.subsys.u.pci.slot,
+ def->source.subsys.u.pci.function);
+}
+
+int
+xenDaemonFormatSxprOnePCI(virDomainHostdevDefPtr def,
+ virBufferPtr buf,
+ int detach)
+{
+ if (def->managed) {
+ XENXS_ERROR(VIR_ERR_NO_SUPPORT, "%s",
+ _("managed PCI devices not supported with XenD"));
+ return -1;
+ }
+
+ virBufferAddLit(buf, "(pci ");
+ xenDaemonFormatSxprPCI(def, buf);
+ if (detach)
+ virBufferAddLit(buf, "(state 'Closing')");
+ else
+ virBufferAddLit(buf, "(state 'Initialising')");
+ virBufferAddLit(buf, ")");
+
+ return 0;
+}
+
+static int
+xenDaemonFormatSxprAllPCI(virDomainDefPtr def,
+ virBufferPtr buf)
+{
+ int hasPCI = 0;
+ int i;
+
+ for (i = 0 ; i < def->nhostdevs ; i++)
+ if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+ def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
+ hasPCI = 1;
+
+ if (!hasPCI)
+ return 0;
+
+ /*
+ * With the (domain ...) block we have the following odd setup
+ *
+ * (device
+ * (pci
+ * (dev (domain 0x0000) (bus 0x00) (slot 0x1b) (func 0x0))
+ * (dev (domain 0x0000) (bus 0x00) (slot 0x13) (func 0x0))
+ * )
+ * )
+ *
+ * Normally there is one (device ...) block per device, but in the
+ * weird world of Xen PCI, one (device ...) covers multiple devices.
+ */
+
+ virBufferAddLit(buf, "(device (pci ");
+ for (i = 0 ; i < def->nhostdevs ; i++) {
+ if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+ def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
+ if (def->hostdevs[i]->managed) {
+ XENXS_ERROR(VIR_ERR_NO_SUPPORT, "%s",
+ _("managed PCI devices not supported with XenD"));
+ return -1;
+ }
+
+ xenDaemonFormatSxprPCI(def->hostdevs[i], buf);
+ }
+ }
+ virBufferAddLit(buf, "))");
+
+ return 0;
+}
+
+int
+xenDaemonFormatSxprSound(virDomainDefPtr def,
+ virBufferPtr buf)
+{
+ const char *str;
+ int i;
+
+ for (i = 0 ; i < def->nsounds ; i++) {
+ if (!(str = virDomainSoundModelTypeToString(def->sounds[i]->model))) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("unexpected sound model %d"),
+ def->sounds[i]->model);
+ return -1;
+ }
+ if (i)
+ virBufferAddChar(buf, ',');
+ virBufferEscapeSexpr(buf, "%s", str);
+ }
+
+ if (virBufferError(buf)) {
+ virReportOOMError();
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int
+xenDaemonFormatSxprInput(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) {
+ XENXS_ERROR(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;
+}
+
+
+/* Computing the vcpu_avail bitmask works because MAX_VIRT_CPUS is
+ either 32, or 64 on a platform where long is big enough. */
+verify(MAX_VIRT_CPUS <= sizeof(1UL) * CHAR_BIT);
+
+/**
+ * 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 terminated 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;
+ char *bufout;
+ int hvm = 0, i;
+
+ VIR_DEBUG0("Formatting domain sexpr");
+
+ virBufferAddLit(&buf, "(vm ");
+ virBufferEscapeSexpr(&buf, "(name '%s')", def->name);
+ virBufferVSprintf(&buf, "(memory %lu)(maxmem %lu)",
+ VIR_DIV_UP(def->mem.cur_balloon, 1024),
+ VIR_DIV_UP(def->mem.max_balloon, 1024));
+ virBufferVSprintf(&buf, "(vcpus %u)", def->maxvcpus);
+ /* Computing the vcpu_avail bitmask works because MAX_VIRT_CPUS is
+ either 32, or 64 on a platform where long is big enough. */
+ if (def->vcpus < def->maxvcpus)
+ virBufferVSprintf(&buf, "(vcpu_avail %lu)", (1UL << def->vcpus) - 1);
+
+ if (def->cpumask) {
+ char *ranges = virDomainCpuSetFormat(def->cpumask, def->cpumasklen);
+ if (ranges == NULL)
+ goto error;
+ virBufferEscapeSexpr(&buf, "(cpus '%s')", ranges);
+ VIR_FREE(ranges);
+ }
+
+ virUUIDFormat(def->uuid, uuidstr);
+ virBufferVSprintf(&buf, "(uuid '%s')", uuidstr);
+
+ if (def->description)
+ virBufferEscapeSexpr(&buf, "(description '%s')", def->description);
+
+ if (def->os.bootloader) {
+ if (def->os.bootloader[0])
+ virBufferEscapeSexpr(&buf, "(bootloader '%s')", def->os.bootloader);
+ else
+ virBufferAddLit(&buf, "(bootloader)");
+
+ if (def->os.bootloaderArgs)
+ virBufferEscapeSexpr(&buf, "(bootloader_args '%s')", def->os.bootloaderArgs);
+ }
+
+ if (!(tmp = virDomainLifecycleTypeToString(def->onPoweroff))) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("unexpected lifecycle value %d"), def->onPoweroff);
+ goto error;
+ }
+ virBufferVSprintf(&buf, "(on_poweroff '%s')", tmp);
+
+ if (!(tmp = virDomainLifecycleTypeToString(def->onReboot))) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("unexpected lifecycle value %d"), def->onReboot);
+ goto error;
+ }
+ virBufferVSprintf(&buf, "(on_reboot '%s')", tmp);
+
+ if (!(tmp = virDomainLifecycleCrashTypeToString(def->onCrash))) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("unexpected lifecycle value %d"), def->onCrash);
+ goto error;
+ }
+ virBufferVSprintf(&buf, "(on_crash '%s')", tmp);
+
+ /* Set localtime here for current XenD (both PV & HVM) */
+ if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME) {
+ if (def->clock.data.timezone) {
+ XENXS_ERROR(VIR_ERR_CONFIG_UNSUPPORTED,
+ "%s", _("configurable timezones are not supported"));
+ goto error;
+ }
+
+ virBufferAddLit(&buf, "(localtime 1)");
+ } else if (def->clock.offset != VIR_DOMAIN_CLOCK_OFFSET_UTC) {
+ XENXS_ERROR(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unsupported clock offset '%s'"),
+ virDomainClockOffsetTypeToString(def->clock.offset));
+ goto error;
+ }
+
+ 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) {
+ XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+ "%s",_("no HVM domain loader"));
+ goto error;
+ }
+
+ if (def->os.kernel)
+ virBufferEscapeSexpr(&buf, "(kernel '%s')", def->os.kernel);
+ if (def->os.initrd)
+ virBufferEscapeSexpr(&buf, "(ramdisk '%s')", def->os.initrd);
+ if (def->os.root)
+ virBufferEscapeSexpr(&buf, "(root '%s')", def->os.root);
+ if (def->os.cmdline)
+ virBufferEscapeSexpr(&buf, "(args '%s')", def->os.cmdline);
+
+ if (hvm) {
+ char bootorder[VIR_DOMAIN_BOOT_LAST+1];
+ if (def->os.kernel)
+ virBufferEscapeSexpr(&buf, "(loader '%s')", def->os.loader);
+ else
+ virBufferEscapeSexpr(&buf, "(kernel '%s')", def->os.loader);
+
+ virBufferVSprintf(&buf, "(vcpus %u)", def->maxvcpus);
+ if (def->vcpus < def->maxvcpus)
+ virBufferVSprintf(&buf, "(vcpu_avail %lu)",
+ (1UL << def->vcpus) - 1);
+
+ 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);
+
+ /* some disk devices are defined here */
+ for (i = 0 ; i < def->ndisks ; i++) {
+ switch (def->disks[i]->device) {
+ case VIR_DOMAIN_DISK_DEVICE_CDROM:
+ /* Only xend <= 3.0.2 wants cdrom config here */
+ if (xendConfigVersion != 1)
+ break;
+ if (!STREQ(def->disks[i]->dst, "hdc") ||
+ def->disks[i]->src == NULL)
+ break;
+
+ virBufferEscapeSexpr(&buf, "(cdrom '%s')",
+ def->disks[i]->src);
+ break;
+
+ case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
+ /* all xend versions define floppies here */
+ virBufferEscapeSexpr(&buf, "(%s ", def->disks[i]->dst);
+ virBufferEscapeSexpr(&buf, "'%s')", def->disks[i]->src);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ 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)");
+ if (def->features & (1 << VIR_DOMAIN_FEATURE_HAP))
+ virBufferAddLit(&buf, "(hap 1)");
+
+ virBufferAddLit(&buf, "(usb 1)");
+
+ for (i = 0 ; i < def->ninputs ; i++)
+ if (xenDaemonFormatSxprInput(def->inputs[i], &buf) < 0)
+ goto error;
+
+ if (def->parallels) {
+ virBufferAddLit(&buf, "(parallel ");
+ if (xenDaemonFormatSxprChr(def->parallels[0], &buf) < 0)
+ goto error;
+ virBufferAddLit(&buf, ")");
+ } else {
+ virBufferAddLit(&buf, "(parallel none)");
+ }
+ if (def->serials) {
+ virBufferAddLit(&buf, "(serial ");
+ if (xenDaemonFormatSxprChr(def->serials[0], &buf) < 0)
+ goto error;
+ virBufferAddLit(&buf, ")");
+ } else {
+ virBufferAddLit(&buf, "(serial none)");
+ }
+
+ /* Set localtime here to keep old XenD happy for HVM */
+ if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME)
+ virBufferAddLit(&buf, "(localtime 1)");
+
+ if (def->sounds) {
+ virBufferAddLit(&buf, "(soundhw '");
+ if (xenDaemonFormatSxprSound(def, &buf) < 0)
+ goto error;
+ virBufferAddLit(&buf, "')");
+ }
+ }
+
+ /* get the device emulation model */
+ if (def->emulator && (hvm || xendConfigVersion >= 3))
+ virBufferEscapeSexpr(&buf, "(device_model '%s')", def->emulator);
+
+
+ /* PV graphics for xen <= 3.0.4, or HVM graphics for xen <= 3.1.0 */
+ if ((!hvm && xendConfigVersion < XEND_CONFIG_MIN_VERS_PVFB_NEWCONF) ||
+ (hvm && xendConfigVersion < 4)) {
+ if ((def->ngraphics == 1) &&
+ xenDaemonFormatSxprGraphicsOld(def->graphics[0],
+ &buf, xendConfigVersion) < 0)
+ goto error;
+ }
+
+ virBufferAddLit(&buf, "))");
+ }
+
+ for (i = 0 ; i < def->ndisks ; i++)
+ if (xenDaemonFormatSxprDisk(conn, def->disks[i],
+ &buf, hvm, xendConfigVersion, 0) < 0)
+ goto error;
+
+ for (i = 0 ; i < def->nnets ; i++)
+ if (xenDaemonFormatSxprNet(conn, def->nets[i],
+ &buf, hvm, xendConfigVersion, 0) < 0)
+ goto error;
+
+ if (xenDaemonFormatSxprAllPCI(def, &buf) < 0)
+ goto error;
+
+ /* New style PV graphics config xen >= 3.0.4,
+ * or HVM graphics config xen >= 3.0.5 */
+ if ((xendConfigVersion >= XEND_CONFIG_MIN_VERS_PVFB_NEWCONF && !hvm) ||
+ (xendConfigVersion >= 4 && hvm)) {
+ if ((def->ngraphics == 1) &&
+ xenDaemonFormatSxprGraphicsNew(def->graphics[0], &buf) < 0)
+ goto error;
+ }
+
+ virBufferAddLit(&buf, ")"); /* closes (vm */
+
+ if (virBufferError(&buf)) {
+ virReportOOMError();
+ goto error;
+ }
+
+ bufout = virBufferContentAndReset(&buf);
+ VIR_DEBUG("Formatted sexpr: \n%s", bufout);
+ return bufout;
+
+error:
+ virBufferFreeAndReset(&buf);
+ return NULL;
+}
xenDaemonParseSxprChar(const char *value,
const char *tty);
+int
+xenDaemonFormatSxprDisk(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainDiskDefPtr def,
+ virBufferPtr buf,
+ int hvm,
+ int xendConfigVersion,
+ int isAttach);
+int
+xenDaemonFormatSxprNet(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainNetDefPtr def,
+ virBufferPtr buf,
+ int hvm,
+ int xendConfigVersion,
+ int isAttach);
+
+int
+xenDaemonFormatSxprOnePCI(virDomainHostdevDefPtr def,
+ virBufferPtr buf,
+ int detach);
+
+int
+xenDaemonFormatSxprChr(virDomainChrDefPtr def,
+ virBufferPtr buf);
+int
+xenDaemonFormatSxprSound(virDomainDefPtr def,
+ virBufferPtr buf);
+
+char *
+xenDaemonFormatSxpr(virConnectPtr conn,
+ virDomainDefPtr def,
+ int xendConfigVersion);
+
#endif /* __VIR_XEN_SXPR_H__ */
# include "internal.h"
+# include <stdint.h>
+# include <xen/xen.h>
+
+/* xen-unstable changeset 19788 removed MAX_VIRT_CPUS from public
+ * headers. Its semantic was retained with XEN_LEGACY_MAX_VCPUS.
+ * Ensure MAX_VIRT_CPUS is defined accordingly.
+ */
+# if !defined(MAX_VIRT_CPUS) && defined(XEN_LEGACY_MAX_VCPUS)
+# define MAX_VIRT_CPUS XEN_LEGACY_MAX_VCPUS
+# endif
+
+# ifdef WITH_RHEL5_API
+# define XEND_CONFIG_MAX_VERS_NET_TYPE_IOEMU 0
+# define XEND_CONFIG_MIN_VERS_PVFB_NEWCONF 2
+# else
+# define XEND_CONFIG_MAX_VERS_NET_TYPE_IOEMU 3
+# define XEND_CONFIG_MIN_VERS_PVFB_NEWCONF 3
+# endif
# define VIR_FROM_THIS VIR_FROM_NONE
#include "internal.h"
#include "xen/xend_internal.h"
+#include "xenxs/xen_sxpr.h"
#include "testutils.h"
#include "testutilsxen.h"