All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] RFC: Full introspection support for QMP
@ 2013-05-22 13:40 Amos Kong
  2013-05-22 14:44 ` Kevin Wolf
                   ` (3 more replies)
  0 siblings, 4 replies; 19+ messages in thread
From: Amos Kong @ 2013-05-22 13:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, Ronen Hod, Markus Armbruster, lcapitulino

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" }}
  -> { "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" }}
  

Welcome your comments, thanks!


Target: 1.6
Related RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=557939

-- 
			Amos.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] RFC: Full introspection support for QMP
  2013-05-22 13:40 [Qemu-devel] RFC: Full introspection support for QMP Amos Kong
@ 2013-05-22 14:44 ` Kevin Wolf
  2013-05-22 16:14   ` Anthony Liguori
  2013-05-22 17:56 ` Luiz Capitulino
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 19+ messages in thread
From: Kevin Wolf @ 2013-05-22 14:44 UTC (permalink / raw)
  To: Amos Kong; +Cc: aliguori, Markus Armbruster, qemu-devel, lcapitulino, Ronen Hod

Am 22.05.2013 um 15:40 hat Amos Kong geschrieben:
> 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().

Yes, the schema as defined in qapi-schema.json should be good to be sent
over the wire.

Maybe we should already now consider that we'll want to have a dynamic
schema eventually: Depending on which modules are compiled in (or even
which modules are loaded when we go forward with shared libraries), some
types, commands or enum values may be available or not.

For example, libvirt wants to query which block drivers it can use. It
doesn't really matter for which drivers we had the source initially, but
only which drivers are compiled in (possibly loaded) and can actually be
used.

> 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" }}
>   -> { "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" }}

Maybe a (shortened) example for the complete schema version? I assume it
will be just an array of the structs you showed here?

Kevin

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] RFC: Full introspection support for QMP
  2013-05-22 14:44 ` Kevin Wolf
@ 2013-05-22 16:14   ` Anthony Liguori
  2013-05-23  8:18     ` Kevin Wolf
  0 siblings, 1 reply; 19+ messages in thread
From: Anthony Liguori @ 2013-05-22 16:14 UTC (permalink / raw)
  To: Kevin Wolf, Amos Kong
  Cc: lcapitulino, Ronen Hod, qemu-devel, Markus Armbruster

Kevin Wolf <kwolf@redhat.com> writes:

> Am 22.05.2013 um 15:40 hat Amos Kong geschrieben:
>> 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().
>
> Yes, the schema as defined in qapi-schema.json should be good to be sent
> over the wire.
>
> Maybe we should already now consider that we'll want to have a dynamic
> schema eventually: Depending on which modules are compiled in (or even
> which modules are loaded when we go forward with shared libraries), some
> types, commands or enum values may be available or not.
>
> For example, libvirt wants to query which block drivers it can use. It
> doesn't really matter for which drivers we had the source initially, but
> only which drivers are compiled in (possibly loaded) and can actually be
> used.

The schema is the wrong place to discover this.

Loading a module wouldn't add an enumeration value.  The enumeration
values are fixed.

We should introduce commands to query this kind of information.

Schema introspection is primarily useful for dynamic languages to
autogenerate bindings.  It's not terribly useful for query
capabilities/features.

Regards,

Anthony Liguori

>> 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" }}
>>   -> { "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" }}
>
> Maybe a (shortened) example for the complete schema version? I assume it
> will be just an array of the structs you showed here?
>
> Kevin

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] RFC: Full introspection support for QMP
  2013-05-22 13:40 [Qemu-devel] RFC: Full introspection support for QMP Amos Kong
  2013-05-22 14:44 ` Kevin Wolf
@ 2013-05-22 17:56 ` Luiz Capitulino
  2013-05-23 12:58 ` Eric Blake
  2013-06-07 10:12 ` [Qemu-devel] RFC: Full introspection support for QMP (with draft patch) Amos Kong
  3 siblings, 0 replies; 19+ messages in thread
From: Luiz Capitulino @ 2013-05-22 17:56 UTC (permalink / raw)
  To: Amos Kong; +Cc: aliguori, Ronen Hod, qemu-devel, Markus Armbruster

On Wed, 22 May 2013 21:40:07 +0800
Amos Kong <akong@redhat.com> 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" }}
>   -> { "execute": "query-qmp-schema" "arguments": { "type": "StatusInfo" }}
>   <- { "return" : "data": { "type": "StatusInfo", "data": {"running": "bool",
>                             "singlestep": "bool", "status": "RunState"} }

Looks good, but as Kevin said an example of the schema output would be good.
Feel free to post patches along :)

>   -> { "execute": "query-qmp-schema" "arguments": { "event": "RX-FILTER-CHANGE" }}

You'll need to add the events to the schema some way. I'm not sure I'd mix
the projects in the same series, maybe you could add event support to the
schema after query-qmp-schema gets merged.

>   
> 
> Welcome your comments, thanks!
> 
> 
> Target: 1.6
> Related RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=557939
> 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] RFC: Full introspection support for QMP
  2013-05-22 16:14   ` Anthony Liguori
@ 2013-05-23  8:18     ` Kevin Wolf
  2013-05-23 12:08       ` Anthony Liguori
  0 siblings, 1 reply; 19+ messages in thread
From: Kevin Wolf @ 2013-05-23  8:18 UTC (permalink / raw)
  To: Anthony Liguori
  Cc: Markus Armbruster, qemu-devel, lcapitulino, Ronen Hod, Amos Kong

Am 22.05.2013 um 18:14 hat Anthony Liguori geschrieben:
> Kevin Wolf <kwolf@redhat.com> writes:
> 
> > Am 22.05.2013 um 15:40 hat Amos Kong geschrieben:
> >> 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().
> >
> > Yes, the schema as defined in qapi-schema.json should be good to be sent
> > over the wire.
> >
> > Maybe we should already now consider that we'll want to have a dynamic
> > schema eventually: Depending on which modules are compiled in (or even
> > which modules are loaded when we go forward with shared libraries), some
> > types, commands or enum values may be available or not.
> >
> > For example, libvirt wants to query which block drivers it can use. It
> > doesn't really matter for which drivers we had the source initially, but
> > only which drivers are compiled in (possibly loaded) and can actually be
> > used.
> 
> The schema is the wrong place to discover this.
> 
> Loading a module wouldn't add an enumeration value.  The enumeration
> values are fixed.
> 
> We should introduce commands to query this kind of information.
> 
> Schema introspection is primarily useful for dynamic languages to
> autogenerate bindings.  It's not terribly useful for query
> capabilities/features.

Then you won't get real modularity. It means that all modules must
already be known during the build time, and if they aren't available
(because they weren't built or aren't loaded) you include them anyway,
some parts of them are a static part of the core. You don't get fully
rid of modules by not linking their object file in, but you always have
the QAPI part left over.

It also makes the schema totally useless. If you can't use it to tell
which commands this qemu can execute and which it can't, then we don't
need introspection at all. There's no user for it then.

We can have hundreds of individual query commands like you suggest
(query-qcow2-creation-option-values, yay!) or we do the modularity
thing and the schema introspection properly and make it dynamic. I
prefer the latter.

Kevin

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] RFC: Full introspection support for QMP
  2013-05-23  8:18     ` Kevin Wolf
@ 2013-05-23 12:08       ` Anthony Liguori
  2013-05-23 12:40         ` Luiz Capitulino
  2013-05-23 12:54         ` Kevin Wolf
  0 siblings, 2 replies; 19+ messages in thread
From: Anthony Liguori @ 2013-05-23 12:08 UTC (permalink / raw)
  To: Kevin Wolf
  Cc: lcapitulino, Amos Kong, Markus Armbruster, Ronen Hod, qemu-devel

Kevin Wolf <kwolf@redhat.com> writes:

> Am 22.05.2013 um 18:14 hat Anthony Liguori geschrieben:
>> Kevin Wolf <kwolf@redhat.com> writes:
>> > For example, libvirt wants to query which block drivers it can use. It
>> > doesn't really matter for which drivers we had the source initially, but
>> > only which drivers are compiled in (possibly loaded) and can actually be
>> > used.
>> 
>> The schema is the wrong place to discover this.
>> 
>> Loading a module wouldn't add an enumeration value.  The enumeration
>> values are fixed.
>> 
>> We should introduce commands to query this kind of information.
>> 
>> Schema introspection is primarily useful for dynamic languages to
>> autogenerate bindings.  It's not terribly useful for query
>> capabilities/features.
>
> Then you won't get real modularity. It means that all modules must
> already be known during the build time, and if they aren't available
> (because they weren't built or aren't loaded) you include them anyway,
> some parts of them are a static part of the core. You don't get fully
> rid of modules by not linking their object file in, but you always have
> the QAPI part left over.

There are two things here: the schema and the generated code.  The
generated code can and should live in the module.

But the schema always stays the same.

Think of the schema like kernel headers.  The kernel headers are always
fixed regardless of what kernel modules are loaded or how the kernel is
configured.

> It also makes the schema totally useless. If you can't use it to tell
> which commands this qemu can execute and which it can't,

query-commands serves that purpose.

> then we don't need introspection at all. There's no user for it then.

Introspection is not the right approach to feature discovery.  The
schema does answer the question of what features are enabled, it just
answers the question of what the signature of the methods are.

> We can have hundreds of individual query commands like you suggest
> (query-qcow2-creation-option-values, yay!) or we do the modularity
> thing and the schema introspection properly and make it dynamic. I
> prefer the latter.

Let's consider a real example.  It sounds like you have something in
mind, can you be more specific?

Regards,

Anthony Liguori

>
> Kevin

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] RFC: Full introspection support for QMP
  2013-05-23 12:08       ` Anthony Liguori
@ 2013-05-23 12:40         ` Luiz Capitulino
  2013-05-23 12:52           ` Anthony Liguori
  2013-05-23 12:54         ` Kevin Wolf
  1 sibling, 1 reply; 19+ messages in thread
From: Luiz Capitulino @ 2013-05-23 12:40 UTC (permalink / raw)
  To: Anthony Liguori
  Cc: Kevin Wolf, Ronen Hod, Amos Kong, Markus Armbruster, qemu-devel

On Thu, 23 May 2013 07:08:59 -0500
Anthony Liguori <aliguori@us.ibm.com> wrote:

> > then we don't need introspection at all. There's no user for it then.
> 
> Introspection is not the right approach to feature discovery.  The
> schema does answer the question of what features are enabled, it just
> answers the question of what the signature of the methods are.

(s/does answer/does not answer)

But there's an intersection here: a new enum value or new argument can
be a new feature too.

If we add new commands to query features, than I'm afraid that in the
long run feature discovery will be split in query-qmp-schema and the
specific feature discovery commands.

I'm not arguing in favor of one or another way, but we need to know
why and where we're going. The real motivation behind full introspection
is to allow commands to be extended.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] RFC: Full introspection support for QMP
  2013-05-23 12:40         ` Luiz Capitulino
@ 2013-05-23 12:52           ` Anthony Liguori
  0 siblings, 0 replies; 19+ messages in thread
From: Anthony Liguori @ 2013-05-23 12:52 UTC (permalink / raw)
  To: Luiz Capitulino
  Cc: Kevin Wolf, Ronen Hod, Amos Kong, Markus Armbruster, qemu-devel

Luiz Capitulino <lcapitulino@redhat.com> writes:

> On Thu, 23 May 2013 07:08:59 -0500
> Anthony Liguori <aliguori@us.ibm.com> wrote:
>
>> > then we don't need introspection at all. There's no user for it then.
>> 
>> Introspection is not the right approach to feature discovery.  The
>> schema does answer the question of what features are enabled, it just
>> answers the question of what the signature of the methods are.
>
> (s/does answer/does not answer)

Yes, -ENOCAFFIENE :-/

> But there's an intersection here: a new enum value or new argument can
> be a new feature too.
>
> If we add new commands to query features, than I'm afraid that in the
> long run feature discovery will be split in query-qmp-schema and the
> specific feature discovery commands.
>
> I'm not arguing in favor of one or another way, but we need to know
> why and where we're going. The real motivation behind full introspection
> is to allow commands to be extended.

Right, so let's look at some examples and see how the introspection
would work for feature detection vs. some other form of feature
detection.

Regards,

Anthony Liguori

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] RFC: Full introspection support for QMP
  2013-05-23 12:08       ` Anthony Liguori
  2013-05-23 12:40         ` Luiz Capitulino
@ 2013-05-23 12:54         ` Kevin Wolf
  2013-05-23 13:52           ` Anthony Liguori
  1 sibling, 1 reply; 19+ messages in thread
From: Kevin Wolf @ 2013-05-23 12:54 UTC (permalink / raw)
  To: Anthony Liguori
  Cc: lcapitulino, Amos Kong, Markus Armbruster, Ronen Hod, qemu-devel

Am 23.05.2013 um 14:08 hat Anthony Liguori geschrieben:
> Kevin Wolf <kwolf@redhat.com> writes:
> 
> > Am 22.05.2013 um 18:14 hat Anthony Liguori geschrieben:
> >> Kevin Wolf <kwolf@redhat.com> writes:
> >> > For example, libvirt wants to query which block drivers it can use. It
> >> > doesn't really matter for which drivers we had the source initially, but
> >> > only which drivers are compiled in (possibly loaded) and can actually be
> >> > used.
> >> 
> >> The schema is the wrong place to discover this.
> >> 
> >> Loading a module wouldn't add an enumeration value.  The enumeration
> >> values are fixed.
> >> 
> >> We should introduce commands to query this kind of information.
> >> 
> >> Schema introspection is primarily useful for dynamic languages to
> >> autogenerate bindings.  It's not terribly useful for query
> >> capabilities/features.
> >
> > Then you won't get real modularity. It means that all modules must
> > already be known during the build time, and if they aren't available
> > (because they weren't built or aren't loaded) you include them anyway,
> > some parts of them are a static part of the core. You don't get fully
> > rid of modules by not linking their object file in, but you always have
> > the QAPI part left over.
> 
> There are two things here: the schema and the generated code.  The
> generated code can and should live in the module.
> 
> But the schema always stays the same.
> 
> Think of the schema like kernel headers.  The kernel headers are always
> fixed regardless of what kernel modules are loaded or how the kernel is
> configured.
> 
> > then we don't need introspection at all. There's no user for it then.
> 
> Introspection is not the right approach to feature discovery.  The
> schema does answer the question of what features are enabled, it just
> answers the question of what the signature of the methods are.

You can see it like this. Then, as I said, it's totally useless, because
nobody has ever asked this question. The context in which libvirt wants
to use it is feature discovery. If we don't support that, then there's
no reason to provide introspection at all.

libvirt already knows how to use features. It must know it, just parsing
the schema doesn't automagically give you libvirt code, so someone must
have coded the libvirt side of things. The interesting part is whether a
given interface is available on this specific qemu binary.

> > It also makes the schema totally useless. If you can't use it to tell
> > which commands this qemu can execute and which it can't,
> 
> query-commands serves that purpose.

It solves a subset of this problem. Optional fields can be added as
arguments or to returned structs, enums can be extended, and so far
we're having a hard time making use of it because the client can't
discover it.

> > We can have hundreds of individual query commands like you suggest
> > (query-qcow2-creation-option-values, yay!) or we do the modularity
> > thing and the schema introspection properly and make it dynamic. I
> > prefer the latter.
> 
> Let's consider a real example.  It sounds like you have something in
> mind, can you be more specific?

Not a very specific one, it's just that the more I discuss about things
like blockdev-add, the more I get the impression that there is an awful
lot of information to query. Each image format can provide different
options, for creating images and for opening them, and some of them may
be enums that could be extended and whose values must be queried etc.

Schema introspection allows you to have one single way to check for all
optional fields, enum values, union branches. The other way is to have a
separate command for each of them.

Basically instead of query-enum(Qcow2PreallocationType) you get
query-qcow2-prellocation-types(). You can imagine how the set of
commands grows once you start doing things this way.

When I discussed with Eric (who is one of the few actual consumers of
the API), he preferred introspection of a dynamic schema as well,
compared to many separate query-* commands.

Kevin

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] RFC: Full introspection support for QMP
  2013-05-22 13:40 [Qemu-devel] RFC: Full introspection support for QMP Amos Kong
  2013-05-22 14:44 ` Kevin Wolf
  2013-05-22 17:56 ` Luiz Capitulino
@ 2013-05-23 12:58 ` Eric Blake
  2013-06-07 10:12 ` [Qemu-devel] RFC: Full introspection support for QMP (with draft patch) Amos Kong
  3 siblings, 0 replies; 19+ messages in thread
From: Eric Blake @ 2013-05-23 12:58 UTC (permalink / raw)
  To: Amos Kong; +Cc: aliguori, lcapitulino, qemu-devel, Ronen Hod, Markus Armbruster

[-- Attachment #1: Type: text/plain, Size: 5668 bytes --]

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 #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 621 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] RFC: Full introspection support for QMP
  2013-05-23 12:54         ` Kevin Wolf
@ 2013-05-23 13:52           ` Anthony Liguori
  2013-05-23 14:17             ` Eric Blake
  2013-05-23 14:29             ` Kevin Wolf
  0 siblings, 2 replies; 19+ messages in thread
From: Anthony Liguori @ 2013-05-23 13:52 UTC (permalink / raw)
  To: Kevin Wolf
  Cc: qemu-devel, Amos Kong, Markus Armbruster, Ronen Hod, lcapitulino

Kevin Wolf <kwolf@redhat.com> writes:

> Am 23.05.2013 um 14:08 hat Anthony Liguori geschrieben:
>> Kevin Wolf <kwolf@redhat.com> writes:
>> 
>> 
>> There are two things here: the schema and the generated code.  The
>> generated code can and should live in the module.
>> 
>> But the schema always stays the same.
>> 
>> Think of the schema like kernel headers.  The kernel headers are always
>> fixed regardless of what kernel modules are loaded or how the kernel is
>> configured.
>> 
>> > then we don't need introspection at all. There's no user for it then.
>> 
>> Introspection is not the right approach to feature discovery.  The
>> schema does answer the question of what features are enabled, it just
>> answers the question of what the signature of the methods are.
>
> You can see it like this. Then, as I said, it's totally useless,

It's not totally useless.  It's impossible to write a reasonable python
client for QMP because arguments are not ordered (they are always
named).  So you can't have:

qmp.block_commit('ide0-hd0', ...)

You have to have:

qmp.block_commit(device='ide0-hd0', ...)

Which is a little less nice.  The schema introspection solves this but I
agree, it's not a critical problem to solve.

> because nobody has ever asked this question. The context in which
> libvirt wants to use it is feature discovery. If we don't support
> that, then there's no reason to provide introspection at all.
>
> libvirt already knows how to use features. It must know it, just parsing
> the schema doesn't automagically give you libvirt code, so someone must
> have coded the libvirt side of things. The interesting part is whether a
> given interface is available on this specific qemu binary.

Take 'drive-mirror' as an example.  The format parameter is a string.
You can't tell what valid arguments are for this parameter with
introspection.

You can certainly say that we can make this an enum, and do
introspection on the enums, but that only works because it's a string.

The same thing can apply to integer arguments.  If a new value becomes
valid that previously was rejected, then libvirt probably needs to be
able to figure that out.

>> > It also makes the schema totally useless. If you can't use it to tell
>> > which commands this qemu can execute and which it can't,
>> 
>> query-commands serves that purpose.
>
> It solves a subset of this problem. Optional fields can be added as
> arguments or to returned structs, enums can be extended, and so far
> we're having a hard time making use of it because the client can't
> discover it.

Ack.

>> > We can have hundreds of individual query commands like you suggest
>> > (query-qcow2-creation-option-values, yay!) or we do the modularity
>> > thing and the schema introspection properly and make it dynamic. I
>> > prefer the latter.
>> 
>> Let's consider a real example.  It sounds like you have something in
>> mind, can you be more specific?
>
> Not a very specific one, it's just that the more I discuss about things
> like blockdev-add, the more I get the impression that there is an awful
> lot of information to query. Each image format can provide different
> options, for creating images and for opening them, and some of them may
> be enums that could be extended and whose values must be queried etc.

But is this specific to blockdev-add?  The supported image formats are
global and apply to multiple commands.

Also, do we need to expose which formats are read-only vs. read-write?
That wouldn't be part of the schema I would think.

> Schema introspection allows you to have one single way to check for all
> optional fields, enum values, union branches. The other way is to have a
> separate command for each of them.

Yes, my only worry is that the schema probably doesn't contain all of
the information that something like libvirt needs.

> Basically instead of query-enum(Qcow2PreallocationType) you get
> query-qcow2-prellocation-types(). You can imagine how the set of
> commands grows once you start doing things this way.
>
> When I discussed with Eric (who is one of the few actual consumers of
> the API), he preferred introspection of a dynamic schema as well,
> compared to many separate query-* commands.

I'm not opposed to schema introspection even if it's used for this type
of use-case.

But I don't think it's a complete solution.  We should think about what
the use-cases are and make sure we have a solution that addresses them.

None of that should hold back schema introspection...

Regards,

Anthony Liguori

>
> Kevin

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] RFC: Full introspection support for QMP
  2013-05-23 13:52           ` Anthony Liguori
@ 2013-05-23 14:17             ` Eric Blake
  2013-05-23 14:29             ` Kevin Wolf
  1 sibling, 0 replies; 19+ messages in thread
From: Eric Blake @ 2013-05-23 14:17 UTC (permalink / raw)
  To: Anthony Liguori
  Cc: Kevin Wolf, Markus Armbruster, qemu-devel, lcapitulino,
	Ronen Hod, Amos Kong

[-- Attachment #1: Type: text/plain, Size: 5272 bytes --]

On 05/23/2013 07:52 AM, Anthony Liguori wrote:
>> libvirt already knows how to use features. It must know it, just parsing
>> the schema doesn't automagically give you libvirt code, so someone must
>> have coded the libvirt side of things. The interesting part is whether a
>> given interface is available on this specific qemu binary.
> 
> Take 'drive-mirror' as an example.  The format parameter is a string.
> You can't tell what valid arguments are for this parameter with
> introspection.
> 
> You can certainly say that we can make this an enum, and do
> introspection on the enums, but that only works because it's a string.

Introspection on an enum and on optional parameters are both nice ways
of learning whether libvirt can expect success when passing a particular
use of that enum or option extension.  That does not cover ALL ways that
features are added, but it sure covers a lot, which makes it a nice
reusable framework for learning about quite a few features.  Yes, I
suspect we will still have to add some query-* commands along the way
for features that aren't quite discernible solely from introspection, or
even where a query can give the information in a nicer format than
crawling through several layers of type information, but I see these as
orthogonal, not competing, so that is not a reason to exclude either
approach from being added to QMP.

> 
> The same thing can apply to integer arguments.  If a new value becomes
> valid that previously was rejected, then libvirt probably needs to be
> able to figure that out.

Changing an integer range is a bit harder; but again, with PROPER
introspection, you can include range information alongside type information.

> 
>>>> It also makes the schema totally useless. If you can't use it to tell
>>>> which commands this qemu can execute and which it can't,
>>>
>>> query-commands serves that purpose.
>>
>> It solves a subset of this problem. Optional fields can be added as
>> arguments or to returned structs, enums can be extended, and so far
>> we're having a hard time making use of it because the client can't
>> discover it.
> 
> Ack.

Yes, this is the primary motivating factor behind asking for
introspection at the moment.

> 
>>>> We can have hundreds of individual query commands like you suggest
>>>> (query-qcow2-creation-option-values, yay!) or we do the modularity
>>>> thing and the schema introspection properly and make it dynamic. I
>>>> prefer the latter.
>>>
>>> Let's consider a real example.  It sounds like you have something in
>>> mind, can you be more specific?
>>
>> Not a very specific one, it's just that the more I discuss about things
>> like blockdev-add, the more I get the impression that there is an awful
>> lot of information to query. Each image format can provide different
>> options, for creating images and for opening them, and some of them may
>> be enums that could be extended and whose values must be queried etc.
> 
> But is this specific to blockdev-add?  The supported image formats are
> global and apply to multiple commands.
> 

But that still argues that having a dynamic approach to learning "what
formats are supported, and what options does a given format provide
beyond the basics".

> Also, do we need to expose which formats are read-only vs. read-write?
> That wouldn't be part of the schema I would think.

True, a pure 'enum' in qapi-schema.json wouldn't expose which types are
read-only vs. read-write, so that argues for a query-* command for
learning details about the various block formats.  Once you have a
query-* command (which is dynamic), then having a non-dynamic 'enum' in
the schema expressing all known types (whether loaded or not) is
reasonable, where the query command then returns the subset of known
formats that are actually loaded and what additional features each
format comes with.

> 
>> Schema introspection allows you to have one single way to check for all
>> optional fields, enum values, union branches. The other way is to have a
>> separate command for each of them.
> 
> Yes, my only worry is that the schema probably doesn't contain all of
> the information that something like libvirt needs.

I don't think that schema introspection can provide everything, but it
can sure provide a lot, and minimize the number of cases where we
actually need a query-* command.

> 
>> Basically instead of query-enum(Qcow2PreallocationType) you get
>> query-qcow2-prellocation-types(). You can imagine how the set of
>> commands grows once you start doing things this way.
>>
>> When I discussed with Eric (who is one of the few actual consumers of
>> the API), he preferred introspection of a dynamic schema as well,
>> compared to many separate query-* commands.
> 
> I'm not opposed to schema introspection even if it's used for this type
> of use-case.
> 
> But I don't think it's a complete solution.  We should think about what
> the use-cases are and make sure we have a solution that addresses them.

Agreed.

> 
> None of that should hold back schema introspection...

Agreed.

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


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 621 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] RFC: Full introspection support for QMP
  2013-05-23 13:52           ` Anthony Liguori
  2013-05-23 14:17             ` Eric Blake
@ 2013-05-23 14:29             ` Kevin Wolf
  1 sibling, 0 replies; 19+ messages in thread
From: Kevin Wolf @ 2013-05-23 14:29 UTC (permalink / raw)
  To: Anthony Liguori
  Cc: qemu-devel, Amos Kong, Markus Armbruster, Ronen Hod, lcapitulino

Am 23.05.2013 um 15:52 hat Anthony Liguori geschrieben:
> Kevin Wolf <kwolf@redhat.com> writes:
> 
> > Am 23.05.2013 um 14:08 hat Anthony Liguori geschrieben:
> >> Kevin Wolf <kwolf@redhat.com> writes:
> >> 
> >> 
> >> There are two things here: the schema and the generated code.  The
> >> generated code can and should live in the module.
> >> 
> >> But the schema always stays the same.
> >> 
> >> Think of the schema like kernel headers.  The kernel headers are always
> >> fixed regardless of what kernel modules are loaded or how the kernel is
> >> configured.
> >> 
> >> > then we don't need introspection at all. There's no user for it then.
> >> 
> >> Introspection is not the right approach to feature discovery.  The
> >> schema does answer the question of what features are enabled, it just
> >> answers the question of what the signature of the methods are.
> >
> > You can see it like this. Then, as I said, it's totally useless,
> 
> It's not totally useless.  It's impossible to write a reasonable python
> client for QMP because arguments are not ordered (they are always
> named).  So you can't have:
> 
> qmp.block_commit('ide0-hd0', ...)
> 
> You have to have:
> 
> qmp.block_commit(device='ide0-hd0', ...)
> 
> Which is a little less nice.  The schema introspection solves this but I
> agree, it's not a critical problem to solve.

Well, yes, totally useless may be exaggerated. But this cosmetic problem
of a Python client is an argument as weak as (or even weaker than) the
needs of your beloved QMP client C library: Both of them are purely
hypothetical, they don't exist and nobody plans to actually implement
them.

If this was the only valid reason for schema introspection, I suspect
developmen would stop immediately.

> > because nobody has ever asked this question. The context in which
> > libvirt wants to use it is feature discovery. If we don't support
> > that, then there's no reason to provide introspection at all.
> >
> > libvirt already knows how to use features. It must know it, just parsing
> > the schema doesn't automagically give you libvirt code, so someone must
> > have coded the libvirt side of things. The interesting part is whether a
> > given interface is available on this specific qemu binary.
> 
> Take 'drive-mirror' as an example.  The format parameter is a string.
> You can't tell what valid arguments are for this parameter with
> introspection.
> 
> You can certainly say that we can make this an enum, and do
> introspection on the enums, but that only works because it's a string.
> 
> The same thing can apply to integer arguments.  If a new value becomes
> valid that previously was rejected, then libvirt probably needs to be
> able to figure that out.

I'm not sure how often this actually happens and if we really need to
consider it. But in theory we could still add versioning information to
fields if we use Eric's proposal and have a struct for each field.

> >> > It also makes the schema totally useless. If you can't use it to tell
> >> > which commands this qemu can execute and which it can't,
> >> 
> >> query-commands serves that purpose.
> >
> > It solves a subset of this problem. Optional fields can be added as
> > arguments or to returned structs, enums can be extended, and so far
> > we're having a hard time making use of it because the client can't
> > discover it.
> 
> Ack.
> 
> >> > We can have hundreds of individual query commands like you suggest
> >> > (query-qcow2-creation-option-values, yay!) or we do the modularity
> >> > thing and the schema introspection properly and make it dynamic. I
> >> > prefer the latter.
> >> 
> >> Let's consider a real example.  It sounds like you have something in
> >> mind, can you be more specific?
> >
> > Not a very specific one, it's just that the more I discuss about things
> > like blockdev-add, the more I get the impression that there is an awful
> > lot of information to query. Each image format can provide different
> > options, for creating images and for opening them, and some of them may
> > be enums that could be extended and whose values must be queried etc.
> 
> But is this specific to blockdev-add?  The supported image formats are
> global and apply to multiple commands.

Sure. There's no reason why enums or the option structs can't be used in
the definition of multiple commands. They are simply named QAPI types
and as such aren't specific to blockdev-add, it's only one user.

> Also, do we need to expose which formats are read-only vs. read-write?
> That wouldn't be part of the schema I would think.

No, probably not. That would be describing capabilities of the object
created by blockdev-add, which is neither an argument nor a return
value. So we wouldn't describe it in the blockdev-add schema or any
types referenced by it.

But do we need this information before creating the block device? It
seems unlikely, but I honestly don't know.

> > Schema introspection allows you to have one single way to check for all
> > optional fields, enum values, union branches. The other way is to have a
> > separate command for each of them.
> 
> Yes, my only worry is that the schema probably doesn't contain all of
> the information that something like libvirt needs.

I think it would already be great if it contained most of the
information. We can always add separate query-* commands if we have to,
but having a uniform way to query the majority of features is certainly
more attractive than using only query-*.

> > Basically instead of query-enum(Qcow2PreallocationType) you get
> > query-qcow2-prellocation-types(). You can imagine how the set of
> > commands grows once you start doing things this way.
> >
> > When I discussed with Eric (who is one of the few actual consumers of
> > the API), he preferred introspection of a dynamic schema as well,
> > compared to many separate query-* commands.
> 
> I'm not opposed to schema introspection even if it's used for this type
> of use-case.
> 
> But I don't think it's a complete solution.  We should think about what
> the use-cases are and make sure we have a solution that addresses them.
> 
> None of that should hold back schema introspection...

Agreed.

With Eric's proposal that involves postprocessing qapi-schema.json for a
more explicit wire format, we actually gain much flexibility to add more
detailed descriptions of fields if needed, and probably also get quite
close to a dynamic schema implementation-wise.

Kevin

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] RFC: Full introspection support for QMP (with draft patch)
  2013-05-22 13:40 [Qemu-devel] RFC: Full introspection support for QMP Amos Kong
                   ` (2 preceding siblings ...)
  2013-05-23 12:58 ` Eric Blake
@ 2013-06-07 10:12 ` Amos Kong
  2013-06-07 10:17   ` Amos Kong
  3 siblings, 1 reply; 19+ messages in thread
From: Amos Kong @ 2013-06-07 10:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: qiaonuohan, aliguori, Ronen Hod, Markus Armbruster, lcapitulino

[-- Attachment #1: Type: text/plain, Size: 6997 bytes --]

Sent out a draft patch in the end of this week. It doesn't support:
* output all stuffs in one shot.
* introspect event
* provide metadata date

How can we define a dynamic dict in qmp-schema.json ?

Currently I just output the raw json dict by a string, Libvirt needs
parse two times, convert the string to json format.

qmp-schema.h: auto generated head file by qapi script

Attached some examples.
* query-qmp-schema-no-param.txt
* query-qmp-schema-filter-by-name.txt
* query-qmp-schema-filter-all-command.txt
* query-qmp-schema-filter-all-type.txt
* query-qmp-schema-filter-all-enum.txt

-----

>From 00fe59bde40a8beadf16196db9ed1bac5d862db0 Mon Sep 17 00:00:00 2001
From: Amos Kong <akong@redhat.com>
Date: Fri, 7 Jun 2013 18:02:21 +0800
Subject: [PATCH] full introspection support for QMP

Signed-off-by: Amos Kong <akong@redhat.com>
---
 qapi-schema.json         |  3 +++
 qmp-commands.hx          | 23 +++++++++++++++++++++++
 qmp.c                    | 36 ++++++++++++++++++++++++++++++++++++
 scripts/qapi-commands.py |  2 +-
 scripts/qapi-types.py    | 27 ++++++++++++++++++++++++++-
 scripts/qapi-visit.py    |  2 +-
 scripts/qapi.py          | 13 ++++++++++++-
 7 files changed, 102 insertions(+), 4 deletions(-)

diff --git a/qapi-schema.json b/qapi-schema.json
index ef1f657..2234e6a 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3618,3 +3618,6 @@
             '*cpuid-input-ecx': 'int',
             'cpuid-register': 'X86CPURegister32',
             'features': 'int' } }
+
+{ 'command': 'query-qmp-schema', 'data': { '*type': 'str', '*name': 'str' },
+  'returns': ['str'] }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index ffd130e..fc56fba 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -2932,3 +2932,26 @@ Example:
 <- { "return": {} }
 
 EQMP
+
+    {
+        .name       = "query-qmp-schema",
+        .args_type  = "type:s?,name:s?",
+        .mhandler.cmd_new = qmp_marshal_input_query_qmp_schema,
+    },
+
+
+SQMP
+query-qmp-schema
+----------------
+
+query qmp schema information
+
+Example:
+
+-> { "execute": "query-qmp-schema", "arguments": { "name" : "query-name" }}
+<- { "return": [
+        "{ 'command': 'query-name', 'returns': 'NameInfo' }"
+      ]
+   }
+
+EQMP
\ No newline at end of file
diff --git a/qmp.c b/qmp.c
index 4c149b3..11ce275 100644
--- a/qmp.c
+++ b/qmp.c
@@ -25,6 +25,7 @@
 #include "sysemu/blockdev.h"
 #include "qom/qom-qobject.h"
 #include "hw/boards.h"
+#include "qmp-schema.h"
 
 NameInfo *qmp_query_name(Error **errp)
 {
@@ -486,6 +487,41 @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
     return arch_query_cpu_definitions(errp);
 }
 
+strList *qmp_query_qmp_schema(bool has_type, const char *type, bool
+                              has_name, const char * name, Error **errp)
+
+{
+    strList *list = NULL, *last_entry, *entry;
+    int i = 0;
+
+    while (qmp_schema_table[i].json_string) {
+        if (has_type && strcmp(type, qmp_schema_table[i].type)) {
+            i++;
+            continue;
+        }
+        if (has_name && strcmp(name, qmp_schema_table[i].name)) {
+            i++;
+            continue;
+        }
+
+        entry = malloc(sizeof(strList *));
+        entry->value = g_strdup(qmp_schema_table[i].json_string);
+        entry->next = NULL;
+
+        if (!list) {
+            list = entry;
+        } else {
+            last_entry->next = entry;
+        }
+        last_entry = entry;
+
+        printf("%d\n", i);
+        i++;
+    }
+
+    return list;
+}
+
 void qmp_add_client(const char *protocol, const char *fdname,
                     bool has_skipauth, bool skipauth, bool has_tls, bool tls,
                     Error **errp)
diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
index e06332b..d15d04f 100644
--- a/scripts/qapi-commands.py
+++ b/scripts/qapi-commands.py
@@ -437,7 +437,7 @@ except os.error, e:
     if e.errno != errno.EEXIST:
         raise
 
-exprs = parse_schema(sys.stdin)
+exprs = parse_schema(sys.stdin)[0]
 commands = filter(lambda expr: expr.has_key('command'), exprs)
 commands = filter(lambda expr: not expr.has_key('gen'), commands)
 
diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index ddcfed9..ce448d8 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -15,6 +15,7 @@ import sys
 import os
 import getopt
 import errno
+import re
 
 def generate_fwd_struct(name, members, builtin_type=False):
     if builtin_type:
@@ -303,7 +304,31 @@ fdecl.write(mcgen('''
 ''',
                   guard=guardname(h_file)))
 
-exprs = parse_schema(sys.stdin)
+exprs_all = parse_schema(sys.stdin)
+
+schema_table = """
+/* convert qapi-schema.json to a string table */
+
+struct qmp_schem {
+const char *json_string;
+const char *type;
+const char *name;
+} qmp_schema_table[] = {
+"""
+
+for i in exprs_all[1]:
+    print i
+    str = re.sub(r'\n', ' \\\n', i[0].strip())
+    str = re.sub(r' +', ' ', str)
+    schema_table += '{"%s", "%s", "%s"},\n' % (str, i[1], i[2])
+
+schema_table += '{NULL, NULL, NULL } };\n'
+
+f = open("qmp-schema.h", "w")
+f.write(schema_table)
+f.close()
+
+exprs = exprs_all[0]
 exprs = filter(lambda expr: not expr.has_key('gen'), exprs)
 
 fdecl.write(guardstart("QAPI_TYPES_BUILTIN_STRUCT_DECL"))
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index 6cac05a..70f80eb 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -334,7 +334,7 @@ fdecl.write(mcgen('''
 ''',
                   prefix=prefix, guard=guardname(h_file)))
 
-exprs = parse_schema(sys.stdin)
+exprs = parse_schema(sys.stdin)[0]
 
 # to avoid header dependency hell, we always generate declarations
 # for built-in types in our header files and simply guard them
diff --git a/scripts/qapi.py b/scripts/qapi.py
index 02ad668..46cc2e4 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -80,6 +80,7 @@ def evaluate(string):
 
 def parse_schema(fp):
     exprs = []
+    raw_exprs = []
     expr = ''
     expr_eval = None
 
@@ -91,6 +92,11 @@ def parse_schema(fp):
             expr += line
         elif expr:
             expr_eval = evaluate(expr)
+
+            for name in ['command', 'type', 'enum', 'union']:
+                if expr_eval.has_key(name):
+                    raw_exprs.append([expr, name, expr_eval[name]])
+
             if expr_eval.has_key('enum'):
                 add_enum(expr_eval['enum'])
             elif expr_eval.has_key('union'):
@@ -102,13 +108,18 @@ def parse_schema(fp):
 
     if expr:
         expr_eval = evaluate(expr)
+
+        for name in ['command', 'type', 'enum', 'union']:
+            if expr_eval.has_key(name):
+                raw_exprs.append([expr, name, expr_eval[name]])
+
         if expr_eval.has_key('enum'):
             add_enum(expr_eval['enum'])
         elif expr_eval.has_key('union'):
             add_enum('%sKind' % expr_eval['union'])
         exprs.append(expr_eval)
 
-    return exprs
+    return exprs, raw_exprs
 
 def parse_args(typeinfo):
     for member in typeinfo:
-- 
1.8.1.4


[-- Attachment #2: qmp-schema.h --]
[-- Type: text/plain, Size: 26493 bytes --]


/* convert qapi-schema.json to a string table */

struct qmp_schem {
const char *json_string;
const char *type;
const char *name;
} qmp_schema_table[] = {
{"{ 'enum': 'ErrorClass', \
 'data': [ 'GenericError', 'CommandNotFound', 'DeviceEncrypted', \
 'DeviceNotActive', 'DeviceNotFound', 'KVMMissingCap' ] }", "enum", "ErrorClass"},
{"{ 'command': 'add_client', \
 'data': { 'protocol': 'str', 'fdname': 'str', '*skipauth': 'bool', \
 '*tls': 'bool' } }", "command", "add_client"},
{"{ 'type': 'NameInfo', 'data': {'*name': 'str'} }", "type", "NameInfo"},
{"{ 'command': 'query-name', 'returns': 'NameInfo' }", "command", "query-name"},
{"{ 'type': 'VersionInfo', \
 'data': {'qemu': {'major': 'int', 'minor': 'int', 'micro': 'int'}, \
 'package': 'str'} }", "type", "VersionInfo"},
{"{ 'command': 'query-version', 'returns': 'VersionInfo' }", "command", "query-version"},
{"{ 'type': 'KvmInfo', 'data': {'enabled': 'bool', 'present': 'bool'} }", "type", "KvmInfo"},
{"{ 'command': 'query-kvm', 'returns': 'KvmInfo' }", "command", "query-kvm"},
{"{ 'enum': 'RunState', \
 'data': [ 'debug', 'inmigrate', 'internal-error', 'io-error', 'paused', \
 'postmigrate', 'prelaunch', 'finish-migrate', 'restore-vm', \
 'running', 'save-vm', 'shutdown', 'suspended', 'watchdog', \
 'guest-panicked' ] }", "enum", "RunState"},
{"{ 'type': 'SnapshotInfo', \
 'data': { 'id': 'str', 'name': 'str', 'vm-state-size': 'int', \
 'date-sec': 'int', 'date-nsec': 'int', \
 'vm-clock-sec': 'int', 'vm-clock-nsec': 'int' } }", "type", "SnapshotInfo"},
{"{ 'type': 'ImageInfo', \
 'data': {'filename': 'str', 'format': 'str', '*dirty-flag': 'bool', \
 '*actual-size': 'int', 'virtual-size': 'int', \
 '*cluster-size': 'int', '*encrypted': 'bool', \
 '*backing-filename': 'str', '*full-backing-filename': 'str', \
 '*backing-filename-format': 'str', '*snapshots': ['SnapshotInfo'] } }", "type", "ImageInfo"},
{"{ 'type': 'ImageCheck', \
 'data': {'filename': 'str', 'format': 'str', 'check-errors': 'int', \
 '*image-end-offset': 'int', '*corruptions': 'int', '*leaks': 'int', \
 '*corruptions-fixed': 'int', '*leaks-fixed': 'int', \
 '*total-clusters': 'int', '*allocated-clusters': 'int', \
 '*fragmented-clusters': 'int', '*compressed-clusters': 'int' } }", "type", "ImageCheck"},
{"{ 'type': 'StatusInfo', \
 'data': {'running': 'bool', 'singlestep': 'bool', 'status': 'RunState'} }", "type", "StatusInfo"},
{"{ 'command': 'query-status', 'returns': 'StatusInfo' }", "command", "query-status"},
{"{ 'type': 'UuidInfo', 'data': {'UUID': 'str'} }", "type", "UuidInfo"},
{"{ 'command': 'query-uuid', 'returns': 'UuidInfo' }", "command", "query-uuid"},
{"{ 'type': 'ChardevInfo', 'data': {'label': 'str', 'filename': 'str'} }", "type", "ChardevInfo"},
{"{ 'command': 'query-chardev', 'returns': ['ChardevInfo'] }", "command", "query-chardev"},
{"{ 'enum': 'DataFormat' \
 'data': [ 'utf8', 'base64' ] }", "enum", "DataFormat"},
{"{ 'command': 'ringbuf-write', \
 'data': {'device': 'str', 'data': 'str', \
 '*format': 'DataFormat'} }", "command", "ringbuf-write"},
{"{ 'command': 'ringbuf-read', \
 'data': {'device': 'str', 'size': 'int', '*format': 'DataFormat'}, \
 'returns': 'str' }", "command", "ringbuf-read"},
{"{ 'type': 'CommandInfo', 'data': {'name': 'str'} }", "type", "CommandInfo"},
{"{ 'command': 'query-commands', 'returns': ['CommandInfo'] }", "command", "query-commands"},
{"{ 'type': 'EventInfo', 'data': {'name': 'str'} }", "type", "EventInfo"},
{"{ 'command': 'query-events', 'returns': ['EventInfo'] }", "command", "query-events"},
{"{ 'type': 'MigrationStats', \
 'data': {'transferred': 'int', 'remaining': 'int', 'total': 'int' , \
 'duplicate': 'int', 'skipped': 'int', 'normal': 'int', \
 'normal-bytes': 'int', 'dirty-pages-rate' : 'int' } }", "type", "MigrationStats"},
{"{ 'type': 'XBZRLECacheStats', \
 'data': {'cache-size': 'int', 'bytes': 'int', 'pages': 'int', \
 'cache-miss': 'int', 'overflow': 'int' } }", "type", "XBZRLECacheStats"},
{"{ 'type': 'MigrationInfo', \
 'data': {'*status': 'str', '*ram': 'MigrationStats', \
 '*disk': 'MigrationStats', \
 '*xbzrle-cache': 'XBZRLECacheStats', \
 '*total-time': 'int', \
 '*expected-downtime': 'int', \
 '*downtime': 'int'} }", "type", "MigrationInfo"},
{"{ 'command': 'query-migrate', 'returns': 'MigrationInfo' }", "command", "query-migrate"},
{"{ 'enum': 'MigrationCapability', \
 'data': ['xbzrle'] }", "enum", "MigrationCapability"},
{"{ 'type': 'MigrationCapabilityStatus', \
 'data': { 'capability' : 'MigrationCapability', 'state' : 'bool' } }", "type", "MigrationCapabilityStatus"},
{"{ 'command': 'migrate-set-capabilities', \
 'data': { 'capabilities': ['MigrationCapabilityStatus'] } }", "command", "migrate-set-capabilities"},
{"{ 'command': 'query-migrate-capabilities', 'returns': ['MigrationCapabilityStatus']}", "command", "query-migrate-capabilities"},
{"{ 'type': 'MouseInfo', \
 'data': {'name': 'str', 'index': 'int', 'current': 'bool', \
 'absolute': 'bool'} }", "type", "MouseInfo"},
{"{ 'command': 'query-mice', 'returns': ['MouseInfo'] }", "command", "query-mice"},
{"{ 'type': 'CpuInfo', \
 'data': {'CPU': 'int', 'current': 'bool', 'halted': 'bool', '*pc': 'int', \
 '*nip': 'int', '*npc': 'int', '*PC': 'int', 'thread_id': 'int'} }", "type", "CpuInfo"},
{"{ 'command': 'query-cpus', 'returns': ['CpuInfo'] }", "command", "query-cpus"},
{"{ 'type': 'BlockDeviceInfo', \
 'data': { 'file': 'str', 'ro': 'bool', 'drv': 'str', \
 '*backing_file': 'str', 'backing_file_depth': 'int', \
 'encrypted': 'bool', 'encryption_key_missing': 'bool', \
 'bps': 'int', 'bps_rd': 'int', 'bps_wr': 'int', \
 'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int'} }", "type", "BlockDeviceInfo"},
{"{ 'enum': 'BlockDeviceIoStatus', 'data': [ 'ok', 'failed', 'nospace' ] }", "enum", "BlockDeviceIoStatus"},
{"{ 'type': 'BlockDirtyInfo', \
 'data': {'count': 'int', 'granularity': 'int'} }", "type", "BlockDirtyInfo"},
{"{ 'type': 'BlockInfo', \
 'data': {'device': 'str', 'type': 'str', 'removable': 'bool', \
 'locked': 'bool', '*inserted': 'BlockDeviceInfo', \
 '*tray_open': 'bool', '*io-status': 'BlockDeviceIoStatus', \
 '*dirty': 'BlockDirtyInfo' } }", "type", "BlockInfo"},
{"{ 'command': 'query-block', 'returns': ['BlockInfo'] }", "command", "query-block"},
{"{ 'type': 'BlockDeviceStats', \
 'data': {'rd_bytes': 'int', 'wr_bytes': 'int', 'rd_operations': 'int', \
 'wr_operations': 'int', 'flush_operations': 'int', \
 'flush_total_time_ns': 'int', 'wr_total_time_ns': 'int', \
 'rd_total_time_ns': 'int', 'wr_highest_offset': 'int' } }", "type", "BlockDeviceStats"},
{"{ 'type': 'BlockStats', \
 'data': {'*device': 'str', 'stats': 'BlockDeviceStats', \
 '*parent': 'BlockStats'} }", "type", "BlockStats"},
{"{ 'command': 'query-blockstats', 'returns': ['BlockStats'] }", "command", "query-blockstats"},
{"{ 'type': 'VncClientInfo', \
 'data': {'host': 'str', 'family': 'str', 'service': 'str', \
 '*x509_dname': 'str', '*sasl_username': 'str'} }", "type", "VncClientInfo"},
{"{ 'type': 'VncInfo', \
 'data': {'enabled': 'bool', '*host': 'str', '*family': 'str', \
 '*service': 'str', '*auth': 'str', '*clients': ['VncClientInfo']} }", "type", "VncInfo"},
{"{ 'command': 'query-vnc', 'returns': 'VncInfo' }", "command", "query-vnc"},
{"{ 'type': 'SpiceChannel', \
 'data': {'host': 'str', 'family': 'str', 'port': 'str', \
 'connection-id': 'int', 'channel-type': 'int', 'channel-id': 'int', \
 'tls': 'bool'} }", "type", "SpiceChannel"},
{"{ 'enum': 'SpiceQueryMouseMode', \
 'data': [ 'client', 'server', 'unknown' ] }", "enum", "SpiceQueryMouseMode"},
{"{ 'type': 'SpiceInfo', \
 'data': {'enabled': 'bool', 'migrated': 'bool', '*host': 'str', '*port': 'int', \
 '*tls-port': 'int', '*auth': 'str', '*compiled-version': 'str', \
 'mouse-mode': 'SpiceQueryMouseMode', '*channels': ['SpiceChannel']} }", "type", "SpiceInfo"},
{"{ 'command': 'query-spice', 'returns': 'SpiceInfo' }", "command", "query-spice"},
{"{ 'type': 'BalloonInfo', 'data': {'actual': 'int' } }", "type", "BalloonInfo"},
{"{ 'command': 'query-balloon', 'returns': 'BalloonInfo' }", "command", "query-balloon"},
{"{ 'type': 'PciMemoryRange', 'data': {'base': 'int', 'limit': 'int'} }", "type", "PciMemoryRange"},
{"{ 'type': 'PciMemoryRegion', \
 'data': {'bar': 'int', 'type': 'str', 'address': 'int', 'size': 'int', \
 '*prefetch': 'bool', '*mem_type_64': 'bool' } }", "type", "PciMemoryRegion"},
{"{ 'type': 'PciBridgeInfo', \
 'data': {'bus': { 'number': 'int', 'secondary': 'int', 'subordinate': 'int', \
 'io_range': 'PciMemoryRange', \
 'memory_range': 'PciMemoryRange', \
 'prefetchable_range': 'PciMemoryRange' }, \
 '*devices': ['PciDeviceInfo']} }", "type", "PciBridgeInfo"},
{"{ 'type': 'PciDeviceInfo', \
 'data': {'bus': 'int', 'slot': 'int', 'function': 'int', \
 'class_info': {'*desc': 'str', 'class': 'int'}, \
 'id': {'device': 'int', 'vendor': 'int'}, \
 '*irq': 'int', 'qdev_id': 'str', '*pci_bridge': 'PciBridgeInfo', \
 'regions': ['PciMemoryRegion']} }", "type", "PciDeviceInfo"},
{"{ 'type': 'PciInfo', 'data': {'bus': 'int', 'devices': ['PciDeviceInfo']} }", "type", "PciInfo"},
{"{ 'command': 'query-pci', 'returns': ['PciInfo'] }", "command", "query-pci"},
{"{ 'enum': 'BlockdevOnError', \
 'data': ['report', 'ignore', 'enospc', 'stop'] }", "enum", "BlockdevOnError"},
{"{ 'enum': 'MirrorSyncMode', \
 'data': ['top', 'full', 'none'] }", "enum", "MirrorSyncMode"},
{"{ 'type': 'BlockJobInfo', \
 'data': {'type': 'str', 'device': 'str', 'len': 'int', \
 'offset': 'int', 'busy': 'bool', 'paused': 'bool', 'speed': 'int', \
 'io-status': 'BlockDeviceIoStatus'} }", "type", "BlockJobInfo"},
{"{ 'command': 'query-block-jobs', 'returns': ['BlockJobInfo'] }", "command", "query-block-jobs"},
{"{ 'command': 'quit' }", "command", "quit"},
{"{ 'command': 'stop' }", "command", "stop"},
{"{ 'command': 'system_reset' }", "command", "system_reset"},
{"{ 'command': 'system_powerdown' }", "command", "system_powerdown"},
{"{ 'command': 'cpu', 'data': {'index': 'int'} }", "command", "cpu"},
{"{ 'command': 'cpu-add', 'data': {'id': 'int'} }", "command", "cpu-add"},
{"{ 'command': 'memsave', \
 'data': {'val': 'int', 'size': 'int', 'filename': 'str', '*cpu-index': 'int'} }", "command", "memsave"},
{"{ 'command': 'pmemsave', \
 'data': {'val': 'int', 'size': 'int', 'filename': 'str'} }", "command", "pmemsave"},
{"{ 'command': 'cont' }", "command", "cont"},
{"{ 'command': 'system_wakeup' }", "command", "system_wakeup"},
{"{ 'command': 'inject-nmi' }", "command", "inject-nmi"},
{"{ 'command': 'set_link', 'data': {'name': 'str', 'up': 'bool'} }", "command", "set_link"},
{"{ 'command': 'block_passwd', 'data': {'device': 'str', 'password': 'str'} }", "command", "block_passwd"},
{"{ 'command': 'balloon', 'data': {'value': 'int'} }", "command", "balloon"},
{"{ 'command': 'block_resize', 'data': { 'device': 'str', 'size': 'int' }}", "command", "block_resize"},
{"{ 'enum': 'NewImageMode' \
 'data': [ 'existing', 'absolute-paths' ] }", "enum", "NewImageMode"},
{"{ 'type': 'BlockdevSnapshot', \
 'data': { 'device': 'str', 'snapshot-file': 'str', '*format': 'str', \
 '*mode': 'NewImageMode' } }", "type", "BlockdevSnapshot"},
{"{ 'union': 'TransactionAction', \
 'data': { \
 'blockdev-snapshot-sync': 'BlockdevSnapshot' \
 } }", "union", "TransactionAction"},
{"{ 'command': 'transaction', \
 'data': { 'actions': [ 'TransactionAction' ] } }", "command", "transaction"},
{"{ 'command': 'blockdev-snapshot-sync', \
 'data': { 'device': 'str', 'snapshot-file': 'str', '*format': 'str', \
 '*mode': 'NewImageMode'} }", "command", "blockdev-snapshot-sync"},
{"{ 'command': 'human-monitor-command', \
 'data': {'command-line': 'str', '*cpu-index': 'int'}, \
 'returns': 'str' }", "command", "human-monitor-command"},
{"{ 'command': 'block-commit', \
 'data': { 'device': 'str', '*base': 'str', 'top': 'str', \
 '*speed': 'int' } }", "command", "block-commit"},
{"{ 'command': 'drive-mirror', \
 'data': { 'device': 'str', 'target': 'str', '*format': 'str', \
 'sync': 'MirrorSyncMode', '*mode': 'NewImageMode', \
 '*speed': 'int', '*granularity': 'uint32', \
 '*buf-size': 'int', '*on-source-error': 'BlockdevOnError', \
 '*on-target-error': 'BlockdevOnError' } }", "command", "drive-mirror"},
{"{ 'command': 'migrate_cancel' }", "command", "migrate_cancel"},
{"{ 'command': 'migrate_set_downtime', 'data': {'value': 'number'} }", "command", "migrate_set_downtime"},
{"{ 'command': 'migrate_set_speed', 'data': {'value': 'int'} }", "command", "migrate_set_speed"},
{"{ 'command': 'migrate-set-cache-size', 'data': {'value': 'int'} }", "command", "migrate-set-cache-size"},
{"{ 'command': 'query-migrate-cache-size', 'returns': 'int' }", "command", "query-migrate-cache-size"},
{"{ 'type': 'ObjectPropertyInfo', \
 'data': { 'name': 'str', 'type': 'str' } }", "type", "ObjectPropertyInfo"},
{"{ 'command': 'qom-list', \
 'data': { 'path': 'str' }, \
 'returns': [ 'ObjectPropertyInfo' ] }", "command", "qom-list"},
{"{ 'command': 'qom-get', \
 'data': { 'path': 'str', 'property': 'str' }, \
 'returns': 'visitor', \
 'gen': 'no' }", "command", "qom-get"},
{"{ 'command': 'qom-set', \
 'data': { 'path': 'str', 'property': 'str', 'value': 'visitor' }, \
 'gen': 'no' }", "command", "qom-set"},
{"{ 'command': 'set_password', \
 'data': {'protocol': 'str', 'password': 'str', '*connected': 'str'} }", "command", "set_password"},
{"{ 'command': 'expire_password', 'data': {'protocol': 'str', 'time': 'str'} }", "command", "expire_password"},
{"{ 'command': 'eject', 'data': {'device': 'str', '*force': 'bool'} }", "command", "eject"},
{"{ 'command': 'change-vnc-password', 'data': {'password': 'str'} }", "command", "change-vnc-password"},
{"{ 'command': 'change', \
 'data': {'device': 'str', 'target': 'str', '*arg': 'str'} }", "command", "change"},
{"{ 'command': 'block_set_io_throttle', \
 'data': { 'device': 'str', 'bps': 'int', 'bps_rd': 'int', 'bps_wr': 'int', \
 'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int' } }", "command", "block_set_io_throttle"},
{"{ 'command': 'block-stream', \
 'data': { 'device': 'str', '*base': 'str', '*speed': 'int', \
 '*on-error': 'BlockdevOnError' } }", "command", "block-stream"},
{"{ 'command': 'block-job-set-speed', \
 'data': { 'device': 'str', 'speed': 'int' } }", "command", "block-job-set-speed"},
{"{ 'command': 'block-job-cancel', 'data': { 'device': 'str', '*force': 'bool' } }", "command", "block-job-cancel"},
{"{ 'command': 'block-job-pause', 'data': { 'device': 'str' } }", "command", "block-job-pause"},
{"{ 'command': 'block-job-resume', 'data': { 'device': 'str' } }", "command", "block-job-resume"},
{"{ 'command': 'block-job-complete', 'data': { 'device': 'str' } }", "command", "block-job-complete"},
{"{ 'type': 'ObjectTypeInfo', \
 'data': { 'name': 'str' } }", "type", "ObjectTypeInfo"},
{"{ 'command': 'qom-list-types', \
 'data': { '*implements': 'str', '*abstract': 'bool' }, \
 'returns': [ 'ObjectTypeInfo' ] }", "command", "qom-list-types"},
{"{ 'type': 'DevicePropertyInfo', \
 'data': { 'name': 'str', 'type': 'str' } }", "type", "DevicePropertyInfo"},
{"{ 'command': 'device-list-properties', \
 'data': { 'typename': 'str'}, \
 'returns': [ 'DevicePropertyInfo' ] }", "command", "device-list-properties"},
{"{ 'command': 'migrate', \
 'data': {'uri': 'str', '*blk': 'bool', '*inc': 'bool', '*detach': 'bool' } }", "command", "migrate"},
{"{ 'command': 'xen-save-devices-state', 'data': {'filename': 'str'} }", "command", "xen-save-devices-state"},
{"{ 'command': 'xen-set-global-dirty-log', 'data': { 'enable': 'bool' } }", "command", "xen-set-global-dirty-log"},
{"{ 'command': 'device_del', 'data': {'id': 'str'} }", "command", "device_del"},
{"{ 'command': 'dump-guest-memory', \
 'data': { 'paging': 'bool', 'protocol': 'str', '*begin': 'int', \
 '*length': 'int' } }", "command", "dump-guest-memory"},
{"{ 'command': 'netdev_add', \
 'data': {'type': 'str', 'id': 'str', '*props': '**'}, \
 'gen': 'no' }", "command", "netdev_add"},
{"{ 'command': 'netdev_del', 'data': {'id': 'str'} }", "command", "netdev_del"},
{"{ 'type': 'NetdevNoneOptions', \
 'data': { } }", "type", "NetdevNoneOptions"},
{"{ 'type': 'NetLegacyNicOptions', \
 'data': { \
 '*netdev': 'str', \
 '*macaddr': 'str', \
 '*model': 'str', \
 '*addr': 'str', \
 '*vectors': 'uint32' } }", "type", "NetLegacyNicOptions"},
{"{ 'type': 'String', \
 'data': { \
 'str': 'str' } }", "type", "String"},
{"{ 'type': 'NetdevUserOptions', \
 'data': { \
 '*hostname': 'str', \
 '*restrict': 'bool', \
 '*ip': 'str', \
 '*net': 'str', \
 '*host': 'str', \
 '*tftp': 'str', \
 '*bootfile': 'str', \
 '*dhcpstart': 'str', \
 '*dns': 'str', \
 '*dnssearch': ['String'], \
 '*smb': 'str', \
 '*smbserver': 'str', \
 '*hostfwd': ['String'], \
 '*guestfwd': ['String'] } }", "type", "NetdevUserOptions"},
{"{ 'type': 'NetdevTapOptions', \
 'data': { \
 '*ifname': 'str', \
 '*fd': 'str', \
 '*fds': 'str', \
 '*script': 'str', \
 '*downscript': 'str', \
 '*helper': 'str', \
 '*sndbuf': 'size', \
 '*vnet_hdr': 'bool', \
 '*vhost': 'bool', \
 '*vhostfd': 'str', \
 '*vhostfds': 'str', \
 '*vhostforce': 'bool', \
 '*queues': 'uint32'} }", "type", "NetdevTapOptions"},
{"{ 'type': 'NetdevSocketOptions', \
 'data': { \
 '*fd': 'str', \
 '*listen': 'str', \
 '*connect': 'str', \
 '*mcast': 'str', \
 '*localaddr': 'str', \
 '*udp': 'str' } }", "type", "NetdevSocketOptions"},
{"{ 'type': 'NetdevVdeOptions', \
 'data': { \
 '*sock': 'str', \
 '*port': 'uint16', \
 '*group': 'str', \
 '*mode': 'uint16' } }", "type", "NetdevVdeOptions"},
{"{ 'type': 'NetdevDumpOptions', \
 'data': { \
 '*len': 'size', \
 '*file': 'str' } }", "type", "NetdevDumpOptions"},
{"{ 'type': 'NetdevBridgeOptions', \
 'data': { \
 '*br': 'str', \
 '*helper': 'str' } }", "type", "NetdevBridgeOptions"},
{"{ 'type': 'NetdevHubPortOptions', \
 'data': { \
 'hubid': 'int32' } }", "type", "NetdevHubPortOptions"},
{"{ 'union': 'NetClientOptions', \
 'data': { \
 'none': 'NetdevNoneOptions', \
 'nic': 'NetLegacyNicOptions', \
 'user': 'NetdevUserOptions', \
 'tap': 'NetdevTapOptions', \
 'socket': 'NetdevSocketOptions', \
 'vde': 'NetdevVdeOptions', \
 'dump': 'NetdevDumpOptions', \
 'bridge': 'NetdevBridgeOptions', \
 'hubport': 'NetdevHubPortOptions' } }", "union", "NetClientOptions"},
{"{ 'type': 'NetLegacy', \
 'data': { \
 '*vlan': 'int32', \
 '*id': 'str', \
 '*name': 'str', \
 'opts': 'NetClientOptions' } }", "type", "NetLegacy"},
{"{ 'type': 'Netdev', \
 'data': { \
 'id': 'str', \
 'opts': 'NetClientOptions' } }", "type", "Netdev"},
{"{ 'type': 'InetSocketAddress', \
 'data': { \
 'host': 'str', \
 'port': 'str', \
 '*to': 'uint16', \
 '*ipv4': 'bool', \
 '*ipv6': 'bool' } }", "type", "InetSocketAddress"},
{"{ 'type': 'UnixSocketAddress', \
 'data': { \
 'path': 'str' } }", "type", "UnixSocketAddress"},
{"{ 'union': 'SocketAddress', \
 'data': { \
 'inet': 'InetSocketAddress', \
 'unix': 'UnixSocketAddress', \
 'fd': 'String' } }", "union", "SocketAddress"},
{"{ 'command': 'getfd', 'data': {'fdname': 'str'} }", "command", "getfd"},
{"{ 'command': 'closefd', 'data': {'fdname': 'str'} }", "command", "closefd"},
{"{ 'type': 'MachineInfo', \
 'data': { 'name': 'str', '*alias': 'str', \
 '*is-default': 'bool', 'cpu-max': 'int' } }", "type", "MachineInfo"},
{"{ 'command': 'query-machines', 'returns': ['MachineInfo'] }", "command", "query-machines"},
{"{ 'type': 'CpuDefinitionInfo', \
 'data': { 'name': 'str' } }", "type", "CpuDefinitionInfo"},
{"{ 'command': 'query-cpu-definitions', 'returns': ['CpuDefinitionInfo'] }", "command", "query-cpu-definitions"},
{"{ 'type': 'AddfdInfo', 'data': {'fdset-id': 'int', 'fd': 'int'} }", "type", "AddfdInfo"},
{"{ 'command': 'add-fd', 'data': {'*fdset-id': 'int', '*opaque': 'str'}, \
 'returns': 'AddfdInfo' }", "command", "add-fd"},
{"{ 'command': 'remove-fd', 'data': {'fdset-id': 'int', '*fd': 'int'} }", "command", "remove-fd"},
{"{ 'type': 'FdsetFdInfo', \
 'data': {'fd': 'int', '*opaque': 'str'} }", "type", "FdsetFdInfo"},
{"{ 'type': 'FdsetInfo', \
 'data': {'fdset-id': 'int', 'fds': ['FdsetFdInfo']} }", "type", "FdsetInfo"},
{"{ 'command': 'query-fdsets', 'returns': ['FdsetInfo'] }", "command", "query-fdsets"},
{"{ 'enum': 'TargetType', \
 'data': [ 'alpha', 'arm', 'cris', 'i386', 'lm32', 'm68k', 'microblazeel', \
 'microblaze', 'mips64el', 'mips64', 'mipsel', 'mips', 'moxie', \
 'or32', 'ppc64', 'ppcemb', 'ppc', 's390x', 'sh4eb', 'sh4', \
 'sparc64', 'sparc', 'unicore32', 'x86_64', 'xtensaeb', 'xtensa' ] }", "enum", "TargetType"},
{"{ 'type': 'TargetInfo', \
 'data': { 'arch': 'TargetType' } }", "type", "TargetInfo"},
{"{ 'command': 'query-target', 'returns': 'TargetInfo' }", "command", "query-target"},
{"{ 'enum': 'QKeyCode', \
 'data': [ 'shift', 'shift_r', 'alt', 'alt_r', 'altgr', 'altgr_r', 'ctrl', \
 'ctrl_r', 'menu', 'esc', '1', '2', '3', '4', '5', '6', '7', '8', \
 '9', '0', 'minus', 'equal', 'backspace', 'tab', 'q', 'w', 'e', \
 'r', 't', 'y', 'u', 'i', 'o', 'p', 'bracket_left', 'bracket_right', \
 'ret', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'semicolon', \
 'apostrophe', 'grave_accent', 'backslash', 'z', 'x', 'c', 'v', 'b', \
 'n', 'm', 'comma', 'dot', 'slash', 'asterisk', 'spc', 'caps_lock', \
 'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'f10', \
 'num_lock', 'scroll_lock', 'kp_divide', 'kp_multiply', \
 'kp_subtract', 'kp_add', 'kp_enter', 'kp_decimal', 'sysrq', 'kp_0', \
 'kp_1', 'kp_2', 'kp_3', 'kp_4', 'kp_5', 'kp_6', 'kp_7', 'kp_8', \
 'kp_9', 'less', 'f11', 'f12', 'print', 'home', 'pgup', 'pgdn', 'end', \
 'left', 'up', 'down', 'right', 'insert', 'delete', 'stop', 'again', \
 'props', 'undo', 'front', 'copy', 'open', 'paste', 'find', 'cut', \
 'lf', 'help', 'meta_l', 'meta_r', 'compose' ] }", "enum", "QKeyCode"},
{"{ 'union': 'KeyValue', \
 'data': { \
 'number': 'int', \
 'qcode': 'QKeyCode' } }", "union", "KeyValue"},
{"{ 'command': 'send-key', \
 'data': { 'keys': ['KeyValue'], '*hold-time': 'int' } }", "command", "send-key"},
{"{ 'command': 'screendump', 'data': {'filename': 'str'} }", "command", "screendump"},
{"{ 'command': 'nbd-server-start', \
 'data': { 'addr': 'SocketAddress' } }", "command", "nbd-server-start"},
{"{ 'command': 'nbd-server-add', 'data': {'device': 'str', '*writable': 'bool'} }", "command", "nbd-server-add"},
{"{ 'command': 'nbd-server-stop' }", "command", "nbd-server-stop"},
{"{ 'type': 'ChardevFile', 'data': { '*in' : 'str', \
 'out' : 'str' } }", "type", "ChardevFile"},
{"{ 'type': 'ChardevHostdev', 'data': { 'device' : 'str' } }", "type", "ChardevHostdev"},
{"{ 'type': 'ChardevSocket', 'data': { 'addr' : 'SocketAddress', \
 '*server' : 'bool', \
 '*wait' : 'bool', \
 '*nodelay' : 'bool', \
 '*telnet' : 'bool' } }", "type", "ChardevSocket"},
{"{ 'type': 'ChardevUdp', 'data': { 'remote' : 'SocketAddress', \
 '*local' : 'SocketAddress' } }", "type", "ChardevUdp"},
{"{ 'type': 'ChardevMux', 'data': { 'chardev' : 'str' } }", "type", "ChardevMux"},
{"{ 'type': 'ChardevStdio', 'data': { '*signal' : 'bool' } }", "type", "ChardevStdio"},
{"{ 'type': 'ChardevSpiceChannel', 'data': { 'type' : 'str' } }", "type", "ChardevSpiceChannel"},
{"{ 'type': 'ChardevSpicePort', 'data': { 'fqdn' : 'str' } }", "type", "ChardevSpicePort"},
{"{ 'type': 'ChardevVC', 'data': { '*width' : 'int', \
 '*height' : 'int', \
 '*cols' : 'int', \
 '*rows' : 'int' } }", "type", "ChardevVC"},
{"{ 'type': 'ChardevMemory', 'data': { '*size' : 'int' } }", "type", "ChardevMemory"},
{"{ 'type': 'ChardevDummy', 'data': { } }", "type", "ChardevDummy"},
{"{ 'union': 'ChardevBackend', 'data': { 'file' : 'ChardevFile', \
 'serial' : 'ChardevHostdev', \
 'parallel': 'ChardevHostdev', \
 'pipe' : 'ChardevHostdev', \
 'socket' : 'ChardevSocket', \
 'udp' : 'ChardevUdp', \
 'pty' : 'ChardevDummy', \
 'null' : 'ChardevDummy', \
 'mux' : 'ChardevMux', \
 'msmouse': 'ChardevDummy', \
 'braille': 'ChardevDummy', \
 'stdio' : 'ChardevStdio', \
 'console': 'ChardevDummy', \
 'spicevmc' : 'ChardevSpiceChannel', \
 'spiceport' : 'ChardevSpicePort', \
 'vc' : 'ChardevVC', \
 'memory' : 'ChardevMemory' } }", "union", "ChardevBackend"},
{"{ 'type' : 'ChardevReturn', 'data': { '*pty' : 'str' } }", "type", "ChardevReturn"},
{"{ 'command': 'chardev-add', 'data': {'id' : 'str', \
 'backend' : 'ChardevBackend' }, \
 'returns': 'ChardevReturn' }", "command", "chardev-add"},
{"{ 'command': 'chardev-remove', 'data': {'id': 'str'} }", "command", "chardev-remove"},
{"{ 'enum': 'TpmModel', 'data': [ 'tpm-tis' ] }", "enum", "TpmModel"},
{"{ 'command': 'query-tpm-models', 'returns': ['TpmModel'] }", "command", "query-tpm-models"},
{"{ 'enum': 'TpmType', 'data': [ 'passthrough' ] }", "enum", "TpmType"},
{"{ 'command': 'query-tpm-types', 'returns': ['TpmType'] }", "command", "query-tpm-types"},
{"{ 'type': 'TPMPassthroughOptions', 'data': { '*path' : 'str', \
 '*cancel-path' : 'str'} }", "type", "TPMPassthroughOptions"},
{"{ 'union': 'TpmTypeOptions', \
 'data': { 'passthrough' : 'TPMPassthroughOptions' } }", "union", "TpmTypeOptions"},
{"{ 'type': 'TPMInfo', \
 'data': {'id': 'str', \
 'model': 'TpmModel', \
 'options': 'TpmTypeOptions' } }", "type", "TPMInfo"},
{"{ 'command': 'query-tpm', 'returns': ['TPMInfo'] }", "command", "query-tpm"},
{"{ 'type': 'AcpiTableOptions', \
 'data': { \
 '*sig': 'str', \
 '*rev': 'uint8', \
 '*oem_id': 'str', \
 '*oem_table_id': 'str', \
 '*oem_rev': 'uint32', \
 '*asl_compiler_id': 'str', \
 '*asl_compiler_rev': 'uint32', \
 '*file': 'str', \
 '*data': 'str' }}", "type", "AcpiTableOptions"},
{"{ 'enum': 'CommandLineParameterType', \
 'data': ['string', 'boolean', 'number', 'size'] }", "enum", "CommandLineParameterType"},
{"{ 'type': 'CommandLineParameterInfo', \
 'data': { 'name': 'str', \
 'type': 'CommandLineParameterType', \
 '*help': 'str' } }", "type", "CommandLineParameterInfo"},
{"{ 'type': 'CommandLineOptionInfo', \
 'data': { 'option': 'str', 'parameters': ['CommandLineParameterInfo'] } }", "type", "CommandLineOptionInfo"},
{"{'command': 'query-command-line-options', 'data': { '*option': 'str' }, \
 'returns': ['CommandLineOptionInfo'] }", "command", "query-command-line-options"},
{"{ 'enum': 'X86CPURegister32', \
 'data': [ 'EAX', 'EBX', 'ECX', 'EDX', 'ESP', 'EBP', 'ESI', 'EDI' ] }", "enum", "X86CPURegister32"},
{"{ 'type': 'X86CPUFeatureWordInfo', \
 'data': { 'cpuid-input-eax': 'int', \
 '*cpuid-input-ecx': 'int', \
 'cpuid-register': 'X86CPURegister32', \
 'features': 'int' } }", "type", "X86CPUFeatureWordInfo"},
{"{ 'command': 'query-qmp-schema', 'data': { '*type': 'str', '*name': 'str' }, \
 'returns': ['str'] }", "command", "query-qmp-schema"},
{NULL, NULL, NULL } };

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] RFC: Full introspection support for QMP (with draft patch)
  2013-06-07 10:12 ` [Qemu-devel] RFC: Full introspection support for QMP (with draft patch) Amos Kong
@ 2013-06-07 10:17   ` Amos Kong
  2013-06-14  9:52     ` Amos Kong
  0 siblings, 1 reply; 19+ messages in thread
From: Amos Kong @ 2013-06-07 10:17 UTC (permalink / raw)
  To: qemu-devel
  Cc: lcapitulino, qiaonuohan, Ronen Hod, aliguori, Markus Armbruster

[-- Attachment #1: Type: text/plain, Size: 987 bytes --]

On Fri, Jun 07, 2013 at 06:12:30PM +0800, Amos Kong wrote:
> Sent out a draft patch in the end of this week. It doesn't support:
> * output all stuffs in one shot.
> * introspect event
> * provide metadata date
> 
> How can we define a dynamic dict in qmp-schema.json ?
> 
> Currently I just output the raw json dict by a string, Libvirt needs
> parse two times, convert the string to json format.
> 
> qmp-schema.h: auto generated head file by qapi script
> 
> Attached some examples.
> * query-qmp-schema-no-param.txt
{'execute': 'query-qmp-schema'}

> * query-qmp-schema-filter-by-name.txt
{"execute": "query-qmp-schema", "arguments": { "name" : "query-name"}}

> * query-qmp-schema-filter-all-command.txt
{'execute': 'query-qmp-schema', 'arguments': {'type': 'command'}}

> * query-qmp-schema-filter-all-type.txt
{'execute': 'query-qmp-schema', 'arguments': {'type': 'type'}}

> * query-qmp-schema-filter-all-enum.txt
{'execute': 'query-qmp-schema', 'arguments': { 'type': 'enum'}}


[-- Attachment #2: query-qmp-schema-no-param.txt --]
[-- Type: text/plain, Size: 22140 bytes --]

{'execute': 'query-qmp-schema'}
{
    "return": [
        "{ 'enum': 'ErrorClass',  'data': [ 'GenericError', 'CommandNotFound', 'DeviceEncrypted',  'DeviceNotActive', 'DeviceNotFound', 'KVMMissingCap' ] }", 
        "{ 'command': 'add_client',  'data': { 'protocol': 'str', 'fdname': 'str', '*skipauth': 'bool',  '*tls': 'bool' } }", 
        "{ 'type': 'NameInfo', 'data': {'*name': 'str'} }", 
        "{ 'command': 'query-name', 'returns': 'NameInfo' }", 
        "{ 'type': 'VersionInfo',  'data': {'qemu': {'major': 'int', 'minor': 'int', 'micro': 'int'},  'package': 'str'} }", 
        "{ 'command': 'query-version', 'returns': 'VersionInfo' }", 
        "{ 'type': 'KvmInfo', 'data': {'enabled': 'bool', 'present': 'bool'} }", 
        "{ 'command': 'query-kvm', 'returns': 'KvmInfo' }", 
        "{ 'enum': 'RunState',  'data': [ 'debug', 'inmigrate', 'internal-error', 'io-error', 'paused',  'postmigrate', 'prelaunch', 'finish-migrate', 'restore-vm',  'running', 'save-vm', 'shutdown', 'suspended', 'watchdog',  'guest-panicked' ] }", 
        "{ 'type': 'SnapshotInfo',  'data': { 'id': 'str', 'name': 'str', 'vm-state-size': 'int',  'date-sec': 'int', 'date-nsec': 'int',  'vm-clock-sec': 'int', 'vm-clock-nsec': 'int' } }", 
        "{ 'type': 'ImageInfo',  'data': {'filename': 'str', 'format': 'str', '*dirty-flag': 'bool',  '*actual-size': 'int', 'virtual-size': 'int',  '*cluster-size': 'int', '*encrypted': 'bool',  '*backing-filename': 'str', '*full-backing-filename': 'str',  '*backing-filename-format': 'str', '*snapshots': ['SnapshotInfo'] } }", 
        "{ 'type': 'ImageCheck',  'data': {'filename': 'str', 'format': 'str', 'check-errors': 'int',  '*image-end-offset': 'int', '*corruptions': 'int', '*leaks': 'int',  '*corruptions-fixed': 'int', '*leaks-fixed': 'int',  '*total-clusters': 'int', '*allocated-clusters': 'int',  '*fragmented-clusters': 'int', '*compressed-clusters': 'int' } }", 
        "{ 'type': 'StatusInfo',  'data': {'running': 'bool', 'singlestep': 'bool', 'status': 'RunState'} }", 
        "{ 'command': 'query-status', 'returns': 'StatusInfo' }", 
        "{ 'type': 'UuidInfo', 'data': {'UUID': 'str'} }", 
        "{ 'command': 'query-uuid', 'returns': 'UuidInfo' }", 
        "{ 'type': 'ChardevInfo', 'data': {'label': 'str', 'filename': 'str'} }", 
        "{ 'command': 'query-chardev', 'returns': ['ChardevInfo'] }", 
        "{ 'enum': 'DataFormat'  'data': [ 'utf8', 'base64' ] }", 
        "{ 'command': 'ringbuf-write',  'data': {'device': 'str', 'data': 'str',  '*format': 'DataFormat'} }", 
        "{ 'command': 'ringbuf-read',  'data': {'device': 'str', 'size': 'int', '*format': 'DataFormat'},  'returns': 'str' }", 
        "{ 'type': 'CommandInfo', 'data': {'name': 'str'} }", 
        "{ 'command': 'query-commands', 'returns': ['CommandInfo'] }", 
        "{ 'type': 'EventInfo', 'data': {'name': 'str'} }", 
        "{ 'command': 'query-events', 'returns': ['EventInfo'] }", 
        "{ 'type': 'MigrationStats',  'data': {'transferred': 'int', 'remaining': 'int', 'total': 'int' ,  'duplicate': 'int', 'skipped': 'int', 'normal': 'int',  'normal-bytes': 'int', 'dirty-pages-rate' : 'int' } }", 
        "{ 'type': 'XBZRLECacheStats',  'data': {'cache-size': 'int', 'bytes': 'int', 'pages': 'int',  'cache-miss': 'int', 'overflow': 'int' } }", 
        "{ 'type': 'MigrationInfo',  'data': {'*status': 'str', '*ram': 'MigrationStats',  '*disk': 'MigrationStats',  '*xbzrle-cache': 'XBZRLECacheStats',  '*total-time': 'int',  '*expected-downtime': 'int',  '*downtime': 'int'} }", 
        "{ 'command': 'query-migrate', 'returns': 'MigrationInfo' }", 
        "{ 'enum': 'MigrationCapability',  'data': ['xbzrle'] }", 
        "{ 'type': 'MigrationCapabilityStatus',  'data': { 'capability' : 'MigrationCapability', 'state' : 'bool' } }", 
        "{ 'command': 'migrate-set-capabilities',  'data': { 'capabilities': ['MigrationCapabilityStatus'] } }", 
        "{ 'command': 'query-migrate-capabilities', 'returns': ['MigrationCapabilityStatus']}", 
        "{ 'type': 'MouseInfo',  'data': {'name': 'str', 'index': 'int', 'current': 'bool',  'absolute': 'bool'} }", 
        "{ 'command': 'query-mice', 'returns': ['MouseInfo'] }", 
        "{ 'type': 'CpuInfo',  'data': {'CPU': 'int', 'current': 'bool', 'halted': 'bool', '*pc': 'int',  '*nip': 'int', '*npc': 'int', '*PC': 'int', 'thread_id': 'int'} }", 
        "{ 'command': 'query-cpus', 'returns': ['CpuInfo'] }", 
        "{ 'type': 'BlockDeviceInfo',  'data': { 'file': 'str', 'ro': 'bool', 'drv': 'str',  '*backing_file': 'str', 'backing_file_depth': 'int',  'encrypted': 'bool', 'encryption_key_missing': 'bool',  'bps': 'int', 'bps_rd': 'int', 'bps_wr': 'int',  'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int'} }", 
        "{ 'enum': 'BlockDeviceIoStatus', 'data': [ 'ok', 'failed', 'nospace' ] }", 
        "{ 'type': 'BlockDirtyInfo',  'data': {'count': 'int', 'granularity': 'int'} }", 
        "{ 'type': 'BlockInfo',  'data': {'device': 'str', 'type': 'str', 'removable': 'bool',  'locked': 'bool', '*inserted': 'BlockDeviceInfo',  '*tray_open': 'bool', '*io-status': 'BlockDeviceIoStatus',  '*dirty': 'BlockDirtyInfo' } }", 
        "{ 'command': 'query-block', 'returns': ['BlockInfo'] }", 
        "{ 'type': 'BlockDeviceStats',  'data': {'rd_bytes': 'int', 'wr_bytes': 'int', 'rd_operations': 'int',  'wr_operations': 'int', 'flush_operations': 'int',  'flush_total_time_ns': 'int', 'wr_total_time_ns': 'int',  'rd_total_time_ns': 'int', 'wr_highest_offset': 'int' } }", 
        "{ 'type': 'BlockStats',  'data': {'*device': 'str', 'stats': 'BlockDeviceStats',  '*parent': 'BlockStats'} }", 
        "{ 'command': 'query-blockstats', 'returns': ['BlockStats'] }", 
        "{ 'type': 'VncClientInfo',  'data': {'host': 'str', 'family': 'str', 'service': 'str',  '*x509_dname': 'str', '*sasl_username': 'str'} }", 
        "{ 'type': 'VncInfo',  'data': {'enabled': 'bool', '*host': 'str', '*family': 'str',  '*service': 'str', '*auth': 'str', '*clients': ['VncClientInfo']} }", 
        "{ 'command': 'query-vnc', 'returns': 'VncInfo' }", 
        "{ 'type': 'SpiceChannel',  'data': {'host': 'str', 'family': 'str', 'port': 'str',  'connection-id': 'int', 'channel-type': 'int', 'channel-id': 'int',  'tls': 'bool'} }", 
        "{ 'enum': 'SpiceQueryMouseMode',  'data': [ 'client', 'server', 'unknown' ] }", 
        "{ 'type': 'SpiceInfo',  'data': {'enabled': 'bool', 'migrated': 'bool', '*host': 'str', '*port': 'int',  '*tls-port': 'int', '*auth': 'str', '*compiled-version': 'str',  'mouse-mode': 'SpiceQueryMouseMode', '*channels': ['SpiceChannel']} }", 
        "{ 'command': 'query-spice', 'returns': 'SpiceInfo' }", 
        "{ 'type': 'BalloonInfo', 'data': {'actual': 'int' } }", 
        "{ 'command': 'query-balloon', 'returns': 'BalloonInfo' }", 
        "{ 'type': 'PciMemoryRange', 'data': {'base': 'int', 'limit': 'int'} }", 
        "{ 'type': 'PciMemoryRegion',  'data': {'bar': 'int', 'type': 'str', 'address': 'int', 'size': 'int',  '*prefetch': 'bool', '*mem_type_64': 'bool' } }", 
        "{ 'type': 'PciBridgeInfo',  'data': {'bus': { 'number': 'int', 'secondary': 'int', 'subordinate': 'int',  'io_range': 'PciMemoryRange',  'memory_range': 'PciMemoryRange',  'prefetchable_range': 'PciMemoryRange' },  '*devices': ['PciDeviceInfo']} }", 
        "{ 'type': 'PciDeviceInfo',  'data': {'bus': 'int', 'slot': 'int', 'function': 'int',  'class_info': {'*desc': 'str', 'class': 'int'},  'id': {'device': 'int', 'vendor': 'int'},  '*irq': 'int', 'qdev_id': 'str', '*pci_bridge': 'PciBridgeInfo',  'regions': ['PciMemoryRegion']} }", 
        "{ 'type': 'PciInfo', 'data': {'bus': 'int', 'devices': ['PciDeviceInfo']} }", 
        "{ 'command': 'query-pci', 'returns': ['PciInfo'] }", 
        "{ 'enum': 'BlockdevOnError',  'data': ['report', 'ignore', 'enospc', 'stop'] }", 
        "{ 'enum': 'MirrorSyncMode',  'data': ['top', 'full', 'none'] }", 
        "{ 'type': 'BlockJobInfo',  'data': {'type': 'str', 'device': 'str', 'len': 'int',  'offset': 'int', 'busy': 'bool', 'paused': 'bool', 'speed': 'int',  'io-status': 'BlockDeviceIoStatus'} }", 
        "{ 'command': 'query-block-jobs', 'returns': ['BlockJobInfo'] }", 
        "{ 'command': 'quit' }", 
        "{ 'command': 'stop' }", 
        "{ 'command': 'system_reset' }", 
        "{ 'command': 'system_powerdown' }", 
        "{ 'command': 'cpu', 'data': {'index': 'int'} }", 
        "{ 'command': 'cpu-add', 'data': {'id': 'int'} }", 
        "{ 'command': 'memsave',  'data': {'val': 'int', 'size': 'int', 'filename': 'str', '*cpu-index': 'int'} }", 
        "{ 'command': 'pmemsave',  'data': {'val': 'int', 'size': 'int', 'filename': 'str'} }", 
        "{ 'command': 'cont' }", 
        "{ 'command': 'system_wakeup' }", 
        "{ 'command': 'inject-nmi' }", 
        "{ 'command': 'set_link', 'data': {'name': 'str', 'up': 'bool'} }", 
        "{ 'command': 'block_passwd', 'data': {'device': 'str', 'password': 'str'} }", 
        "{ 'command': 'balloon', 'data': {'value': 'int'} }", 
        "{ 'command': 'block_resize', 'data': { 'device': 'str', 'size': 'int' }}", 
        "{ 'enum': 'NewImageMode'  'data': [ 'existing', 'absolute-paths' ] }", 
        "{ 'type': 'BlockdevSnapshot',  'data': { 'device': 'str', 'snapshot-file': 'str', '*format': 'str',  '*mode': 'NewImageMode' } }", 
        "{ 'union': 'TransactionAction',  'data': {  'blockdev-snapshot-sync': 'BlockdevSnapshot'  } }", 
        "{ 'command': 'transaction',  'data': { 'actions': [ 'TransactionAction' ] } }", 
        "{ 'command': 'blockdev-snapshot-sync',  'data': { 'device': 'str', 'snapshot-file': 'str', '*format': 'str',  '*mode': 'NewImageMode'} }", 
        "{ 'command': 'human-monitor-command',  'data': {'command-line': 'str', '*cpu-index': 'int'},  'returns': 'str' }", 
        "{ 'command': 'block-commit',  'data': { 'device': 'str', '*base': 'str', 'top': 'str',  '*speed': 'int' } }", 
        "{ 'command': 'drive-mirror',  'data': { 'device': 'str', 'target': 'str', '*format': 'str',  'sync': 'MirrorSyncMode', '*mode': 'NewImageMode',  '*speed': 'int', '*granularity': 'uint32',  '*buf-size': 'int', '*on-source-error': 'BlockdevOnError',  '*on-target-error': 'BlockdevOnError' } }", 
        "{ 'command': 'migrate_cancel' }", 
        "{ 'command': 'migrate_set_downtime', 'data': {'value': 'number'} }", 
        "{ 'command': 'migrate_set_speed', 'data': {'value': 'int'} }", 
        "{ 'command': 'migrate-set-cache-size', 'data': {'value': 'int'} }", 
        "{ 'command': 'query-migrate-cache-size', 'returns': 'int' }", 
        "{ 'type': 'ObjectPropertyInfo',  'data': { 'name': 'str', 'type': 'str' } }", 
        "{ 'command': 'qom-list',  'data': { 'path': 'str' },  'returns': [ 'ObjectPropertyInfo' ] }", 
        "{ 'command': 'qom-get',  'data': { 'path': 'str', 'property': 'str' },  'returns': 'visitor',  'gen': 'no' }", 
        "{ 'command': 'qom-set',  'data': { 'path': 'str', 'property': 'str', 'value': 'visitor' },  'gen': 'no' }", 
        "{ 'command': 'set_password',  'data': {'protocol': 'str', 'password': 'str', '*connected': 'str'} }", 
        "{ 'command': 'expire_password', 'data': {'protocol': 'str', 'time': 'str'} }", 
        "{ 'command': 'eject', 'data': {'device': 'str', '*force': 'bool'} }", 
        "{ 'command': 'change-vnc-password', 'data': {'password': 'str'} }", 
        "{ 'command': 'change',  'data': {'device': 'str', 'target': 'str', '*arg': 'str'} }", 
        "{ 'command': 'block_set_io_throttle',  'data': { 'device': 'str', 'bps': 'int', 'bps_rd': 'int', 'bps_wr': 'int',  'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int' } }", 
        "{ 'command': 'block-stream',  'data': { 'device': 'str', '*base': 'str', '*speed': 'int',  '*on-error': 'BlockdevOnError' } }", 
        "{ 'command': 'block-job-set-speed',  'data': { 'device': 'str', 'speed': 'int' } }", 
        "{ 'command': 'block-job-cancel', 'data': { 'device': 'str', '*force': 'bool' } }", 
        "{ 'command': 'block-job-pause', 'data': { 'device': 'str' } }", 
        "{ 'command': 'block-job-resume', 'data': { 'device': 'str' } }", 
        "{ 'command': 'block-job-complete', 'data': { 'device': 'str' } }", 
        "{ 'type': 'ObjectTypeInfo',  'data': { 'name': 'str' } }", 
        "{ 'command': 'qom-list-types',  'data': { '*implements': 'str', '*abstract': 'bool' },  'returns': [ 'ObjectTypeInfo' ] }", 
        "{ 'type': 'DevicePropertyInfo',  'data': { 'name': 'str', 'type': 'str' } }", 
        "{ 'command': 'device-list-properties',  'data': { 'typename': 'str'},  'returns': [ 'DevicePropertyInfo' ] }", 
        "{ 'command': 'migrate',  'data': {'uri': 'str', '*blk': 'bool', '*inc': 'bool', '*detach': 'bool' } }", 
        "{ 'command': 'xen-save-devices-state', 'data': {'filename': 'str'} }", 
        "{ 'command': 'xen-set-global-dirty-log', 'data': { 'enable': 'bool' } }", 
        "{ 'command': 'device_del', 'data': {'id': 'str'} }", 
        "{ 'command': 'dump-guest-memory',  'data': { 'paging': 'bool', 'protocol': 'str', '*begin': 'int',  '*length': 'int' } }", 
        "{ 'command': 'netdev_add',  'data': {'type': 'str', 'id': 'str', '*props': '**'},  'gen': 'no' }", 
        "{ 'command': 'netdev_del', 'data': {'id': 'str'} }", 
        "{ 'type': 'NetdevNoneOptions',  'data': { } }", 
        "{ 'type': 'NetLegacyNicOptions',  'data': {  '*netdev': 'str',  '*macaddr': 'str',  '*model': 'str',  '*addr': 'str',  '*vectors': 'uint32' } }", 
        "{ 'type': 'String',  'data': {  'str': 'str' } }", 
        "{ 'type': 'NetdevUserOptions',  'data': {  '*hostname': 'str',  '*restrict': 'bool',  '*ip': 'str',  '*net': 'str',  '*host': 'str',  '*tftp': 'str',  '*bootfile': 'str',  '*dhcpstart': 'str',  '*dns': 'str',  '*dnssearch': ['String'],  '*smb': 'str',  '*smbserver': 'str',  '*hostfwd': ['String'],  '*guestfwd': ['String'] } }", 
        "{ 'type': 'NetdevTapOptions',  'data': {  '*ifname': 'str',  '*fd': 'str',  '*fds': 'str',  '*script': 'str',  '*downscript': 'str',  '*helper': 'str',  '*sndbuf': 'size',  '*vnet_hdr': 'bool',  '*vhost': 'bool',  '*vhostfd': 'str',  '*vhostfds': 'str',  '*vhostforce': 'bool',  '*queues': 'uint32'} }", 
        "{ 'type': 'NetdevSocketOptions',  'data': {  '*fd': 'str',  '*listen': 'str',  '*connect': 'str',  '*mcast': 'str',  '*localaddr': 'str',  '*udp': 'str' } }", 
        "{ 'type': 'NetdevVdeOptions',  'data': {  '*sock': 'str',  '*port': 'uint16',  '*group': 'str',  '*mode': 'uint16' } }", 
        "{ 'type': 'NetdevDumpOptions',  'data': {  '*len': 'size',  '*file': 'str' } }", 
        "{ 'type': 'NetdevBridgeOptions',  'data': {  '*br': 'str',  '*helper': 'str' } }", 
        "{ 'type': 'NetdevHubPortOptions',  'data': {  'hubid': 'int32' } }", 
        "{ 'union': 'NetClientOptions',  'data': {  'none': 'NetdevNoneOptions',  'nic': 'NetLegacyNicOptions',  'user': 'NetdevUserOptions',  'tap': 'NetdevTapOptions',  'socket': 'NetdevSocketOptions',  'vde': 'NetdevVdeOptions',  'dump': 'NetdevDumpOptions',  'bridge': 'NetdevBridgeOptions',  'hubport': 'NetdevHubPortOptions' } }", 
        "{ 'type': 'NetLegacy',  'data': {  '*vlan': 'int32',  '*id': 'str',  '*name': 'str',  'opts': 'NetClientOptions' } }", 
        "{ 'type': 'Netdev',  'data': {  'id': 'str',  'opts': 'NetClientOptions' } }", 
        "{ 'type': 'InetSocketAddress',  'data': {  'host': 'str',  'port': 'str',  '*to': 'uint16',  '*ipv4': 'bool',  '*ipv6': 'bool' } }", 
        "{ 'type': 'UnixSocketAddress',  'data': {  'path': 'str' } }", 
        "{ 'union': 'SocketAddress',  'data': {  'inet': 'InetSocketAddress',  'unix': 'UnixSocketAddress',  'fd': 'String' } }", 
        "{ 'command': 'getfd', 'data': {'fdname': 'str'} }", 
        "{ 'command': 'closefd', 'data': {'fdname': 'str'} }", 
        "{ 'command': 'query-machines', 'returns': ['MachineInfo'] }", 
        "{ 'type': 'CpuDefinitionInfo',  'data': { 'name': 'str' } }", 
        "{ 'command': 'query-cpu-definitions', 'returns': ['CpuDefinitionInfo'] }", 
        "{ 'type': 'AddfdInfo', 'data': {'fdset-id': 'int', 'fd': 'int'} }", 
        "{ 'command': 'add-fd', 'data': {'*fdset-id': 'int', '*opaque': 'str'},  'returns': 'AddfdInfo' }", 
        "{ 'command': 'remove-fd', 'data': {'fdset-id': 'int', '*fd': 'int'} }", 
        "{ 'type': 'FdsetFdInfo',  'data': {'fd': 'int', '*opaque': 'str'} }", 
        "{ 'type': 'FdsetInfo',  'data': {'fdset-id': 'int', 'fds': ['FdsetFdInfo']} }", 
        "{ 'command': 'query-fdsets', 'returns': ['FdsetInfo'] }", 
        "{ 'enum': 'TargetType',  'data': [ 'alpha', 'arm', 'cris', 'i386', 'lm32', 'm68k', 'microblazeel',  'microblaze', 'mips64el', 'mips64', 'mipsel', 'mips', 'moxie',  'or32', 'ppc64', 'ppcemb', 'ppc', 's390x', 'sh4eb', 'sh4',  'sparc64', 'sparc', 'unicore32', 'x86_64', 'xtensaeb', 'xtensa' ] }", 
        "{ 'type': 'TargetInfo',  'data': { 'arch': 'TargetType' } }", 
        "{ 'command': 'query-target', 'returns': 'TargetInfo' }", 
        "{ 'enum': 'QKeyCode',  'data': [ 'shift', 'shift_r', 'alt', 'alt_r', 'altgr', 'altgr_r', 'ctrl',  'ctrl_r', 'menu', 'esc', '1', '2', '3', '4', '5', '6', '7', '8',  '9', '0', 'minus', 'equal', 'backspace', 'tab', 'q', 'w', 'e',  'r', 't', 'y', 'u', 'i', 'o', 'p', 'bracket_left', 'bracket_right',  'ret', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'semicolon',  'apostrophe', 'grave_accent', 'backslash', 'z', 'x', 'c', 'v', 'b',  'n', 'm', 'comma', 'dot', 'slash', 'asterisk', 'spc', 'caps_lock',  'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'f10',  'num_lock', 'scroll_lock', 'kp_divide', 'kp_multiply',  'kp_subtract', 'kp_add', 'kp_enter', 'kp_decimal', 'sysrq', 'kp_0',  'kp_1', 'kp_2', 'kp_3', 'kp_4', 'kp_5', 'kp_6', 'kp_7', 'kp_8',  'kp_9', 'less', 'f11', 'f12', 'print', 'home', 'pgup', 'pgdn', 'end',  'left', 'up', 'down', 'right', 'insert', 'delete', 'stop', 'again',  'props', 'undo', 'front', 'copy', 'open', 'paste', 'find', 'cut',  'lf', 'help', 'meta_l', 'meta_r', 'compose' ] }", 
        "{ 'union': 'KeyValue',  'data': {  'number': 'int',  'qcode': 'QKeyCode' } }", 
        "{ 'command': 'send-key',  'data': { 'keys': ['KeyValue'], '*hold-time': 'int' } }", 
        "{ 'command': 'screendump', 'data': {'filename': 'str'} }", 
        "{ 'command': 'nbd-server-start',  'data': { 'addr': 'SocketAddress' } }", 
        "{ 'command': 'nbd-server-add', 'data': {'device': 'str', '*writable': 'bool'} }", 
        "{ 'command': 'nbd-server-stop' }", 
        "{ 'type': 'ChardevFile', 'data': { '*in' : 'str',  'out' : 'str' } }", 
        "{ 'type': 'ChardevHostdev', 'data': { 'device' : 'str' } }", 
        "{ 'type': 'ChardevSocket', 'data': { 'addr' : 'SocketAddress',  '*server' : 'bool',  '*wait' : 'bool',  '*nodelay' : 'bool',  '*telnet' : 'bool' } }", 
        "{ 'type': 'ChardevUdp', 'data': { 'remote' : 'SocketAddress',  '*local' : 'SocketAddress' } }", 
        "{ 'type': 'ChardevMux', 'data': { 'chardev' : 'str' } }", 
        "{ 'type': 'ChardevStdio', 'data': { '*signal' : 'bool' } }", 
        "{ 'type': 'ChardevSpiceChannel', 'data': { 'type' : 'str' } }", 
        "{ 'type': 'ChardevSpicePort', 'data': { 'fqdn' : 'str' } }", 
        "{ 'type': 'ChardevVC', 'data': { '*width' : 'int',  '*height' : 'int',  '*cols' : 'int',  '*rows' : 'int' } }", 
        "{ 'type': 'ChardevMemory', 'data': { '*size' : 'int' } }", 
        "{ 'type': 'ChardevDummy', 'data': { } }", 
        "{ 'union': 'ChardevBackend', 'data': { 'file' : 'ChardevFile',  'serial' : 'ChardevHostdev',  'parallel': 'ChardevHostdev',  'pipe' : 'ChardevHostdev',  'socket' : 'ChardevSocket',  'udp' : 'ChardevUdp',  'pty' : 'ChardevDummy',  'null' : 'ChardevDummy',  'mux' : 'ChardevMux',  'msmouse': 'ChardevDummy',  'braille': 'ChardevDummy',  'stdio' : 'ChardevStdio',  'console': 'ChardevDummy',  'spicevmc' : 'ChardevSpiceChannel',  'spiceport' : 'ChardevSpicePort',  'vc' : 'ChardevVC',  'memory' : 'ChardevMemory' } }", 
        "{ 'type' : 'ChardevReturn', 'data': { '*pty' : 'str' } }", 
        "{ 'command': 'chardev-add', 'data': {'id' : 'str',  'backend' : 'ChardevBackend' },  'returns': 'ChardevReturn' }", 
        "{ 'command': 'chardev-remove', 'data': {'id': 'str'} }", 
        "{ 'enum': 'TpmModel', 'data': [ 'tpm-tis' ] }", 
        "{ 'command': 'query-tpm-models', 'returns': ['TpmModel'] }", 
        "{ 'enum': 'TpmType', 'data': [ 'passthrough' ] }", 
        "{ 'command': 'query-tpm-types', 'returns': ['TpmType'] }", 
        "{ 'type': 'TPMPassthroughOptions', 'data': { '*path' : 'str',  '*cancel-path' : 'str'} }", 
        "{ 'union': 'TpmTypeOptions',  'data': { 'passthrough' : 'TPMPassthroughOptions' } }", 
        "{ 'type': 'TPMInfo',  'data': {'id': 'str',  'model': 'TpmModel',  'options': 'TpmTypeOptions' } }", 
        "{ 'command': 'query-tpm', 'returns': ['TPMInfo'] }", 
        "{ 'type': 'AcpiTableOptions',  'data': {  '*sig': 'str',  '*rev': 'uint8',  '*oem_id': 'str',  '*oem_table_id': 'str',  '*oem_rev': 'uint32',  '*asl_compiler_id': 'str',  '*asl_compiler_rev': 'uint32',  '*file': 'str',  '*data': 'str' }}", 
        "{ 'enum': 'CommandLineParameterType',  'data': ['string', 'boolean', 'number', 'size'] }", 
        "{ 'type': 'CommandLineParameterInfo',  'data': { 'name': 'str',  'type': 'CommandLineParameterType',  '*help': 'str' } }", 
        "{ 'type': 'CommandLineOptionInfo',  'data': { 'option': 'str', 'parameters': ['CommandLineParameterInfo'] } }", 
        "{'command': 'query-command-line-options', 'data': { '*option': 'str' },  'returns': ['CommandLineOptionInfo'] }", 
        "{ 'enum': 'X86CPURegister32',  'data': [ 'EAX', 'EBX', 'ECX', 'EDX', 'ESP', 'EBP', 'ESI', 'EDI' ] }", 
        "{ 'type': 'X86CPUFeatureWordInfo',  'data': { 'cpuid-input-eax': 'int',  '*cpuid-input-ecx': 'int',  'cpuid-register': 'X86CPURegister32',  'features': 'int' } }", 
        "{ 'command': 'query-qmp-schema', 'data': { '*type': 'str', '*name': 'str' },  'returns': ['str'] }"
    ]
}


[-- Attachment #3: query-qmp-schema-filter-by-name.txt --]
[-- Type: text/plain, Size: 160 bytes --]

{"execute": "query-qmp-schema", "arguments": { "name" : "query-name" }}
{
    "return": [
        "{ 'command': 'query-name', 'returns': 'NameInfo' }"
    ]
}


[-- Attachment #4: query-qmp-schema-filter-all-command.txt --]
[-- Type: text/plain, Size: 7910 bytes --]

{'execute': 'query-qmp-schema', 'arguments': {'type': 'command'}}
{
    "return": [
        "{ 'command': 'add_client',  'data': { 'protocol': 'str', 'fdname': 'str', '*skipauth': 'bool',  '*tls': 'bool' } }", 
        "{ 'command': 'query-name', 'returns': 'NameInfo' }", 
        "{ 'command': 'query-version', 'returns': 'VersionInfo' }", 
        "{ 'command': 'query-kvm', 'returns': 'KvmInfo' }", 
        "{ 'command': 'query-status', 'returns': 'StatusInfo' }", 
        "{ 'command': 'query-uuid', 'returns': 'UuidInfo' }", 
        "{ 'command': 'query-chardev', 'returns': ['ChardevInfo'] }", 
        "{ 'command': 'ringbuf-write',  'data': {'device': 'str', 'data': 'str',  '*format': 'DataFormat'} }", 
        "{ 'command': 'ringbuf-read',  'data': {'device': 'str', 'size': 'int', '*format': 'DataFormat'},  'returns': 'str' }", 
        "{ 'command': 'query-commands', 'returns': ['CommandInfo'] }", 
        "{ 'command': 'query-events', 'returns': ['EventInfo'] }", 
        "{ 'command': 'query-migrate', 'returns': 'MigrationInfo' }", 
        "{ 'command': 'migrate-set-capabilities',  'data': { 'capabilities': ['MigrationCapabilityStatus'] } }", 
        "{ 'command': 'query-migrate-capabilities', 'returns': ['MigrationCapabilityStatus']}", 
        "{ 'command': 'query-mice', 'returns': ['MouseInfo'] }", 
        "{ 'command': 'query-cpus', 'returns': ['CpuInfo'] }", 
        "{ 'command': 'query-block', 'returns': ['BlockInfo'] }", 
        "{ 'command': 'query-blockstats', 'returns': ['BlockStats'] }", 
        "{ 'command': 'query-vnc', 'returns': 'VncInfo' }", 
        "{ 'command': 'query-spice', 'returns': 'SpiceInfo' }", 
        "{ 'command': 'query-balloon', 'returns': 'BalloonInfo' }", 
        "{ 'command': 'query-pci', 'returns': ['PciInfo'] }", 
        "{ 'command': 'query-block-jobs', 'returns': ['BlockJobInfo'] }", 
        "{ 'command': 'quit' }", 
        "{ 'command': 'stop' }", 
        "{ 'command': 'system_reset' }", 
        "{ 'command': 'system_powerdown' }", 
        "{ 'command': 'cpu', 'data': {'index': 'int'} }", 
        "{ 'command': 'cpu-add', 'data': {'id': 'int'} }", 
        "{ 'command': 'memsave',  'data': {'val': 'int', 'size': 'int', 'filename': 'str', '*cpu-index': 'int'} }", 
        "{ 'command': 'pmemsave',  'data': {'val': 'int', 'size': 'int', 'filename': 'str'} }", 
        "{ 'command': 'cont' }", 
        "{ 'command': 'system_wakeup' }", 
        "{ 'command': 'inject-nmi' }", 
        "{ 'command': 'block_passwd', 'data': {'device': 'str', 'password': 'str'} }", 
        "{ 'command': 'balloon', 'data': {'value': 'int'} }", 
        "{ 'command': 'block_resize', 'data': { 'device': 'str', 'size': 'int' }}", 
        "{ 'command': 'transaction',  'data': { 'actions': [ 'TransactionAction' ] } }", 
        "{ 'command': 'blockdev-snapshot-sync',  'data': { 'device': 'str', 'snapshot-file': 'str', '*format': 'str',  '*mode': 'NewImageMode'} }", 
        "{ 'command': 'human-monitor-command',  'data': {'command-line': 'str', '*cpu-index': 'int'},  'returns': 'str' }", 
        "{ 'command': 'block-commit',  'data': { 'device': 'str', '*base': 'str', 'top': 'str',  '*speed': 'int' } }", 
        "{ 'command': 'drive-mirror',  'data': { 'device': 'str', 'target': 'str', '*format': 'str',  'sync': 'MirrorSyncMode', '*mode': 'NewImageMode',  '*speed': 'int', '*granularity': 'uint32',  '*buf-size': 'int', '*on-source-error': 'BlockdevOnError',  '*on-target-error': 'BlockdevOnError' } }", 
        "{ 'command': 'migrate_cancel' }", 
        "{ 'command': 'migrate_set_downtime', 'data': {'value': 'number'} }", 
        "{ 'command': 'migrate_set_speed', 'data': {'value': 'int'} }", 
        "{ 'command': 'migrate-set-cache-size', 'data': {'value': 'int'} }", 
        "{ 'command': 'query-migrate-cache-size', 'returns': 'int' }", 
        "{ 'command': 'qom-list',  'data': { 'path': 'str' },  'returns': [ 'ObjectPropertyInfo' ] }", 
        "{ 'command': 'qom-get',  'data': { 'path': 'str', 'property': 'str' },  'returns': 'visitor',  'gen': 'no' }", 
        "{ 'command': 'qom-set',  'data': { 'path': 'str', 'property': 'str', 'value': 'visitor' },  'gen': 'no' }", 
        "{ 'command': 'set_password',  'data': {'protocol': 'str', 'password': 'str', '*connected': 'str'} }", 
        "{ 'command': 'expire_password', 'data': {'protocol': 'str', 'time': 'str'} }", 
        "{ 'command': 'eject', 'data': {'device': 'str', '*force': 'bool'} }", 
        "{ 'command': 'change-vnc-password', 'data': {'password': 'str'} }", 
        "{ 'command': 'change',  'data': {'device': 'str', 'target': 'str', '*arg': 'str'} }", 
        "{ 'command': 'block_set_io_throttle',  'data': { 'device': 'str', 'bps': 'int', 'bps_rd': 'int', 'bps_wr': 'int',  'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int' } }", 
        "{ 'command': 'block-stream',  'data': { 'device': 'str', '*base': 'str', '*speed': 'int',  '*on-error': 'BlockdevOnError' } }", 
        "{ 'command': 'block-job-set-speed',  'data': { 'device': 'str', 'speed': 'int' } }", 
        "{ 'command': 'block-job-cancel', 'data': { 'device': 'str', '*force': 'bool' } }", 
        "{ 'command': 'block-job-pause', 'data': { 'device': 'str' } }", 
        "{ 'command': 'block-job-resume', 'data': { 'device': 'str' } }", 
        "{ 'command': 'block-job-complete', 'data': { 'device': 'str' } }", 
        "{ 'command': 'qom-list-types',  'data': { '*implements': 'str', '*abstract': 'bool' },  'returns': [ 'ObjectTypeInfo' ] }", 
        "{ 'command': 'device-list-properties',  'data': { 'typename': 'str'},  'returns': [ 'DevicePropertyInfo' ] }", 
        "{ 'command': 'migrate',  'data': {'uri': 'str', '*blk': 'bool', '*inc': 'bool', '*detach': 'bool' } }", 
        "{ 'command': 'xen-save-devices-state', 'data': {'filename': 'str'} }", 
        "{ 'command': 'xen-set-global-dirty-log', 'data': { 'enable': 'bool' } }", 
        "{ 'command': 'device_del', 'data': {'id': 'str'} }", 
        "{ 'command': 'dump-guest-memory',  'data': { 'paging': 'bool', 'protocol': 'str', '*begin': 'int',  '*length': 'int' } }", 
        "{ 'command': 'netdev_add',  'data': {'type': 'str', 'id': 'str', '*props': '**'},  'gen': 'no' }", 
        "{ 'command': 'netdev_del', 'data': {'id': 'str'} }", 
        "{ 'command': 'getfd', 'data': {'fdname': 'str'} }", 
        "{ 'command': 'closefd', 'data': {'fdname': 'str'} }", 
        "{ 'command': 'query-machines', 'returns': ['MachineInfo'] }", 
        "{ 'command': 'query-cpu-definitions', 'returns': ['CpuDefinitionInfo'] }", 
        "{ 'command': 'add-fd', 'data': {'*fdset-id': 'int', '*opaque': 'str'},  'returns': 'AddfdInfo' }", 
        "{ 'command': 'remove-fd', 'data': {'fdset-id': 'int', '*fd': 'int'} }", 
        "{ 'command': 'query-fdsets', 'returns': ['FdsetInfo'] }", 
        "{ 'command': 'query-target', 'returns': 'TargetInfo' }", 
        "{ 'command': 'send-key',  'data': { 'keys': ['KeyValue'], '*hold-time': 'int' } }", 
        "{ 'command': 'screendump', 'data': {'filename': 'str'} }", 
        "{ 'command': 'nbd-server-start',  'data': { 'addr': 'SocketAddress' } }", 
        "{ 'command': 'nbd-server-add', 'data': {'device': 'str', '*writable': 'bool'} }", 
        "{ 'command': 'nbd-server-stop' }", 
        "{ 'command': 'chardev-add', 'data': {'id' : 'str',  'backend' : 'ChardevBackend' },  'returns': 'ChardevReturn' }", 
        "{ 'command': 'chardev-remove', 'data': {'id': 'str'} }", 
        "{ 'command': 'query-tpm-models', 'returns': ['TpmModel'] }", 
        "{ 'command': 'query-tpm-types', 'returns': ['TpmType'] }", 
        "{ 'command': 'query-tpm', 'returns': ['TPMInfo'] }", 
        "{'command': 'query-command-line-options', 'data': { '*option': 'str' },  'returns': ['CommandLineOptionInfo'] }", 
        "{ 'command': 'query-qmp-schema', 'data': { '*type': 'str', '*name': 'str' },  'returns': ['str'] }"
    ]
}


[-- Attachment #5: query-qmp-schema-filter-all-enum.txt --]
[-- Type: text/plain, Size: 2730 bytes --]

{'execute': 'query-qmp-schema', 'arguments': { 'type': 'enum'}}
{
    "return": [
        "{ 'enum': 'ErrorClass',  'data': [ 'GenericError', 'CommandNotFound', 'DeviceEncrypted',  'DeviceNotActive', 'DeviceNotFound', 'KVMMissingCap' ] }", 
        "{ 'enum': 'RunState',  'data': [ 'debug', 'inmigrate', 'internal-error', 'io-error', 'paused',  'postmigrate', 'prelaunch', 'finish-migrate', 'restore-vm',  'running', 'save-vm', 'shutdown', 'suspended', 'watchdog',  'guest-panicked' ] }", 
        "{ 'enum': 'DataFormat'  'data': [ 'utf8', 'base64' ] }", 
        "{ 'enum': 'MigrationCapability',  'data': ['xbzrle'] }", 
        "{ 'enum': 'BlockDeviceIoStatus', 'data': [ 'ok', 'failed', 'nospace' ] }", 
        "{ 'enum': 'SpiceQueryMouseMode',  'data': [ 'client', 'server', 'unknown' ] }", 
        "{ 'enum': 'BlockdevOnError',  'data': ['report', 'ignore', 'enospc', 'stop'] }", 
        "{ 'enum': 'MirrorSyncMode',  'data': ['top', 'full', 'none'] }", 
        "{ 'enum': 'NewImageMode'  'data': [ 'existing', 'absolute-paths' ] }", 
        "{ 'enum': 'TargetType',  'data': [ 'alpha', 'arm', 'cris', 'i386', 'lm32', 'm68k', 'microblazeel',  'microblaze', 'mips64el', 'mips64', 'mipsel', 'mips', 'moxie',  'or32', 'ppc64', 'ppcemb', 'ppc', 's390x', 'sh4eb', 'sh4',  'sparc64', 'sparc', 'unicore32', 'x86_64', 'xtensaeb', 'xtensa' ] }", 
        "{ 'enum': 'QKeyCode',  'data': [ 'shift', 'shift_r', 'alt', 'alt_r', 'altgr', 'altgr_r', 'ctrl',  'ctrl_r', 'menu', 'esc', '1', '2', '3', '4', '5', '6', '7', '8',  '9', '0', 'minus', 'equal', 'backspace', 'tab', 'q', 'w', 'e',  'r', 't', 'y', 'u', 'i', 'o', 'p', 'bracket_left', 'bracket_right',  'ret', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'semicolon',  'apostrophe', 'grave_accent', 'backslash', 'z', 'x', 'c', 'v', 'b',  'n', 'm', 'comma', 'dot', 'slash', 'asterisk', 'spc', 'caps_lock',  'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'f10',  'num_lock', 'scroll_lock', 'kp_divide', 'kp_multiply',  'kp_subtract', 'kp_add', 'kp_enter', 'kp_decimal', 'sysrq', 'kp_0',  'kp_1', 'kp_2', 'kp_3', 'kp_4', 'kp_5', 'kp_6', 'kp_7', 'kp_8',  'kp_9', 'less', 'f11', 'f12', 'print', 'home', 'pgup', 'pgdn', 'end',  'left', 'up', 'down', 'right', 'insert', 'delete', 'stop', 'again',  'props', 'undo', 'front', 'copy', 'open', 'paste', 'find', 'cut',  'lf', 'help', 'meta_l', 'meta_r', 'compose' ] }", 
        "{ 'enum': 'TpmModel', 'data': [ 'tpm-tis' ] }", 
        "{ 'enum': 'TpmType', 'data': [ 'passthrough' ] }", 
        "{ 'enum': 'CommandLineParameterType',  'data': ['string', 'boolean', 'number', 'size'] }", 
        "{ 'enum': 'X86CPURegister32',  'data': [ 'EAX', 'EBX', 'ECX', 'EDX', 'ESP', 'EBP', 'ESI', 'EDI' ] }"
    ]
}


[-- Attachment #6: query-qmp-schema-filter-all-type.txt --]
[-- Type: text/plain, Size: 10136 bytes --]

{'execute': 'query-qmp-schema', 'arguments': {'type': 'type'}}
{
    "return": [
        "{ 'type': 'NameInfo', 'data': {'*name': 'str'} }", 
        "{ 'type': 'VersionInfo',  'data': {'qemu': {'major': 'int', 'minor': 'int', 'micro': 'int'},  'package': 'str'} }", 
        "{ 'type': 'KvmInfo', 'data': {'enabled': 'bool', 'present': 'bool'} }", 
        "{ 'type': 'SnapshotInfo',  'data': { 'id': 'str', 'name': 'str', 'vm-state-size': 'int',  'date-sec': 'int', 'date-nsec': 'int',  'vm-clock-sec': 'int', 'vm-clock-nsec': 'int' } }", 
        "{ 'type': 'ImageInfo',  'data': {'filename': 'str', 'format': 'str', '*dirty-flag': 'bool',  '*actual-size': 'int', 'virtual-size': 'int',  '*cluster-size': 'int', '*encrypted': 'bool',  '*backing-filename': 'str', '*full-backing-filename': 'str',  '*backing-filename-format': 'str', '*snapshots': ['SnapshotInfo'] } }", 
        "{ 'type': 'ImageCheck',  'data': {'filename': 'str', 'format': 'str', 'check-errors': 'int',  '*image-end-offset': 'int', '*corruptions': 'int', '*leaks': 'int',  '*corruptions-fixed': 'int', '*leaks-fixed': 'int',  '*total-clusters': 'int', '*allocated-clusters': 'int',  '*fragmented-clusters': 'int', '*compressed-clusters': 'int' } }", 
        "{ 'type': 'StatusInfo',  'data': {'running': 'bool', 'singlestep': 'bool', 'status': 'RunState'} }", 
        "{ 'type': 'UuidInfo', 'data': {'UUID': 'str'} }", 
        "{ 'type': 'ChardevInfo', 'data': {'label': 'str', 'filename': 'str'} }", 
        "{ 'type': 'CommandInfo', 'data': {'name': 'str'} }", 
        "{ 'type': 'EventInfo', 'data': {'name': 'str'} }", 
        "{ 'type': 'MigrationStats',  'data': {'transferred': 'int', 'remaining': 'int', 'total': 'int' ,  'duplicate': 'int', 'skipped': 'int', 'normal': 'int',  'normal-bytes': 'int', 'dirty-pages-rate' : 'int' } }", 
        "{ 'type': 'XBZRLECacheStats',  'data': {'cache-size': 'int', 'bytes': 'int', 'pages': 'int',  'cache-miss': 'int', 'overflow': 'int' } }", 
        "{ 'type': 'MigrationInfo',  'data': {'*status': 'str', '*ram': 'MigrationStats',  '*disk': 'MigrationStats',  '*xbzrle-cache': 'XBZRLECacheStats',  '*total-time': 'int',  '*expected-downtime': 'int',  '*downtime': 'int'} }", 
        "{ 'type': 'MigrationCapabilityStatus',  'data': { 'capability' : 'MigrationCapability', 'state' : 'bool' } }", 
        "{ 'type': 'MouseInfo',  'data': {'name': 'str', 'index': 'int', 'current': 'bool',  'absolute': 'bool'} }", 
        "{ 'type': 'CpuInfo',  'data': {'CPU': 'int', 'current': 'bool', 'halted': 'bool', '*pc': 'int',  '*nip': 'int', '*npc': 'int', '*PC': 'int', 'thread_id': 'int'} }", 
        "{ 'type': 'BlockDeviceInfo',  'data': { 'file': 'str', 'ro': 'bool', 'drv': 'str',  '*backing_file': 'str', 'backing_file_depth': 'int',  'encrypted': 'bool', 'encryption_key_missing': 'bool',  'bps': 'int', 'bps_rd': 'int', 'bps_wr': 'int',  'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int'} }", 
        "{ 'type': 'BlockDirtyInfo',  'data': {'count': 'int', 'granularity': 'int'} }", 
        "{ 'type': 'BlockInfo',  'data': {'device': 'str', 'type': 'str', 'removable': 'bool',  'locked': 'bool', '*inserted': 'BlockDeviceInfo',  '*tray_open': 'bool', '*io-status': 'BlockDeviceIoStatus',  '*dirty': 'BlockDirtyInfo' } }", 
        "{ 'type': 'BlockDeviceStats',  'data': {'rd_bytes': 'int', 'wr_bytes': 'int', 'rd_operations': 'int',  'wr_operations': 'int', 'flush_operations': 'int',  'flush_total_time_ns': 'int', 'wr_total_time_ns': 'int',  'rd_total_time_ns': 'int', 'wr_highest_offset': 'int' } }", 
        "{ 'type': 'BlockStats',  'data': {'*device': 'str', 'stats': 'BlockDeviceStats',  '*parent': 'BlockStats'} }", 
        "{ 'type': 'VncClientInfo',  'data': {'host': 'str', 'family': 'str', 'service': 'str',  '*x509_dname': 'str', '*sasl_username': 'str'} }", 
        "{ 'type': 'SpiceChannel',  'data': {'host': 'str', 'family': 'str', 'port': 'str',  'connection-id': 'int', 'channel-type': 'int', 'channel-id': 'int',  'tls': 'bool'} }", 
        "{ 'type': 'SpiceInfo',  'data': {'enabled': 'bool', 'migrated': 'bool', '*host': 'str', '*port': 'int',  '*tls-port': 'int', '*auth': 'str', '*compiled-version': 'str',  'mouse-mode': 'SpiceQueryMouseMode', '*channels': ['SpiceChannel']} }", 
        "{ 'type': 'BalloonInfo', 'data': {'actual': 'int' } }", 
        "{ 'type': 'PciMemoryRange', 'data': {'base': 'int', 'limit': 'int'} }", 
        "{ 'type': 'PciMemoryRegion',  'data': {'bar': 'int', 'type': 'str', 'address': 'int', 'size': 'int',  '*prefetch': 'bool', '*mem_type_64': 'bool' } }", 
        "{ 'type': 'PciBridgeInfo',  'data': {'bus': { 'number': 'int', 'secondary': 'int', 'subordinate': 'int',  'io_range': 'PciMemoryRange',  'memory_range': 'PciMemoryRange',  'prefetchable_range': 'PciMemoryRange' },  '*devices': ['PciDeviceInfo']} }", 
        "{ 'type': 'PciDeviceInfo',  'data': {'bus': 'int', 'slot': 'int', 'function': 'int',  'class_info': {'*desc': 'str', 'class': 'int'},  'id': {'device': 'int', 'vendor': 'int'},  '*irq': 'int', 'qdev_id': 'str', '*pci_bridge': 'PciBridgeInfo',  'regions': ['PciMemoryRegion']} }", 
        "{ 'type': 'PciInfo', 'data': {'bus': 'int', 'devices': ['PciDeviceInfo']} }", 
        "{ 'type': 'BlockJobInfo',  'data': {'type': 'str', 'device': 'str', 'len': 'int',  'offset': 'int', 'busy': 'bool', 'paused': 'bool', 'speed': 'int',  'io-status': 'BlockDeviceIoStatus'} }", 
        "{ 'type': 'BlockdevSnapshot',  'data': { 'device': 'str', 'snapshot-file': 'str', '*format': 'str',  '*mode': 'NewImageMode' } }", 
        "{ 'type': 'ObjectPropertyInfo',  'data': { 'name': 'str', 'type': 'str' } }", 
        "{ 'type': 'ObjectTypeInfo',  'data': { 'name': 'str' } }", 
        "{ 'type': 'DevicePropertyInfo',  'data': { 'name': 'str', 'type': 'str' } }", 
        "{ 'type': 'NetdevNoneOptions',  'data': { } }", 
        "{ 'type': 'NetLegacyNicOptions',  'data': {  '*netdev': 'str',  '*macaddr': 'str',  '*model': 'str',  '*addr': 'str',  '*vectors': 'uint32' } }", 
        "{ 'type': 'String',  'data': {  'str': 'str' } }", 
        "{ 'type': 'NetdevUserOptions',  'data': {  '*hostname': 'str',  '*restrict': 'bool',  '*ip': 'str',  '*net': 'str',  '*host': 'str',  '*tftp': 'str',  '*bootfile': 'str',  '*dhcpstart': 'str',  '*dns': 'str',  '*dnssearch': ['String'],  '*smb': 'str',  '*smbserver': 'str',  '*hostfwd': ['String'],  '*guestfwd': ['String'] } }", 
        "{ 'type': 'NetdevTapOptions',  'data': {  '*ifname': 'str',  '*fd': 'str',  '*fds': 'str',  '*script': 'str',  '*downscript': 'str',  '*helper': 'str',  '*sndbuf': 'size',  '*vnet_hdr': 'bool',  '*vhost': 'bool',  '*vhostfd': 'str',  '*vhostfds': 'str',  '*vhostforce': 'bool',  '*queues': 'uint32'} }", 
        "{ 'type': 'NetdevSocketOptions',  'data': {  '*fd': 'str',  '*listen': 'str',  '*connect': 'str',  '*mcast': 'str',  '*localaddr': 'str',  '*udp': 'str' } }", 
        "{ 'type': 'NetdevVdeOptions',  'data': {  '*sock': 'str',  '*port': 'uint16',  '*group': 'str',  '*mode': 'uint16' } }", 
        "{ 'type': 'NetdevDumpOptions',  'data': {  '*len': 'size',  '*file': 'str' } }", 
        "{ 'type': 'NetdevBridgeOptions',  'data': {  '*br': 'str',  '*helper': 'str' } }", 
        "{ 'type': 'NetdevHubPortOptions',  'data': {  'hubid': 'int32' } }", 
        "{ 'type': 'NetLegacy',  'data': {  '*vlan': 'int32',  '*id': 'str',  '*name': 'str',  'opts': 'NetClientOptions' } }", 
        "{ 'type': 'Netdev',  'data': {  'id': 'str',  'opts': 'NetClientOptions' } }", 
        "{ 'type': 'InetSocketAddress',  'data': {  'host': 'str',  'port': 'str',  '*to': 'uint16',  '*ipv4': 'bool',  '*ipv6': 'bool' } }", 
        "{ 'type': 'UnixSocketAddress',  'data': {  'path': 'str' } }", 
        "{ 'type': 'MachineInfo',  'data': { 'name': 'str', '*alias': 'str',  '*is-default': 'bool', 'cpu-max': 'int' } }", 
        "{ 'type': 'CpuDefinitionInfo',  'data': { 'name': 'str' } }", 
        "{ 'type': 'AddfdInfo', 'data': {'fdset-id': 'int', 'fd': 'int'} }", 
        "{ 'type': 'FdsetFdInfo',  'data': {'fd': 'int', '*opaque': 'str'} }", 
        "{ 'type': 'FdsetInfo',  'data': {'fdset-id': 'int', 'fds': ['FdsetFdInfo']} }", 
        "{ 'type': 'TargetInfo',  'data': { 'arch': 'TargetType' } }", 
        "{ 'type': 'ChardevFile', 'data': { '*in' : 'str',  'out' : 'str' } }", 
        "{ 'type': 'ChardevHostdev', 'data': { 'device' : 'str' } }", 
        "{ 'type': 'ChardevSocket', 'data': { 'addr' : 'SocketAddress',  '*server' : 'bool',  '*wait' : 'bool',  '*nodelay' : 'bool',  '*telnet' : 'bool' } }", 
        "{ 'type': 'ChardevUdp', 'data': { 'remote' : 'SocketAddress',  '*local' : 'SocketAddress' } }", 
        "{ 'type': 'ChardevMux', 'data': { 'chardev' : 'str' } }", 
        "{ 'type': 'ChardevStdio', 'data': { '*signal' : 'bool' } }", 
        "{ 'type': 'ChardevSpiceChannel', 'data': { 'type' : 'str' } }", 
        "{ 'type': 'ChardevSpicePort', 'data': { 'fqdn' : 'str' } }", 
        "{ 'type': 'ChardevVC', 'data': { '*width' : 'int',  '*height' : 'int',  '*cols' : 'int',  '*rows' : 'int' } }", 
        "{ 'type': 'ChardevMemory', 'data': { '*size' : 'int' } }", 
        "{ 'type': 'ChardevDummy', 'data': { } }", 
        "{ 'type' : 'ChardevReturn', 'data': { '*pty' : 'str' } }", 
        "{ 'type': 'TPMPassthroughOptions', 'data': { '*path' : 'str',  '*cancel-path' : 'str'} }", 
        "{ 'type': 'TPMInfo',  'data': {'id': 'str',  'model': 'TpmModel',  'options': 'TpmTypeOptions' } }", 
        "{ 'type': 'AcpiTableOptions',  'data': {  '*sig': 'str',  '*rev': 'uint8',  '*oem_id': 'str',  '*oem_table_id': 'str',  '*oem_rev': 'uint32',  '*asl_compiler_id': 'str',  '*asl_compiler_rev': 'uint32',  '*file': 'str',  '*data': 'str' }}", 
        "{ 'type': 'CommandLineParameterInfo',  'data': { 'name': 'str',  'type': 'CommandLineParameterType',  '*help': 'str' } }", 
        "{ 'type': 'CommandLineOptionInfo',  'data': { 'option': 'str', 'parameters': ['CommandLineParameterInfo'] } }", 
        "{ 'type': 'X86CPUFeatureWordInfo',  'data': { 'cpuid-input-eax': 'int',  '*cpuid-input-ecx': 'int',  'cpuid-register': 'X86CPURegister32',  'features': 'int' } }"
    ]
}


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] RFC: Full introspection support for QMP (with draft patch)
  2013-06-07 10:17   ` Amos Kong
@ 2013-06-14  9:52     ` Amos Kong
  2013-06-14 10:59       ` Eric Blake
  2013-06-14 11:09       ` Eric Blake
  0 siblings, 2 replies; 19+ messages in thread
From: Amos Kong @ 2013-06-14  9:52 UTC (permalink / raw)
  To: qemu-devel
  Cc: aliguori, mdroth, Markus Armbruster, qiaonuohan, Ronen Hod, lcapitulino

[-- Attachment #1: Type: text/plain, Size: 1964 bytes --]

On Fri, Jun 07, 2013 at 06:17:26PM +0800, Amos Kong wrote:
> On Fri, Jun 07, 2013 at 06:12:30PM +0800, Amos Kong wrote:
> > Sent out a draft patch in the end of this week. It doesn't support:
> > * output all stuffs in one shot.
> > * introspect event
> > * provide metadata date
> > 
> > How can we define a dynamic dict in qmp-schema.json ?
> > 
> > Currently I just output the raw json dict by a string, Libvirt needs
> > parse two times, convert the string to json format.
> > 
> > qmp-schema.h: auto generated head file by qapi script
> > 
> > Attached some examples.


Hello all,

I defined a new type 'SchemaData', it contains 4 keys (type, name, data, returns)

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

Then we can provice meaningful result to Libvirt. Currently I set a string
for SchemaData['data'].


I tried to define a dynamical dict for 'data', but it's failed. 

| { 'type': 'SchemaData',
|   'data': { 'type': 'str', 'name': 'str', '*data': '**', '*returns': 'str' } }  (Failed!!)


Does qapi support to define a dynamical dict, then I can convert dict string
and set to SchemaData['data'] ?



{ "execute": "query-qmp-schema"}
{
    "return": [
        {
            "name": "ErrorClass", 
            "type": "enum", 
            "data": "['GenericError', 'CommandNotFound', 'DeviceEncrypted', 'DeviceNotActive', 'DeviceNotFound', 'KVMMissingCap']"
        }, 
        {
            "name": "SchemaData", 
            "type": "type", 
            "data": "{'*returns': 'str', 'type': 'str', 'name': 'str', '*data': 'str'}"
        }, 
        ......
        ......
        {
            "name": "query-qmp-schema", 
            "type": "command", 
            "returns": "['SchemaData']", 
            "data": "{'*name': 'str', '*type': 'str'}"
        }
    ]
}


[-- Attachment #2: qmp-schema.h --]
[-- Type: text/plain, Size: 18851 bytes --]


/* convert qapi-schema.json to a string table */

struct qmp_schem {
const char *type;
const char *name;
const char *data;
const char *returns;
} qmp_schema_table[] = {
{"enum", "ErrorClass", "['GenericError', 'CommandNotFound', 'DeviceEncrypted', 'DeviceNotActive', 'DeviceNotFound', 'KVMMissingCap']", ""},
{"command", "add_client", "{'*skipauth': 'bool', 'protocol': 'str', 'fdname': 'str', '*tls': 'bool'}", ""},
{"type", "NameInfo", "{'*name': 'str'}", ""},
{"command", "query-name", "", "NameInfo"},
{"type", "VersionInfo", "{'qemu': OrderedDict([('major', 'int'), ('minor', 'int'), ('micro', 'int')]), 'package': 'str'}", ""},
{"command", "query-version", "", "VersionInfo"},
{"type", "KvmInfo", "{'enabled': 'bool', 'present': 'bool'}", ""},
{"command", "query-kvm", "", "KvmInfo"},
{"enum", "RunState", "['debug', 'inmigrate', 'internal-error', 'io-error', 'paused', 'postmigrate', 'prelaunch', 'finish-migrate', 'restore-vm', 'running', 'save-vm', 'shutdown', 'suspended', 'watchdog', 'guest-panicked']", ""},
{"type", "SnapshotInfo", "{'name': 'str', 'date-sec': 'int', 'vm-state-size': 'int', 'vm-clock-nsec': 'int', 'vm-clock-sec': 'int', 'date-nsec': 'int', 'id': 'str'}", ""},
{"type", "ImageInfo", "{'*snapshots': ['SnapshotInfo'], 'format': 'str', '*encrypted': 'bool', '*dirty-flag': 'bool', '*backing-filename-format': 'str', '*backing-filename': 'str', '*actual-size': 'int', 'filename': 'str', 'virtual-size': 'int', '*full-backing-filename': 'str', '*cluster-size': 'int'}", ""},
{"type", "ImageCheck", "{'check-errors': 'int', '*image-end-offset': 'int', '*corruptions-fixed': 'int', '*allocated-clusters': 'int', 'format': 'str', '*corruptions': 'int', '*total-clusters': 'int', 'filename': 'str', '*fragmented-clusters': 'int', '*leaks-fixed': 'int', '*compressed-clusters': 'int', '*leaks': 'int'}", ""},
{"type", "StatusInfo", "{'singlestep': 'bool', 'status': 'RunState', 'running': 'bool'}", ""},
{"command", "query-status", "", "StatusInfo"},
{"type", "UuidInfo", "{'UUID': 'str'}", ""},
{"command", "query-uuid", "", "UuidInfo"},
{"type", "ChardevInfo", "{'filename': 'str', 'label': 'str'}", ""},
{"command", "query-chardev", "", "['ChardevInfo']"},
{"enum", "DataFormat", "['utf8', 'base64']", ""},
{"command", "ringbuf-write", "{'device': 'str', '*format': 'DataFormat', 'data': 'str'}", ""},
{"command", "ringbuf-read", "{'device': 'str', '*format': 'DataFormat', 'size': 'int'}", "str"},
{"type", "CommandInfo", "{'name': 'str'}", ""},
{"command", "query-commands", "", "['CommandInfo']"},
{"type", "EventInfo", "{'name': 'str'}", ""},
{"command", "query-events", "", "['EventInfo']"},
{"type", "MigrationStats", "{'skipped': 'int', 'dirty-pages-rate': 'int', 'normal': 'int', 'transferred': 'int', 'duplicate': 'int', 'total': 'int', 'remaining': 'int', 'normal-bytes': 'int'}", ""},
{"type", "XBZRLECacheStats", "{'cache-miss': 'int', 'overflow': 'int', 'bytes': 'int', 'pages': 'int', 'cache-size': 'int'}", ""},
{"type", "MigrationInfo", "{'*ram': 'MigrationStats', '*total-time': 'int', '*downtime': 'int', '*expected-downtime': 'int', '*status': 'str', '*xbzrle-cache': 'XBZRLECacheStats', '*disk': 'MigrationStats'}", ""},
{"command", "query-migrate", "", "MigrationInfo"},
{"enum", "MigrationCapability", "['xbzrle']", ""},
{"type", "MigrationCapabilityStatus", "{'capability': 'MigrationCapability', 'state': 'bool'}", ""},
{"command", "migrate-set-capabilities", "{'capabilities': ['MigrationCapabilityStatus']}", ""},
{"command", "query-migrate-capabilities", "", "['MigrationCapabilityStatus']"},
{"type", "MouseInfo", "{'current': 'bool', 'index': 'int', 'name': 'str', 'absolute': 'bool'}", ""},
{"command", "query-mice", "", "['MouseInfo']"},
{"type", "CpuInfo", "{'halted': 'bool', '*npc': 'int', '*PC': 'int', '*pc': 'int', 'current': 'bool', 'thread_id': 'int', 'CPU': 'int', '*nip': 'int'}", ""},
{"command", "query-cpus", "", "['CpuInfo']"},
{"type", "BlockDeviceInfo", "{'bps_rd': 'int', 'backing_file_depth': 'int', 'encrypted': 'bool', '*backing_file': 'str', 'bps_wr': 'int', 'drv': 'str', 'bps': 'int', 'iops': 'int', 'file': 'str', 'iops_rd': 'int', 'encryption_key_missing': 'bool', 'ro': 'bool', 'iops_wr': 'int'}", ""},
{"enum", "BlockDeviceIoStatus", "['ok', 'failed', 'nospace']", ""},
{"type", "BlockDirtyInfo", "{'count': 'int', 'granularity': 'int'}", ""},
{"type", "BlockInfo", "{'*tray_open': 'bool', 'locked': 'bool', '*io-status': 'BlockDeviceIoStatus', '*dirty': 'BlockDirtyInfo', '*inserted': 'BlockDeviceInfo', 'removable': 'bool', 'device': 'str', 'type': 'str'}", ""},
{"command", "query-block", "", "['BlockInfo']"},
{"type", "BlockDeviceStats", "{'rd_operations': 'int', 'flush_total_time_ns': 'int', 'wr_highest_offset': 'int', 'rd_total_time_ns': 'int', 'rd_bytes': 'int', 'wr_total_time_ns': 'int', 'flush_operations': 'int', 'wr_operations': 'int', 'wr_bytes': 'int'}", ""},
{"type", "BlockStats", "{'stats': 'BlockDeviceStats', '*parent': 'BlockStats', '*device': 'str'}", ""},
{"command", "query-blockstats", "", "['BlockStats']"},
{"type", "VncClientInfo", "{'*sasl_username': 'str', 'host': 'str', 'service': 'str', 'family': 'str', '*x509_dname': 'str'}", ""},
{"type", "VncInfo", "{'*auth': 'str', 'enabled': 'bool', '*host': 'str', '*clients': ['VncClientInfo'], '*family': 'str', '*service': 'str'}", ""},
{"command", "query-vnc", "", "VncInfo"},
{"type", "SpiceChannel", "{'tls': 'bool', 'family': 'str', 'host': 'str', 'channel-type': 'int', 'connection-id': 'int', 'port': 'str', 'channel-id': 'int'}", ""},
{"enum", "SpiceQueryMouseMode", "['client', 'server', 'unknown']", ""},
{"type", "SpiceInfo", "{'migrated': 'bool', '*tls-port': 'int', '*port': 'int', '*auth': 'str', 'enabled': 'bool', '*host': 'str', '*channels': ['SpiceChannel'], 'mouse-mode': 'SpiceQueryMouseMode', '*compiled-version': 'str'}", ""},
{"command", "query-spice", "", "SpiceInfo"},
{"type", "BalloonInfo", "{'actual': 'int'}", ""},
{"command", "query-balloon", "", "BalloonInfo"},
{"type", "PciMemoryRange", "{'base': 'int', 'limit': 'int'}", ""},
{"type", "PciMemoryRegion", "{'bar': 'int', '*prefetch': 'bool', 'address': 'int', 'type': 'str', '*mem_type_64': 'bool', 'size': 'int'}", ""},
{"type", "PciBridgeInfo", "{'bus': OrderedDict([('number', 'int'), ('secondary', 'int'), ('subordinate', 'int'), ('io_range', 'PciMemoryRange'), ('memory_range', 'PciMemoryRange'), ('prefetchable_range', 'PciMemoryRange')]), '*devices': ['PciDeviceInfo']}", ""},
{"type", "PciDeviceInfo", "{'slot': 'int', 'function': 'int', 'bus': 'int', 'class_info': OrderedDict([('*desc', 'str'), ('class', 'int')]), '*pci_bridge': 'PciBridgeInfo', '*irq': 'int', 'regions': ['PciMemoryRegion'], 'qdev_id': 'str', 'id': OrderedDict([('device', 'int'), ('vendor', 'int')])}", ""},
{"type", "PciInfo", "{'bus': 'int', 'devices': ['PciDeviceInfo']}", ""},
{"command", "query-pci", "", "['PciInfo']"},
{"enum", "BlockdevOnError", "['report', 'ignore', 'enospc', 'stop']", ""},
{"enum", "MirrorSyncMode", "['top', 'full', 'none']", ""},
{"type", "BlockJobInfo", "{'busy': 'bool', 'speed': 'int', 'len': 'int', 'paused': 'bool', 'io-status': 'BlockDeviceIoStatus', 'offset': 'int', 'device': 'str', 'type': 'str'}", ""},
{"command", "query-block-jobs", "", "['BlockJobInfo']"},
{"command", "quit", "", ""},
{"command", "stop", "", ""},
{"command", "system_reset", "", ""},
{"command", "system_powerdown", "", ""},
{"command", "cpu", "{'index': 'int'}", ""},
{"command", "cpu-add", "{'id': 'int'}", ""},
{"command", "memsave", "{'filename': 'str', '*cpu-index': 'int', 'val': 'int', 'size': 'int'}", ""},
{"command", "pmemsave", "{'filename': 'str', 'val': 'int', 'size': 'int'}", ""},
{"command", "cont", "", ""},
{"command", "system_wakeup", "", ""},
{"command", "inject-nmi", "", ""},
{"command", "set_link", "{'name': 'str', 'up': 'bool'}", ""},
{"command", "block_passwd", "{'device': 'str', 'password': 'str'}", ""},
{"command", "balloon", "{'value': 'int'}", ""},
{"command", "block_resize", "{'device': 'str', 'size': 'int'}", ""},
{"enum", "NewImageMode", "['existing', 'absolute-paths']", ""},
{"type", "BlockdevSnapshot", "{'device': 'str', '*format': 'str', 'snapshot-file': 'str', '*mode': 'NewImageMode'}", ""},
{"union", "TransactionAction", "{'blockdev-snapshot-sync': 'BlockdevSnapshot'}", ""},
{"command", "transaction", "{'actions': ['TransactionAction']}", ""},
{"command", "blockdev-snapshot-sync", "{'device': 'str', '*format': 'str', 'snapshot-file': 'str', '*mode': 'NewImageMode'}", ""},
{"command", "human-monitor-command", "{'*cpu-index': 'int', 'command-line': 'str'}", "str"},
{"command", "block-commit", "{'device': 'str', 'top': 'str', '*base': 'str', '*speed': 'int'}", ""},
{"command", "drive-mirror", "{'*on-target-error': 'BlockdevOnError', '*buf-size': 'int', 'target': 'str', '*granularity': 'uint32', '*format': 'str', '*speed': 'int', 'sync': 'MirrorSyncMode', '*mode': 'NewImageMode', 'device': 'str', '*on-source-error': 'BlockdevOnError'}", ""},
{"command", "migrate_cancel", "", ""},
{"command", "migrate_set_downtime", "{'value': 'number'}", ""},
{"command", "migrate_set_speed", "{'value': 'int'}", ""},
{"command", "migrate-set-cache-size", "{'value': 'int'}", ""},
{"command", "query-migrate-cache-size", "", "int"},
{"type", "ObjectPropertyInfo", "{'type': 'str', 'name': 'str'}", ""},
{"command", "qom-list", "{'path': 'str'}", "['ObjectPropertyInfo']"},
{"command", "qom-get", "{'path': 'str', 'property': 'str'}", "visitor"},
{"command", "qom-set", "{'path': 'str', 'property': 'str', 'value': 'visitor'}", ""},
{"command", "set_password", "{'password': 'str', 'protocol': 'str', '*connected': 'str'}", ""},
{"command", "expire_password", "{'protocol': 'str', 'time': 'str'}", ""},
{"command", "eject", "{'device': 'str', '*force': 'bool'}", ""},
{"command", "change-vnc-password", "{'password': 'str'}", ""},
{"command", "change", "{'device': 'str', 'target': 'str', '*arg': 'str'}", ""},
{"command", "block_set_io_throttle", "{'bps_rd': 'int', 'bps_wr': 'int', 'bps': 'int', 'iops': 'int', 'iops_rd': 'int', 'device': 'str', 'iops_wr': 'int'}", ""},
{"command", "block-stream", "{'device': 'str', '*on-error': 'BlockdevOnError', '*base': 'str', '*speed': 'int'}", ""},
{"command", "block-job-set-speed", "{'device': 'str', 'speed': 'int'}", ""},
{"command", "block-job-cancel", "{'device': 'str', '*force': 'bool'}", ""},
{"command", "block-job-pause", "{'device': 'str'}", ""},
{"command", "block-job-resume", "{'device': 'str'}", ""},
{"command", "block-job-complete", "{'device': 'str'}", ""},
{"type", "ObjectTypeInfo", "{'name': 'str'}", ""},
{"command", "qom-list-types", "{'*abstract': 'bool', '*implements': 'str'}", "['ObjectTypeInfo']"},
{"type", "DevicePropertyInfo", "{'type': 'str', 'name': 'str'}", ""},
{"command", "device-list-properties", "{'typename': 'str'}", "['DevicePropertyInfo']"},
{"command", "migrate", "{'*detach': 'bool', 'uri': 'str', '*inc': 'bool', '*blk': 'bool'}", ""},
{"command", "xen-save-devices-state", "{'filename': 'str'}", ""},
{"command", "xen-set-global-dirty-log", "{'enable': 'bool'}", ""},
{"command", "device_del", "{'id': 'str'}", ""},
{"command", "dump-guest-memory", "{'*length': 'int', 'paging': 'bool', 'protocol': 'str', '*begin': 'int'}", ""},
{"command", "netdev_add", "{'*props': '**', 'type': 'str', 'id': 'str'}", ""},
{"command", "netdev_del", "{'id': 'str'}", ""},
{"type", "NetdevNoneOptions", "{}", ""},
{"type", "NetLegacyNicOptions", "{'*macaddr': 'str', '*model': 'str', '*addr': 'str', '*vectors': 'uint32', '*netdev': 'str'}", ""},
{"type", "String", "{'str': 'str'}", ""},
{"type", "NetdevUserOptions", "{'*hostname': 'str', '*tftp': 'str', '*dhcpstart': 'str', '*guestfwd': ['String'], '*smbserver': 'str', '*hostfwd': ['String'], '*host': 'str', '*net': 'str', '*restrict': 'bool', '*dnssearch': ['String'], '*ip': 'str', '*dns': 'str', '*smb': 'str', '*bootfile': 'str'}", ""},
{"type", "NetdevTapOptions", "{'*vhostfd': 'str', '*script': 'str', '*helper': 'str', '*vhostfds': 'str', '*vnet_hdr': 'bool', '*downscript': 'str', '*queues': 'uint32', '*fd': 'str', '*vhostforce': 'bool', '*ifname': 'str', '*fds': 'str', '*vhost': 'bool', '*sndbuf': 'size'}", ""},
{"type", "NetdevSocketOptions", "{'*mcast': 'str', '*connect': 'str', '*fd': 'str', '*listen': 'str', '*udp': 'str', '*localaddr': 'str'}", ""},
{"type", "NetdevVdeOptions", "{'*mode': 'uint16', '*group': 'str', '*port': 'uint16', '*sock': 'str'}", ""},
{"type", "NetdevDumpOptions", "{'*len': 'size', '*file': 'str'}", ""},
{"type", "NetdevBridgeOptions", "{'*helper': 'str', '*br': 'str'}", ""},
{"type", "NetdevHubPortOptions", "{'hubid': 'int32'}", ""},
{"union", "NetClientOptions", "{'bridge': 'NetdevBridgeOptions', 'none': 'NetdevNoneOptions', 'tap': 'NetdevTapOptions', 'socket': 'NetdevSocketOptions', 'dump': 'NetdevDumpOptions', 'nic': 'NetLegacyNicOptions', 'vde': 'NetdevVdeOptions', 'user': 'NetdevUserOptions', 'hubport': 'NetdevHubPortOptions'}", ""},
{"type", "NetLegacy", "{'*id': 'str', '*vlan': 'int32', '*name': 'str', 'opts': 'NetClientOptions'}", ""},
{"type", "Netdev", "{'id': 'str', 'opts': 'NetClientOptions'}", ""},
{"type", "InetSocketAddress", "{'*ipv6': 'bool', 'host': 'str', '*to': 'uint16', 'port': 'str', '*ipv4': 'bool'}", ""},
{"type", "UnixSocketAddress", "{'path': 'str'}", ""},
{"union", "SocketAddress", "{'unix': 'UnixSocketAddress', 'fd': 'String', 'inet': 'InetSocketAddress'}", ""},
{"command", "getfd", "{'fdname': 'str'}", ""},
{"command", "closefd", "{'fdname': 'str'}", ""},
{"type", "MachineInfo", "{'*alias': 'str', '*is-default': 'bool', 'cpu-max': 'int', 'name': 'str'}", ""},
{"command", "query-machines", "", "['MachineInfo']"},
{"type", "CpuDefinitionInfo", "{'name': 'str'}", ""},
{"command", "query-cpu-definitions", "", "['CpuDefinitionInfo']"},
{"type", "AddfdInfo", "{'fdset-id': 'int', 'fd': 'int'}", ""},
{"command", "add-fd", "{'*opaque': 'str', '*fdset-id': 'int'}", "AddfdInfo"},
{"command", "remove-fd", "{'fdset-id': 'int', '*fd': 'int'}", ""},
{"type", "FdsetFdInfo", "{'*opaque': 'str', 'fd': 'int'}", ""},
{"type", "FdsetInfo", "{'fdset-id': 'int', 'fds': ['FdsetFdInfo']}", ""},
{"command", "query-fdsets", "", "['FdsetInfo']"},
{"enum", "TargetType", "['alpha', 'arm', 'cris', 'i386', 'lm32', 'm68k', 'microblazeel', 'microblaze', 'mips64el', 'mips64', 'mipsel', 'mips', 'moxie', 'or32', 'ppc64', 'ppcemb', 'ppc', 's390x', 'sh4eb', 'sh4', 'sparc64', 'sparc', 'unicore32', 'x86_64', 'xtensaeb', 'xtensa']", ""},
{"type", "TargetInfo", "{'arch': 'TargetType'}", ""},
{"command", "query-target", "", "TargetInfo"},
{"enum", "QKeyCode", "['shift', 'shift_r', 'alt', 'alt_r', 'altgr', 'altgr_r', 'ctrl', 'ctrl_r', 'menu', 'esc', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'minus', 'equal', 'backspace', 'tab', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', 'bracket_left', 'bracket_right', 'ret', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'semicolon', 'apostrophe', 'grave_accent', 'backslash', 'z', 'x', 'c', 'v', 'b', 'n', 'm', 'comma', 'dot', 'slash', 'asterisk', 'spc', 'caps_lock', 'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'f10', 'num_lock', 'scroll_lock', 'kp_divide', 'kp_multiply', 'kp_subtract', 'kp_add', 'kp_enter', 'kp_decimal', 'sysrq', 'kp_0', 'kp_1', 'kp_2', 'kp_3', 'kp_4', 'kp_5', 'kp_6', 'kp_7', 'kp_8', 'kp_9', 'less', 'f11', 'f12', 'print', 'home', 'pgup', 'pgdn', 'end', 'left', 'up', 'down', 'right', 'insert', 'delete', 'stop', 'again', 'props', 'undo', 'front', 'copy', 'open', 'paste', 'find', 'cut', 'lf', 'help', 'meta_l', 'meta_r', 'compose']", ""},
{"union", "KeyValue", "{'qcode': 'QKeyCode', 'number': 'int'}", ""},
{"command", "send-key", "{'keys': ['KeyValue'], '*hold-time': 'int'}", ""},
{"command", "screendump", "{'filename': 'str'}", ""},
{"command", "nbd-server-start", "{'addr': 'SocketAddress'}", ""},
{"command", "nbd-server-add", "{'device': 'str', '*writable': 'bool'}", ""},
{"command", "nbd-server-stop", "", ""},
{"type", "ChardevFile", "{'*in': 'str', 'out': 'str'}", ""},
{"type", "ChardevHostdev", "{'device': 'str'}", ""},
{"type", "ChardevSocket", "{'*nodelay': 'bool', '*wait': 'bool', '*server': 'bool', 'addr': 'SocketAddress', '*telnet': 'bool'}", ""},
{"type", "ChardevUdp", "{'*local': 'SocketAddress', 'remote': 'SocketAddress'}", ""},
{"type", "ChardevMux", "{'chardev': 'str'}", ""},
{"type", "ChardevStdio", "{'*signal': 'bool'}", ""},
{"type", "ChardevSpiceChannel", "{'type': 'str'}", ""},
{"type", "ChardevSpicePort", "{'fqdn': 'str'}", ""},
{"type", "ChardevVC", "{'*width': 'int', '*height': 'int', '*cols': 'int', '*rows': 'int'}", ""},
{"type", "ChardevMemory", "{'*size': 'int'}", ""},
{"type", "ChardevDummy", "{}", ""},
{"union", "ChardevBackend", "{'udp': 'ChardevUdp', 'vc': 'ChardevVC', 'console': 'ChardevDummy', 'socket': 'ChardevSocket', 'braille': 'ChardevDummy', 'stdio': 'ChardevStdio', 'spiceport': 'ChardevSpicePort', 'mux': 'ChardevMux', 'pipe': 'ChardevHostdev', 'msmouse': 'ChardevDummy', 'file': 'ChardevFile', 'memory': 'ChardevMemory', 'spicevmc': 'ChardevSpiceChannel', 'serial': 'ChardevHostdev', 'null': 'ChardevDummy', 'parallel': 'ChardevHostdev', 'pty': 'ChardevDummy'}", ""},
{"type", "ChardevReturn", "{'*pty': 'str'}", ""},
{"command", "chardev-add", "{'id': 'str', 'backend': 'ChardevBackend'}", "ChardevReturn"},
{"command", "chardev-remove", "{'id': 'str'}", ""},
{"enum", "TpmModel", "['tpm-tis']", ""},
{"command", "query-tpm-models", "", "['TpmModel']"},
{"enum", "TpmType", "['passthrough']", ""},
{"command", "query-tpm-types", "", "['TpmType']"},
{"type", "TPMPassthroughOptions", "{'*cancel-path': 'str', '*path': 'str'}", ""},
{"union", "TpmTypeOptions", "{'passthrough': 'TPMPassthroughOptions'}", ""},
{"type", "TPMInfo", "{'model': 'TpmModel', 'id': 'str', 'options': 'TpmTypeOptions'}", ""},
{"command", "query-tpm", "", "['TPMInfo']"},
{"type", "AcpiTableOptions", "{'*asl_compiler_rev': 'uint32', '*oem_rev': 'uint32', '*sig': 'str', '*file': 'str', '*data': 'str', '*rev': 'uint8', '*asl_compiler_id': 'str', '*oem_table_id': 'str', '*oem_id': 'str'}", ""},
{"enum", "CommandLineParameterType", "['string', 'boolean', 'number', 'size']", ""},
{"type", "CommandLineParameterInfo", "{'type': 'CommandLineParameterType', 'name': 'str', '*help': 'str'}", ""},
{"type", "CommandLineOptionInfo", "{'option': 'str', 'parameters': ['CommandLineParameterInfo']}", ""},
{"command", "query-command-line-options", "{'*option': 'str'}", "['CommandLineOptionInfo']"},
{"enum", "X86CPURegister32", "['EAX', 'EBX', 'ECX', 'EDX', 'ESP', 'EBP', 'ESI', 'EDI']", ""},
{"type", "X86CPUFeatureWordInfo", "{'cpuid-register': 'X86CPURegister32', '*cpuid-input-ecx': 'int', 'cpuid-input-eax': 'int', 'features': 'int'}", ""},
{"type", "SchemaData", "{'*returns': 'str', 'type': 'str', 'name': 'str', '*data': 'str'}", ""},
{"command", "query-qmp-schema", "{'*name': 'str', '*type': 'str'}", "['SchemaData']"},
{NULL, NULL, NULL } };

[-- Attachment #3: query-qmp-schema.output.txt --]
[-- Type: text/plain, Size: 33405 bytes --]

{ "execute": "query-qmp-schema"}
{
    "return": [
        {
            "name": "ErrorClass", 
            "type": "enum", 
            "data": "['GenericError', 'CommandNotFound', 'DeviceEncrypted', 'DeviceNotActive', 'DeviceNotFound', 'KVMMissingCap']"
        }, 
        {
            "name": "add_client", 
            "type": "command", 
            "data": "{'*skipauth': 'bool', 'protocol': 'str', 'fdname': 'str', '*tls': 'bool'}"
        }, 
        {
            "name": "NameInfo", 
            "type": "type", 
            "data": "{'*name': 'str'}"
        }, 
        {
            "name": "query-name", 
            "type": "command", 
            "returns": "NameInfo"
        }, 
        {
            "name": "VersionInfo", 
            "type": "type", 
            "data": "{'qemu': OrderedDict([('major', 'int'), ('minor', 'int'), ('micro', 'int')]), 'package': 'str'}"
        }, 
        {
            "name": "query-version", 
            "type": "command", 
            "returns": "VersionInfo"
        }, 
        {
            "name": "KvmInfo", 
            "type": "type", 
            "data": "{'enabled': 'bool', 'present': 'bool'}"
        }, 
        {
            "name": "query-kvm", 
            "type": "command", 
            "returns": "KvmInfo"
        }, 
        {
            "name": "RunState", 
            "type": "enum", 
            "data": "['debug', 'inmigrate', 'internal-error', 'io-error', 'paused', 'postmigrate', 'prelaunch', 'finish-migrate', 'restore-vm', 'running', 'save-vm', 'shutdown', 'suspended', 'watchdog', 'guest-panicked']"
        }, 
        {
            "name": "SnapshotInfo", 
            "type": "type", 
            "data": "{'name': 'str', 'date-sec': 'int', 'vm-state-size': 'int', 'vm-clock-nsec': 'int', 'vm-clock-sec': 'int', 'date-nsec': 'int', 'id': 'str'}"
        }, 
        {
            "name": "ImageInfo", 
            "type": "type", 
            "data": "{'*snapshots': ['SnapshotInfo'], 'format': 'str', '*encrypted': 'bool', '*dirty-flag': 'bool', '*backing-filename-format': 'str', '*backing-filename': 'str', '*actual-size': 'int', 'filename': 'str', 'virtual-size': 'int', '*full-backing-filename': 'str', '*cluster-size': 'int'}"
        }, 
        {
            "name": "ImageCheck", 
            "type": "type", 
            "data": "{'check-errors': 'int', '*image-end-offset': 'int', '*corruptions-fixed': 'int', '*allocated-clusters': 'int', 'format': 'str', '*corruptions': 'int', '*total-clusters': 'int', 'filename': 'str', '*fragmented-clusters': 'int', '*leaks-fixed': 'int', '*compressed-clusters': 'int', '*leaks': 'int'}"
        }, 
        {
            "name": "StatusInfo", 
            "type": "type", 
            "data": "{'singlestep': 'bool', 'status': 'RunState', 'running': 'bool'}"
        }, 
        {
            "name": "query-status", 
            "type": "command", 
            "returns": "StatusInfo"
        }, 
        {
            "name": "UuidInfo", 
            "type": "type", 
            "data": "{'UUID': 'str'}"
        }, 
        {
            "name": "query-uuid", 
            "type": "command", 
            "returns": "UuidInfo"
        }, 
        {
            "name": "ChardevInfo", 
            "type": "type", 
            "data": "{'filename': 'str', 'label': 'str'}"
        }, 
        {
            "name": "query-chardev", 
            "type": "command", 
            "returns": "['ChardevInfo']"
        }, 
        {
            "name": "DataFormat", 
            "type": "enum", 
            "data": "['utf8', 'base64']"
        }, 
        {
            "name": "ringbuf-write", 
            "type": "command", 
            "data": "{'device': 'str', '*format': 'DataFormat', 'data': 'str'}"
        }, 
        {
            "name": "ringbuf-read", 
            "type": "command", 
            "returns": "str", 
            "data": "{'device': 'str', '*format': 'DataFormat', 'size': 'int'}"
        }, 
        {
            "name": "CommandInfo", 
            "type": "type", 
            "data": "{'name': 'str'}"
        }, 
        {
            "name": "query-commands", 
            "type": "command", 
            "returns": "['CommandInfo']"
        }, 
        {
            "name": "EventInfo", 
            "type": "type", 
            "data": "{'name': 'str'}"
        }, 
        {
            "name": "query-events", 
            "type": "command", 
            "returns": "['EventInfo']"
        }, 
        {
            "name": "MigrationStats", 
            "type": "type", 
            "data": "{'skipped': 'int', 'dirty-pages-rate': 'int', 'normal': 'int', 'transferred': 'int', 'duplicate': 'int', 'total': 'int', 'remaining': 'int', 'normal-bytes': 'int'}"
        }, 
        {
            "name": "XBZRLECacheStats", 
            "type": "type", 
            "data": "{'cache-miss': 'int', 'overflow': 'int', 'bytes': 'int', 'pages': 'int', 'cache-size': 'int'}"
        }, 
        {
            "name": "MigrationInfo", 
            "type": "type", 
            "data": "{'*ram': 'MigrationStats', '*total-time': 'int', '*downtime': 'int', '*expected-downtime': 'int', '*status': 'str', '*xbzrle-cache': 'XBZRLECacheStats', '*disk': 'MigrationStats'}"
        }, 
        {
            "name": "query-migrate", 
            "type": "command", 
            "returns": "MigrationInfo"
        }, 
        {
            "name": "MigrationCapability", 
            "type": "enum", 
            "data": "['xbzrle']"
        }, 
        {
            "name": "MigrationCapabilityStatus", 
            "type": "type", 
            "data": "{'capability': 'MigrationCapability', 'state': 'bool'}"
        }, 
        {
            "name": "migrate-set-capabilities", 
            "type": "command", 
            "data": "{'capabilities': ['MigrationCapabilityStatus']}"
        }, 
        {
            "name": "query-migrate-capabilities", 
            "type": "command", 
            "returns": "['MigrationCapabilityStatus']"
        }, 
        {
            "name": "MouseInfo", 
            "type": "type", 
            "data": "{'current': 'bool', 'index': 'int', 'name': 'str', 'absolute': 'bool'}"
        }, 
        {
            "name": "query-mice", 
            "type": "command", 
            "returns": "['MouseInfo']"
        }, 
        {
            "name": "CpuInfo", 
            "type": "type", 
            "data": "{'halted': 'bool', '*npc': 'int', '*PC': 'int', '*pc': 'int', 'current': 'bool', 'thread_id': 'int', 'CPU': 'int', '*nip': 'int'}"
        }, 
        {
            "name": "query-cpus", 
            "type": "command", 
            "returns": "['CpuInfo']"
        }, 
        {
            "name": "BlockDeviceInfo", 
            "type": "type", 
            "data": "{'bps_rd': 'int', 'backing_file_depth': 'int', 'encrypted': 'bool', '*backing_file': 'str', 'bps_wr': 'int', 'drv': 'str', 'bps': 'int', 'iops': 'int', 'file': 'str', 'iops_rd': 'int', 'encryption_key_missing': 'bool', 'ro': 'bool', 'iops_wr': 'int'}"
        }, 
        {
            "name": "BlockDeviceIoStatus", 
            "type": "enum", 
            "data": "['ok', 'failed', 'nospace']"
        }, 
        {
            "name": "BlockDirtyInfo", 
            "type": "type", 
            "data": "{'count': 'int', 'granularity': 'int'}"
        }, 
        {
            "name": "BlockInfo", 
            "type": "type", 
            "data": "{'*tray_open': 'bool', 'locked': 'bool', '*io-status': 'BlockDeviceIoStatus', '*dirty': 'BlockDirtyInfo', '*inserted': 'BlockDeviceInfo', 'removable': 'bool', 'device': 'str', 'type': 'str'}"
        }, 
        {
            "name": "query-block", 
            "type": "command", 
            "returns": "['BlockInfo']"
        }, 
        {
            "name": "BlockDeviceStats", 
            "type": "type", 
            "data": "{'rd_operations': 'int', 'flush_total_time_ns': 'int', 'wr_highest_offset': 'int', 'rd_total_time_ns': 'int', 'rd_bytes': 'int', 'wr_total_time_ns': 'int', 'flush_operations': 'int', 'wr_operations': 'int', 'wr_bytes': 'int'}"
        }, 
        {
            "name": "BlockStats", 
            "type": "type", 
            "data": "{'stats': 'BlockDeviceStats', '*parent': 'BlockStats', '*device': 'str'}"
        }, 
        {
            "name": "query-blockstats", 
            "type": "command", 
            "returns": "['BlockStats']"
        }, 
        {
            "name": "VncClientInfo", 
            "type": "type", 
            "data": "{'*sasl_username': 'str', 'host': 'str', 'service': 'str', 'family': 'str', '*x509_dname': 'str'}"
        }, 
        {
            "name": "VncInfo", 
            "type": "type", 
            "data": "{'*auth': 'str', 'enabled': 'bool', '*host': 'str', '*clients': ['VncClientInfo'], '*family': 'str', '*service': 'str'}"
        }, 
        {
            "name": "query-vnc", 
            "type": "command", 
            "returns": "VncInfo"
        }, 
        {
            "name": "SpiceChannel", 
            "type": "type", 
            "data": "{'tls': 'bool', 'family': 'str', 'host': 'str', 'channel-type': 'int', 'connection-id': 'int', 'port': 'str', 'channel-id': 'int'}"
        }, 
        {
            "name": "SpiceQueryMouseMode", 
            "type": "enum", 
            "data": "['client', 'server', 'unknown']"
        }, 
        {
            "name": "SpiceInfo", 
            "type": "type", 
            "data": "{'migrated': 'bool', '*tls-port': 'int', '*port': 'int', '*auth': 'str', 'enabled': 'bool', '*host': 'str', '*channels': ['SpiceChannel'], 'mouse-mode': 'SpiceQueryMouseMode', '*compiled-version': 'str'}"
        }, 
        {
            "name": "query-spice", 
            "type": "command", 
            "returns": "SpiceInfo"
        }, 
        {
            "name": "BalloonInfo", 
            "type": "type", 
            "data": "{'actual': 'int'}"
        }, 
        {
            "name": "query-balloon", 
            "type": "command", 
            "returns": "BalloonInfo"
        }, 
        {
            "name": "PciMemoryRange", 
            "type": "type", 
            "data": "{'base': 'int', 'limit': 'int'}"
        }, 
        {
            "name": "PciMemoryRegion", 
            "type": "type", 
            "data": "{'bar': 'int', '*prefetch': 'bool', 'address': 'int', 'type': 'str', '*mem_type_64': 'bool', 'size': 'int'}"
        }, 
        {
            "name": "PciBridgeInfo", 
            "type": "type", 
            "data": "{'bus': OrderedDict([('number', 'int'), ('secondary', 'int'), ('subordinate', 'int'), ('io_range', 'PciMemoryRange'), ('memory_range', 'PciMemoryRange'), ('prefetchable_range', 'PciMemoryRange')]), '*devices': ['PciDeviceInfo']}"
        }, 
        {
            "name": "PciDeviceInfo", 
            "type": "type", 
            "data": "{'slot': 'int', 'function': 'int', 'bus': 'int', 'class_info': OrderedDict([('*desc', 'str'), ('class', 'int')]), '*pci_bridge': 'PciBridgeInfo', '*irq': 'int', 'regions': ['PciMemoryRegion'], 'qdev_id': 'str', 'id': OrderedDict([('device', 'int'), ('vendor', 'int')])}"
        }, 
        {
            "name": "PciInfo", 
            "type": "type", 
            "data": "{'bus': 'int', 'devices': ['PciDeviceInfo']}"
        }, 
        {
            "name": "query-pci", 
            "type": "command", 
            "returns": "['PciInfo']"
        }, 
        {
            "name": "BlockdevOnError", 
            "type": "enum", 
            "data": "['report', 'ignore', 'enospc', 'stop']"
        }, 
        {
            "name": "MirrorSyncMode", 
            "type": "enum", 
            "data": "['top', 'full', 'none']"
        }, 
        {
            "name": "BlockJobInfo", 
            "type": "type", 
            "data": "{'busy': 'bool', 'speed': 'int', 'len': 'int', 'paused': 'bool', 'io-status': 'BlockDeviceIoStatus', 'offset': 'int', 'device': 'str', 'type': 'str'}"
        }, 
        {
            "name": "query-block-jobs", 
            "type": "command", 
            "returns": "['BlockJobInfo']"
        }, 
        {
            "name": "quit", 
            "type": "command"
        }, 
        {
            "name": "stop", 
            "type": "command"
        }, 
        {
            "name": "system_reset", 
            "type": "command"
        }, 
        {
            "name": "system_powerdown", 
            "type": "command"
        }, 
        {
            "name": "cpu", 
            "type": "command", 
            "data": "{'index': 'int'}"
        }, 
        {
            "name": "cpu-add", 
            "type": "command", 
            "data": "{'id': 'int'}"
        }, 
        {
            "name": "memsave", 
            "type": "command", 
            "data": "{'filename': 'str', '*cpu-index': 'int', 'val': 'int', 'size': 'int'}"
        }, 
        {
            "name": "pmemsave", 
            "type": "command", 
            "data": "{'filename': 'str', 'val': 'int', 'size': 'int'}"
        }, 
        {
            "name": "cont", 
            "type": "command"
        }, 
        {
            "name": "system_wakeup", 
            "type": "command"
        }, 
        {
            "name": "inject-nmi", 
            "type": "command"
        }, 
        {
            "name": "set_link", 
            "type": "command", 
            "data": "{'name': 'str', 'up': 'bool'}"
        }, 
        {
            "name": "block_passwd", 
            "type": "command", 
            "data": "{'device': 'str', 'password': 'str'}"
        }, 
        {
            "name": "balloon", 
            "type": "command", 
            "data": "{'value': 'int'}"
        }, 
        {
            "name": "block_resize", 
            "type": "command", 
            "data": "{'device': 'str', 'size': 'int'}"
        }, 
        {
            "name": "NewImageMode", 
            "type": "enum", 
            "data": "['existing', 'absolute-paths']"
        }, 
        {
            "name": "BlockdevSnapshot", 
            "type": "type", 
            "data": "{'device': 'str', '*format': 'str', 'snapshot-file': 'str', '*mode': 'NewImageMode'}"
        }, 
        {
            "name": "TransactionAction", 
            "type": "union", 
            "data": "{'blockdev-snapshot-sync': 'BlockdevSnapshot'}"
        }, 
        {
            "name": "transaction", 
            "type": "command", 
            "data": "{'actions': ['TransactionAction']}"
        }, 
        {
            "name": "blockdev-snapshot-sync", 
            "type": "command", 
            "data": "{'device': 'str', '*format': 'str', 'snapshot-file': 'str', '*mode': 'NewImageMode'}"
        }, 
        {
            "name": "human-monitor-command", 
            "type": "command", 
            "returns": "str", 
            "data": "{'*cpu-index': 'int', 'command-line': 'str'}"
        }, 
        {
            "name": "block-commit", 
            "type": "command", 
            "data": "{'device': 'str', 'top': 'str', '*base': 'str', '*speed': 'int'}"
        }, 
        {
            "name": "drive-mirror", 
            "type": "command", 
            "data": "{'*on-target-error': 'BlockdevOnError', '*buf-size': 'int', 'target': 'str', '*granularity': 'uint32', '*format': 'str', '*speed': 'int', 'sync': 'MirrorSyncMode', '*mode': 'NewImageMode', 'device': 'str', '*on-source-error': 'BlockdevOnError'}"
        }, 
        {
            "name": "migrate_cancel", 
            "type": "command"
        }, 
        {
            "name": "migrate_set_downtime", 
            "type": "command", 
            "data": "{'value': 'number'}"
        }, 
        {
            "name": "migrate_set_speed", 
            "type": "command", 
            "data": "{'value': 'int'}"
        }, 
        {
            "name": "migrate-set-cache-size", 
            "type": "command", 
            "data": "{'value': 'int'}"
        }, 
        {
            "name": "query-migrate-cache-size", 
            "type": "command", 
            "returns": "int"
        }, 
        {
            "name": "ObjectPropertyInfo", 
            "type": "type", 
            "data": "{'type': 'str', 'name': 'str'}"
        }, 
        {
            "name": "qom-list", 
            "type": "command", 
            "returns": "['ObjectPropertyInfo']", 
            "data": "{'path': 'str'}"
        }, 
        {
            "name": "qom-get", 
            "type": "command", 
            "returns": "visitor", 
            "data": "{'path': 'str', 'property': 'str'}"
        }, 
        {
            "name": "qom-set", 
            "type": "command", 
            "data": "{'path': 'str', 'property': 'str', 'value': 'visitor'}"
        }, 
        {
            "name": "set_password", 
            "type": "command", 
            "data": "{'password': 'str', 'protocol': 'str', '*connected': 'str'}"
        }, 
        {
            "name": "expire_password", 
            "type": "command", 
            "data": "{'protocol': 'str', 'time': 'str'}"
        }, 
        {
            "name": "eject", 
            "type": "command", 
            "data": "{'device': 'str', '*force': 'bool'}"
        }, 
        {
            "name": "change-vnc-password", 
            "type": "command", 
            "data": "{'password': 'str'}"
        }, 
        {
            "name": "change", 
            "type": "command", 
            "data": "{'device': 'str', 'target': 'str', '*arg': 'str'}"
        }, 
        {
            "name": "block_set_io_throttle", 
            "type": "command", 
            "data": "{'bps_rd': 'int', 'bps_wr': 'int', 'bps': 'int', 'iops': 'int', 'iops_rd': 'int', 'device': 'str', 'iops_wr': 'int'}"
        }, 
        {
            "name": "block-stream", 
            "type": "command", 
            "data": "{'device': 'str', '*on-error': 'BlockdevOnError', '*base': 'str', '*speed': 'int'}"
        }, 
        {
            "name": "block-job-set-speed", 
            "type": "command", 
            "data": "{'device': 'str', 'speed': 'int'}"
        }, 
        {
            "name": "block-job-cancel", 
            "type": "command", 
            "data": "{'device': 'str', '*force': 'bool'}"
        }, 
        {
            "name": "block-job-pause", 
            "type": "command", 
            "data": "{'device': 'str'}"
        }, 
        {
            "name": "block-job-resume", 
            "type": "command", 
            "data": "{'device': 'str'}"
        }, 
        {
            "name": "block-job-complete", 
            "type": "command", 
            "data": "{'device': 'str'}"
        }, 
        {
            "name": "ObjectTypeInfo", 
            "type": "type", 
            "data": "{'name': 'str'}"
        }, 
        {
            "name": "qom-list-types", 
            "type": "command", 
            "returns": "['ObjectTypeInfo']", 
            "data": "{'*abstract': 'bool', '*implements': 'str'}"
        }, 
        {
            "name": "DevicePropertyInfo", 
            "type": "type", 
            "data": "{'type': 'str', 'name': 'str'}"
        }, 
        {
            "name": "device-list-properties", 
            "type": "command", 
            "returns": "['DevicePropertyInfo']", 
            "data": "{'typename': 'str'}"
        }, 
        {
            "name": "migrate", 
            "type": "command", 
            "data": "{'*detach': 'bool', 'uri': 'str', '*inc': 'bool', '*blk': 'bool'}"
        }, 
        {
            "name": "xen-save-devices-state", 
            "type": "command", 
            "data": "{'filename': 'str'}"
        }, 
        {
            "name": "xen-set-global-dirty-log", 
            "type": "command", 
            "data": "{'enable': 'bool'}"
        }, 
        {
            "name": "device_del", 
            "type": "command", 
            "data": "{'id': 'str'}"
        }, 
        {
            "name": "dump-guest-memory", 
            "type": "command", 
            "data": "{'*length': 'int', 'paging': 'bool', 'protocol': 'str', '*begin': 'int'}"
        }, 
        {
            "name": "netdev_add", 
            "type": "command", 
            "data": "{'*props': '**', 'type': 'str', 'id': 'str'}"
        }, 
        {
            "name": "netdev_del", 
            "type": "command", 
            "data": "{'id': 'str'}"
        }, 
        {
            "name": "NetdevNoneOptions", 
            "type": "type", 
            "data": "{}"
        }, 
        {
            "name": "NetLegacyNicOptions", 
            "type": "type", 
            "data": "{'*macaddr': 'str', '*model': 'str', '*addr': 'str', '*vectors': 'uint32', '*netdev': 'str'}"
        }, 
        {
            "name": "String", 
            "type": "type", 
            "data": "{'str': 'str'}"
        }, 
        {
            "name": "NetdevUserOptions", 
            "type": "type", 
            "data": "{'*hostname': 'str', '*tftp': 'str', '*dhcpstart': 'str', '*guestfwd': ['String'], '*smbserver': 'str', '*hostfwd': ['String'], '*host': 'str', '*net': 'str', '*restrict': 'bool', '*dnssearch': ['String'], '*ip': 'str', '*dns': 'str', '*smb': 'str', '*bootfile': 'str'}"
        }, 
        {
            "name": "NetdevTapOptions", 
            "type": "type", 
            "data": "{'*vhostfd': 'str', '*script': 'str', '*helper': 'str', '*vhostfds': 'str', '*vnet_hdr': 'bool', '*downscript': 'str', '*queues': 'uint32', '*fd': 'str', '*vhostforce': 'bool', '*ifname': 'str', '*fds': 'str', '*vhost': 'bool', '*sndbuf': 'size'}"
        }, 
        {
            "name": "NetdevSocketOptions", 
            "type": "type", 
            "data": "{'*mcast': 'str', '*connect': 'str', '*fd': 'str', '*listen': 'str', '*udp': 'str', '*localaddr': 'str'}"
        }, 
        {
            "name": "NetdevVdeOptions", 
            "type": "type", 
            "data": "{'*mode': 'uint16', '*group': 'str', '*port': 'uint16', '*sock': 'str'}"
        }, 
        {
            "name": "NetdevDumpOptions", 
            "type": "type", 
            "data": "{'*len': 'size', '*file': 'str'}"
        }, 
        {
            "name": "NetdevBridgeOptions", 
            "type": "type", 
            "data": "{'*helper': 'str', '*br': 'str'}"
        }, 
        {
            "name": "NetdevHubPortOptions", 
            "type": "type", 
            "data": "{'hubid': 'int32'}"
        }, 
        {
            "name": "NetClientOptions", 
            "type": "union", 
            "data": "{'bridge': 'NetdevBridgeOptions', 'none': 'NetdevNoneOptions', 'tap': 'NetdevTapOptions', 'socket': 'NetdevSocketOptions', 'dump': 'NetdevDumpOptions', 'nic': 'NetLegacyNicOptions', 'vde': 'NetdevVdeOptions', 'user': 'NetdevUserOptions', 'hubport': 'NetdevHubPortOptions'}"
        }, 
        {
            "name": "NetLegacy", 
            "type": "type", 
            "data": "{'*id': 'str', '*vlan': 'int32', '*name': 'str', 'opts': 'NetClientOptions'}"
        }, 
        {
            "name": "Netdev", 
            "type": "type", 
            "data": "{'id': 'str', 'opts': 'NetClientOptions'}"
        }, 
        {
            "name": "InetSocketAddress", 
            "type": "type", 
            "data": "{'*ipv6': 'bool', 'host': 'str', '*to': 'uint16', 'port': 'str', '*ipv4': 'bool'}"
        }, 
        {
            "name": "UnixSocketAddress", 
            "type": "type", 
            "data": "{'path': 'str'}"
        }, 
        {
            "name": "SocketAddress", 
            "type": "union", 
            "data": "{'unix': 'UnixSocketAddress', 'fd': 'String', 'inet': 'InetSocketAddress'}"
        }, 
        {
            "name": "getfd", 
            "type": "command", 
            "data": "{'fdname': 'str'}"
        }, 
        {
            "name": "closefd", 
            "type": "command", 
            "data": "{'fdname': 'str'}"
        }, 
        {
            "name": "MachineInfo", 
            "type": "type", 
            "data": "{'*alias': 'str', '*is-default': 'bool', 'cpu-max': 'int', 'name': 'str'}"
        }, 
        {
            "name": "query-machines", 
            "type": "command", 
            "returns": "['MachineInfo']"
        }, 
        {
            "name": "CpuDefinitionInfo", 
            "type": "type", 
            "data": "{'name': 'str'}"
        }, 
        {
            "name": "query-cpu-definitions", 
            "type": "command", 
            "returns": "['CpuDefinitionInfo']"
        }, 
        {
            "name": "AddfdInfo", 
            "type": "type", 
            "data": "{'fdset-id': 'int', 'fd': 'int'}"
        }, 
        {
            "name": "add-fd", 
            "type": "command", 
            "returns": "AddfdInfo", 
            "data": "{'*opaque': 'str', '*fdset-id': 'int'}"
        }, 
        {
            "name": "remove-fd", 
            "type": "command", 
            "data": "{'fdset-id': 'int', '*fd': 'int'}"
        }, 
        {
            "name": "FdsetFdInfo", 
            "type": "type", 
            "data": "{'*opaque': 'str', 'fd': 'int'}"
        }, 
        {
            "name": "FdsetInfo", 
            "type": "type", 
            "data": "{'fdset-id': 'int', 'fds': ['FdsetFdInfo']}"
        }, 
        {
            "name": "query-fdsets", 
            "type": "command", 
            "returns": "['FdsetInfo']"
        }, 
        {
            "name": "TargetType", 
            "type": "enum", 
            "data": "['alpha', 'arm', 'cris', 'i386', 'lm32', 'm68k', 'microblazeel', 'microblaze', 'mips64el', 'mips64', 'mipsel', 'mips', 'moxie', 'or32', 'ppc64', 'ppcemb', 'ppc', 's390x', 'sh4eb', 'sh4', 'sparc64', 'sparc', 'unicore32', 'x86_64', 'xtensaeb', 'xtensa']"
        }, 
        {
            "name": "TargetInfo", 
            "type": "type", 
            "data": "{'arch': 'TargetType'}"
        }, 
        {
            "name": "query-target", 
            "type": "command", 
            "returns": "TargetInfo"
        }, 
        {
            "name": "QKeyCode", 
            "type": "enum", 
            "data": "['shift', 'shift_r', 'alt', 'alt_r', 'altgr', 'altgr_r', 'ctrl', 'ctrl_r', 'menu', 'esc', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'minus', 'equal', 'backspace', 'tab', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', 'bracket_left', 'bracket_right', 'ret', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'semicolon', 'apostrophe', 'grave_accent', 'backslash', 'z', 'x', 'c', 'v', 'b', 'n', 'm', 'comma', 'dot', 'slash', 'asterisk', 'spc', 'caps_lock', 'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'f10', 'num_lock', 'scroll_lock', 'kp_divide', 'kp_multiply', 'kp_subtract', 'kp_add', 'kp_enter', 'kp_decimal', 'sysrq', 'kp_0', 'kp_1', 'kp_2', 'kp_3', 'kp_4', 'kp_5', 'kp_6', 'kp_7', 'kp_8', 'kp_9', 'less', 'f11', 'f12', 'print', 'home', 'pgup', 'pgdn', 'end', 'left', 'up', 'down', 'right', 'insert', 'delete', 'stop', 'again', 'props', 'undo', 'front', 'copy', 'open', 'paste', 'find', 'cut', 'lf', 'help', 'meta_l', 'meta_r', 'compose']"
        }, 
        {
            "name": "KeyValue", 
            "type": "union", 
            "data": "{'qcode': 'QKeyCode', 'number': 'int'}"
        }, 
        {
            "name": "send-key", 
            "type": "command", 
            "data": "{'keys': ['KeyValue'], '*hold-time': 'int'}"
        }, 
        {
            "name": "screendump", 
            "type": "command", 
            "data": "{'filename': 'str'}"
        }, 
        {
            "name": "nbd-server-start", 
            "type": "command", 
            "data": "{'addr': 'SocketAddress'}"
        }, 
        {
            "name": "nbd-server-add", 
            "type": "command", 
            "data": "{'device': 'str', '*writable': 'bool'}"
        }, 
        {
            "name": "nbd-server-stop", 
            "type": "command"
        }, 
        {
            "name": "ChardevFile", 
            "type": "type", 
            "data": "{'*in': 'str', 'out': 'str'}"
        }, 
        {
            "name": "ChardevHostdev", 
            "type": "type", 
            "data": "{'device': 'str'}"
        }, 
        {
            "name": "ChardevSocket", 
            "type": "type", 
            "data": "{'*nodelay': 'bool', '*wait': 'bool', '*server': 'bool', 'addr': 'SocketAddress', '*telnet': 'bool'}"
        }, 
        {
            "name": "ChardevUdp", 
            "type": "type", 
            "data": "{'*local': 'SocketAddress', 'remote': 'SocketAddress'}"
        }, 
        {
            "name": "ChardevMux", 
            "type": "type", 
            "data": "{'chardev': 'str'}"
        }, 
        {
            "name": "ChardevStdio", 
            "type": "type", 
            "data": "{'*signal': 'bool'}"
        }, 
        {
            "name": "ChardevSpiceChannel", 
            "type": "type", 
            "data": "{'type': 'str'}"
        }, 
        {
            "name": "ChardevSpicePort", 
            "type": "type", 
            "data": "{'fqdn': 'str'}"
        }, 
        {
            "name": "ChardevVC", 
            "type": "type", 
            "data": "{'*width': 'int', '*height': 'int', '*cols': 'int', '*rows': 'int'}"
        }, 
        {
            "name": "ChardevMemory", 
            "type": "type", 
            "data": "{'*size': 'int'}"
        }, 
        {
            "name": "ChardevDummy", 
            "type": "type", 
            "data": "{}"
        }, 
        {
            "name": "ChardevBackend", 
            "type": "union", 
            "data": "{'udp': 'ChardevUdp', 'vc': 'ChardevVC', 'console': 'ChardevDummy', 'socket': 'ChardevSocket', 'braille': 'ChardevDummy', 'stdio': 'ChardevStdio', 'spiceport': 'ChardevSpicePort', 'mux': 'ChardevMux', 'pipe': 'ChardevHostdev', 'msmouse': 'ChardevDummy', 'file': 'ChardevFile', 'memory': 'ChardevMemory', 'spicevmc': 'ChardevSpiceChannel', 'serial': 'ChardevHostdev', 'null': 'ChardevDummy', 'parallel': 'ChardevHostdev', 'pty': 'ChardevDummy'}"
        }, 
        {
            "name": "ChardevReturn", 
            "type": "type", 
            "data": "{'*pty': 'str'}"
        }, 
        {
            "name": "chardev-add", 
            "type": "command", 
            "returns": "ChardevReturn", 
            "data": "{'id': 'str', 'backend': 'ChardevBackend'}"
        }, 
        {
            "name": "chardev-remove", 
            "type": "command", 
            "data": "{'id': 'str'}"
        }, 
        {
            "name": "TpmModel", 
            "type": "enum", 
            "data": "['tpm-tis']"
        }, 
        {
            "name": "query-tpm-models", 
            "type": "command", 
            "returns": "['TpmModel']"
        }, 
        {
            "name": "TpmType", 
            "type": "enum", 
            "data": "['passthrough']"
        }, 
        {
            "name": "query-tpm-types", 
            "type": "command", 
            "returns": "['TpmType']"
        }, 
        {
            "name": "TPMPassthroughOptions", 
            "type": "type", 
            "data": "{'*cancel-path': 'str', '*path': 'str'}"
        }, 
        {
            "name": "TpmTypeOptions", 
            "type": "union", 
            "data": "{'passthrough': 'TPMPassthroughOptions'}"
        }, 
        {
            "name": "TPMInfo", 
            "type": "type", 
            "data": "{'model': 'TpmModel', 'id': 'str', 'options': 'TpmTypeOptions'}"
        }, 
        {
            "name": "query-tpm", 
            "type": "command", 
            "returns": "['TPMInfo']"
        }, 
        {
            "name": "AcpiTableOptions", 
            "type": "type", 
            "data": "{'*asl_compiler_rev': 'uint32', '*oem_rev': 'uint32', '*sig': 'str', '*file': 'str', '*data': 'str', '*rev': 'uint8', '*asl_compiler_id': 'str', '*oem_table_id': 'str', '*oem_id': 'str'}"
        }, 
        {
            "name": "CommandLineParameterType", 
            "type": "enum", 
            "data": "['string', 'boolean', 'number', 'size']"
        }, 
        {
            "name": "CommandLineParameterInfo", 
            "type": "type", 
            "data": "{'type': 'CommandLineParameterType', 'name': 'str', '*help': 'str'}"
        }, 
        {
            "name": "CommandLineOptionInfo", 
            "type": "type", 
            "data": "{'option': 'str', 'parameters': ['CommandLineParameterInfo']}"
        }, 
        {
            "name": "query-command-line-options", 
            "type": "command", 
            "returns": "['CommandLineOptionInfo']", 
            "data": "{'*option': 'str'}"
        }, 
        {
            "name": "X86CPURegister32", 
            "type": "enum", 
            "data": "['EAX', 'EBX', 'ECX', 'EDX', 'ESP', 'EBP', 'ESI', 'EDI']"
        }, 
        {
            "name": "X86CPUFeatureWordInfo", 
            "type": "type", 
            "data": "{'cpuid-register': 'X86CPURegister32', '*cpuid-input-ecx': 'int', 'cpuid-input-eax': 'int', 'features': 'int'}"
        }, 
        {
            "name": "SchemaData", 
            "type": "type", 
            "data": "{'*returns': 'str', 'type': 'str', 'name': 'str', '*data': 'str'}"
        }, 
        {
            "name": "query-qmp-schema", 
            "type": "command", 
            "returns": "['SchemaData']", 
            "data": "{'*name': 'str', '*type': 'str'}"
        }
    ]
}


[-- Attachment #4: 0001-full-introspection-support-for-QMP.patch --]
[-- Type: text/plain, Size: 7344 bytes --]

>From 2b39fe0f380eea6a96de3589b3d148673d28c1ff Mon Sep 17 00:00:00 2001
From: Amos Kong <akong@redhat.com>
Date: Fri, 7 Jun 2013 18:02:21 +0800
Subject: [PATCH] full introspection support for QMP

Signed-off-by: Amos Kong <akong@redhat.com>
---
 qapi-schema.json         |  6 ++++++
 qmp-commands.hx          | 23 +++++++++++++++++++++++
 qmp.c                    | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 scripts/qapi-commands.py |  2 +-
 scripts/qapi-types.py    | 42 +++++++++++++++++++++++++++++++++++++++++-
 scripts/qapi-visit.py    |  2 +-
 scripts/qapi.py          | 13 ++++++++++++-
 7 files changed, 130 insertions(+), 4 deletions(-)

diff --git a/qapi-schema.json b/qapi-schema.json
index ef1f657..128cc58 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3618,3 +3618,9 @@
             '*cpuid-input-ecx': 'int',
             'cpuid-register': 'X86CPURegister32',
             'features': 'int' } }
+
+{ 'type': 'SchemaData',
+  'data': { 'type': 'str', 'name': 'str', '*data': 'str', '*returns': 'str' } }
+
+{ 'command': 'query-qmp-schema', 'data': { '*type': 'str', '*name': 'str' },
+  'returns': ['SchemaData'] }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index ffd130e..fc56fba 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -2932,3 +2932,26 @@ Example:
 <- { "return": {} }
 
 EQMP
+
+    {
+        .name       = "query-qmp-schema",
+        .args_type  = "type:s?,name:s?",
+        .mhandler.cmd_new = qmp_marshal_input_query_qmp_schema,
+    },
+
+
+SQMP
+query-qmp-schema
+----------------
+
+query qmp schema information
+
+Example:
+
+-> { "execute": "query-qmp-schema", "arguments": { "name" : "query-name" }}
+<- { "return": [
+        "{ 'command': 'query-name', 'returns': 'NameInfo' }"
+      ]
+   }
+
+EQMP
\ No newline at end of file
diff --git a/qmp.c b/qmp.c
index 4c149b3..c062f88 100644
--- a/qmp.c
+++ b/qmp.c
@@ -25,6 +25,7 @@
 #include "sysemu/blockdev.h"
 #include "qom/qom-qobject.h"
 #include "hw/boards.h"
+#include "qmp-schema.h"
 
 NameInfo *qmp_query_name(Error **errp)
 {
@@ -486,6 +487,51 @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
     return arch_query_cpu_definitions(errp);
 }
 
+SchemaDataList * qmp_query_qmp_schema(bool has_type, const char * type,
+                                      bool has_name, const char * name,
+                                      Error **errp)
+{
+    SchemaDataList *list = NULL, *last_entry, *entry;
+    SchemaData *info;
+    int i;
+
+    for (i = 0; qmp_schema_table[i].type; i++) {
+        if (has_type && strcmp(type, qmp_schema_table[i].type)) {
+            continue;
+        }
+        if (has_name && strcmp(name, qmp_schema_table[i].name)) {
+            continue;
+        }
+
+        info = g_malloc0(sizeof(*info));
+        info->type = g_strdup(qmp_schema_table[i].type);
+        info->name = g_strdup(qmp_schema_table[i].name);
+
+        if (qmp_schema_table[i].data && strlen(qmp_schema_table[i].data) > 0) {
+            info->has_data = true;
+        }
+        info->data = g_strdup(qmp_schema_table[i].data);
+
+        if (qmp_schema_table[i].returns && strlen(qmp_schema_table[i].returns) > 0) {
+            info->has_returns = true;
+        }
+        info->returns = g_strdup(qmp_schema_table[i].returns);
+
+        entry = malloc(sizeof(SchemaDataList *));
+        entry->value = info;
+        entry->next = NULL;
+
+        if (!list) {
+            list = entry;
+        } else {
+            last_entry->next = entry;
+        }
+        last_entry = entry;
+    }
+
+    return list;
+}
+
 void qmp_add_client(const char *protocol, const char *fdname,
                     bool has_skipauth, bool skipauth, bool has_tls, bool tls,
                     Error **errp)
diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
index e06332b..d15d04f 100644
--- a/scripts/qapi-commands.py
+++ b/scripts/qapi-commands.py
@@ -437,7 +437,7 @@ except os.error, e:
     if e.errno != errno.EEXIST:
         raise
 
-exprs = parse_schema(sys.stdin)
+exprs = parse_schema(sys.stdin)[0]
 commands = filter(lambda expr: expr.has_key('command'), exprs)
 commands = filter(lambda expr: not expr.has_key('gen'), commands)
 
diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index ddcfed9..30e7e56 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -15,6 +15,7 @@ import sys
 import os
 import getopt
 import errno
+import re
 
 def generate_fwd_struct(name, members, builtin_type=False):
     if builtin_type:
@@ -303,7 +304,46 @@ fdecl.write(mcgen('''
 ''',
                   guard=guardname(h_file)))
 
-exprs = parse_schema(sys.stdin)
+exprs_all = parse_schema(sys.stdin)
+
+schema_table = """
+/* convert qapi-schema.json to a string table */
+
+struct qmp_schem {
+const char *type;
+const char *name;
+const char *data;
+const char *returns;
+} qmp_schema_table[] = {
+"""
+
+for i in exprs_all[1]:
+    print i
+
+    data = returns = ""
+    type = i.keys()[0]
+    name = i[type]
+    for k in i.keys():
+        if isinstance(i[k], OrderedDict):
+            ret = {}
+            for key in i[k]:
+                ret[key] = i[k][key]
+            i[k] = ret
+
+    if i.has_key('data'):
+        data = i['data']
+    if i.has_key('returns'):
+        returns = i['returns']
+
+    schema_table += '{"%s", "%s", "%s", "%s"},\n' % (type, name, data, returns)
+
+schema_table += '{NULL, NULL, NULL } };\n'
+
+f = open("qmp-schema.h", "w")
+f.write(schema_table)
+f.close()
+
+exprs = exprs_all[0]
 exprs = filter(lambda expr: not expr.has_key('gen'), exprs)
 
 fdecl.write(guardstart("QAPI_TYPES_BUILTIN_STRUCT_DECL"))
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index 6cac05a..70f80eb 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -334,7 +334,7 @@ fdecl.write(mcgen('''
 ''',
                   prefix=prefix, guard=guardname(h_file)))
 
-exprs = parse_schema(sys.stdin)
+exprs = parse_schema(sys.stdin)[0]
 
 # to avoid header dependency hell, we always generate declarations
 # for built-in types in our header files and simply guard them
diff --git a/scripts/qapi.py b/scripts/qapi.py
index 02ad668..076b5dc 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -80,6 +80,7 @@ def evaluate(string):
 
 def parse_schema(fp):
     exprs = []
+    raw_exprs = []
     expr = ''
     expr_eval = None
 
@@ -91,6 +92,11 @@ def parse_schema(fp):
             expr += line
         elif expr:
             expr_eval = evaluate(expr)
+
+            for name in ['command', 'type', 'enum', 'union']:
+                if expr_eval.has_key(name):
+                    raw_exprs.append(expr_eval)
+
             if expr_eval.has_key('enum'):
                 add_enum(expr_eval['enum'])
             elif expr_eval.has_key('union'):
@@ -102,13 +108,18 @@ def parse_schema(fp):
 
     if expr:
         expr_eval = evaluate(expr)
+
+        for name in ['command', 'type', 'enum', 'union']:
+            if expr_eval.has_key(name):
+                raw_exprs.append(expr_eval)
+
         if expr_eval.has_key('enum'):
             add_enum(expr_eval['enum'])
         elif expr_eval.has_key('union'):
             add_enum('%sKind' % expr_eval['union'])
         exprs.append(expr_eval)
 
-    return exprs
+    return exprs, raw_exprs
 
 def parse_args(typeinfo):
     for member in typeinfo:
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] RFC: Full introspection support for QMP (with draft patch)
  2013-06-14  9:52     ` Amos Kong
@ 2013-06-14 10:59       ` Eric Blake
  2013-06-14 11:09       ` Eric Blake
  1 sibling, 0 replies; 19+ messages in thread
From: Eric Blake @ 2013-06-14 10:59 UTC (permalink / raw)
  To: Amos Kong
  Cc: aliguori, mdroth, Markus Armbruster, qemu-devel, qiaonuohan,
	Ronen Hod, lcapitulino

[-- Attachment #1: Type: text/plain, Size: 3495 bytes --]

On 06/14/2013 10:52 AM, Amos Kong wrote:
> On Fri, Jun 07, 2013 at 06:17:26PM +0800, Amos Kong wrote:
>> On Fri, Jun 07, 2013 at 06:12:30PM +0800, Amos Kong wrote:
>>> Sent out a draft patch in the end of this week. It doesn't support:
>>> * output all stuffs in one shot.
>>> * introspect event
>>> * provide metadata date
>>>
>>> How can we define a dynamic dict in qmp-schema.json ?
>>>
>>> Currently I just output the raw json dict by a string, Libvirt needs
>>> parse two times, convert the string to json format.
>>>
>>> qmp-schema.h: auto generated head file by qapi script
>>>
>>> Attached some examples.
> 
> 
> Hello all,
> 
> I defined a new type 'SchemaData', it contains 4 keys (type, name, data, returns)
> 
> | { 'type': 'SchemaData',
> |   'data': { 'type': 'str', 'name': 'str', '*data': 'str', '*returns': 'str' } }

It seems like 'type' should be an enum rather than an open-coded 'str'.

Returning 'data' and 'returns' as an open-coded 'str' is not nice - it
requires the client to do further parsing.  I was serious when I
suggested adding additional layers of formalized structure to the
result.  My suggestion was something 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' ] } }

> | 
> | { 'command': 'query-qmp-schema', 'data': { '*type': 'str', '*name': 'str' },
> |   'returns': ['SchemaData'] }


I'm still not sure whether optional filtering will be used by libvirt,
or if it adds any complexity on your end (I'm not opposed to it, but I
know that there hasn't been universal agreement on filtering queries yet).

Again, it seems like 'type' should be an enum.  Something like:

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

> 
> Then we can provice meaningful result to Libvirt. Currently I set a string
> for SchemaData['data'].
> 
> 
> I tried to define a dynamical dict for 'data', but it's failed. 
> 
> | { 'type': 'SchemaData',
> |   'data': { 'type': 'str', 'name': 'str', '*data': '**', '*returns': 'str' } }  (Failed!!)
> 
> 
> Does qapi support to define a dynamical dict, then I can convert dict string
> and set to SchemaData['data'] ?

Rather, you want to take an arbitrary dict, and turn it into an array
describing each key of the dict.  That is, given the .json file containing:

{ 'command': 'add_client',
  'data': { 'protocol': 'str', 'fdname': 'str', '*skipauth': 'bool',
            '*tls': 'bool' } }

you would create an array of four members, describing each of the four
dict members, resulting in this exchange:

=> { "execute": "query-qmp-schema",
     "arguments": { "name": "add_client" } }
<= { "return": [
     { "name": "add_client",
       "type": "command",
       "data": [
         { "name": "protocol",
           "type": "str" },
         { "name": "fdname",
           "type": "str" },
         { "name": "skipauth",
           "type": "bool",
           "optional": true },
         { "name": "tls",
           "type": "bool",
           "optional": true }
       ] } ] }

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


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 621 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] RFC: Full introspection support for QMP (with draft patch)
  2013-06-14  9:52     ` Amos Kong
  2013-06-14 10:59       ` Eric Blake
@ 2013-06-14 11:09       ` Eric Blake
  2013-06-18 12:21         ` Amos Kong
  1 sibling, 1 reply; 19+ messages in thread
From: Eric Blake @ 2013-06-14 11:09 UTC (permalink / raw)
  To: Amos Kong
  Cc: aliguori, mdroth, Markus Armbruster, qemu-devel, qiaonuohan,
	Ronen Hod, lcapitulino

[-- Attachment #1: Type: text/plain, Size: 2878 bytes --]

On 06/14/2013 10:52 AM, Amos Kong wrote:

>>From 2b39fe0f380eea6a96de3589b3d148673d28c1ff Mon Sep 17 00:00:00 2001
> From: Amos Kong <akong@redhat.com>
> Date: Fri, 7 Jun 2013 18:02:21 +0800
> Subject: [PATCH] full introspection support for QMP
> 
> Signed-off-by: Amos Kong <akong@redhat.com>
> ---
>  qapi-schema.json         |  6 ++++++
>  qmp-commands.hx          | 23 +++++++++++++++++++++++
>  qmp.c                    | 46 ++++++++++++++++++++++++++++++++++++++++++++++
>  scripts/qapi-commands.py |  2 +-
>  scripts/qapi-types.py    | 42 +++++++++++++++++++++++++++++++++++++++++-
>  scripts/qapi-visit.py    |  2 +-
>  scripts/qapi.py          | 13 ++++++++++++-
>  7 files changed, 130 insertions(+), 4 deletions(-)
> 
> diff --git a/qapi-schema.json b/qapi-schema.json
> index ef1f657..128cc58 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -3618,3 +3618,9 @@
>              '*cpuid-input-ecx': 'int',
>              'cpuid-register': 'X86CPURegister32',
>              'features': 'int' } }
> +
> +{ 'type': 'SchemaData',
> +  'data': { 'type': 'str', 'name': 'str', '*data': 'str', '*returns': 'str' } }
> +
> +{ 'command': 'query-qmp-schema', 'data': { '*type': 'str', '*name': 'str' },
> +  'returns': ['SchemaData'] }

Needs documentation, and a since 1.6 notation in the docs (assuming that
we still make it in time for 1.6).  Also, see my other mail complaining
that this is not structured enough, yet.

> diff --git a/qmp-commands.hx b/qmp-commands.hx
> index ffd130e..fc56fba 100644
> --- a/qmp-commands.hx
> +++ b/qmp-commands.hx
> @@ -2932,3 +2932,26 @@ Example:

> +
> +EQMP
> \ No newline at end of file

Fix that.


>  }
>  
> +SchemaDataList * qmp_query_qmp_schema(bool has_type, const char * type,

No space after '*' when declaring a pointer return or pointer argument.
 Should be:

SchemaDataList *qmp_query_qmp_schema(bool has_type, const char *type,

> +++ b/scripts/qapi-types.py

> +
> +struct qmp_schem {

Aren't structs supposed to be named in CamelCase?

> +const char *type;
> +const char *name;
> +const char *data;
> +const char *returns;
> +} qmp_schema_table[] = {
> +"""
> +
> +for i in exprs_all[1]:
> +    print i
> +
> +    data = returns = ""
> +    type = i.keys()[0]
> +    name = i[type]
> +    for k in i.keys():
> +        if isinstance(i[k], OrderedDict):
> +            ret = {}
> +            for key in i[k]:
> +                ret[key] = i[k][key]
> +            i[k] = ret
> +
> +    if i.has_key('data'):
> +        data = i['data']

I think this is where you'd need to do more processing of data to spit
it out in a more structured format, but my python is too weak to
actually write that conversion.

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


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 621 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] RFC: Full introspection support for QMP (with draft patch)
  2013-06-14 11:09       ` Eric Blake
@ 2013-06-18 12:21         ` Amos Kong
  0 siblings, 0 replies; 19+ messages in thread
From: Amos Kong @ 2013-06-18 12:21 UTC (permalink / raw)
  To: Eric Blake
  Cc: aliguori, mdroth, Markus Armbruster, qemu-devel, qiaonuohan,
	Ronen Hod, lcapitulino

On Fri, Jun 14, 2013 at 12:09:33PM +0100, Eric Blake wrote:
> On 06/14/2013 10:52 AM, Amos Kong wrote:

> > +const char *type;
> > +const char *name;
> > +const char *data;
> > +const char *returns;
> > +} qmp_schema_table[] = {
> > +"""
> > +
> > +for i in exprs_all[1]:
> > +    print i
> > +
> > +    data = returns = ""
> > +    type = i.keys()[0]
> > +    name = i[type]
> > +    for k in i.keys():
> > +        if isinstance(i[k], OrderedDict):
> > +            ret = {}
> > +            for key in i[k]:
> > +                ret[key] = i[k][key]
> > +            i[k] = ret
> > +
> > +    if i.has_key('data'):
> > +        data = i['data']
> 
> I think this is where you'd need to do more processing of data to spit
> it out in a more structured format, but my python is too weak to
> actually write that conversion.

I found a solution :-)

 Generate a string array in C head file to record the raw json string;
 Convert each json string to QObject, and convert the QObject to QDict
 for traversal by recursion;

 Define a new type and uion [1] to describe dynamical date for QMP.
 and allocate & connect nested members in recursion function.

 Finally, we can provide dynamical data with metadate according the
 definition in json file.

I will send a v1 patch later.


---- [1] ----
{ 'union': 'DataValue', 'data': { 'string': 'str', 'obj': 'DataObj' } }
{ 'type': 'DataObj', 'data': { '*key': 'str', 'value': 'DataValue' } }
{ 'type': 'SchemaData',
  'data': { 'type': 'str', 'name': 'str', '*data': ['DataObj'], '*returns': ['DataObj'] } }

-- 
			Amos.

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2013-06-18 12:22 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-05-22 13:40 [Qemu-devel] RFC: Full introspection support for QMP Amos Kong
2013-05-22 14:44 ` Kevin Wolf
2013-05-22 16:14   ` Anthony Liguori
2013-05-23  8:18     ` Kevin Wolf
2013-05-23 12:08       ` Anthony Liguori
2013-05-23 12:40         ` Luiz Capitulino
2013-05-23 12:52           ` Anthony Liguori
2013-05-23 12:54         ` Kevin Wolf
2013-05-23 13:52           ` Anthony Liguori
2013-05-23 14:17             ` Eric Blake
2013-05-23 14:29             ` Kevin Wolf
2013-05-22 17:56 ` Luiz Capitulino
2013-05-23 12:58 ` Eric Blake
2013-06-07 10:12 ` [Qemu-devel] RFC: Full introspection support for QMP (with draft patch) Amos Kong
2013-06-07 10:17   ` Amos Kong
2013-06-14  9:52     ` Amos Kong
2013-06-14 10:59       ` Eric Blake
2013-06-14 11:09       ` Eric Blake
2013-06-18 12:21         ` Amos Kong

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.