We discussed adding a new XML element for representing video devices a few weeks back. This is my work in progress patch for the XML parsing routines supporting <video> <model type='vga|cirrus|vmvga|xen' vram='64' heads='1'/> </video> For compatability, if an existing guest has a <graphics> tag, but no <video> tag, then the parser automatically adds a <video> tag for type=cirrus. Still todo - Tweak the addition of default <video> tag a little so it uses the correct type for the type of guest - eg it should use type=xen in some cases. - Add RNG XML schemas & website docs - Make QEMU driver use this info for setting -vga argument - Make Xen drivers use this info for setting stdvga=1|0 config arg - Make VirtualBox use this info in whatever way it needs Daniel domain_conf.c | 168 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ domain_conf.h | 26 ++++++++ 2 files changed, 194 insertions(+) diff -r 66fa9bfc797c src/domain_conf.c --- a/src/domain_conf.c Mon May 18 11:28:46 2009 +0100 +++ b/src/domain_conf.c Mon May 18 11:29:00 2009 +0100 @@ -80,6 +80,7 @@ VIR_ENUM_IMPL(virDomainDevice, VIR_DOMAI "interface", "input", "sound", + "video", "hostdev") VIR_ENUM_IMPL(virDomainDisk, VIR_DOMAIN_DISK_TYPE_LAST, @@ -140,6 +141,12 @@ VIR_ENUM_IMPL(virDomainSoundModel, VIR_D "pcspk", "ac97") +VIR_ENUM_IMPL(virDomainVideo, VIR_DOMAIN_VIDEO_TYPE_LAST, + "vga", + "cirrus", + "vmvga", + "xen") + VIR_ENUM_IMPL(virDomainInput, VIR_DOMAIN_INPUT_TYPE_LAST, "mouse", "tablet") @@ -372,6 +379,14 @@ void virDomainSoundDefFree(virDomainSoun VIR_FREE(def); } +void virDomainVideoDefFree(virDomainVideoDefPtr def) +{ + if (!def) + return; + + VIR_FREE(def); +} + void virDomainHostdevDefFree(virDomainHostdevDefPtr def) { if (!def) @@ -399,6 +414,9 @@ void virDomainDeviceDefFree(virDomainDev case VIR_DOMAIN_DEVICE_SOUND: virDomainSoundDefFree(def->data.sound); break; + case VIR_DOMAIN_DEVICE_VIDEO: + virDomainVideoDefFree(def->data.video); + break; case VIR_DOMAIN_DEVICE_HOSTDEV: virDomainHostdevDefFree(def->data.hostdev); break; @@ -456,6 +474,10 @@ void virDomainDefFree(virDomainDefPtr de virDomainSoundDefFree(def->sounds[i]); VIR_FREE(def->sounds); + for (i = 0 ; i < def->nvideos ; i++) + virDomainVideoDefFree(def->videos[i]); + VIR_FREE(def->videos); + for (i = 0 ; i < def->nhostdevs ; i++) virDomainHostdevDefFree(def->hostdevs[i]); VIR_FREE(def->hostdevs); @@ -1638,6 +1660,84 @@ error: goto cleanup; } +static virDomainVideoDefPtr +virDomainVideoDefParseXML(virConnectPtr conn, + const xmlNodePtr node, + int flags ATTRIBUTE_UNUSED) { + virDomainVideoDefPtr def; + xmlNodePtr cur; + char *type = NULL; + char *heads = NULL; + char *vram = NULL; + + if (VIR_ALLOC(def) < 0) { + virReportOOMError(conn); + return NULL; + } + + cur = node->children; + while (cur != NULL) { + if (cur->type == XML_ELEMENT_NODE) { + if ((type == NULL) && (vram == NULL) && (heads == NULL) && + xmlStrEqual(cur->name, BAD_CAST "model")) { + type = virXMLPropString(cur, "type"); + vram = virXMLPropString(cur, "vram"); + heads = virXMLPropString(cur, "heads"); + } + } + cur = cur->next; + } + + if (type && + (def->type = virDomainVideoTypeFromString(type)) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unknown video model '%s'"), type); + goto error; + } + + if (vram && + virStrToLong_ui(vram, NULL, 10, &def->vram) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("cannot parse video ram '%s'"), vram); + goto error; + } else { + switch (def->type) { + /* Wierd, QEMU defaults to 9 MB ??! */ + case VIR_DOMAIN_VIDEO_TYPE_VGA: + case VIR_DOMAIN_VIDEO_TYPE_CIRRUS: + case VIR_DOMAIN_VIDEO_TYPE_VMVGA: + def->vram = 9 * 1024; + break; + case VIR_DOMAIN_VIDEO_TYPE_XEN: + /* Original PVFB hardcoded to 4 MB */ + def->vram = 4 * 1024; + break; + } + } + + if (heads && + virStrToLong_ui(heads, NULL, 10, &def->heads) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("cannot parse video heads '%s'"), heads); + goto error; + } else { + def->heads = 1; + } + + VIR_FREE(type); + VIR_FREE(vram); + VIR_FREE(heads); + + return def; + +error: + virDomainVideoDefFree(def); + VIR_FREE(type); + VIR_FREE(vram); + VIR_FREE(heads); + return NULL; +} + static int virDomainHostdevSubsysUsbDefParseXML(virConnectPtr conn, const xmlNodePtr node, @@ -2064,6 +2164,10 @@ virDomainDeviceDefPtr virDomainDeviceDef dev->type = VIR_DOMAIN_DEVICE_SOUND; if (!(dev->data.sound = virDomainSoundDefParseXML(conn, node, flags))) goto error; + } else if (xmlStrEqual(node->name, BAD_CAST "video")) { + dev->type = VIR_DOMAIN_DEVICE_VIDEO; + if (!(dev->data.video = virDomainVideoDefParseXML(conn, node, flags))) + goto error; } else if (xmlStrEqual(node->name, BAD_CAST "hostdev")) { dev->type = VIR_DOMAIN_DEVICE_HOSTDEV; if (!(dev->data.hostdev = virDomainHostdevDefParseXML(conn, node, flags))) @@ -2584,6 +2688,40 @@ static virDomainDefPtr virDomainDefParse } VIR_FREE(nodes); + /* analysis of the video devices */ + if ((n = virXPathNodeSet(conn, "./devices/video", ctxt, &nodes)) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("cannot extract video devices")); + goto error; + } + if (n && VIR_ALLOC_N(def->videos, n) < 0) + goto no_memory; + for (i = 0 ; i < n ; i++) { + virDomainVideoDefPtr video = virDomainVideoDefParseXML(conn, + nodes[i], + flags); + if (!video) + goto error; + def->videos[def->nvideos++] = video; + } + VIR_FREE(nodes); + + /* For backwards compatability, if no <video> tag is set but there + * is a <graphics> tag, then we add a single video tag */ + if (def->ngraphics && !def->nvideos) { + virDomainVideoDefPtr video; + if (VIR_ALLOC(video) < 0) + goto no_memory; + video->type = VIR_DOMAIN_VIDEO_TYPE_CIRRUS; + video->vram = 9 * 1024; + video->heads = 1; + if (VIR_ALLOC_N(def->videos, 1) < 0) { + virDomainVideoDefFree(video); + goto no_memory; + } + def->videos[def->nvideos++] = video; + } + /* analysis of the host devices */ if ((n = virXPathNodeSet(conn, "./devices/hostdev", ctxt, &nodes)) < 0) { virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, @@ -3286,6 +3424,32 @@ virDomainSoundDefFormat(virConnectPtr co } static int +virDomainVideoDefFormat(virConnectPtr conn, + virBufferPtr buf, + virDomainVideoDefPtr def) +{ + const char *model = virDomainVideoTypeToString(def->type); + + if (!model) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unexpected video model %d"), def->type); + return -1; + } + + virBufferAddLit(buf, " <video>\n"); + virBufferVSprintf(buf, " <model type='%s'", + model); + if (def->vram) + virBufferVSprintf(buf, " vram='%u'", def->vram); + if (def->heads) + virBufferVSprintf(buf, " heads='%u'", def->heads); + virBufferAddLit(buf, "/>\n"); + virBufferAddLit(buf, " </video>\n"); + + return 0; +} + +static int virDomainInputDefFormat(virConnectPtr conn, virBufferPtr buf, virDomainInputDefPtr def) @@ -3660,6 +3824,10 @@ char *virDomainDefFormat(virConnectPtr c if (virDomainSoundDefFormat(conn, &buf, def->sounds[n]) < 0) goto cleanup; + for (n = 0 ; n < def->nvideos ; n++) + if (virDomainVideoDefFormat(conn, &buf, def->videos[n]) < 0) + goto cleanup; + for (n = 0 ; n < def->nhostdevs ; n++) if (virDomainHostdevDefFormat(conn, &buf, def->hostdevs[n]) < 0) goto cleanup; diff -r 66fa9bfc797c src/domain_conf.h --- a/src/domain_conf.h Mon May 18 11:28:46 2009 +0100 +++ b/src/domain_conf.h Mon May 18 11:29:00 2009 +0100 @@ -264,6 +264,25 @@ struct _virDomainSoundDef { int model; }; + +enum virDomainVideoType { + VIR_DOMAIN_VIDEO_TYPE_VGA, + VIR_DOMAIN_VIDEO_TYPE_CIRRUS, + VIR_DOMAIN_VIDEO_TYPE_VMVGA, + VIR_DOMAIN_VIDEO_TYPE_XEN, + + VIR_DOMAIN_VIDEO_TYPE_LAST +}; + + +typedef struct _virDomainVideoDef virDomainVideoDef; +typedef virDomainVideoDef *virDomainVideoDefPtr; +struct _virDomainVideoDef { + int type; + unsigned int vram; + unsigned int heads; +}; + /* 3 possible graphics console modes */ enum virDomainGraphicsType { VIR_DOMAIN_GRAPHICS_TYPE_SDL, @@ -360,6 +379,7 @@ enum virDomainDeviceType { VIR_DOMAIN_DEVICE_NET, VIR_DOMAIN_DEVICE_INPUT, VIR_DOMAIN_DEVICE_SOUND, + VIR_DOMAIN_DEVICE_VIDEO, VIR_DOMAIN_DEVICE_HOSTDEV, VIR_DOMAIN_DEVICE_LAST, @@ -375,6 +395,7 @@ struct _virDomainDeviceDef { virDomainNetDefPtr net; virDomainInputDefPtr input; virDomainSoundDefPtr sound; + virDomainVideoDefPtr video; virDomainHostdevDefPtr hostdev; } data; }; @@ -491,6 +512,9 @@ struct _virDomainDef { int nsounds; virDomainSoundDefPtr *sounds; + int nvideos; + virDomainVideoDefPtr *videos; + int nhostdevs; virDomainHostdevDefPtr *hostdevs; @@ -557,6 +581,7 @@ void virDomainFSDefFree(virDomainFSDefPt void virDomainNetDefFree(virDomainNetDefPtr def); void virDomainChrDefFree(virDomainChrDefPtr def); void virDomainSoundDefFree(virDomainSoundDefPtr def); +void virDomainVideoDefFree(virDomainVideoDefPtr def); void virDomainHostdevDefFree(virDomainHostdevDefPtr def); void virDomainDeviceDefFree(virDomainDeviceDefPtr def); void virDomainDefFree(virDomainDefPtr vm); @@ -671,6 +696,7 @@ VIR_ENUM_DECL(virDomainFS) VIR_ENUM_DECL(virDomainNet) VIR_ENUM_DECL(virDomainChr) VIR_ENUM_DECL(virDomainSoundModel) +VIR_ENUM_DECL(virDomainVideo) VIR_ENUM_DECL(virDomainHostdevMode) VIR_ENUM_DECL(virDomainHostdevSubsys) VIR_ENUM_DECL(virDomainInput) -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list