634c82c163
The introduction to the QAPI schema is somewhat rambling. Rewrite for clarity. Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Message-Id: <20190913201349.24332-15-armbru@redhat.com>
1624 lines
56 KiB
Plaintext
1624 lines
56 KiB
Plaintext
= How to use the QAPI code generator =
|
|
|
|
Copyright IBM Corp. 2011
|
|
Copyright (C) 2012-2016 Red Hat, Inc.
|
|
|
|
This work is licensed under the terms of the GNU GPL, version 2 or
|
|
later. See the COPYING file in the top-level directory.
|
|
|
|
== Introduction ==
|
|
|
|
QAPI is a native C API within QEMU which provides management-level
|
|
functionality to internal and external users. For external
|
|
users/processes, this interface is made available by a JSON-based wire
|
|
format for the QEMU Monitor Protocol (QMP) for controlling qemu, as
|
|
well as the QEMU Guest Agent (QGA) for communicating with the guest.
|
|
The remainder of this document uses "Client JSON Protocol" when
|
|
referring to the wire contents of a QMP or QGA connection.
|
|
|
|
To map between Client JSON Protocol interfaces and the native C API,
|
|
we generate C code from a QAPI schema. This document describes the
|
|
QAPI schema language, and how it gets mapped to the Client JSON
|
|
Protocol and to C. It additionally provides guidance on maintaining
|
|
Client JSON Protocol compatibility.
|
|
|
|
|
|
== The QAPI schema language ==
|
|
|
|
The QAPI schema defines the Client JSON Protocol's commands and
|
|
events, as well as types used by them. Forward references are
|
|
allowed.
|
|
|
|
It is permissible for the schema to contain additional types not used
|
|
by any commands or events, for the side effect of generated C code
|
|
used internally.
|
|
|
|
There are several kinds of types: simple types (a number of built-in
|
|
types, such as 'int' and 'str'; as well as enumerations), arrays,
|
|
complex types (structs and two flavors of unions), and alternate types
|
|
(a choice between other types).
|
|
|
|
|
|
=== Schema syntax ===
|
|
|
|
Syntax is loosely based on JSON (http://www.ietf.org/rfc/rfc8259.txt).
|
|
Differences:
|
|
|
|
* Comments: start with a hash character (#) that is not part of a
|
|
string, and extend to the end of the line.
|
|
|
|
* Strings are enclosed in 'single quotes', not "double quotes".
|
|
|
|
* Strings are restricted to printable ASCII, and escape sequences to
|
|
just '\\'.
|
|
|
|
* Numbers are not supported.
|
|
|
|
A QAPI schema consists of a series of top-level expressions (JSON
|
|
objects). Code and documentation is generated in schema definition
|
|
order. Code order should not matter.
|
|
|
|
The order of keys within JSON objects does not matter unless
|
|
explicitly noted.
|
|
|
|
There are eight kinds of top-level expressions: 'include', 'pragma',
|
|
'command', 'struct', 'enum', 'union', 'alternate', and 'event'. These
|
|
are discussed in detail below.
|
|
|
|
In the rest of this document, usage lines are given for each
|
|
expression type, with literal strings written in lower case and
|
|
placeholders written in capitals. If a literal string includes a
|
|
prefix of '*', that key/value pair can be omitted from the expression.
|
|
For example, a usage statement that includes '*base':STRUCT-NAME
|
|
means that an expression has an optional key 'base', which if present
|
|
must have a value that forms a struct name.
|
|
|
|
|
|
=== Built-in Types ===
|
|
|
|
The following types are predefined, and map to C as follows:
|
|
|
|
Schema C JSON
|
|
str char * any JSON string, UTF-8
|
|
number double any JSON number
|
|
int int64_t a JSON number without fractional part
|
|
that fits into the C integer type
|
|
int8 int8_t likewise
|
|
int16 int16_t likewise
|
|
int32 int32_t likewise
|
|
int64 int64_t likewise
|
|
uint8 uint8_t likewise
|
|
uint16 uint16_t likewise
|
|
uint32 uint32_t likewise
|
|
uint64 uint64_t likewise
|
|
size uint64_t like uint64_t, except StringInputVisitor
|
|
accepts size suffixes
|
|
bool bool JSON true or false
|
|
null QNull * JSON null
|
|
any QObject * any JSON value
|
|
QType QType JSON string matching enum QType values
|
|
|
|
|
|
=== Include directives ===
|
|
|
|
Usage: { 'include': STRING }
|
|
|
|
The QAPI schema definitions can be modularized using the 'include' directive:
|
|
|
|
{ 'include': 'path/to/file.json' }
|
|
|
|
The directive is evaluated recursively, and include paths are relative to the
|
|
file using the directive. Multiple includes of the same file are
|
|
idempotent. No other keys should appear in the expression, and the include
|
|
value should be a string.
|
|
|
|
As a matter of style, it is a good idea to have all files be
|
|
self-contained, but at the moment, nothing prevents an included file
|
|
from making a forward reference to a type that is only introduced by
|
|
an outer file. The parser may be made stricter in the future to
|
|
prevent incomplete include files.
|
|
|
|
|
|
=== Pragma directives ===
|
|
|
|
Usage: { 'pragma': DICT }
|
|
|
|
The pragma directive lets you control optional generator behavior.
|
|
The dictionary's entries are pragma names and values.
|
|
|
|
Pragma's scope is currently the complete schema. Setting the same
|
|
pragma to different values in parts of the schema doesn't work.
|
|
|
|
Pragma 'doc-required' takes a boolean value. If true, documentation
|
|
is required. Default is false.
|
|
|
|
Pragma 'returns-whitelist' takes a list of command names that may
|
|
violate the rules on permitted return types. Default is none.
|
|
|
|
Pragma 'name-case-whitelist' takes a list of names that may violate
|
|
rules on use of upper- vs. lower-case letters. Default is none.
|
|
|
|
|
|
=== Enumeration types ===
|
|
|
|
Usage: { 'enum': STRING, 'data': ARRAY-OF-STRING }
|
|
{ 'enum': STRING, '*prefix': STRING, 'data': ARRAY-OF-STRING }
|
|
|
|
An enumeration type is a dictionary containing a single 'data' key
|
|
whose value is a list of strings. An example enumeration is:
|
|
|
|
{ 'enum': 'MyEnum', 'data': [ 'value1', 'value2', 'value3' ] }
|
|
|
|
Nothing prevents an empty enumeration, although it is probably not
|
|
useful. The list of strings should be lower case; if an enum name
|
|
represents multiple words, use '-' between words. The string 'max' is
|
|
not allowed as an enum value, and values should not be repeated.
|
|
|
|
The enum constants will be named by using a heuristic to turn the
|
|
type name into a set of underscore separated words. For the example
|
|
above, 'MyEnum' will turn into 'MY_ENUM' giving a constant name
|
|
of 'MY_ENUM_VALUE1' for the first value. If the default heuristic
|
|
does not result in a desirable name, the optional 'prefix' member
|
|
can be used when defining the enum.
|
|
|
|
The enumeration values are passed as strings over the Client JSON
|
|
Protocol, but are encoded as C enum integral values in generated code.
|
|
While the C code starts numbering at 0, it is better to use explicit
|
|
comparisons to enum values than implicit comparisons to 0; the C code
|
|
will also include a generated enum member ending in _MAX for tracking
|
|
the size of the enum, useful when using common functions for
|
|
converting between strings and enum values.
|
|
|
|
For any struct that has a member that will only contain a finite set
|
|
of string values, using an enum type for that member is better than
|
|
open-coding the member to be type 'str'.
|
|
|
|
=== Struct types ===
|
|
|
|
Usage: { 'struct': STRING, 'data': DICT, '*base': STRUCT-NAME }
|
|
|
|
A struct is a dictionary containing a single 'data' key whose value is
|
|
a dictionary; the dictionary may be empty. This corresponds to a
|
|
struct in C or an Object in JSON. Each value of the 'data' dictionary
|
|
must be the name of a type, or a one-element array containing a type
|
|
name. An example of a struct is:
|
|
|
|
{ 'struct': 'MyType',
|
|
'data': { 'member1': 'str', 'member2': 'int', '*member3': 'str' } }
|
|
|
|
The use of '*' as a prefix to the name means the member is optional in
|
|
the corresponding JSON protocol usage.
|
|
|
|
A struct definition can specify another struct as its base.
|
|
In this case, the members of the base type are included as top-level members
|
|
of the new struct's dictionary in the Client JSON Protocol wire
|
|
format. An example definition is:
|
|
|
|
{ 'struct': 'BlockdevOptionsGenericFormat', 'data': { 'file': 'str' } }
|
|
{ 'struct': 'BlockdevOptionsGenericCOWFormat',
|
|
'base': 'BlockdevOptionsGenericFormat',
|
|
'data': { '*backing': 'str' } }
|
|
|
|
An example BlockdevOptionsGenericCOWFormat object on the wire could use
|
|
both members like this:
|
|
|
|
{ "file": "/some/place/my-image",
|
|
"backing": "/some/place/my-backing-file" }
|
|
|
|
|
|
=== Union types ===
|
|
|
|
Usage: { 'union': STRING, 'data': DICT }
|
|
or: { 'union': STRING, 'data': DICT, 'base': STRUCT-NAME-OR-DICT,
|
|
'discriminator': ENUM-MEMBER-OF-BASE }
|
|
|
|
Union types are used to let the user choose between several different
|
|
variants for an object. There are two flavors: simple (no
|
|
discriminator or base), and flat (both discriminator and base). A union
|
|
type is defined using a data dictionary as explained in the following
|
|
paragraphs. Unions must have at least one branch.
|
|
|
|
A simple union type defines a mapping from automatic discriminator
|
|
values to data types like in this example:
|
|
|
|
{ 'struct': 'BlockdevOptionsFile', 'data': { 'filename': 'str' } }
|
|
{ 'struct': 'BlockdevOptionsQcow2',
|
|
'data': { 'backing': 'str', '*lazy-refcounts': 'bool' } }
|
|
|
|
{ 'union': 'BlockdevOptionsSimple',
|
|
'data': { 'file': 'BlockdevOptionsFile',
|
|
'qcow2': 'BlockdevOptionsQcow2' } }
|
|
|
|
In the Client JSON Protocol, a simple union is represented by a
|
|
dictionary that contains the 'type' member as a discriminator, and a
|
|
'data' member that is of the specified data type corresponding to the
|
|
discriminator value, as in these examples:
|
|
|
|
{ "type": "file", "data": { "filename": "/some/place/my-image" } }
|
|
{ "type": "qcow2", "data": { "backing": "/some/place/my-image",
|
|
"lazy-refcounts": true } }
|
|
|
|
The generated C code uses a struct containing a union. Additionally,
|
|
an implicit C enum 'NameKind' is created, corresponding to the union
|
|
'Name', for accessing the various branches of the union. The value
|
|
for each branch can be of any type.
|
|
|
|
A flat union definition avoids nesting on the wire, and specifies a
|
|
set of common members that occur in all variants of the union. The
|
|
'base' key must specify either a type name (the type must be a
|
|
struct, not a union), or a dictionary representing an anonymous type.
|
|
All branches of the union must be struct types, and the top-level
|
|
members of the union dictionary on the wire will be combination of
|
|
members from both the base type and the appropriate branch type (when
|
|
merging two dictionaries, there must be no keys in common). The
|
|
'discriminator' member must be the name of a non-optional enum-typed
|
|
member of the base struct.
|
|
|
|
The following example enhances the above simple union example by
|
|
adding an optional common member 'read-only', renaming the
|
|
discriminator to something more applicable than the simple union's
|
|
default of 'type', and reducing the number of {} required on the wire:
|
|
|
|
{ 'enum': 'BlockdevDriver', 'data': [ 'file', 'qcow2' ] }
|
|
{ 'union': 'BlockdevOptions',
|
|
'base': { 'driver': 'BlockdevDriver', '*read-only': 'bool' },
|
|
'discriminator': 'driver',
|
|
'data': { 'file': 'BlockdevOptionsFile',
|
|
'qcow2': 'BlockdevOptionsQcow2' } }
|
|
|
|
Resulting in these JSON objects:
|
|
|
|
{ "driver": "file", "read-only": true,
|
|
"filename": "/some/place/my-image" }
|
|
{ "driver": "qcow2", "read-only": false,
|
|
"backing": "/some/place/my-image", "lazy-refcounts": true }
|
|
|
|
Notice that in a flat union, the discriminator name is controlled by
|
|
the user, but because it must map to a base member with enum type, the
|
|
code generator ensures that branches match the existing values of the
|
|
enum. The order of the keys need not match the declaration of the enum.
|
|
The keys need not cover all possible enum values. Omitted enum values
|
|
are still valid branches that add no additional members to the data type.
|
|
In the resulting generated C data types, a flat union is
|
|
represented as a struct with the base members included directly, and
|
|
then a union of structures for each branch of the struct.
|
|
|
|
A simple union can always be re-written as a flat union where the base
|
|
class has a single member named 'type', and where each branch of the
|
|
union has a struct with a single member named 'data'. That is,
|
|
|
|
{ 'union': 'Simple', 'data': { 'one': 'str', 'two': 'int' } }
|
|
|
|
is identical on the wire to:
|
|
|
|
{ 'enum': 'Enum', 'data': ['one', 'two'] }
|
|
{ 'struct': 'Branch1', 'data': { 'data': 'str' } }
|
|
{ 'struct': 'Branch2', 'data': { 'data': 'int' } }
|
|
{ 'union': 'Flat': 'base': { 'type': 'Enum' }, 'discriminator': 'type',
|
|
'data': { 'one': 'Branch1', 'two': 'Branch2' } }
|
|
|
|
|
|
=== Alternate types ===
|
|
|
|
Usage: { 'alternate': STRING, 'data': DICT }
|
|
|
|
An alternate type is one that allows a choice between two or more JSON
|
|
data types (string, integer, number, or object, but currently not
|
|
array) on the wire. The definition is similar to a simple union type,
|
|
where each branch of the union names a QAPI type. For example:
|
|
|
|
{ 'alternate': 'BlockdevRef',
|
|
'data': { 'definition': 'BlockdevOptions',
|
|
'reference': 'str' } }
|
|
|
|
Unlike a union, the discriminator string is never passed on the wire
|
|
for the Client JSON Protocol. Instead, the value's JSON type serves
|
|
as an implicit discriminator, which in turn means that an alternate
|
|
can only express a choice between types represented differently in
|
|
JSON. If a branch is typed as the 'bool' built-in, the alternate
|
|
accepts true and false; if it is typed as any of the various numeric
|
|
built-ins, it accepts a JSON number; if it is typed as a 'str'
|
|
built-in or named enum type, it accepts a JSON string; if it is typed
|
|
as the 'null' built-in, it accepts JSON null; and if it is typed as a
|
|
complex type (struct or union), it accepts a JSON object. Two
|
|
different complex types, for instance, aren't permitted, because both
|
|
are represented as a JSON object.
|
|
|
|
The example alternate declaration above allows using both of the
|
|
following example objects:
|
|
|
|
{ "file": "my_existing_block_device_id" }
|
|
{ "file": { "driver": "file",
|
|
"read-only": false,
|
|
"filename": "/tmp/mydisk.qcow2" } }
|
|
|
|
|
|
=== Commands ===
|
|
|
|
--- General Command Layout ---
|
|
|
|
Usage: { 'command': STRING, '*data': COMPLEX-TYPE-NAME-OR-DICT,
|
|
'*returns': TYPE-NAME, '*boxed': true,
|
|
'*gen': false, '*success-response': false,
|
|
'*allow-oob': true, '*allow-preconfig': true }
|
|
|
|
Commands are defined by using a dictionary containing several members,
|
|
where three members are most common. The 'command' member is a
|
|
mandatory string, and determines the "execute" value passed in a
|
|
Client JSON Protocol command exchange.
|
|
|
|
The 'data' argument maps to the "arguments" dictionary passed in as
|
|
part of a Client JSON Protocol command. The 'data' member is optional
|
|
and defaults to {} (an empty dictionary). If present, it must be the
|
|
string name of a complex type, or a dictionary that declares an
|
|
anonymous type with the same semantics as a 'struct' expression.
|
|
|
|
The 'returns' member describes what will appear in the "return" member
|
|
of a Client JSON Protocol reply on successful completion of a command.
|
|
The member is optional from the command declaration; if absent, the
|
|
"return" member will be an empty dictionary. If 'returns' is present,
|
|
it must be the string name of a complex type, or a
|
|
one-element array containing the name of a complex type.
|
|
To return anything else, you have to list the command in pragma
|
|
'returns-whitelist'. If you do this, the command cannot be extended
|
|
to return additional information in the future. Use of
|
|
'returns-whitelist' for new commands is strongly discouraged.
|
|
|
|
All commands in Client JSON Protocol use a dictionary to report
|
|
failure, with no way to specify that in QAPI. Where the error return
|
|
is different than the usual GenericError class in order to help the
|
|
client react differently to certain error conditions, it is worth
|
|
documenting this in the comments before the command declaration.
|
|
|
|
Some example commands:
|
|
|
|
{ 'command': 'my-first-command',
|
|
'data': { 'arg1': 'str', '*arg2': 'str' } }
|
|
{ 'struct': 'MyType', 'data': { '*value': 'str' } }
|
|
{ 'command': 'my-second-command',
|
|
'returns': [ 'MyType' ] }
|
|
|
|
which would validate this Client JSON Protocol transaction:
|
|
|
|
=> { "execute": "my-first-command",
|
|
"arguments": { "arg1": "hello" } }
|
|
<= { "return": { } }
|
|
=> { "execute": "my-second-command" }
|
|
<= { "return": [ { "value": "one" }, { } ] }
|
|
|
|
The generator emits a prototype for the user's function implementing
|
|
the command. Normally, 'data' is a dictionary for an anonymous type,
|
|
or names a struct type (possibly empty, but not a union), and its
|
|
members are passed as separate arguments to this function. If the
|
|
command definition includes a key 'boxed' with the boolean value true,
|
|
then 'data' is instead the name of any non-empty complex type (struct
|
|
or union), and a pointer to that QAPI type is passed as a single
|
|
argument.
|
|
|
|
The generator also emits a marshalling function that extracts
|
|
arguments for the user's function out of an input QDict, calls the
|
|
user's function, and if it succeeded, builds an output QObject from
|
|
its return value.
|
|
|
|
In rare cases, QAPI cannot express a type-safe representation of a
|
|
corresponding Client JSON Protocol command. You then have to suppress
|
|
generation of a marshalling function by including a key 'gen' with
|
|
boolean value false, and instead write your own function. For
|
|
example:
|
|
|
|
{ 'command': 'netdev_add',
|
|
'data': {'type': 'str', 'id': 'str'},
|
|
'gen': false }
|
|
|
|
Please try to avoid adding new commands that rely on this, and instead
|
|
use type-safe unions.
|
|
|
|
Normally, the QAPI schema is used to describe synchronous exchanges,
|
|
where a response is expected. But in some cases, the action of a
|
|
command is expected to change state in a way that a successful
|
|
response is not possible (although the command will still return a
|
|
normal dictionary error on failure). When a successful reply is not
|
|
possible, the command expression includes the optional key
|
|
'success-response' with boolean value false. So far, only QGA makes
|
|
use of this member.
|
|
|
|
Key 'allow-oob' declares whether the command supports out-of-band
|
|
(OOB) execution. It defaults to false. For example:
|
|
|
|
{ 'command': 'migrate_recover',
|
|
'data': { 'uri': 'str' }, 'allow-oob': true }
|
|
|
|
See qmp-spec.txt for out-of-band execution syntax and semantics.
|
|
|
|
Commands supporting out-of-band execution can still be executed
|
|
in-band.
|
|
|
|
When a command is executed in-band, its handler runs in the main
|
|
thread with the BQL held.
|
|
|
|
When a command is executed out-of-band, its handler runs in a
|
|
dedicated monitor I/O thread with the BQL *not* held.
|
|
|
|
An OOB-capable command handler must satisfy the following conditions:
|
|
|
|
- It terminates quickly.
|
|
- It does not invoke system calls that may block.
|
|
- It does not access guest RAM that may block when userfaultfd is
|
|
enabled for postcopy live migration.
|
|
- It takes only "fast" locks, i.e. all critical sections protected by
|
|
any lock it takes also satisfy the conditions for OOB command
|
|
handler code.
|
|
|
|
The restrictions on locking limit access to shared state. Such access
|
|
requires synchronization, but OOB commands can't take the BQL or any
|
|
other "slow" lock.
|
|
|
|
When in doubt, do not implement OOB execution support.
|
|
|
|
Key 'allow-preconfig' declares whether the command is available before
|
|
the machine is built. It defaults to false. For example:
|
|
|
|
{ 'command': 'qmp_capabilities',
|
|
'data': { '*enable': [ 'QMPCapability' ] },
|
|
'allow-preconfig': true }
|
|
|
|
QMP is available before the machine is built only when QEMU was
|
|
started with --preconfig.
|
|
|
|
=== Events ===
|
|
|
|
Usage: { 'event': STRING, '*data': COMPLEX-TYPE-NAME-OR-DICT,
|
|
'*boxed': true }
|
|
|
|
Events are defined with the keyword 'event'. When 'data' is also
|
|
specified, additional info will be included in the event, with similar
|
|
semantics to a 'struct' expression. Finally there will be C API
|
|
generated in qapi-events.h; when called by QEMU code, a message with
|
|
timestamp will be emitted on the wire.
|
|
|
|
An example event is:
|
|
|
|
{ 'event': 'EVENT_C',
|
|
'data': { '*a': 'int', 'b': 'str' } }
|
|
|
|
Resulting in this JSON object:
|
|
|
|
{ "event": "EVENT_C",
|
|
"data": { "b": "test string" },
|
|
"timestamp": { "seconds": 1267020223, "microseconds": 435656 } }
|
|
|
|
The generator emits a function to send the event. Normally, 'data' is
|
|
a dictionary for an anonymous type, or names a struct type (possibly
|
|
empty, but not a union), and its members are passed as separate
|
|
arguments to this function. If the event definition includes a key
|
|
'boxed' with the boolean value true, then 'data' is instead the name
|
|
of any non-empty complex type (struct or union), and a pointer to that
|
|
QAPI type is passed as a single argument.
|
|
|
|
|
|
=== Features ===
|
|
|
|
Sometimes, the behaviour of QEMU changes compatibly, but without a
|
|
change in the QMP syntax (usually by allowing values or operations that
|
|
previously resulted in an error). QMP clients may still need to know
|
|
whether the extension is available.
|
|
|
|
For this purpose, a list of features can be specified for a struct type.
|
|
This is exposed to the client as a list of string, where each string
|
|
signals that this build of QEMU shows a certain behaviour.
|
|
|
|
In the schema, features can be specified as simple strings, for example:
|
|
|
|
{ 'struct': 'TestType',
|
|
'data': { 'number': 'int' },
|
|
'features': [ 'allow-negative-numbers' ] }
|
|
|
|
Another option is to specify features as dictionaries, where the key
|
|
'name' specifies the feature string to be exposed to clients:
|
|
|
|
{ 'struct': 'TestType',
|
|
'data': { 'number': 'int' },
|
|
'features': [ { 'name': 'allow-negative-numbers' } ] }
|
|
|
|
This expanded form is necessary if you want to make the feature
|
|
conditional (see below in "Configuring the schema").
|
|
|
|
|
|
=== Naming rules and reserved names ===
|
|
|
|
All names must begin with a letter, and contain only ASCII letters,
|
|
digits, hyphen, and underscore. There are two exceptions: enum values
|
|
may start with a digit, and names that are downstream extensions (see
|
|
section Downstream extensions) start with underscore.
|
|
|
|
Names beginning with 'q_' are reserved for the generator, which uses
|
|
them for munging QMP names that resemble C keywords or other
|
|
problematic strings. For example, a member named "default" in qapi
|
|
becomes "q_default" in the generated C code.
|
|
|
|
Types, commands, and events share a common namespace. Therefore,
|
|
generally speaking, type definitions should always use CamelCase for
|
|
user-defined type names, while built-in types are lowercase.
|
|
|
|
Type names ending with 'Kind' or 'List' are reserved for the
|
|
generator, which uses them for implicit union enums and array types,
|
|
respectively.
|
|
|
|
Command names, and member names within a type, should be all lower
|
|
case with words separated by a hyphen. However, some existing older
|
|
commands and complex types use underscore; when extending such
|
|
expressions, consistency is preferred over blindly avoiding
|
|
underscore.
|
|
|
|
Event names should be ALL_CAPS with words separated by underscore.
|
|
|
|
Member name 'u' and names starting with 'has-' or 'has_' are reserved
|
|
for the generator, which uses them for unions and for tracking
|
|
optional members.
|
|
|
|
Any name (command, event, type, member, or enum value) beginning with
|
|
"x-" is marked experimental, and may be withdrawn or changed
|
|
incompatibly in a future release.
|
|
|
|
Pragma 'name-case-whitelist' lets you violate the rules on use of
|
|
upper and lower case. Use for new code is strongly discouraged.
|
|
|
|
|
|
=== Downstream extensions ===
|
|
|
|
QAPI schema names that are externally visible, say in the Client JSON
|
|
Protocol, need to be managed with care. Names starting with a
|
|
downstream prefix of the form __RFQDN_ are reserved for the downstream
|
|
who controls the valid, reverse fully qualified domain name RFQDN.
|
|
RFQDN may only contain ASCII letters, digits, hyphen and period.
|
|
|
|
Example: Red Hat, Inc. controls redhat.com, and may therefore add a
|
|
downstream command __com.redhat_drive-mirror.
|
|
|
|
|
|
=== Configuring the schema ===
|
|
|
|
The 'struct', 'enum', 'union', 'alternate', 'command' and 'event'
|
|
top-level expressions can take an 'if' key. Its value must be a string
|
|
or a list of strings. A string is shorthand for a list containing just
|
|
that string. The code generated for the top-level expression will then
|
|
be guarded by #if COND for each COND in the list.
|
|
|
|
Example: a conditional struct
|
|
|
|
{ 'struct': 'IfStruct', 'data': { 'foo': 'int' },
|
|
'if': ['defined(CONFIG_FOO)', 'defined(HAVE_BAR)'] }
|
|
|
|
gets its generated code guarded like this:
|
|
|
|
#if defined(CONFIG_FOO)
|
|
#if defined(HAVE_BAR)
|
|
... generated code ...
|
|
#endif /* defined(HAVE_BAR) */
|
|
#endif /* defined(CONFIG_FOO) */
|
|
|
|
Where a member can be defined with a single string value for its type,
|
|
it is also possible to supply a dictionary instead with both 'type'
|
|
and 'if' keys.
|
|
|
|
Example: a conditional 'bar' member
|
|
|
|
{ 'struct': 'IfStruct', 'data':
|
|
{ 'foo': 'int',
|
|
'bar': { 'type': 'int', 'if': 'defined(IFCOND)'} } }
|
|
|
|
An enum value can be replaced by a dictionary with a 'name' and a 'if'
|
|
key.
|
|
|
|
Example: a conditional 'bar' enum member.
|
|
|
|
{ 'enum': 'IfEnum', 'data':
|
|
[ 'foo',
|
|
{ 'name' : 'bar', 'if': 'defined(IFCOND)' } ] }
|
|
|
|
Similarly, features can be specified as a dictionary with a 'name' and
|
|
an 'if' key.
|
|
|
|
Example: a conditional 'allow-negative-numbers' feature
|
|
|
|
{ 'struct': 'TestType',
|
|
'data': { 'number': 'int' },
|
|
'features': [ { 'name': 'allow-negative-numbers',
|
|
'if' 'defined(IFCOND)' } ] }
|
|
|
|
Please note that you are responsible to ensure that the C code will
|
|
compile with an arbitrary combination of conditions, since the
|
|
generators are unable to check it at this point.
|
|
|
|
The presence of 'if' keys in the schema is reflected through to the
|
|
introspection output depending on the build configuration.
|
|
|
|
|
|
=== Documentation comments ===
|
|
|
|
A multi-line comment that starts and ends with a '##' line is a
|
|
documentation comment. These are parsed by the documentation
|
|
generator, which recognizes certain markup detailed below.
|
|
|
|
|
|
==== Documentation markup ====
|
|
|
|
Comment text starting with '=' is a section title:
|
|
|
|
# = Section title
|
|
|
|
Double the '=' for a subsection title:
|
|
|
|
# == Subsection title
|
|
|
|
'|' denotes examples:
|
|
|
|
# | Text of the example, may span
|
|
# | multiple lines
|
|
|
|
'*' starts an itemized list:
|
|
|
|
# * First item, may span
|
|
# multiple lines
|
|
# * Second item
|
|
|
|
You can also use '-' instead of '*'.
|
|
|
|
A decimal number followed by '.' starts a numbered list:
|
|
|
|
# 1. First item, may span
|
|
# multiple lines
|
|
# 2. Second item
|
|
|
|
The actual number doesn't matter. You could even use '*' instead of
|
|
'2.' for the second item.
|
|
|
|
Lists can't be nested. Blank lines are currently not supported within
|
|
lists.
|
|
|
|
Additional whitespace between the initial '#' and the comment text is
|
|
permitted.
|
|
|
|
*foo* and _foo_ are for strong and emphasis styles respectively (they
|
|
do not work over multiple lines). @foo is used to reference a name in
|
|
the schema.
|
|
|
|
Example:
|
|
|
|
##
|
|
# = Section
|
|
# == Subsection
|
|
#
|
|
# Some text foo with *strong* and _emphasis_
|
|
# 1. with a list
|
|
# 2. like that
|
|
#
|
|
# And some code:
|
|
# | $ echo foo
|
|
# | -> do this
|
|
# | <- get that
|
|
#
|
|
##
|
|
|
|
|
|
==== Expression documentation ====
|
|
|
|
Expressions other than include and pragma directives may be preceded
|
|
by a documentation block. Such blocks are called expression
|
|
documentation blocks.
|
|
|
|
When documentation is required (see pragma 'doc-required'), expression
|
|
documentation blocks are mandatory.
|
|
|
|
The documentation block consists of a first line naming the
|
|
expression, an optional overview, a description of each argument (for
|
|
commands and events) or member (for structs, unions and alternates),
|
|
and optional tagged sections.
|
|
|
|
FIXME: the parser accepts these things in almost any order.
|
|
|
|
Extensions added after the expression was first released carry a
|
|
'(since x.y.z)' comment.
|
|
|
|
A tagged section starts with one of the following words:
|
|
"Note:"/"Notes:", "Since:", "Example"/"Examples", "Returns:", "TODO:".
|
|
The section ends with the start of a new section.
|
|
|
|
A 'Since: x.y.z' tagged section lists the release that introduced the
|
|
expression.
|
|
|
|
For example:
|
|
|
|
##
|
|
# @BlockStats:
|
|
#
|
|
# Statistics of a virtual block device or a block backing device.
|
|
#
|
|
# @device: If the stats are for a virtual block device, the name
|
|
# corresponding to the virtual block device.
|
|
#
|
|
# @node-name: The node name of the device. (since 2.3)
|
|
#
|
|
# ... more members ...
|
|
#
|
|
# Since: 0.14.0
|
|
##
|
|
{ 'struct': 'BlockStats',
|
|
'data': {'*device': 'str', '*node-name': 'str',
|
|
... more members ... } }
|
|
|
|
##
|
|
# @query-blockstats:
|
|
#
|
|
# Query the @BlockStats for all virtual block devices.
|
|
#
|
|
# @query-nodes: If true, the command will query all the
|
|
# block nodes ... explain, explain ... (since 2.3)
|
|
#
|
|
# Returns: A list of @BlockStats for each virtual block devices.
|
|
#
|
|
# Since: 0.14.0
|
|
#
|
|
# Example:
|
|
#
|
|
# -> { "execute": "query-blockstats" }
|
|
# <- {
|
|
# ... lots of output ...
|
|
# }
|
|
#
|
|
##
|
|
{ 'command': 'query-blockstats',
|
|
'data': { '*query-nodes': 'bool' },
|
|
'returns': ['BlockStats'] }
|
|
|
|
==== Free-form documentation ====
|
|
|
|
A documentation block that isn't an expression documentation block is
|
|
a free-form documentation block. These may be used to provide
|
|
additional text and structuring content.
|
|
|
|
|
|
== Client JSON Protocol introspection ==
|
|
|
|
Clients of a Client JSON Protocol commonly need to figure out what
|
|
exactly the server (QEMU) supports.
|
|
|
|
For this purpose, QMP provides introspection via command
|
|
query-qmp-schema. QGA currently doesn't support introspection.
|
|
|
|
While Client JSON Protocol wire compatibility should be maintained
|
|
between qemu versions, we cannot make the same guarantees for
|
|
introspection stability. For example, one version of qemu may provide
|
|
a non-variant optional member of a struct, and a later version rework
|
|
the member to instead be non-optional and associated with a variant.
|
|
Likewise, one version of qemu may list a member with open-ended type
|
|
'str', and a later version could convert it to a finite set of strings
|
|
via an enum type; or a member may be converted from a specific type to
|
|
an alternate that represents a choice between the original type and
|
|
something else.
|
|
|
|
query-qmp-schema returns a JSON array of SchemaInfo objects. These
|
|
objects together describe the wire ABI, as defined in the QAPI schema.
|
|
There is no specified order to the SchemaInfo objects returned; a
|
|
client must search for a particular name throughout the entire array
|
|
to learn more about that name, but is at least guaranteed that there
|
|
will be no collisions between type, command, and event names.
|
|
|
|
However, the SchemaInfo can't reflect all the rules and restrictions
|
|
that apply to QMP. It's interface introspection (figuring out what's
|
|
there), not interface specification. The specification is in the QAPI
|
|
schema. To understand how QMP is to be used, you need to study the
|
|
QAPI schema.
|
|
|
|
Like any other command, query-qmp-schema is itself defined in the QAPI
|
|
schema, along with the SchemaInfo type. This text attempts to give an
|
|
overview how things work. For details you need to consult the QAPI
|
|
schema.
|
|
|
|
SchemaInfo objects have common members "name" and "meta-type", and
|
|
additional variant members depending on the value of meta-type.
|
|
|
|
Each SchemaInfo object describes a wire ABI entity of a certain
|
|
meta-type: a command, event or one of several kinds of type.
|
|
|
|
SchemaInfo for commands and events have the same name as in the QAPI
|
|
schema.
|
|
|
|
Command and event names are part of the wire ABI, but type names are
|
|
not. Therefore, the SchemaInfo for types have auto-generated
|
|
meaningless names. For readability, the examples in this section use
|
|
meaningful type names instead.
|
|
|
|
To examine a type, start with a command or event using it, then follow
|
|
references by name.
|
|
|
|
QAPI schema definitions not reachable that way are omitted.
|
|
|
|
The SchemaInfo for a command has meta-type "command", and variant
|
|
members "arg-type", "ret-type" and "allow-oob". On the wire, the
|
|
"arguments" member of a client's "execute" command must conform to the
|
|
object type named by "arg-type". The "return" member that the server
|
|
passes in a success response conforms to the type named by
|
|
"ret-type". When "allow-oob" is set, it means the command supports
|
|
out-of-band execution.
|
|
|
|
If the command takes no arguments, "arg-type" names an object type
|
|
without members. Likewise, if the command returns nothing, "ret-type"
|
|
names an object type without members.
|
|
|
|
Example: the SchemaInfo for command query-qmp-schema
|
|
|
|
{ "name": "query-qmp-schema", "meta-type": "command",
|
|
"arg-type": "q_empty", "ret-type": "SchemaInfoList" }
|
|
|
|
Type "q_empty" is an automatic object type without members, and type
|
|
"SchemaInfoList" is the array of SchemaInfo type.
|
|
|
|
The SchemaInfo for an event has meta-type "event", and variant member
|
|
"arg-type". On the wire, a "data" member that the server passes in an
|
|
event conforms to the object type named by "arg-type".
|
|
|
|
If the event carries no additional information, "arg-type" names an
|
|
object type without members. The event may not have a data member on
|
|
the wire then.
|
|
|
|
Each command or event defined with dictionary-valued 'data' in the
|
|
QAPI schema implicitly defines an object type.
|
|
|
|
Example: the SchemaInfo for EVENT_C from section Events
|
|
|
|
{ "name": "EVENT_C", "meta-type": "event",
|
|
"arg-type": "q_obj-EVENT_C-arg" }
|
|
|
|
Type "q_obj-EVENT_C-arg" is an implicitly defined object type with
|
|
the two members from the event's definition.
|
|
|
|
The SchemaInfo for struct and union types has meta-type "object".
|
|
|
|
The SchemaInfo for a struct type has variant member "members".
|
|
|
|
The SchemaInfo for a union type additionally has variant members "tag"
|
|
and "variants".
|
|
|
|
"members" is a JSON array describing the object's common members, if
|
|
any. Each element is a JSON object with members "name" (the member's
|
|
name), "type" (the name of its type), and optionally "default". The
|
|
member is optional if "default" is present. Currently, "default" can
|
|
only have value null. Other values are reserved for future
|
|
extensions. The "members" array is in no particular order; clients
|
|
must search the entire object when learning whether a particular
|
|
member is supported.
|
|
|
|
Example: the SchemaInfo for MyType from section Struct types
|
|
|
|
{ "name": "MyType", "meta-type": "object",
|
|
"members": [
|
|
{ "name": "member1", "type": "str" },
|
|
{ "name": "member2", "type": "int" },
|
|
{ "name": "member3", "type": "str", "default": null } ] }
|
|
|
|
"tag" is the name of the common member serving as type tag.
|
|
"variants" is a JSON array describing the object's variant members.
|
|
Each element is a JSON object with members "case" (the value of type
|
|
tag this element applies to) and "type" (the name of an object type
|
|
that provides the variant members for this type tag value). The
|
|
"variants" array is in no particular order, and is not guaranteed to
|
|
list cases in the same order as the corresponding "tag" enum type.
|
|
|
|
Example: the SchemaInfo for flat union BlockdevOptions from section
|
|
Union types
|
|
|
|
{ "name": "BlockdevOptions", "meta-type": "object",
|
|
"members": [
|
|
{ "name": "driver", "type": "BlockdevDriver" },
|
|
{ "name": "read-only", "type": "bool", "default": null } ],
|
|
"tag": "driver",
|
|
"variants": [
|
|
{ "case": "file", "type": "BlockdevOptionsFile" },
|
|
{ "case": "qcow2", "type": "BlockdevOptionsQcow2" } ] }
|
|
|
|
Note that base types are "flattened": its members are included in the
|
|
"members" array.
|
|
|
|
A simple union implicitly defines an enumeration type for its implicit
|
|
discriminator (called "type" on the wire, see section Union types).
|
|
|
|
A simple union implicitly defines an object type for each of its
|
|
variants.
|
|
|
|
Example: the SchemaInfo for simple union BlockdevOptionsSimple from section
|
|
Union types
|
|
|
|
{ "name": "BlockdevOptionsSimple", "meta-type": "object",
|
|
"members": [
|
|
{ "name": "type", "type": "BlockdevOptionsSimpleKind" } ],
|
|
"tag": "type",
|
|
"variants": [
|
|
{ "case": "file", "type": "q_obj-BlockdevOptionsFile-wrapper" },
|
|
{ "case": "qcow2", "type": "q_obj-BlockdevOptionsQcow2-wrapper" } ] }
|
|
|
|
Enumeration type "BlockdevOptionsSimpleKind" and the object types
|
|
"q_obj-BlockdevOptionsFile-wrapper", "q_obj-BlockdevOptionsQcow2-wrapper"
|
|
are implicitly defined.
|
|
|
|
The SchemaInfo for an alternate type has meta-type "alternate", and
|
|
variant member "members". "members" is a JSON array. Each element is
|
|
a JSON object with member "type", which names a type. Values of the
|
|
alternate type conform to exactly one of its member types. There is
|
|
no guarantee on the order in which "members" will be listed.
|
|
|
|
Example: the SchemaInfo for BlockdevRef from section Alternate types
|
|
|
|
{ "name": "BlockdevRef", "meta-type": "alternate",
|
|
"members": [
|
|
{ "type": "BlockdevOptions" },
|
|
{ "type": "str" } ] }
|
|
|
|
The SchemaInfo for an array type has meta-type "array", and variant
|
|
member "element-type", which names the array's element type. Array
|
|
types are implicitly defined. For convenience, the array's name may
|
|
resemble the element type; however, clients should examine member
|
|
"element-type" instead of making assumptions based on parsing member
|
|
"name".
|
|
|
|
Example: the SchemaInfo for ['str']
|
|
|
|
{ "name": "[str]", "meta-type": "array",
|
|
"element-type": "str" }
|
|
|
|
The SchemaInfo for an enumeration type has meta-type "enum" and
|
|
variant member "values". The values are listed in no particular
|
|
order; clients must search the entire enum when learning whether a
|
|
particular value is supported.
|
|
|
|
Example: the SchemaInfo for MyEnum from section Enumeration types
|
|
|
|
{ "name": "MyEnum", "meta-type": "enum",
|
|
"values": [ "value1", "value2", "value3" ] }
|
|
|
|
The SchemaInfo for a built-in type has the same name as the type in
|
|
the QAPI schema (see section Built-in Types), with one exception
|
|
detailed below. It has variant member "json-type" that shows how
|
|
values of this type are encoded on the wire.
|
|
|
|
Example: the SchemaInfo for str
|
|
|
|
{ "name": "str", "meta-type": "builtin", "json-type": "string" }
|
|
|
|
The QAPI schema supports a number of integer types that only differ in
|
|
how they map to C. They are identical as far as SchemaInfo is
|
|
concerned. Therefore, they get all mapped to a single type "int" in
|
|
SchemaInfo.
|
|
|
|
As explained above, type names are not part of the wire ABI. Not even
|
|
the names of built-in types. Clients should examine member
|
|
"json-type" instead of hard-coding names of built-in types.
|
|
|
|
|
|
== Compatibility considerations ==
|
|
|
|
Maintaining backward compatibility at the Client JSON Protocol level
|
|
while evolving the schema requires some care. This section is about
|
|
syntactic compatibility, which is necessary, but not sufficient, for
|
|
actual compatibility.
|
|
|
|
Clients send commands with argument data, and receive command
|
|
responses with return data and events with event data.
|
|
|
|
Adding opt-in functionality to the send direction is backwards
|
|
compatible: adding commands, optional arguments, enumeration values,
|
|
union and alternate branches; turning an argument type into an
|
|
alternate of that type; making mandatory arguments optional. Clients
|
|
oblivious of the new functionality continue to work.
|
|
|
|
Incompatible changes include removing commands, command arguments,
|
|
enumeration values, union and alternate branches, adding mandatory
|
|
command arguments, and making optional arguments mandatory.
|
|
|
|
The specified behavior of an absent optional argument should remain
|
|
the same. With proper documentation, this policy still allows some
|
|
flexibility; for example, when an optional 'buffer-size' argument is
|
|
specified to default to a sensible buffer size, the actual default
|
|
value can still be changed. The specified default behavior is not the
|
|
exact size of the buffer, only that the default size is sensible.
|
|
|
|
Adding functionality to the receive direction is generally backwards
|
|
compatible: adding events, adding return and event data members.
|
|
Clients are expected to ignore the ones they don't know.
|
|
|
|
Removing "unreachable" stuff like events that can't be triggered
|
|
anymore, optional return or event data members that can't be sent
|
|
anymore, and return or event data member (enumeration) values that
|
|
can't be sent anymore makes no difference to clients, except for
|
|
introspection. The latter can conceivably confuse clients, so tread
|
|
carefully.
|
|
|
|
Incompatible changes include removing return and event data members.
|
|
|
|
Any change to a command definition's 'data' or one of the types used
|
|
there (recursively) needs to consider send direction compatibility.
|
|
|
|
Any change to a command definition's 'return', an event definition's
|
|
'data', or one of the types used there (recursively) needs to consider
|
|
receive direction compatibility.
|
|
|
|
Any change to types used in both contexts need to consider both.
|
|
|
|
Members of enumeration types, complex types and alternate types may be
|
|
reordered freely. For enumerations and alternate types, this doesn't
|
|
affect the wire encoding. For complex types, this might make the
|
|
implementation emit JSON object members in a different order, which
|
|
the Client JSON Protocol permits.
|
|
|
|
Since type names are not visible in the Client JSON Protocol, types
|
|
may be freely renamed. Even certain refactorings are invisible, such
|
|
as splitting members from one type into a common base type.
|
|
|
|
|
|
== Code generation ==
|
|
|
|
The QAPI code generator qapi-gen.py generates code and documentation
|
|
from the schema. Together with the core QAPI libraries, this code
|
|
provides everything required to take JSON commands read in by a Client
|
|
JSON Protocol server, unmarshal the arguments into the underlying C
|
|
types, call into the corresponding C function, map the response back
|
|
to a Client JSON Protocol response to be returned to the user, and
|
|
introspect the commands.
|
|
|
|
As an example, we'll use the following schema, which describes a
|
|
single complex user-defined type, along with command which takes a
|
|
list of that type as a parameter, and returns a single element of that
|
|
type. The user is responsible for writing the implementation of
|
|
qmp_my_command(); everything else is produced by the generator.
|
|
|
|
$ cat example-schema.json
|
|
{ 'struct': 'UserDefOne',
|
|
'data': { 'integer': 'int', '*string': 'str' } }
|
|
|
|
{ 'command': 'my-command',
|
|
'data': { 'arg1': ['UserDefOne'] },
|
|
'returns': 'UserDefOne' }
|
|
|
|
{ 'event': 'MY_EVENT' }
|
|
|
|
We run qapi-gen.py like this:
|
|
|
|
$ python scripts/qapi-gen.py --output-dir="qapi-generated" \
|
|
--prefix="example-" example-schema.json
|
|
|
|
For a more thorough look at generated code, the testsuite includes
|
|
tests/qapi-schema/qapi-schema-tests.json that covers more examples of
|
|
what the generator will accept, and compiles the resulting C code as
|
|
part of 'make check-unit'.
|
|
|
|
=== Code generated for QAPI types ===
|
|
|
|
The following files are created:
|
|
|
|
$(prefix)qapi-types.h - C types corresponding to types defined in
|
|
the schema
|
|
|
|
$(prefix)qapi-types.c - Cleanup functions for the above C types
|
|
|
|
The $(prefix) is an optional parameter used as a namespace to keep the
|
|
generated code from one schema/code-generation separated from others so code
|
|
can be generated/used from multiple schemas without clobbering previously
|
|
created code.
|
|
|
|
Example:
|
|
|
|
$ cat qapi-generated/example-qapi-types.h
|
|
[Uninteresting stuff omitted...]
|
|
|
|
#ifndef EXAMPLE_QAPI_TYPES_H
|
|
#define EXAMPLE_QAPI_TYPES_H
|
|
|
|
#include "qapi/qapi-builtin-types.h"
|
|
|
|
typedef struct UserDefOne UserDefOne;
|
|
|
|
typedef struct UserDefOneList UserDefOneList;
|
|
|
|
typedef struct q_obj_my_command_arg q_obj_my_command_arg;
|
|
|
|
struct UserDefOne {
|
|
int64_t integer;
|
|
bool has_string;
|
|
char *string;
|
|
};
|
|
|
|
void qapi_free_UserDefOne(UserDefOne *obj);
|
|
|
|
struct UserDefOneList {
|
|
UserDefOneList *next;
|
|
UserDefOne *value;
|
|
};
|
|
|
|
void qapi_free_UserDefOneList(UserDefOneList *obj);
|
|
|
|
struct q_obj_my_command_arg {
|
|
UserDefOneList *arg1;
|
|
};
|
|
|
|
#endif /* EXAMPLE_QAPI_TYPES_H */
|
|
$ cat qapi-generated/example-qapi-types.c
|
|
[Uninteresting stuff omitted...]
|
|
|
|
void qapi_free_UserDefOne(UserDefOne *obj)
|
|
{
|
|
Visitor *v;
|
|
|
|
if (!obj) {
|
|
return;
|
|
}
|
|
|
|
v = qapi_dealloc_visitor_new();
|
|
visit_type_UserDefOne(v, NULL, &obj, NULL);
|
|
visit_free(v);
|
|
}
|
|
|
|
void qapi_free_UserDefOneList(UserDefOneList *obj)
|
|
{
|
|
Visitor *v;
|
|
|
|
if (!obj) {
|
|
return;
|
|
}
|
|
|
|
v = qapi_dealloc_visitor_new();
|
|
visit_type_UserDefOneList(v, NULL, &obj, NULL);
|
|
visit_free(v);
|
|
}
|
|
|
|
[Uninteresting stuff omitted...]
|
|
|
|
For a modular QAPI schema (see section Include directives), code for
|
|
each sub-module SUBDIR/SUBMODULE.json is actually generated into
|
|
|
|
SUBDIR/$(prefix)qapi-types-SUBMODULE.h
|
|
SUBDIR/$(prefix)qapi-types-SUBMODULE.c
|
|
|
|
If qapi-gen.py is run with option --builtins, additional files are
|
|
created:
|
|
|
|
qapi-builtin-types.h - C types corresponding to built-in types
|
|
|
|
qapi-builtin-types.c - Cleanup functions for the above C types
|
|
|
|
=== Code generated for visiting QAPI types ===
|
|
|
|
These are the visitor functions used to walk through and convert
|
|
between a native QAPI C data structure and some other format (such as
|
|
QObject); the generated functions are named visit_type_FOO() and
|
|
visit_type_FOO_members().
|
|
|
|
The following files are generated:
|
|
|
|
$(prefix)qapi-visit.c: Visitor function for a particular C type, used
|
|
to automagically convert QObjects into the
|
|
corresponding C type and vice-versa, as well
|
|
as for deallocating memory for an existing C
|
|
type
|
|
|
|
$(prefix)qapi-visit.h: Declarations for previously mentioned visitor
|
|
functions
|
|
|
|
Example:
|
|
|
|
$ cat qapi-generated/example-qapi-visit.h
|
|
[Uninteresting stuff omitted...]
|
|
|
|
#ifndef EXAMPLE_QAPI_VISIT_H
|
|
#define EXAMPLE_QAPI_VISIT_H
|
|
|
|
#include "qapi/qapi-builtin-visit.h"
|
|
#include "example-qapi-types.h"
|
|
|
|
|
|
void visit_type_UserDefOne_members(Visitor *v, UserDefOne *obj, Error **errp);
|
|
void visit_type_UserDefOne(Visitor *v, const char *name, UserDefOne **obj, Error **errp);
|
|
void visit_type_UserDefOneList(Visitor *v, const char *name, UserDefOneList **obj, Error **errp);
|
|
|
|
void visit_type_q_obj_my_command_arg_members(Visitor *v, q_obj_my_command_arg *obj, Error **errp);
|
|
|
|
#endif /* EXAMPLE_QAPI_VISIT_H */
|
|
$ cat qapi-generated/example-qapi-visit.c
|
|
[Uninteresting stuff omitted...]
|
|
|
|
void visit_type_UserDefOne_members(Visitor *v, UserDefOne *obj, Error **errp)
|
|
{
|
|
Error *err = NULL;
|
|
|
|
visit_type_int(v, "integer", &obj->integer, &err);
|
|
if (err) {
|
|
goto out;
|
|
}
|
|
if (visit_optional(v, "string", &obj->has_string)) {
|
|
visit_type_str(v, "string", &obj->string, &err);
|
|
if (err) {
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
out:
|
|
error_propagate(errp, err);
|
|
}
|
|
|
|
void visit_type_UserDefOne(Visitor *v, const char *name, UserDefOne **obj, Error **errp)
|
|
{
|
|
Error *err = NULL;
|
|
|
|
visit_start_struct(v, name, (void **)obj, sizeof(UserDefOne), &err);
|
|
if (err) {
|
|
goto out;
|
|
}
|
|
if (!*obj) {
|
|
goto out_obj;
|
|
}
|
|
visit_type_UserDefOne_members(v, *obj, &err);
|
|
if (err) {
|
|
goto out_obj;
|
|
}
|
|
visit_check_struct(v, &err);
|
|
out_obj:
|
|
visit_end_struct(v, (void **)obj);
|
|
if (err && visit_is_input(v)) {
|
|
qapi_free_UserDefOne(*obj);
|
|
*obj = NULL;
|
|
}
|
|
out:
|
|
error_propagate(errp, err);
|
|
}
|
|
|
|
void visit_type_UserDefOneList(Visitor *v, const char *name, UserDefOneList **obj, Error **errp)
|
|
{
|
|
Error *err = NULL;
|
|
UserDefOneList *tail;
|
|
size_t size = sizeof(**obj);
|
|
|
|
visit_start_list(v, name, (GenericList **)obj, size, &err);
|
|
if (err) {
|
|
goto out;
|
|
}
|
|
|
|
for (tail = *obj; tail;
|
|
tail = (UserDefOneList *)visit_next_list(v, (GenericList *)tail, size)) {
|
|
visit_type_UserDefOne(v, NULL, &tail->value, &err);
|
|
if (err) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!err) {
|
|
visit_check_list(v, &err);
|
|
}
|
|
visit_end_list(v, (void **)obj);
|
|
if (err && visit_is_input(v)) {
|
|
qapi_free_UserDefOneList(*obj);
|
|
*obj = NULL;
|
|
}
|
|
out:
|
|
error_propagate(errp, err);
|
|
}
|
|
|
|
void visit_type_q_obj_my_command_arg_members(Visitor *v, q_obj_my_command_arg *obj, Error **errp)
|
|
{
|
|
Error *err = NULL;
|
|
|
|
visit_type_UserDefOneList(v, "arg1", &obj->arg1, &err);
|
|
if (err) {
|
|
goto out;
|
|
}
|
|
|
|
out:
|
|
error_propagate(errp, err);
|
|
}
|
|
|
|
[Uninteresting stuff omitted...]
|
|
|
|
For a modular QAPI schema (see section Include directives), code for
|
|
each sub-module SUBDIR/SUBMODULE.json is actually generated into
|
|
|
|
SUBDIR/$(prefix)qapi-visit-SUBMODULE.h
|
|
SUBDIR/$(prefix)qapi-visit-SUBMODULE.c
|
|
|
|
If qapi-gen.py is run with option --builtins, additional files are
|
|
created:
|
|
|
|
qapi-builtin-visit.h - Visitor functions for built-in types
|
|
|
|
qapi-builtin-visit.c - Declarations for these visitor functions
|
|
|
|
=== Code generated for commands ===
|
|
|
|
These are the marshaling/dispatch functions for the commands defined
|
|
in the schema. The generated code provides qmp_marshal_COMMAND(), and
|
|
declares qmp_COMMAND() that the user must implement.
|
|
|
|
The following files are generated:
|
|
|
|
$(prefix)qapi-commands.c: Command marshal/dispatch functions for each
|
|
QMP command defined in the schema
|
|
|
|
$(prefix)qapi-commands.h: Function prototypes for the QMP commands
|
|
specified in the schema
|
|
|
|
Example:
|
|
|
|
$ cat qapi-generated/example-qapi-commands.h
|
|
[Uninteresting stuff omitted...]
|
|
|
|
#ifndef EXAMPLE_QAPI_COMMANDS_H
|
|
#define EXAMPLE_QAPI_COMMANDS_H
|
|
|
|
#include "example-qapi-types.h"
|
|
#include "qapi/qmp/dispatch.h"
|
|
|
|
UserDefOne *qmp_my_command(UserDefOneList *arg1, Error **errp);
|
|
void qmp_marshal_my_command(QDict *args, QObject **ret, Error **errp);
|
|
void example_qmp_init_marshal(QmpCommandList *cmds);
|
|
|
|
#endif /* EXAMPLE_QAPI_COMMANDS_H */
|
|
$ cat qapi-generated/example-qapi-commands.c
|
|
[Uninteresting stuff omitted...]
|
|
|
|
static void qmp_marshal_output_UserDefOne(UserDefOne *ret_in, QObject **ret_out, Error **errp)
|
|
{
|
|
Error *err = NULL;
|
|
Visitor *v;
|
|
|
|
v = qobject_output_visitor_new(ret_out);
|
|
visit_type_UserDefOne(v, "unused", &ret_in, &err);
|
|
if (!err) {
|
|
visit_complete(v, ret_out);
|
|
}
|
|
error_propagate(errp, err);
|
|
visit_free(v);
|
|
v = qapi_dealloc_visitor_new();
|
|
visit_type_UserDefOne(v, "unused", &ret_in, NULL);
|
|
visit_free(v);
|
|
}
|
|
|
|
void qmp_marshal_my_command(QDict *args, QObject **ret, Error **errp)
|
|
{
|
|
Error *err = NULL;
|
|
UserDefOne *retval;
|
|
Visitor *v;
|
|
q_obj_my_command_arg arg = {0};
|
|
|
|
v = qobject_input_visitor_new(QOBJECT(args));
|
|
visit_start_struct(v, NULL, NULL, 0, &err);
|
|
if (err) {
|
|
goto out;
|
|
}
|
|
visit_type_q_obj_my_command_arg_members(v, &arg, &err);
|
|
if (!err) {
|
|
visit_check_struct(v, &err);
|
|
}
|
|
visit_end_struct(v, NULL);
|
|
if (err) {
|
|
goto out;
|
|
}
|
|
|
|
retval = qmp_my_command(arg.arg1, &err);
|
|
if (err) {
|
|
goto out;
|
|
}
|
|
|
|
qmp_marshal_output_UserDefOne(retval, ret, &err);
|
|
|
|
out:
|
|
error_propagate(errp, err);
|
|
visit_free(v);
|
|
v = qapi_dealloc_visitor_new();
|
|
visit_start_struct(v, NULL, NULL, 0, NULL);
|
|
visit_type_q_obj_my_command_arg_members(v, &arg, NULL);
|
|
visit_end_struct(v, NULL);
|
|
visit_free(v);
|
|
}
|
|
|
|
void example_qmp_init_marshal(QmpCommandList *cmds)
|
|
{
|
|
QTAILQ_INIT(cmds);
|
|
|
|
qmp_register_command(cmds, "my-command",
|
|
qmp_marshal_my_command, QCO_NO_OPTIONS);
|
|
}
|
|
|
|
[Uninteresting stuff omitted...]
|
|
|
|
For a modular QAPI schema (see section Include directives), code for
|
|
each sub-module SUBDIR/SUBMODULE.json is actually generated into
|
|
|
|
SUBDIR/$(prefix)qapi-commands-SUBMODULE.h
|
|
SUBDIR/$(prefix)qapi-commands-SUBMODULE.c
|
|
|
|
=== Code generated for events ===
|
|
|
|
This is the code related to events defined in the schema, providing
|
|
qapi_event_send_EVENT().
|
|
|
|
The following files are created:
|
|
|
|
$(prefix)qapi-events.h - Function prototypes for each event type
|
|
|
|
$(prefix)qapi-events.c - Implementation of functions to send an event
|
|
|
|
$(prefix)qapi-emit-events.h - Enumeration of all event names, and
|
|
common event code declarations
|
|
|
|
$(prefix)qapi-emit-events.c - Common event code definitions
|
|
|
|
Example:
|
|
|
|
$ cat qapi-generated/example-qapi-events.h
|
|
[Uninteresting stuff omitted...]
|
|
|
|
#ifndef EXAMPLE_QAPI_EVENTS_H
|
|
#define EXAMPLE_QAPI_EVENTS_H
|
|
|
|
#include "qapi/util.h"
|
|
#include "example-qapi-types.h"
|
|
|
|
void qapi_event_send_my_event(void);
|
|
|
|
#endif /* EXAMPLE_QAPI_EVENTS_H */
|
|
$ cat qapi-generated/example-qapi-events.c
|
|
[Uninteresting stuff omitted...]
|
|
|
|
void qapi_event_send_my_event(void)
|
|
{
|
|
QDict *qmp;
|
|
|
|
qmp = qmp_event_build_dict("MY_EVENT");
|
|
|
|
example_qapi_event_emit(EXAMPLE_QAPI_EVENT_MY_EVENT, qmp);
|
|
|
|
qobject_unref(qmp);
|
|
}
|
|
|
|
[Uninteresting stuff omitted...]
|
|
$ cat qapi-generated/example-qapi-emit-events.h
|
|
[Uninteresting stuff omitted...]
|
|
|
|
#ifndef EXAMPLE_QAPI_EMIT_EVENTS_H
|
|
#define EXAMPLE_QAPI_EMIT_EVENTS_H
|
|
|
|
#include "qapi/util.h"
|
|
|
|
typedef enum example_QAPIEvent {
|
|
EXAMPLE_QAPI_EVENT_MY_EVENT,
|
|
EXAMPLE_QAPI_EVENT__MAX,
|
|
} example_QAPIEvent;
|
|
|
|
#define example_QAPIEvent_str(val) \
|
|
qapi_enum_lookup(&example_QAPIEvent_lookup, (val))
|
|
|
|
extern const QEnumLookup example_QAPIEvent_lookup;
|
|
|
|
void example_qapi_event_emit(example_QAPIEvent event, QDict *qdict);
|
|
|
|
#endif /* EXAMPLE_QAPI_EMIT_EVENTS_H */
|
|
$ cat qapi-generated/example-qapi-emit-events.c
|
|
[Uninteresting stuff omitted...]
|
|
|
|
const QEnumLookup example_QAPIEvent_lookup = {
|
|
.array = (const char *const[]) {
|
|
[EXAMPLE_QAPI_EVENT_MY_EVENT] = "MY_EVENT",
|
|
},
|
|
.size = EXAMPLE_QAPI_EVENT__MAX
|
|
};
|
|
|
|
[Uninteresting stuff omitted...]
|
|
|
|
For a modular QAPI schema (see section Include directives), code for
|
|
each sub-module SUBDIR/SUBMODULE.json is actually generated into
|
|
|
|
SUBDIR/$(prefix)qapi-events-SUBMODULE.h
|
|
SUBDIR/$(prefix)qapi-events-SUBMODULE.c
|
|
|
|
=== Code generated for introspection ===
|
|
|
|
The following files are created:
|
|
|
|
$(prefix)qapi-introspect.c - Defines a string holding a JSON
|
|
description of the schema
|
|
|
|
$(prefix)qapi-introspect.h - Declares the above string
|
|
|
|
Example:
|
|
|
|
$ cat qapi-generated/example-qapi-introspect.h
|
|
[Uninteresting stuff omitted...]
|
|
|
|
#ifndef EXAMPLE_QAPI_INTROSPECT_H
|
|
#define EXAMPLE_QAPI_INTROSPECT_H
|
|
|
|
#include "qapi/qmp/qlit.h"
|
|
|
|
extern const QLitObject example_qmp_schema_qlit;
|
|
|
|
#endif /* EXAMPLE_QAPI_INTROSPECT_H */
|
|
$ cat qapi-generated/example-qapi-introspect.c
|
|
[Uninteresting stuff omitted...]
|
|
|
|
const QLitObject example_qmp_schema_qlit = QLIT_QLIST(((QLitObject[]) {
|
|
QLIT_QDICT(((QLitDictEntry[]) {
|
|
{ "arg-type", QLIT_QSTR("0"), },
|
|
{ "meta-type", QLIT_QSTR("command"), },
|
|
{ "name", QLIT_QSTR("my-command"), },
|
|
{ "ret-type", QLIT_QSTR("1"), },
|
|
{}
|
|
})),
|
|
QLIT_QDICT(((QLitDictEntry[]) {
|
|
{ "arg-type", QLIT_QSTR("2"), },
|
|
{ "meta-type", QLIT_QSTR("event"), },
|
|
{ "name", QLIT_QSTR("MY_EVENT"), },
|
|
{}
|
|
})),
|
|
/* "0" = q_obj_my-command-arg */
|
|
QLIT_QDICT(((QLitDictEntry[]) {
|
|
{ "members", QLIT_QLIST(((QLitObject[]) {
|
|
QLIT_QDICT(((QLitDictEntry[]) {
|
|
{ "name", QLIT_QSTR("arg1"), },
|
|
{ "type", QLIT_QSTR("[1]"), },
|
|
{}
|
|
})),
|
|
{}
|
|
})), },
|
|
{ "meta-type", QLIT_QSTR("object"), },
|
|
{ "name", QLIT_QSTR("0"), },
|
|
{}
|
|
})),
|
|
/* "1" = UserDefOne */
|
|
QLIT_QDICT(((QLitDictEntry[]) {
|
|
{ "members", QLIT_QLIST(((QLitObject[]) {
|
|
QLIT_QDICT(((QLitDictEntry[]) {
|
|
{ "name", QLIT_QSTR("integer"), },
|
|
{ "type", QLIT_QSTR("int"), },
|
|
{}
|
|
})),
|
|
QLIT_QDICT(((QLitDictEntry[]) {
|
|
{ "default", QLIT_QNULL, },
|
|
{ "name", QLIT_QSTR("string"), },
|
|
{ "type", QLIT_QSTR("str"), },
|
|
{}
|
|
})),
|
|
{}
|
|
})), },
|
|
{ "meta-type", QLIT_QSTR("object"), },
|
|
{ "name", QLIT_QSTR("1"), },
|
|
{}
|
|
})),
|
|
/* "2" = q_empty */
|
|
QLIT_QDICT(((QLitDictEntry[]) {
|
|
{ "members", QLIT_QLIST(((QLitObject[]) {
|
|
{}
|
|
})), },
|
|
{ "meta-type", QLIT_QSTR("object"), },
|
|
{ "name", QLIT_QSTR("2"), },
|
|
{}
|
|
})),
|
|
QLIT_QDICT(((QLitDictEntry[]) {
|
|
{ "element-type", QLIT_QSTR("1"), },
|
|
{ "meta-type", QLIT_QSTR("array"), },
|
|
{ "name", QLIT_QSTR("[1]"), },
|
|
{}
|
|
})),
|
|
QLIT_QDICT(((QLitDictEntry[]) {
|
|
{ "json-type", QLIT_QSTR("int"), },
|
|
{ "meta-type", QLIT_QSTR("builtin"), },
|
|
{ "name", QLIT_QSTR("int"), },
|
|
{}
|
|
})),
|
|
QLIT_QDICT(((QLitDictEntry[]) {
|
|
{ "json-type", QLIT_QSTR("string"), },
|
|
{ "meta-type", QLIT_QSTR("builtin"), },
|
|
{ "name", QLIT_QSTR("str"), },
|
|
{}
|
|
})),
|
|
{}
|
|
}));
|
|
|
|
[Uninteresting stuff omitted...]
|