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
This commit is contained in:
Daniel P. Berrange 2009-07-06 14:54:44 +01:00
parent c6cd55d38e
commit 6b4d18c7b3
4 changed files with 293 additions and 0 deletions

View File

@ -785,6 +785,39 @@
</choice>
</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"/>

View File

@ -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,
@ -3485,6 +3680,32 @@ virDomainSoundDefFormat(virConnectPtr conn,
return 0;
}
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,
@ -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;

View File

@ -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)

View File

@ -100,6 +100,11 @@ virDomainSaveStatus;
virDomainSoundDefFree;
virDomainSoundModelTypeFromString;
virDomainSoundModelTypeToString;
virDomainVideoDefFree;
virDomainVideoTypeToString;
virDomainVideoTypeFromString;
virDomainVideoDefaultRAM;
virDomainVideoDefaultType;
virDomainVirtTypeToString;
virDomainFSDefFree;
virDomainObjLock;