[3/5] domaincaps: Report graphics spiceGL

Message ID 2bd768bf0279c507cf0686827cc598ef74603179.1462729517.git.crobinso@redhat.com
State New
Headers show

Commit Message

Cole Robinson May 8, 2016, 5:49 p.m.
Reports a tristate enum value for acceptable graphics type=spice
<gl enable=XXX/>.

Wire it up for qemu too. 'no' is always a valid value, so we
unconditionally report it.
---
 docs/formatdomaincaps.html.in                           | 8 ++++++++
 src/conf/domain_capabilities.c                          | 1 +
 src/conf/domain_capabilities.h                          | 1 +
 src/qemu/qemu_capabilities.c                            | 4 ++++
 tests/domaincapsschemadata/domaincaps-full.xml          | 5 +++++
 tests/domaincapsschemadata/domaincaps-qemu_1.6.50-1.xml | 3 +++
 tests/domaincapsschemadata/domaincaps-qemu_2.6.0-1.xml  | 4 ++++
 tests/domaincapsschemadata/domaincaps-qemu_2.6.0-2.xml  | 3 +++
 tests/domaincapsschemadata/domaincaps-qemu_2.6.0-3.xml  | 3 +++
 tests/domaincapsschemadata/domaincaps-qemu_2.6.0-4.xml  | 3 +++
 tests/domaincapsschemadata/domaincaps-qemu_2.6.0-5.xml  | 3 +++
 tests/domaincapstest.c                                  | 1 +
 12 files changed, 39 insertions(+)

-- 
2.7.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Comments

Cole Robinson May 9, 2016, 1:30 p.m. | #1
On 05/09/2016 07:30 AM, Pavel Hrdina wrote:
> On Sun, May 08, 2016 at 01:49:06PM -0400, Cole Robinson wrote:

>> Reports a tristate enum value for acceptable graphics type=spice

>> <gl enable=XXX/>.

>>

>> Wire it up for qemu too. 'no' is always a valid value, so we

>> unconditionally report it.

>> ---

> 

> [...]

> 

>> diff --git a/tests/domaincapsschemadata/domaincaps-full.xml b/tests/domaincapsschemadata/domaincaps-full.xml

>> index 2f529ff..4eb5637 100644

>> --- a/tests/domaincapsschemadata/domaincaps-full.xml

>> +++ b/tests/domaincapsschemadata/domaincaps-full.xml

>> @@ -47,6 +47,11 @@

>>          <value>desktop</value>

>>          <value>spice</value>

>>        </enum>

>> +      <enum name='spiceGL'>

>> +        <value>default</value>

>> +        <value>yes</value>

>> +        <value>no</value>

>> +      </enum>

> 

> Ewww, this doesn't look good and I agree with Michal that what if we add

> support for another graphics device and what if one graphics device will have

> more than one capability?

> 

> I would suggest something like this:

> 

>     <graphics supported='yes'>

>       <enum name='type'>

>         <value>spice</value>

>         <value>vnc</value>

>         <value>sdl</value>

>       </enum>

>       <type name='spice'>

>         <gl supported='yes'/>

>       </type>

>     </graphics>

> 

> or even do something like this:

> 

>     <graphics supported='yes'>

>       <type name='spice'>

>         <gl supported='yes'/>

>       </type>

>       <type name='vnc'/>

>       <type name='sdl'/>

>     </graphics>

> 


Really wish someone would have chimed in with this to my (unresponded) RFC
email about these things...

http://www.redhat.com/archives/libvir-list/2016-April/msg01839.html

That pattern is fine in this case, but what about the case of ports= element
that is only supported with a controller type=usb model=nec-xhci ? Do we have
new XML like:

<controller supported='yes'>
  <type name='usb'>
    <model name='nec-xhci'/>
      <param name='ports' supported='yes'/>
    </model>
  </type>
</controller>

It seems like these types of relationships could grow deeply nested, so I
opted for following the limited existing convention of adding unique enum
names to represent the relationship.

I'm not really opposed to the nesting, but I'd like others on the list to
state their preference before I rework this

Thanks,
Cole

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Cole Robinson May 9, 2016, 1:35 p.m. | #2
On 05/09/2016 05:26 AM, Michal Privoznik wrote:
> On 08.05.2016 19:49, Cole Robinson wrote:

>> Reports a tristate enum value for acceptable graphics type=spice

>> <gl enable=XXX/>.

> 

> This ^^ is part of graphics element as follows:

> 

> <graphics>

>   <gl enable='yes'/>

> </graphics> ..

> 

>>

>> Wire it up for qemu too. 'no' is always a valid value, so we

>> unconditionally report it.

>> ---

>>  docs/formatdomaincaps.html.in                           | 8 ++++++++

>>  src/conf/domain_capabilities.c                          | 1 +

>>  src/conf/domain_capabilities.h                          | 1 +

>>  src/qemu/qemu_capabilities.c                            | 4 ++++

>>  tests/domaincapsschemadata/domaincaps-full.xml          | 5 +++++

>>  tests/domaincapsschemadata/domaincaps-qemu_1.6.50-1.xml | 3 +++

>>  tests/domaincapsschemadata/domaincaps-qemu_2.6.0-1.xml  | 4 ++++

>>  tests/domaincapsschemadata/domaincaps-qemu_2.6.0-2.xml  | 3 +++

>>  tests/domaincapsschemadata/domaincaps-qemu_2.6.0-3.xml  | 3 +++

>>  tests/domaincapsschemadata/domaincaps-qemu_2.6.0-4.xml  | 3 +++

>>  tests/domaincapsschemadata/domaincaps-qemu_2.6.0-5.xml  | 3 +++

>>  tests/domaincapstest.c                                  | 1 +

>>  12 files changed, 39 insertions(+)

>>

>> diff --git a/docs/formatdomaincaps.html.in b/docs/formatdomaincaps.html.in

>> index d5a8414..c424107 100644

>> --- a/docs/formatdomaincaps.html.in

>> +++ b/docs/formatdomaincaps.html.in

>> @@ -231,6 +231,10 @@

>>          &lt;value&gt;vnc&lt;/value&gt;

>>          &lt;value&gt;spice&lt;/value&gt;

>>        &lt;/enum&gt;

>> +      &lt;enum name='spiceGL'&gt;

>> +        &lt;value&gt;yes&lt;/value&gt;

>> +        &lt;value&gt;no&lt;/value&gt;

>> +      &lt;/enum&gt;

>>      &lt;/graphics&gt;

> 

> 

> .. and while it's true that just Spice supports OpenGL currently, I'd

> vote for a less specific naming. BTW: wasn't virgl implemented for SDL

> initially? I know we don't support it, but my point is, what if XYZ

> graphics type gains support for something equivalent to virgl? Would we

> end up having yet another 'xyzGL' enum? Well, on the other hand, we

> already have pciBackend enum to hostdev elem where we report VFIO/KVM

> caps for hostdev[@type='pci']/driver/@name.

> So I guess it's your call whether to change this or not. The only name I

> can suggest right now (if you're out of ideas) is just 'gl'.

> 


I think just reporting <enum name='gl'/> gives insufficient info to apps. What
if hypothetically VNC starts support 3D... then apps have no way of
distinguishing which libvirt+qemu combos support spice + 3D vs the new VNC +
3D, and they are stuck in the current position of trying to guess what is
supported by checking libvirt version numbers.

So IMO the domcaps need to report this fine grained value some how. Either
this way or the XML suggested by Pavel, please give your thoughts there as well

Thanks,
Cole

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Cole Robinson May 9, 2016, 10:53 p.m. | #3
On 05/09/2016 09:48 AM, Daniel P. Berrange wrote:
> On Mon, May 09, 2016 at 09:30:30AM -0400, Cole Robinson wrote:

>> On 05/09/2016 07:30 AM, Pavel Hrdina wrote:

>>> On Sun, May 08, 2016 at 01:49:06PM -0400, Cole Robinson wrote:

>>>> Reports a tristate enum value for acceptable graphics type=spice

>>>> <gl enable=XXX/>.

>>>>

>>>> Wire it up for qemu too. 'no' is always a valid value, so we

>>>> unconditionally report it.

>>>> ---

>>>

>>> [...]

>>>

>>>> diff --git a/tests/domaincapsschemadata/domaincaps-full.xml b/tests/domaincapsschemadata/domaincaps-full.xml

>>>> index 2f529ff..4eb5637 100644

>>>> --- a/tests/domaincapsschemadata/domaincaps-full.xml

>>>> +++ b/tests/domaincapsschemadata/domaincaps-full.xml

>>>> @@ -47,6 +47,11 @@

>>>>          <value>desktop</value>

>>>>          <value>spice</value>

>>>>        </enum>

>>>> +      <enum name='spiceGL'>

>>>> +        <value>default</value>

>>>> +        <value>yes</value>

>>>> +        <value>no</value>

>>>> +      </enum>

>>>

>>> Ewww, this doesn't look good and I agree with Michal that what if we add

>>> support for another graphics device and what if one graphics device will have

>>> more than one capability?

>>>

>>> I would suggest something like this:

>>>

>>>     <graphics supported='yes'>

>>>       <enum name='type'>

>>>         <value>spice</value>

>>>         <value>vnc</value>

>>>         <value>sdl</value>

>>>       </enum>

>>>       <type name='spice'>

>>>         <gl supported='yes'/>

>>>       </type>

>>>     </graphics>

>>>

>>> or even do something like this:

>>>

>>>     <graphics supported='yes'>

>>>       <type name='spice'>

>>>         <gl supported='yes'/>

>>>       </type>

>>>       <type name='vnc'/>

>>>       <type name='sdl'/>

>>>     </graphics>

>>>

>>

>> Really wish someone would have chimed in with this to my (unresponded) RFC

>> email about these things...

>>

>> http://www.redhat.com/archives/libvir-list/2016-April/msg01839.html

>>

>> That pattern is fine in this case, but what about the case of ports= element

>> that is only supported with a controller type=usb model=nec-xhci ? Do we have

>> new XML like:

>>

>> <controller supported='yes'>

>>   <type name='usb'>

>>     <model name='nec-xhci'/>

>>       <param name='ports' supported='yes'/>

>>     </model>

>>   </type>

>> </controller>

>>

>> It seems like these types of relationships could grow deeply nested, so I

>> opted for following the limited existing convention of adding unique enum

>> names to represent the relationship.

> 

> Yeah, I find flat modelling quite desirable, because the relationships

> between attributes will certainly grow quite complicate, and they do

> not neccessarily form a nice simple tree relationship.

> 

> ie, whether  foo=bar is permitted may depend on whether wizz=eek *AND*

> when lala=ooh, and you can't have the enum for 'foo' nested underneath

> the enum for 'wizz' & 'lala' at the same time.  Also with nesting, if

> you want the same values reported for multiple options, we end up

> repeating the same information multiple times which is not good.

> 

> At the same time the flat modelling with "spiceGL" also doesn't scale

> as you have to invent new names for each one, and again it doesn't

> work if the 'gl' enum depended on type="spice" *and* something else

> at the same time.

> 

> So I think we need a more flexible way to express dependancies here.

> 

> We could let the <enum> be repeated multiple times and express conditional

> rules against each instance of the enum

> 

> So for example

> 

>     <graphics supported='yes'>

>       <enum name='type'>

>         <value>spice</value>

>         <value>vnc</value>

>         <value>sdl</value>

>       </enum>

>       <enum name='gl'>

>         <condition>

> 	  <enum name="type" value="spice">

> 	</condition>

>         <value>default</value>

>         <value>yes</value>

>         <value>no</value>

>       </enum>

>       <enum name='gl'>

>         <value>default</value>

>         <value>no</value>

>       </enum>

>     </graphics>

> 

> 

> This would express that the first <enum type="gl"> entry only applies

> when the @type == spice. If that doesn't match them fallback to the

> second <enum type="gl">.  The nice thing about this is that we can

> make the conditions arbitrarly complex

> 

> For example:

> 

>     <graphics supported='yes'>

>       <enum name='type'>

>         <value>spice</value>

>         <value>vnc</value>

>         <value>sdl</value>

>       </enum>

>       <enum name='gl'>

>         <condition op="and">

> 	  <enum name="type" value="spice">

> 	  <condition op="or">

>             <enum name="type" value="vnc">

> 	    <enum name="wibble" value="eek">

> 	  </condition>

> 	</condition>

>         <value>default</value>

>         <value>yes</value>

>         <value>no</value>

>       </enum>

>       <enum name='gl'>

>         <value>default</value>

>         <value>no</value>

>       </enum>

>     </graphics>

> 

> 

> This shows how the "gl" option can be used with VNC, but only if you

> also have the @wibble attribute set to "eek".

> 

> Of course complex conditions like this become quite tedious & verbose

> so obviously we should strive to keep them as simple as possible and

> not use nested conditions unless absolutely needed.

> 


Writing a parser for this type of XML, that maintains behavior in a future
proof way, is going to be a lot of work. Hypothetical example:

  <video supported='yes'>
    <enum name='modelType'/>
      <value>cirrus</value>
      <value>qxl</value>
    </enum>
    <enum name='accel2d'/>
      <value>no</value>
    </enum>
  </video>

6 months later, qemu gets some accel2d support for model=qxl

  <video supported='yes'>
    <enum name='modelType'/>
      <value>cirrus</value>
      <value>qxl</value>
    </enum>
    <enum name='accel2d'/>
      <value>no</value>
    </enum>
    <enum name='accel2d'/>
      <condition>
	<enum name="modelType" value="qxl">
      </condition>
      <value>yes</value>
      <value>no</value>
    </enum>
  </video>

Another 6 months later, qemu gets accel2d support for cirrus only, but it
requires <address type='pci'/> and doesn't work for <address type='isa'/>

  <video supported='yes'>
    <enum name='modelType'/>
      <value>cirrus</value>
      <value>qxl</value>
    </enum>
    <enum name='addressType'/>
      <value>pci</value>
      <value>isa</value>
    </enum>
    <enum name='accel2d'/>
      <value>no</value>
    </enum>
    <enum name='accel2d'/>
      <condition>
	<enum name="modelType" value="qxl">
      </condition>
      <value>yes</value>
      <value>no</value>
    </enum>
    <enum name='accel2d'/>
      <condition>
	<enum name="modelType" value="cirrus">
        <enum name="addressType" value="pci">
      </condition>
      <value>yes</value>
      <value>no</value>
    </enum>
  </video>


The app wants to answer the question 'can I specify accel2d by default for
model=cirrus?' (note, cirrus, and not qxl)

For the first example, the code parses the accel2d enum, doesn't see 'yes', so
it doesn't enable accel2d. The code will need to contain some knowledge that
enum name='accel2d' == ./video/acceleration/@accel2d but that's presently
unavoidable.

For the second example, code will need to be added to parse the basic
condition, see that modelType=cirrus (./video/model/@type) doesn't match the
condition, and so again accel2d=no

For the third example, code hits the modelType=cirrus condition, but then also
needs to check that addressType (./video/address/@type) == pci, and if so,
sets accel2d=yes

So, that's all achievable. But what kind of parser does the app write at each
step that may fall over with the next XML iteration?

What if the parser in step 1 doesn't expect multiple <enum name='accel2d'/> ?
If it naively parses only the first instance, then nothing will regress in
step #2 or step #3. step #3's conclusion will be wrong, but that's okay. Note
this depends on libvirt being smart about appending conditional enums, and not
putting them first.

However if it parses the last instance, such as by iterating over every XML
node and taking the last one that matches name='accel2d' (virtinst used to
have a pattern like this when parsing capabilities XML), on step #2 the code
will think the <enum> with the 'qxl' condition is the only instance. The
parser doesn't know about <condition> yet, will assume accel2d is supported
for everyone, and set accel2d=on for cirrus which will probably fail.

Okay, starting from a working step #2. The parser knows about multiple enums,
and basic <condition> statements. Upgrade to step #3. If the parser was dumb,
maybe it didn't know about multiple <condition> enums, which may cause an
incorrect match, setting accel2d=yes, and the config fails.

Assume the parser is smart enough to know about multiple <condition> enums. It
sees addressType, but it doesn't know what XML value it maps to. Does the app
just ignore it and hope the config works, possibly generating an error? Does
the app completely abandon the check even though it may work correctly? The
latter is certainly the safest, but coding errors/naive impls could make
mistakes or possible even throw other errors.

Now consider that pattern expanding out with conditional or/and/not operators,
maybe even numerical comparisons like <, >, etc. The only way for the parser
from step #1 to not make a fatal error in step #3 is to implement <condition>
parsing from the start and code very defensively. That's a lot of upfront
overhead. And I think it will be tempting for apps to try and get by _without_
implementing the whole comparison engine and potentially set themselves up for
future pain.

Also having a very interconnected schema like this means that if we ever need
to extend the XML format we need to think _very_ hard about how parsers are
likely handing the existing XML, and how our additions might screw things up,
because we are requiring users to perform some kind of comparison on the
result. This is much different than extending the domain XML which is largely
just a config file. <capabilities> XML is the closet analog but even that
requires very little processing, the only tricky bit is handling that <domain
type='kvm'> has its own <machine> list

And even after all that, the XML is not going to be completely introspectable
unless we find a way to describe addressType=./video/address/@type in the XML.
So any general parser is still going to need to be extended regularly to
handle new enum names. So we end up with XML that
appears-introspectable-but-not-quite


So let's redo the example with the unique string names and flat namespace:

Step #1 is identical
Step #2 addition is

    <enum name='qxlAccel2D'/>
      <value>yes</value>
      <value>no</value>
    </enum>

Step #3 addition is

    <enum name='cirrusAccel2D'/>
      <value>yes</value>
      <value>no</value>
    </enum>

And for step #3 we document that it's only valid for address type=pci, If
address type=isa grows support later, we add a new top level string if we
think it's worth it. The type=pci vs type=isa is a misleading example here, if
it was some more obscure option that cirrus accel2d depended on, maybe we
would want to put that in the string name.

The misinterpretation problems for the app are non-existent. Yes it will need
to be extended at step #3 to support cirrus accel2d=yes but that's completely
fine IMO.

If the next day, xen supports domcaps and wants to expose cirrusAccel2D but
with sufficiently different semantics, then we would have to add a new string.
Yes that sucks, but it's the safest way by far for apps.

Benefits:
- The app XML parser is much simpler
- The app XML parser is much quicker to bring up. Important because I bet most
apps will only want to check a small set of support checks
- I suspect extending the libvirt code will be much simpler
- We can always come up with a way to add a comparison engine later if this
approach gets too out of hand

Downsides:
- Much less generalizable (but as I said above I don't think this there _is_ a
generalizable domcaps XML schema, nor should it be the goal)
- Apps/readers need to look to the docs to understand the enum semantics
- The app's parser requires more maintenance in relation to how many features
it wants to parse

I think the guide here should largely be exposing the types of things that we
already track with qemu capabilities, and at that granularity. Give that
information to the user (which they presently can't find out reliably on their
own), and leave the rest of the bits like interdependence of XML options up to
them to figure out. So, 'qemu supports spiceGL', and not 'a working spiceGL
config is spiceGL with listen=none or listen=unix and video virtio with accel3D'

All that said, I'm probably missing some examples where this flat modeling
especially sucks too :) So please throw them my way

Thanks,
Cole

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Cole Robinson May 10, 2016, 3:26 p.m. | #4
On 05/10/2016 05:10 AM, Daniel P. Berrange wrote:
> On Mon, May 09, 2016 at 06:53:01PM -0400, Cole Robinson wrote:

>> On 05/09/2016 09:48 AM, Daniel P. Berrange wrote:

> 

> IMHO it is a total failure if we require the application to extend its

> parser every time we add a new enum to the domain capabilities. We have

> the ability to design something that is data driven - we should not build

> something it is forced to be code driven with code changes for every

> libvirt addition.


This is ignoring the point I made previously that the schema is not already
fully introspectable. Most of the current enums cannot be programmatically
consumed anyways, because there's no way to map an enum name to its domain XML
property. So if that's our goal to be data driven, we should address that
issue first.

I can't really think of a good way to represent that without nesting deeply or
using specially formatted strings. Do you have a suggestion for that?

Thanks,
Cole

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Cole Robinson May 10, 2016, 11:15 p.m. | #5
On 05/10/2016 11:50 AM, Daniel P. Berrange wrote:
> On Tue, May 10, 2016 at 11:26:29AM -0400, Cole Robinson wrote:

>> On 05/10/2016 05:10 AM, Daniel P. Berrange wrote:

>>> On Mon, May 09, 2016 at 06:53:01PM -0400, Cole Robinson wrote:

>>>> On 05/09/2016 09:48 AM, Daniel P. Berrange wrote:

>>>

>>> IMHO it is a total failure if we require the application to extend its

>>> parser every time we add a new enum to the domain capabilities. We have

>>> the ability to design something that is data driven - we should not build

>>> something it is forced to be code driven with code changes for every

>>> libvirt addition.

>>

>> This is ignoring the point I made previously that the schema is not already

>> fully introspectable. Most of the current enums cannot be programmatically

>> consumed anyways, because there's no way to map an enum name to its domain XML

>> property. So if that's our goal to be data driven, we should address that

>> issue first.

> 

> Knowing the mapping of the capabilities enums to the domain schema is

> a pre-requisite for consuming the capabilities data, no matter which

> approach discussed in this thread is chosen. Assuming the app knows

> that mapping, then the enum conditionals can be programmatically

> handled with the approach I describe.

> 

> Providing a way for the app to automatically determine the mapping

> from capabilities enums to the domain schema would be a nice

> addition, but it isn't a pre-requisite blocker for what's discussed

> here. It is something that can be deal with in parallel.

> 

>> I can't really think of a good way to represent that without nesting

>> deeply or using specially formatted strings. Do you have a suggestion

>> for that?

> 

> Probably the best thing is to use a very simplified xpath style notation.

> If we add a 'mapping' attribute to the <enum> that expresses the attribute

> or element it is associated with, relative to the parent container element.

> 

> eg, consider the tests/domaincapsschemadata/domaincaps-qemu_1.6.50-1.xml

> data file with the mapping info:

> 

> <domainCapabilities>

>   <path>/usr/bin/qemu-system-x86_64</path>

>   <domain>kvm</domain>

>   <machine>pc-1.2</machine>

>   <arch>x86_64</arch>

>   <os supported='yes'>

>     <loader supported='yes'>

>       <value>/usr/share/AAVMF/AAVMF_CODE.fd</value>

>       <value>/usr/share/OVMF/OVMF_CODE.fd</value>

>       <enum name='type' mapping="@type">

>         <value>rom</value>

>         <value>pflash</value>

>       </enum>

>       <enum name='readonly' mapping="@readonly">

>         <value>yes</value>

>         <value>no</value>

>       </enum>

>     </loader>

>   </os>

>   <devices>

>     <disk supported='yes'>

>       <enum name='diskDevice' mapping="@device">

>         <value>disk</value>

>         <value>cdrom</value>

>         <value>floppy</value>

>         <value>lun</value>

>       </enum>

>       <enum name='bus' mapping="target/@bus">

>         <value>ide</value>

>         <value>fdc</value>

>         <value>scsi</value>

>         <value>virtio</value>

>         <value>usb</value>

>       </enum>

>     </disk>

>     <hostdev supported='yes'>

>       <enum name='mode' mapping="@mode">

>         <value>subsystem</value>

>       </enum>

>       <enum name='startupPolicy' mapping="source/@startupPolicy">

>         <value>default</value>

>         <value>mandatory</value>

>         <value>requisite</value>

>         <value>optional</value>

>       </enum>

>       <enum name='subsysType' mapping="@type">

>         <value>usb</value>

>         <value>pci</value>

>         <value>scsi</value>

>       </enum>

>       <enum name='capsType' mapping="@type"/>

>       <enum name='pciBackend' mapping="driver/@name">

>         <value>default</value>

>         <value>kvm</value>

>         <value>vfio</value>

>       </enum>

>     </hostdev>

>   </devices>

>   <features>

>     <gic supported='no'/>

>   </features>

> </domainCapabilities>

> 

> 

> NB, with my proposed conditionals, the hostdev enums above would actually

> want to be different. eg it would want to look like this:

> 

>       <enum name='mode' mapping="@mode">

>         <value>subsystem</value>

>       </enum>

>       <enum name='startupPolicy' mapping="source/@startupPolicy">

>         <value>default</value>

>         <value>mandatory</value>

>         <value>requisite</value>

>         <value>optional</value>

>       </enum>

>       <enum name='type' mapping="@type">

>         <condition>

> 	  <enum name='mode' value='subsystem'/>

> 	</condition>

>         <value>usb</value>

>         <value>pci</value>

>         <value>scsi</value>

>       </enum>

>       <enum name='driver' mapping="driver/@name">

>         <condition>

> 	  <enum name='mode' value='subsystem'/>

> 	  <enum name='type' value='pci'/>

> 	</condition>

>         <value>default</value>

>         <value>kvm</value>

>         <value>vfio</value>

>       </enum>

> 


Yeah that mapping= bit makes sense to me.

I don't have time to see pick this up now though, so I've stuffed it in a bug:

https://bugzilla.redhat.com/show_bug.cgi?id=1334958

Thanks,
Cole

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Cole Robinson May 11, 2016, 3:25 p.m. | #6
On 05/11/2016 04:49 AM, Daniel P. Berrange wrote:
> On Tue, May 10, 2016 at 07:15:01PM -0400, Cole Robinson wrote:

>> On 05/10/2016 11:50 AM, Daniel P. Berrange wrote:

>>> On Tue, May 10, 2016 at 11:26:29AM -0400, Cole Robinson wrote:

>>>> On 05/10/2016 05:10 AM, Daniel P. Berrange wrote:

>>>>> On Mon, May 09, 2016 at 06:53:01PM -0400, Cole Robinson wrote:

>>>>>> On 05/09/2016 09:48 AM, Daniel P. Berrange wrote:

>>>>>

>>>>> IMHO it is a total failure if we require the application to extend its

>>>>> parser every time we add a new enum to the domain capabilities. We have

>>>>> the ability to design something that is data driven - we should not build

>>>>> something it is forced to be code driven with code changes for every

>>>>> libvirt addition.

>>>>

>>>> This is ignoring the point I made previously that the schema is not already

>>>> fully introspectable. Most of the current enums cannot be programmatically

>>>> consumed anyways, because there's no way to map an enum name to its domain XML

>>>> property. So if that's our goal to be data driven, we should address that

>>>> issue first.

>>>

>>> Knowing the mapping of the capabilities enums to the domain schema is

>>> a pre-requisite for consuming the capabilities data, no matter which

>>> approach discussed in this thread is chosen. Assuming the app knows

>>> that mapping, then the enum conditionals can be programmatically

>>> handled with the approach I describe.

>>>

>>> Providing a way for the app to automatically determine the mapping

>>> from capabilities enums to the domain schema would be a nice

>>> addition, but it isn't a pre-requisite blocker for what's discussed

>>> here. It is something that can be deal with in parallel.

>>>

>>>> I can't really think of a good way to represent that without nesting

>>>> deeply or using specially formatted strings. Do you have a suggestion

>>>> for that?

>>>

>>> Probably the best thing is to use a very simplified xpath style notation.

>>> If we add a 'mapping' attribute to the <enum> that expresses the attribute

>>> or element it is associated with, relative to the parent container element.

>>>

>>> eg, consider the tests/domaincapsschemadata/domaincaps-qemu_1.6.50-1.xml

>>> data file with the mapping info:

>>>

>>> <domainCapabilities>

>>>   <path>/usr/bin/qemu-system-x86_64</path>

>>>   <domain>kvm</domain>

>>>   <machine>pc-1.2</machine>

>>>   <arch>x86_64</arch>

>>>   <os supported='yes'>

>>>     <loader supported='yes'>

>>>       <value>/usr/share/AAVMF/AAVMF_CODE.fd</value>

>>>       <value>/usr/share/OVMF/OVMF_CODE.fd</value>

>>>       <enum name='type' mapping="@type">

>>>         <value>rom</value>

>>>         <value>pflash</value>

>>>       </enum>

>>>       <enum name='readonly' mapping="@readonly">

>>>         <value>yes</value>

>>>         <value>no</value>

>>>       </enum>

>>>     </loader>

>>>   </os>

>>>   <devices>

>>>     <disk supported='yes'>

>>>       <enum name='diskDevice' mapping="@device">

>>>         <value>disk</value>

>>>         <value>cdrom</value>

>>>         <value>floppy</value>

>>>         <value>lun</value>

>>>       </enum>

>>>       <enum name='bus' mapping="target/@bus">

>>>         <value>ide</value>

>>>         <value>fdc</value>

>>>         <value>scsi</value>

>>>         <value>virtio</value>

>>>         <value>usb</value>

>>>       </enum>

>>>     </disk>

>>>     <hostdev supported='yes'>

>>>       <enum name='mode' mapping="@mode">

>>>         <value>subsystem</value>

>>>       </enum>

>>>       <enum name='startupPolicy' mapping="source/@startupPolicy">

>>>         <value>default</value>

>>>         <value>mandatory</value>

>>>         <value>requisite</value>

>>>         <value>optional</value>

>>>       </enum>

>>>       <enum name='subsysType' mapping="@type">

>>>         <value>usb</value>

>>>         <value>pci</value>

>>>         <value>scsi</value>

>>>       </enum>

>>>       <enum name='capsType' mapping="@type"/>

>>>       <enum name='pciBackend' mapping="driver/@name">

>>>         <value>default</value>

>>>         <value>kvm</value>

>>>         <value>vfio</value>

>>>       </enum>

>>>     </hostdev>

>>>   </devices>

>>>   <features>

>>>     <gic supported='no'/>

>>>   </features>

>>> </domainCapabilities>

>>>

>>>

>>> NB, with my proposed conditionals, the hostdev enums above would actually

>>> want to be different. eg it would want to look like this:

>>>

>>>       <enum name='mode' mapping="@mode">

>>>         <value>subsystem</value>

>>>       </enum>

>>>       <enum name='startupPolicy' mapping="source/@startupPolicy">

>>>         <value>default</value>

>>>         <value>mandatory</value>

>>>         <value>requisite</value>

>>>         <value>optional</value>

>>>       </enum>

>>>       <enum name='type' mapping="@type">

>>>         <condition>

>>> 	  <enum name='mode' value='subsystem'/>

>>> 	</condition>

>>>         <value>usb</value>

>>>         <value>pci</value>

>>>         <value>scsi</value>

>>>       </enum>

>>>       <enum name='driver' mapping="driver/@name">

>>>         <condition>

>>> 	  <enum name='mode' value='subsystem'/>

>>> 	  <enum name='type' value='pci'/>

>>> 	</condition>

>>>         <value>default</value>

>>>         <value>kvm</value>

>>>         <value>vfio</value>

>>>       </enum>

>>>

>>

>> Yeah that mapping= bit makes sense to me.

>>

>> I don't have time to see pick this up now though, so I've stuffed it in a bug:

> 

> Thinking about this some more last night, I realize that once we have

> the 'mapping' attribute, then the choice of values in the 'name' attribute

> becomes totally irrelevant.

> 

> IOW, we could use your suggestion for giving each enum a unique name,

> eg 'spiceGL', 'vncGL', etc, etc. So apps which want to consume this

> data have a choice between just matching on explicit enum names and

> ignoring the <condition> rules, or they can match on the 'mapping'

> attribute and use the <condition> rules.. So we get the best of both

> ideas.


Hmm, but does that mean that once we assign an enum name, its semantics are
locked in stone? Can we add new conditions to an existing enum to clarify
semantics, or does extending the condition list always mandate a new enum?

- Cole

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Patch

diff --git a/docs/formatdomaincaps.html.in b/docs/formatdomaincaps.html.in
index d5a8414..c424107 100644
--- a/docs/formatdomaincaps.html.in
+++ b/docs/formatdomaincaps.html.in
@@ -231,6 +231,10 @@ 
         &lt;value&gt;vnc&lt;/value&gt;
         &lt;value&gt;spice&lt;/value&gt;
       &lt;/enum&gt;
+      &lt;enum name='spiceGL'&gt;
+        &lt;value&gt;yes&lt;/value&gt;
+        &lt;value&gt;no&lt;/value&gt;
+      &lt;/enum&gt;
     &lt;/graphics&gt;
     ...
   &lt;/devices&gt;
@@ -241,6 +245,10 @@ 
       <dt><code>type</code></dt>
       <dd>Options for the <code>type</code> attribute of the &lt;graphics/&gt;
       element.</dd>
+
+      <dt><code>spiceGL</code></dt>
+      <dd>Options for the <code>enable</code> attribute of the
+      &lt;graphics type='spice'&gt;&lt;gl/&gt; element.</dd>
     </dl>
 
 
diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c
index 1676f0e..344955c 100644
--- a/src/conf/domain_capabilities.c
+++ b/src/conf/domain_capabilities.c
@@ -253,6 +253,7 @@  virDomainCapsDeviceGraphicsFormat(virBufferPtr buf,
     FORMAT_PROLOGUE(graphics);
 
     ENUM_PROCESS(graphics, type, virDomainGraphicsTypeToString);
+    ENUM_PROCESS(graphics, spiceGL, virTristateBoolTypeToString);
 
     FORMAT_EPILOGUE(graphics);
 }
diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h
index d0ca009..916dba0 100644
--- a/src/conf/domain_capabilities.h
+++ b/src/conf/domain_capabilities.h
@@ -74,6 +74,7 @@  typedef virDomainCapsDeviceGraphics *virDomainCapsDeviceGraphicsPtr;
 struct _virDomainCapsDeviceGraphics {
     bool supported;
     virDomainCapsEnum type;   /* virDomainGraphicsType */
+    virDomainCapsEnum spiceGL;   /* type=spice <gl enable=X/> tristate */
 };
 
 typedef struct _virDomainCapsDeviceVideo virDomainCapsDeviceVideo;
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 1bddf43..f228f4f 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -4183,6 +4183,10 @@  virQEMUCapsFillDomainDeviceGraphicsCaps(virQEMUCapsPtr qemuCaps,
     if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SPICE))
         VIR_DOMAIN_CAPS_ENUM_SET(dev->type, VIR_DOMAIN_GRAPHICS_TYPE_SPICE);
 
+    VIR_DOMAIN_CAPS_ENUM_SET(dev->spiceGL, VIR_TRISTATE_BOOL_NO);
+    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SPICE_GL))
+        VIR_DOMAIN_CAPS_ENUM_SET(dev->spiceGL, VIR_TRISTATE_BOOL_YES);
+
     return 0;
 }
 
diff --git a/tests/domaincapsschemadata/domaincaps-full.xml b/tests/domaincapsschemadata/domaincaps-full.xml
index 2f529ff..4eb5637 100644
--- a/tests/domaincapsschemadata/domaincaps-full.xml
+++ b/tests/domaincapsschemadata/domaincaps-full.xml
@@ -47,6 +47,11 @@ 
         <value>desktop</value>
         <value>spice</value>
       </enum>
+      <enum name='spiceGL'>
+        <value>default</value>
+        <value>yes</value>
+        <value>no</value>
+      </enum>
     </graphics>
     <video supported='yes'>
       <enum name='modelType'>
diff --git a/tests/domaincapsschemadata/domaincaps-qemu_1.6.50-1.xml b/tests/domaincapsschemadata/domaincaps-qemu_1.6.50-1.xml
index 161d0ab..6213297 100644
--- a/tests/domaincapsschemadata/domaincaps-qemu_1.6.50-1.xml
+++ b/tests/domaincapsschemadata/domaincaps-qemu_1.6.50-1.xml
@@ -40,6 +40,9 @@ 
         <value>vnc</value>
         <value>spice</value>
       </enum>
+      <enum name='spiceGL'>
+        <value>no</value>
+      </enum>
     </graphics>
     <video supported='yes'>
       <enum name='modelType'>
diff --git a/tests/domaincapsschemadata/domaincaps-qemu_2.6.0-1.xml b/tests/domaincapsschemadata/domaincaps-qemu_2.6.0-1.xml
index f42d239..2a1477f 100644
--- a/tests/domaincapsschemadata/domaincaps-qemu_2.6.0-1.xml
+++ b/tests/domaincapsschemadata/domaincaps-qemu_2.6.0-1.xml
@@ -40,6 +40,10 @@ 
         <value>vnc</value>
         <value>spice</value>
       </enum>
+      <enum name='spiceGL'>
+        <value>yes</value>
+        <value>no</value>
+      </enum>
     </graphics>
     <video supported='yes'>
       <enum name='modelType'>
diff --git a/tests/domaincapsschemadata/domaincaps-qemu_2.6.0-2.xml b/tests/domaincapsschemadata/domaincaps-qemu_2.6.0-2.xml
index 4e87cd2..4349998 100644
--- a/tests/domaincapsschemadata/domaincaps-qemu_2.6.0-2.xml
+++ b/tests/domaincapsschemadata/domaincaps-qemu_2.6.0-2.xml
@@ -39,6 +39,9 @@ 
         <value>sdl</value>
         <value>vnc</value>
       </enum>
+      <enum name='spiceGL'>
+        <value>no</value>
+      </enum>
     </graphics>
     <video supported='yes'>
       <enum name='modelType'>
diff --git a/tests/domaincapsschemadata/domaincaps-qemu_2.6.0-3.xml b/tests/domaincapsschemadata/domaincaps-qemu_2.6.0-3.xml
index f5f0f1c..27173c4 100644
--- a/tests/domaincapsschemadata/domaincaps-qemu_2.6.0-3.xml
+++ b/tests/domaincapsschemadata/domaincaps-qemu_2.6.0-3.xml
@@ -39,6 +39,9 @@ 
         <value>sdl</value>
         <value>vnc</value>
       </enum>
+      <enum name='spiceGL'>
+        <value>no</value>
+      </enum>
     </graphics>
     <video supported='yes'>
       <enum name='modelType'>
diff --git a/tests/domaincapsschemadata/domaincaps-qemu_2.6.0-4.xml b/tests/domaincapsschemadata/domaincaps-qemu_2.6.0-4.xml
index 1ae8172..d7d81b5 100644
--- a/tests/domaincapsschemadata/domaincaps-qemu_2.6.0-4.xml
+++ b/tests/domaincapsschemadata/domaincaps-qemu_2.6.0-4.xml
@@ -39,6 +39,9 @@ 
         <value>sdl</value>
         <value>vnc</value>
       </enum>
+      <enum name='spiceGL'>
+        <value>no</value>
+      </enum>
     </graphics>
     <video supported='yes'>
       <enum name='modelType'>
diff --git a/tests/domaincapsschemadata/domaincaps-qemu_2.6.0-5.xml b/tests/domaincapsschemadata/domaincaps-qemu_2.6.0-5.xml
index 583fdf0..51c5615 100644
--- a/tests/domaincapsschemadata/domaincaps-qemu_2.6.0-5.xml
+++ b/tests/domaincapsschemadata/domaincaps-qemu_2.6.0-5.xml
@@ -37,6 +37,9 @@ 
         <value>sdl</value>
         <value>vnc</value>
       </enum>
+      <enum name='spiceGL'>
+        <value>no</value>
+      </enum>
     </graphics>
     <video supported='yes'>
       <enum name='modelType'>
diff --git a/tests/domaincapstest.c b/tests/domaincapstest.c
index 6ae3f35..1b62781 100644
--- a/tests/domaincapstest.c
+++ b/tests/domaincapstest.c
@@ -83,6 +83,7 @@  fillAllCaps(virDomainCapsPtr domCaps)
 
     graphics->supported = true;
     SET_ALL_BITS(graphics->type);
+    SET_ALL_BITS(graphics->spiceGL);
 
     video->supported = true;
     SET_ALL_BITS(video->modelType);