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

Daniel P. Berrange berrange at redhat.com
Tue Jul 7 22:12:52 UTC 2009


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 at 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 :|




More information about the libvir-list mailing list