* [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 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-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 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 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 (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 a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).