The <code>model</code> element has a mandatory <code>type</code>
attribute which takes the value "vga", "cirrus", "vmvga", "xen",
"vbox", "qxl" (<span class="since">since 0.8.6</span>),
- "virtio" (<span class="since">since 1.3.0</span>)
- or "gop" (<span class="since">since 3.2.0</span>)
+ "virtio" (<span class="since">since 1.3.0</span>),
+ "gop" (<span class="since">since 3.2.0</span>), or
+ "none" (<span class="since">since 4.6.0</span>)
depending on the hypervisor features available.
+ The purpose of the type <code>none</code> is to instruct libvirt not
+ to add a default video device in the guest (see the paragraph above).
+ This legacy behaviour can be inconvenient in cases where GPU mediated
+ devices are meant to be the only rendering device within a guest and
+ so specifying another <code>video</code> device along with type
+ <code>none</code>.
+ Refer to <a id="elementsHostDev">Host device assignment</a> to see
+ how to add a mediated device into a guest.
</p>
<p>
You can provide the amount of video memory in kibibytes (blocks of
<value>vbox</value>
<value>virtio</value>
<value>gop</value>
+ <value>none</value>
</choice>
</attribute>
<group>
"qxl",
"parallels",
"virtio",
- "gop")
+ "gop",
+ "none")
VIR_ENUM_IMPL(virDomainVideoVGAConf, VIR_DOMAIN_VIDEO_VGACONF_LAST,
"io",
if (def->nvideos == 0)
return 0;
- virDomainDeviceDef device = {
- .type = VIR_DOMAIN_DEVICE_VIDEO,
- .data.video = def->videos[0],
- };
+ if (def->videos[0]->type == VIR_DOMAIN_VIDEO_TYPE_NONE) {
+ /* we don't want to format any values we automatically fill in for
+ * videos into the XML, so clear them
+ */
+ virDomainVideoDefClear(def->videos[0]);
+ def->videos[0]->type = VIR_DOMAIN_VIDEO_TYPE_NONE;
+ } else {
+ virDomainDeviceDef device = {
+ .type = VIR_DOMAIN_DEVICE_VIDEO,
+ .data.video = def->videos[0],
+ };
- /* Mark the first video as primary. If the user specified
- * primary="yes", the parser already inserted the device at
- * def->videos[0]
- */
- def->videos[0]->primary = true;
+ /* Mark the first video as primary. If the user specified
+ * primary="yes", the parser already inserted the device at
+ * def->videos[0]
+ */
+ def->videos[0]->primary = true;
- /* videos[0] might have been added in AddImplicitDevices, after we've
- * done the per-device post-parse */
- if (virDomainDefPostParseDeviceIterator(def, &device,
- NULL, opaque) < 0)
- return -1;
+ /* videos[0] might have been added in AddImplicitDevices, after we've
+ * done the per-device post-parse */
+ if (virDomainDefPostParseDeviceIterator(def, &device,
+ NULL, opaque) < 0)
+ return -1;
+ }
return 0;
}
static int
-virDomainVideoDefValidate(const virDomainVideoDef *video)
+virDomainVideoDefValidate(const virDomainVideoDef *video,
+ const virDomainDef *def)
{
+ size_t i;
+
if (video->type == VIR_DOMAIN_VIDEO_TYPE_DEFAULT) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("missing video model and cannot determine default"));
return -1;
}
+
+ /* it doesn't make sense to pair video device type 'none' with any other
+ * types, there can be only a single video device in such case
+ */
+ for (i = 0; i < def->nvideos; i++) {
+ if (def->videos[i]->type == VIR_DOMAIN_VIDEO_TYPE_NONE &&
+ def->nvideos > 1) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("a '%s' video type must be the only video device "
+ "defined for the domain"));
+ return -1;
+ }
+ }
+
return 0;
}
return virDomainHostdevDefValidate(dev->data.hostdev);
case VIR_DOMAIN_DEVICE_VIDEO:
- return virDomainVideoDefValidate(dev->data.video);
+ return virDomainVideoDefValidate(dev->data.video, def);
case VIR_DOMAIN_DEVICE_MEMORY:
return virDomainMemoryDefValidate(dev->data.memory);
case VIR_DOMAIN_VIDEO_TYPE_PARALLELS:
case VIR_DOMAIN_VIDEO_TYPE_VIRTIO:
case VIR_DOMAIN_VIDEO_TYPE_GOP:
+ case VIR_DOMAIN_VIDEO_TYPE_NONE:
case VIR_DOMAIN_VIDEO_TYPE_LAST:
default:
return 0;
VIR_DOMAIN_VIDEO_TYPE_PARALLELS, /* pseudo device for VNC in containers */
VIR_DOMAIN_VIDEO_TYPE_VIRTIO,
VIR_DOMAIN_VIDEO_TYPE_GOP,
+ VIR_DOMAIN_VIDEO_TYPE_NONE,
VIR_DOMAIN_VIDEO_TYPE_LAST
} virDomainVideoType;
"qxl",
"", /* don't support parallels */
"", /* no need for virtio */
- "" /* don't support gop */);
+ "" /* don't support gop */,
+ "" /* 'none' doesn't make sense here */);
VIR_ENUM_DECL(qemuDeviceVideo)
"qxl-vga",
"", /* don't support parallels */
"virtio-vga",
- "" /* don't support gop */);
+ "" /* don't support gop */,
+ "" /* 'none' doesn't make sense here */);
VIR_ENUM_DECL(qemuDeviceVideoSecondary)
"qxl",
"", /* don't support parallels */
"virtio-gpu",
- "" /* don't support gop */);
+ "" /* don't support gop */,
+ "" /* 'none' doesn't make sense here */);
VIR_ENUM_DECL(qemuSoundCodec)
char *str = NULL;
virDomainVideoDefPtr video = def->videos[i];
+ if (video->type == VIR_DOMAIN_VIDEO_TYPE_NONE)
+ continue;
+
if (video->primary) {
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY)) {
qemuDomainDeviceDefValidateVideo(const virDomainVideoDef *video)
{
switch ((virDomainVideoType) video->type) {
+ case VIR_DOMAIN_VIDEO_TYPE_NONE:
+ return 0;
case VIR_DOMAIN_VIDEO_TYPE_XEN:
case VIR_DOMAIN_VIDEO_TYPE_VBOX:
case VIR_DOMAIN_VIDEO_TYPE_PARALLELS:
case VIR_DOMAIN_VIDEO_TYPE_DEFAULT:
case VIR_DOMAIN_VIDEO_TYPE_GOP:
+ case VIR_DOMAIN_VIDEO_TYPE_NONE:
case VIR_DOMAIN_VIDEO_TYPE_LAST:
return 0;
}
goto cleanup;
}
- if (def->nvideos > 0) {
+ if (def->nvideos > 0 &&
+ def->videos[0]->type != VIR_DOMAIN_VIDEO_TYPE_NONE) {
/* Because the PIIX3 integrated IDE/USB controllers are
* already at slot 1, when qemu looks for the first free slot
* to place the VGA controller (which is always the first
* at slot 2.
*/
virDomainVideoDefPtr primaryVideo = def->videos[0];
+
if (virDeviceInfoPCIAddressWanted(&primaryVideo->info)) {
memset(&tmp_addr, 0, sizeof(tmp_addr));
tmp_addr.slot = 2;
/* Video devices */
for (i = 0; i < def->nvideos; i++) {
+ if (def->videos[i]->type == VIR_DOMAIN_VIDEO_TYPE_NONE)
+ continue;
if (!virDeviceInfoPCIAddressWanted(&def->videos[i]->info))
continue;
<value>parallels</value>
<value>virtio</value>
<value>gop</value>
+ <value>none</value>
</enum>
</video>
<hostdev supported='yes'>
--- /dev/null
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219100</memory>
+ <currentMemory unit='KiB'>219100</currentMemory>
+ <vcpu placement='static' cpuset='1-4,8-20,525'>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu-system-i686</emulator>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+ </disk>
+ <controller type='usb' index='0'/>
+ <controller type='ide' index='0'/>
+ <controller type='pci' index='0' model='pci-root'/>
+ <video>
+ <model type='qxl'/>
+ </video>
+ <video>
+ <model type='none'/>
+ </video>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
--- /dev/null
+LC_ALL=C \
+PATH=/bin \
+HOME=/home/test \
+USER=test \
+LOGNAME=test \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu-system-i686 \
+-name QEMUGuest1 \
+-S \
+-machine pc,accel=tcg,usb=off,dump-guest-core=off \
+-m 214 \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-no-user-config \
+-nodefaults \
+-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,\
+server,nowait \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-rtc base=utc \
+-no-shutdown \
+-no-acpi \
+-boot c \
+-usb \
+-drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-ide0-0-0 \
+-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 \
+-vnc 127.0.0.1:0 \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
--- /dev/null
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219136</memory>
+ <currentMemory unit='KiB'>219136</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu-system-i686</emulator>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+ </disk>
+ <controller type='usb' index='0'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
+ </controller>
+ <controller type='ide' index='0'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
+ </controller>
+ <controller type='pci' index='0' model='pci-root'/>
+ <input type='mouse' bus='ps2'/>
+ <input type='keyboard' bus='ps2'/>
+ <graphics type='vnc'/>
+ <video>
+ <model type='none'/>
+ </video>
+ <memballoon model='virtio'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
+ </memballoon>
+ </devices>
+</domain>
QEMU_CAPS_DEVICE_VIRTIO_VGA,
QEMU_CAPS_DEVICE_VIDEO_PRIMARY,
QEMU_CAPS_VIRTIO_GPU_MAX_OUTPUTS);
- DO_TEST_PARSE_ERROR("video-invalid", NONE);
+ DO_TEST("video-none-device",
+ QEMU_CAPS_VNC);
+ DO_TEST_PARSE_ERROR("video-invalid-multiple-devices", NONE);
DO_TEST("virtio-rng-default",
QEMU_CAPS_DEVICE_VIRTIO_RNG,
--- /dev/null
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219136</memory>
+ <currentMemory unit='KiB'>219136</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu-system-i686</emulator>
+ <disk type='block' device='disk'>
+ <driver name='qemu' type='raw'/>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+ </disk>
+ <controller type='usb' index='0'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
+ </controller>
+ <controller type='ide' index='0'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
+ </controller>
+ <controller type='pci' index='0' model='pci-root'/>
+ <input type='mouse' bus='ps2'/>
+ <input type='keyboard' bus='ps2'/>
+ <graphics type='vnc' port='-1' autoport='yes'>
+ <listen type='address'/>
+ </graphics>
+ <video>
+ <model type='none'/>
+ </video>
+ <memballoon model='virtio'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
+ </memballoon>
+ </devices>
+</domain>
QEMU_CAPS_VIRTIO_GPU_MAX_OUTPUTS,
QEMU_CAPS_VNC,
QEMU_CAPS_DEVICE_VIRTIO_GPU_CCW);
+ DO_TEST("video-none-device", NONE);
DO_TEST("intel-iommu",
QEMU_CAPS_DEVICE_INTEL_IOMMU);