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@xxxxxxxxxx> 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 :| -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list