qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] RFC: Full introspection support for QMP


From: Eric Blake
Subject: Re: [Qemu-devel] RFC: Full introspection support for QMP
Date: Thu, 23 May 2013 06:58:50 -0600
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130514 Thunderbird/17.0.6

On 05/22/2013 07:40 AM, Amos Kong wrote:
> Hi all,
> 
> We already have query-command-line-options to query details of command-line
> options. As we discussed in the list, we also need full introspection of QMP
> (command). The qmp-events also need to be dumped, we can define events in
> qai-schema.json. We can also dump QMP errors in future if it's needed.
> 
> Command name: query-qmp-schema
> Return: returns the contents of qapi-schema.json in json format.
> 
> Solution to query json content from C code:
>   qapi-schema.json is processed by qapi python scripts to generate C
>   files, I found the content is good enough for Libvirt to know the
>   QMP command schema. We can change qapi scripts to generate a talbe/list
>   to record the raw string, then we can return the raw string in
>   qmp_query_qmp_schema().
> 
> By default, return the complete schema in one go.
> 
> And support to query of unknown type in new command.
>   -> { "execute": "query-qmp-schema" "arguments": { "command": "query-status" 
> }}
>   <- { "return" : "data": { "command': "query-status", "returns": 
> "StatusInfo" }}

If you are planning on returning everything in one shot, then this has
to be an array-of-dict return, rather than a single dict return.  If
filtering is used, the result should be an array-of-one, and I
definitely want to have a non-filtered mode that returns everything at once.

>   -> { "execute": "query-qmp-schema" "arguments": { "type": "StatusInfo" }}
>   <- { "return" : "data": { "type": "StatusInfo", "data": {"running": "bool",
>                             "singlestep": "bool", "status": "RunState"} }
>   -> { "execute": "query-qmp-schema" "arguments": { "event": 
> "RX-FILTER-CHANGE" }}

You need a schema for this command :)  It looks like you are proposing
something like:

{ 'command': 'query-qmp-schema', 'arguments': {
    '*command':'str', '*type':'str', '*event':'str' },
  'returns': [ 'SchemaData' ] }

and 'SchemaData' needs to be spelled out as what an actual entry in
qapi-schema.json must actually look like (goes back to Stefan's
complaint on the 'drive-add' thread that we should avoid sending
schema-less data over QAPI).  Besides, having a schema in place for what
all QAPI must look like may force us to be more robust in our additions
to QAPI.

Hmm, my schema doesn't adequately express that you are probably only
allowing a single 'command', 'type', or 'event' filtering to be used at
once.  We've had some ideas on other threads about providing smarter
magic on handling a discriminated union embedded inside a top-level
dictionary, rather than nesting type/data members of a nested
dictionary; figuring out how to express this may improve ease of use of
other aspects of QAPI.  In fact, it would be simpler to just say that
filtering uses a 'name' argument, and hold ourselves to a design that
command names, types, and events never have overlapping namespace, as in:

{ 'command': 'query-qmp-schema',
  'arguments': { '*name':'str' },
  'returns': [ 'SchemaData' ] }

Another issue (or rather, more thoughts on my opaque 'SchemaData' type).
 QAPI expresses optional elements with markup, as in:

{ 'command': 'blockdev-snapshot-sync',
  'data': { 'device': 'str', 'snapshot-file': 'str', '*format': 'str',
            '*mode': 'NewImageMode'} }

But our argument has always been that if you have to post-process a QAPI
argument, you were cramming too much information into a single element.
 Optional arguments are a case of post-processing - libvirt would have
to check if an option name begins with '*' to learn whether an option is
optional.  If you return qapi-schema.json contents as-is, you are
forcing management to post-process.  Contrast that with
query-command-line-options, where we INTENTIONALLY called out a rather
nested layout, but where that layout allows us to give additional
details.  In other words, rather than replaying qemu-schema.json as-is,
I think your C code should munge the text into a format more useful over
QAPI.  That is, I'd rather see:

-> { "execute": "query-qmp-schema", "arguments":
     { "name": "blockdev-snapshot-sync" }}
<- { "return" : "data": [
     { "metatype": "command",
       "name": "blockdev-snapshot-sync",
       "data": [
        { "option": "device", "type": "str" },
        { "option": "snapshot-file", "type", "str" },
        { "option": "format", "type", "str", "optional": true },
        { "option": "mode", "type", "NewImageMode", "optional": true }
     ] } }

and possibly with further extensions that express the default value of
an optional argument.  Note that this post-processing (turning a
free-form dictionary from the .json file into an array of dictionaries
that all match a given schema) makes the data a little easier to handle.
 In fact, with that layer of structuring, I can now define what the
schema looks like:

{ 'type': 'SchemaDataMember', 'data': {
    'option': 'str', 'type': 'str', '*optional': 'bool' } }
{ 'enum': 'SchemaMetatype', 'data': [ 'command', 'type', 'event' ] }
{ 'type': 'SchemaData', 'data': {
    'name': 'str',
    'metatype': 'SchemaMetatype',
    '*returns': 'str',
    '*data': [ 'SchemaDataMember' ] } }

Well, maybe the '*returns' element still needs some thought on how we
represent an array return vs. a dictionary return.

But I'd definitely favor some structure into the new QMP command, where
you build up that structure by actually parsing qapi-schema.json instead
of using it as-is.

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org

Attachment: signature.asc
Description: OpenPGP digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]