[libvirt] PATCH 1/2: Support <video> element in domain config

This patch implements the basic domain config support for a <video> element as per http://www.redhat.com/archives/libvir-list/2009-May/msg00424.html Since last time this - Centralized the logic for default video model & default RAM - Added a type=vbox for their custom graphics card Daniel From: Daniel P. Berrange <berrange@redhat.com> Date: Mon, 6 Jul 2009 14:54:44 +0100 Subject: [PATCH 1/3] Support <video> tag for defining VGA card properties * docs/schemas/domain.rng: Define <video> element schema * src/domain_conf.c, src/domain_conf.h, src/libvirt_private.syms: Add parsing and formatting for <video> element --- docs/schemas/domain.rng | 34 +++++++ src/domain_conf.c | 225 ++++++++++++++++++++++++++++++++++++++++++++++ src/domain_conf.h | 29 ++++++ src/libvirt_private.syms | 5 + 4 files changed, 293 insertions(+), 0 deletions(-) diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng index 11cf04a..f857301 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -786,6 +786,39 @@ </element> </define> <!-- + A graphic description, currently in Xen only 2 types are supported: + - sdl with optional display, xauth and fullscreen + - vnc with a required port and optional listen IP address, password + and keymap + --> + <define name="video"> + <element name="video"> + <optional> + <element name="model"> + <attribute name="type"> + <choice> + <value>vga</value> + <value>cirrus</value> + <value>vmvga</value> + <value>xen</value> + <value>vbox</value> + </choice> + </attribute> + <optional> + <attribute name="vram"> + <ref name="unsignedInt"/> + </attribute> + </optional> + <optional> + <attribute name="heads"> + <ref name="unsignedInt"/> + </attribute> + </optional> + </element> + </optional> + </element> + </define> + <!-- When a domain terminates multiple policies can be applied depending on how it ended: --> @@ -1032,6 +1065,7 @@ <ref name="sound"/> <ref name="hostdev"/> <ref name="graphic"/> + <ref name="video"/> <ref name="console"/> <ref name="parallel"/> <ref name="serial"/> diff --git a/src/domain_conf.c b/src/domain_conf.c index ffa2aef..cc8c3ef 100644 --- a/src/domain_conf.c +++ b/src/domain_conf.c @@ -82,6 +82,7 @@ VIR_ENUM_IMPL(virDomainDevice, VIR_DOMAIN_DEVICE_LAST, "interface", "input", "sound", + "video", "hostdev") VIR_ENUM_IMPL(virDomainDisk, VIR_DOMAIN_DISK_TYPE_LAST, @@ -142,6 +143,13 @@ VIR_ENUM_IMPL(virDomainSoundModel, VIR_DOMAIN_SOUND_MODEL_LAST, "pcspk", "ac97") +VIR_ENUM_IMPL(virDomainVideo, VIR_DOMAIN_VIDEO_TYPE_LAST, + "vga", + "cirrus", + "vmvga", + "xen", + "vbox") + VIR_ENUM_IMPL(virDomainInput, VIR_DOMAIN_INPUT_TYPE_LAST, "mouse", "tablet") @@ -374,6 +382,14 @@ void virDomainSoundDefFree(virDomainSoundDefPtr def) VIR_FREE(def); } +void virDomainVideoDefFree(virDomainVideoDefPtr def) +{ + if (!def) + return; + + VIR_FREE(def); +} + void virDomainHostdevDefFree(virDomainHostdevDefPtr def) { if (!def) @@ -401,6 +417,9 @@ void virDomainDeviceDefFree(virDomainDeviceDefPtr def) 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; @@ -458,6 +477,10 @@ void virDomainDefFree(virDomainDefPtr def) 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); @@ -1653,6 +1676,133 @@ error: goto cleanup; } + +int +virDomainVideoDefaultRAM(virDomainDefPtr def, + int type) +{ + switch (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: + if (def->virtType == VIR_DOMAIN_VIRT_VBOX) + return 8 * 1024; + else + return 9 * 1024; + break; + + case VIR_DOMAIN_VIDEO_TYPE_XEN: + /* Original Xen PVFB hardcoded to 4 MB */ + return 4 * 1024; + + default: + return 0; + } +} + + +int +virDomainVideoDefaultType(virDomainDefPtr def) +{ + switch (def->virtType) { + case VIR_DOMAIN_VIRT_TEST: + case VIR_DOMAIN_VIRT_QEMU: + case VIR_DOMAIN_VIRT_KQEMU: + case VIR_DOMAIN_VIRT_KVM: + case VIR_DOMAIN_VIRT_XEN: + if (def->os.type && + (STREQ(def->os.type, "xen") || + STREQ(def->os.type, "linux"))) + return VIR_DOMAIN_VIDEO_TYPE_XEN; + else + return VIR_DOMAIN_VIDEO_TYPE_CIRRUS; + + case VIR_DOMAIN_VIRT_VBOX: + return VIR_DOMAIN_VIDEO_TYPE_VBOX; + + default: + return -1; + } +} + +static virDomainVideoDefPtr +virDomainVideoDefParseXML(virConnectPtr conn, + const xmlNodePtr node, + virDomainDefPtr dom, + 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) { + if ((def->type = virDomainVideoTypeFromString(type)) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unknown video model '%s'"), type); + goto error; + } + } else { + if ((def->type = virDomainVideoDefaultType(dom)) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", + _("missing video model and cannot determine default")); + goto error; + } + } + + if (vram) { + if (virStrToLong_ui(vram, NULL, 10, &def->vram) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("cannot parse video ram '%s'"), vram); + goto error; + } + } else { + def->vram = virDomainVideoDefaultRAM(dom, def->type); + } + + if (heads) { + if (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, @@ -2091,6 +2241,10 @@ virDomainDeviceDefPtr virDomainDeviceDefParse(virConnectPtr conn, 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, def, 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))) @@ -2649,6 +2803,47 @@ static virDomainDefPtr virDomainDefParseXML(virConnectPtr conn, } 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], + def, + 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 = virDomainVideoDefaultType(def); + if (video->type < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot determine default video type")); + VIR_FREE(video); + goto error; + } + video->vram = virDomainVideoDefaultRAM(def, video->type); + 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, @@ -3486,6 +3681,32 @@ virDomainSoundDefFormat(virConnectPtr conn, } 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) @@ -3860,6 +4081,10 @@ char *virDomainDefFormat(virConnectPtr conn, 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 --git a/src/domain_conf.h b/src/domain_conf.h index 51310c1..51dd6d3 100644 --- a/src/domain_conf.h +++ b/src/domain_conf.h @@ -265,6 +265,26 @@ 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_VBOX, + + 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, @@ -361,6 +381,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, @@ -376,6 +397,7 @@ struct _virDomainDeviceDef { virDomainNetDefPtr net; virDomainInputDefPtr input; virDomainSoundDefPtr sound; + virDomainVideoDefPtr video; virDomainHostdevDefPtr hostdev; } data; }; @@ -492,6 +514,9 @@ struct _virDomainDef { int nsounds; virDomainSoundDefPtr *sounds; + int nvideos; + virDomainVideoDefPtr *videos; + int nhostdevs; virDomainHostdevDefPtr *hostdevs; @@ -557,6 +582,7 @@ void virDomainFSDefFree(virDomainFSDefPtr def); 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); @@ -666,6 +692,8 @@ int virDiskNameToBusDeviceIndex(virDomainDiskDefPtr disk, int *devIdx); virDomainFSDefPtr virDomainGetRootFilesystem(virDomainDefPtr def); +int virDomainVideoDefaultType(virDomainDefPtr def); +int virDomainVideoDefaultRAM(virDomainDefPtr def, int type); void virDomainObjLock(virDomainObjPtr obj); void virDomainObjUnlock(virDomainObjPtr obj); @@ -683,6 +711,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) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index bd7910b..d43620f 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -100,6 +100,11 @@ virDomainSaveStatus; virDomainSoundDefFree; virDomainSoundModelTypeFromString; virDomainSoundModelTypeToString; +virDomainVideoDefFree; +virDomainVideoTypeToString; +virDomainVideoTypeFromString; +virDomainVideoDefaultRAM; +virDomainVideoDefaultType; virDomainVirtTypeToString; virDomainFSDefFree; virDomainObjLock; -- 1.6.2.5 -- |: 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 :|

On Tue, Jul 07, 2009 at 11:12:52PM +0100, Daniel P. Berrange wrote:
This patch implements the basic domain config support for a <video> element as per
http://www.redhat.com/archives/libvir-list/2009-May/msg00424.html
Since last time this
- Centralized the logic for default video model & default RAM - Added a type=vbox for their custom graphics card
Patch looks fine to me, but it seems to miss 3dSupport as discussed with Pritesh. But it will be easy to add this, and that will allow Tom Hughes to rebase his patch on top of this ACK, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

On Wed, Jul 08, 2009 at 12:18:37PM +0200, Daniel Veillard wrote:
On Tue, Jul 07, 2009 at 11:12:52PM +0100, Daniel P. Berrange wrote:
This patch implements the basic domain config support for a <video> element as per
http://www.redhat.com/archives/libvir-list/2009-May/msg00424.html
Since last time this
- Centralized the logic for default video model & default RAM - Added a type=vbox for their custom graphics card
Patch looks fine to me, but it seems to miss 3dSupport as discussed with Pritesh. But it will be easy to add this, and that will allow Tom Hughes to rebase his patch on top of this
Oh yes, I meant to mention that. I was looking at the VirtualBox SDK docs I have and they didn't seem to include details on 3dSupport. Perhaps its a newer Vbox feature not available in the verison I have. In any case, its easy enough to add later if someone wires up this <video> tag into the vbox driver Daniel -- |: 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 :|

- Centralized the logic for default video model & default RAM - Added a type=vbox for their custom graphics card
Patch looks fine to me, but it seems to miss 3dSupport as discussed with Pritesh. But it will be easy to add this, and that will allow Tom Hughes to rebase his patch on top of this
Oh yes, I meant to mention that. I was looking at the VirtualBox SDK docs I have and they didn't seem to include details on 3dSupport. Perhaps its a newer Vbox feature not available in the verison I have. In any case, its easy enough to add later if someone wires up this <video> tag into the vbox driver
Sorry for replying late was busy with Vbox version 3.0 support. The 3D support is available since 2.2 onwards, will add support for it and post a patch soon. Regards, Pritesh
participants (3)
-
Daniel P. Berrange
-
Daniel Veillard
-
Pritesh Kothari