[libvirt] [PATCH 5/5] conf: Introduce new video type 'none'

John Ferlan jferlan at redhat.com
Mon Jul 2 19:48:10 UTC 2018



On 06/28/2018 08:15 AM, Erik Skultety wrote:
> Historically, we've always enabled an emulated video device every time we
> see that graphics should be supported with a guest. With the appearance
> of mediated devices which can support QEMU's vfio-display capability,
> users might want to use such a device as the only video device.
> Therefore introduce a new, effectively a 'disable', type for video
> device.
> 
> Signed-off-by: Erik Skultety <eskultet at redhat.com>
> ---
>  docs/formatdomain.html.in                          | 10 +++-
>  docs/schemas/domaincommon.rng                      |  1 +
>  src/conf/domain_conf.c                             | 55 ++++++++++++++++------
>  src/conf/domain_conf.h                             |  1 +
>  src/qemu/qemu_command.c                            | 13 +++--
>  src/qemu/qemu_domain.c                             |  3 ++
>  src/qemu/qemu_domain_address.c                     | 10 ++++
>  tests/domaincapsschemadata/full.xml                |  1 +
>  .../video-invalid-multiple-devices.xml             | 33 +++++++++++++
>  tests/qemuxml2argvdata/video-none-device.args      | 27 +++++++++++
>  tests/qemuxml2argvdata/video-none-device.xml       | 39 +++++++++++++++
>  tests/qemuxml2argvtest.c                           |  4 +-
>  tests/qemuxml2xmloutdata/video-none-device.xml     | 42 +++++++++++++++++
>  tests/qemuxml2xmltest.c                            |  1 +
>  14 files changed, 219 insertions(+), 21 deletions(-)
>  create mode 100644 tests/qemuxml2argvdata/video-invalid-multiple-devices.xml
>  create mode 100644 tests/qemuxml2argvdata/video-none-device.args
>  create mode 100644 tests/qemuxml2argvdata/video-none-device.xml
>  create mode 100644 tests/qemuxml2xmloutdata/video-none-device.xml
> 

I assume this has to do with the egl-headless discussion from the other
series, so rather than "none", why not go with headless?  The problem I
see w/ NONE is it's usage/meaning typically as, well, NONE or not
defined; whereas, for graphics it would then mean, well it's defined,
but it's something else.

If this isn't a headless device, then I'll need to revisit my comments
below...

Also please split domain/docs/xml2ml from qemu/xml2argv

> diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
> index f45eee6812..2e8196c21f 100644
> --- a/docs/formatdomain.html.in
> +++ b/docs/formatdomain.html.in
> @@ -6639,9 +6639,15 @@ qemu-kvm -net nic,model=? /dev/null
>            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.
> +          Note that type <code>"none"</code> is currently only available for
> +          QEMU and the intended use case is to prevent libvirt from adding a
> +          default emulated video card in case a host device like mdev should
> +          handle the rendering, see also
> +          <a href="#elementsGraphics">Graphical framebuffers</a>.

"host device like mdev" - I assume you meant "type"... In any case, not
sure it's possible from the domain/xml2xml viewpoint to say QEMU only -
having it in domain. Perhaps consider something like:

"The <code>headless</code> type is designed to be used in coordination
with a host device graphics co-processor such as is provided via
Mediated Device vGPUs. When using a <code>headless</code> type, it must
be the only graphics device defined for the domain.

You could add a link from mdev to
https://libvirt.org/drvnodedev.html#MDEV just like the host device mdev
description did or a link to the hostdev section. It's too bad there
wasn't an anchor for that directly...



>          </p>
>          <p>
>            You can provide the amount of video memory in kibibytes (blocks of
> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
> index 1df479cda2..55da8c079b 100644
> --- a/docs/schemas/domaincommon.rng
> +++ b/docs/schemas/domaincommon.rng
> @@ -3468,6 +3468,7 @@
>                  <value>vbox</value>
>                  <value>virtio</value>
>                  <value>gop</value>
> +                <value>none</value>

headless

>                </choice>
>              </attribute>
>              <group>
> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> index 96ab6cf520..cd2a6c991c 100644
> --- a/src/conf/domain_conf.c
> +++ b/src/conf/domain_conf.c
> @@ -589,7 +589,8 @@ VIR_ENUM_IMPL(virDomainVideo, VIR_DOMAIN_VIDEO_TYPE_LAST,
>                "qxl",
>                "parallels",
>                "virtio",
> -              "gop")
> +              "gop",
> +              "none")

"headless"

>  
>  VIR_ENUM_IMPL(virDomainVideoVGAConf, VIR_DOMAIN_VIDEO_VGACONF_LAST,
>                "io",
> @@ -5125,25 +5126,48 @@ static int
>  virDomainDefPostParseVideo(virDomainDefPtr def,
>                             void *opaque)
>  {
> +    size_t i;
> +
>      if (def->nvideos == 0)
>          return 0;
>  
> -    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]
> +    /* 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
>       */
> -    def->videos[0]->primary = true;
> +    for (i = 0; i < def->nvideos; i++) {
> +        if (def->videos[i]->type == VIR_DOMAIN_VIDEO_TYPE_NONE &&

_HEADLESS

> +            def->nvideos > 1) {
> +            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> +                           _("video device type='none' cannot be paired "
> +                             "with any other video device types"));

Consider, "A '%s' video type must be the only video device defined for
the domain."  virDomainVideoTypeToString(VIR_DOMAIN_VIDEO_TYPE_HEADLESS);


> +            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;
> +    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;
> +
> +        /* 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;
>  }
> @@ -15093,6 +15117,7 @@ virDomainVideoDefaultRAM(const virDomainDef *def,
>      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;
> diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
> index 6d73a0b5d3..c1970e0f62 100644
> --- a/src/conf/domain_conf.h
> +++ b/src/conf/domain_conf.h
> @@ -1424,6 +1424,7 @@ typedef enum {
>      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;
> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
> index a2a27b5b9b..bc798f9d2d 100644
> --- a/src/qemu/qemu_command.c
> +++ b/src/qemu/qemu_command.c
> @@ -105,7 +105,8 @@ VIR_ENUM_IMPL(qemuVideo, VIR_DOMAIN_VIDEO_TYPE_LAST,
>                "qxl",
>                "", /* don't support parallels */
>                "", /* no need for virtio */
> -              "" /* don't support gop */);
> +              "" /* don't support gop */,
> +              "none" /* no display */);
>  
>  VIR_ENUM_DECL(qemuDeviceVideo)
>  
> @@ -119,7 +120,8 @@ VIR_ENUM_IMPL(qemuDeviceVideo, VIR_DOMAIN_VIDEO_TYPE_LAST,
>                "qxl-vga",
>                "", /* don't support parallels */
>                "virtio-vga",
> -              "" /* don't support gop */);
> +              "" /* don't support gop */,
> +              "none" /* no display */);
>  

I assume these become egl-headless, although I'm not 100% sure based on
Gerd's comment from the other series today.

>  VIR_ENUM_DECL(qemuDeviceVideoSecondary)
>  
> @@ -133,7 +135,8 @@ VIR_ENUM_IMPL(qemuDeviceVideoSecondary, VIR_DOMAIN_VIDEO_TYPE_LAST,
>                "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)
>  
> @@ -4421,6 +4424,10 @@ qemuBuildVideoCommandLine(virCommandPtr cmd,
>          char *str = NULL;
>          virDomainVideoDefPtr video = def->videos[i];
>  
> +        /* no cmdline needed for type 'none' */
> +        if (video->type == VIR_DOMAIN_VIDEO_TYPE_NONE)
> +            return 0;
> +

This could go outside the loop and a direct def->videos[0].type == type
logic, although it's technically fine as is, just makes it "appear" as
if we quit when we find this rather than knowing that it only can occur
at [0]. Of course that's true in qemuDomainAssignDevicePCISlots too I
suppose, so whatever. Just looks strange.

John

>          if (video->primary) {
>              if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY)) {
>  
> diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
> index 42b7635ef4..51aba8d527 100644
> --- a/src/qemu/qemu_domain.c
> +++ b/src/qemu/qemu_domain.c
> @@ -4444,6 +4444,9 @@ static int
>  qemuDomainDeviceDefValidateVideo(const virDomainVideoDef *video)
>  {
>      switch ((virDomainVideoType) video->type) {
> +    case VIR_DOMAIN_VIDEO_TYPE_NONE:
> +        /* nothing to be validated for 'none' */
> +        return 0;
>      case VIR_DOMAIN_VIDEO_TYPE_XEN:
>      case VIR_DOMAIN_VIDEO_TYPE_VBOX:
>      case VIR_DOMAIN_VIDEO_TYPE_PARALLELS:
> diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c
> index ab2ac022f1..bc9786dd60 100644
> --- a/src/qemu/qemu_domain_address.c
> +++ b/src/qemu/qemu_domain_address.c
> @@ -821,6 +821,7 @@ qemuDomainDeviceCalculatePCIConnectFlags(virDomainDeviceDefPtr dev,
>  
>          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;
>          }
> @@ -1540,6 +1541,13 @@ qemuDomainValidateDevicePCISlotsPIIX3(virDomainDefPtr def,
>           * at slot 2.
>           */
>          virDomainVideoDefPtr primaryVideo = def->videos[0];
> +
> +        /* for video type 'none' skip this whole procedure */
> +        if (primaryVideo->type == VIR_DOMAIN_VIDEO_TYPE_NONE) {
> +            ret = 0;
> +            goto cleanup;
> +        }
> +
>          if (virDeviceInfoPCIAddressWanted(&primaryVideo->info)) {
>              memset(&tmp_addr, 0, sizeof(tmp_addr));
>              tmp_addr.slot = 2;
> @@ -2105,6 +2113,8 @@ qemuDomainAssignDevicePCISlots(virDomainDefPtr def,
>  
>      /* Video devices */
>      for (i = 0; i < def->nvideos; i++) {
> +        if (def->videos[i]->type == VIR_DOMAIN_VIDEO_TYPE_NONE)
> +            break;
>  
>          if (!virDeviceInfoPCIAddressWanted(&def->videos[i]->info))
>              continue;
> diff --git a/tests/domaincapsschemadata/full.xml b/tests/domaincapsschemadata/full.xml
> index d3faf38da0..474df90283 100644
> --- a/tests/domaincapsschemadata/full.xml
> +++ b/tests/domaincapsschemadata/full.xml
> @@ -73,6 +73,7 @@
>          <value>parallels</value>
>          <value>virtio</value>
>          <value>gop</value>
> +        <value>none</value>
>        </enum>
>      </video>
>      <hostdev supported='yes'>
> diff --git a/tests/qemuxml2argvdata/video-invalid-multiple-devices.xml b/tests/qemuxml2argvdata/video-invalid-multiple-devices.xml
> new file mode 100644
> index 0000000000..3f105efaae
> --- /dev/null
> +++ b/tests/qemuxml2argvdata/video-invalid-multiple-devices.xml
> @@ -0,0 +1,33 @@
> +<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>
> diff --git a/tests/qemuxml2argvdata/video-none-device.args b/tests/qemuxml2argvdata/video-none-device.args
> new file mode 100644
> index 0000000000..1b03c0cb97
> --- /dev/null
> +++ b/tests/qemuxml2argvdata/video-none-device.args
> @@ -0,0 +1,27 @@
> +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
> diff --git a/tests/qemuxml2argvdata/video-none-device.xml b/tests/qemuxml2argvdata/video-none-device.xml
> new file mode 100644
> index 0000000000..4b591562b7
> --- /dev/null
> +++ b/tests/qemuxml2argvdata/video-none-device.xml
> @@ -0,0 +1,39 @@
> +<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>
> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
> index 8293be949d..4ed165d76b 100644
> --- a/tests/qemuxml2argvtest.c
> +++ b/tests/qemuxml2argvtest.c
> @@ -2010,7 +2010,9 @@ mymain(void)
>              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,
> diff --git a/tests/qemuxml2xmloutdata/video-none-device.xml b/tests/qemuxml2xmloutdata/video-none-device.xml
> new file mode 100644
> index 0000000000..6e76b394fe
> --- /dev/null
> +++ b/tests/qemuxml2xmloutdata/video-none-device.xml
> @@ -0,0 +1,42 @@
> +<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>
> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
> index 0095c27cf6..e482705f0e 100644
> --- a/tests/qemuxml2xmltest.c
> +++ b/tests/qemuxml2xmltest.c
> @@ -1143,6 +1143,7 @@ mymain(void)
>              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);
> 




More information about the libvir-list mailing list