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(a)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 :|