diff --git a/src/domain_conf.c b/src/domain_conf.c index ffa2aef..0f1f249 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,12 @@ VIR_ENUM_IMPL(virDomainSoundModel, VIR_DOMAIN_SOUND_MODEL_LAST, "pcspk", "ac97") +VIR_ENUM_IMPL(virDomainVideo, VIR_DOMAIN_VIDEO_TYPE_LAST, + "vga", + "cirrus", + "vmvga", + "xen") + VIR_ENUM_IMPL(virDomainInput, VIR_DOMAIN_INPUT_TYPE_LAST, "mouse", "tablet") @@ -374,6 +381,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 +416,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 +476,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 +1675,84 @@ error: goto cleanup; } +static virDomainVideoDefPtr +virDomainVideoDefParseXML(virConnectPtr conn, + const xmlNodePtr node, + 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 && + (def->type = virDomainVideoTypeFromString(type)) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unknown video model '%s'"), type); + goto error; + } + + if (vram && + virStrToLong_ui(vram, NULL, 10, &def->vram) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("cannot parse video ram '%s'"), vram); + goto error; + } else { + switch (def->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: + def->vram = 9 * 1024; + break; + case VIR_DOMAIN_VIDEO_TYPE_XEN: + /* Original PVFB hardcoded to 4 MB */ + def->vram = 4 * 1024; + break; + } + } + + if (heads && + 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 +2191,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, 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 +2753,49 @@ 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], + flags); + if (!video) + goto error; + def->videos[def->nvideos++] = video; + } + VIR_FREE(nodes); + + /* For backwards compatability, if no