|
@@ -502,13 +502,206 @@ Resulting in this JSON object:
|
|
"timestamp": { "seconds": 1267020223, "microseconds": 435656 } }
|
|
"timestamp": { "seconds": 1267020223, "microseconds": 435656 } }
|
|
|
|
|
|
|
|
|
|
|
|
+== 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.
|
|
|
|
+
|
|
|
|
+query-qmp-schema returns a JSON array of SchemaInfo objects. These
|
|
|
|
+objects together describe the wire ABI, as defined in the QAPI schema.
|
|
|
|
+
|
|
|
|
+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 entities defined in the QAPI schema have the same name
|
|
|
|
+as in the schema. This is the case for all commands and events, and
|
|
|
|
+most types.
|
|
|
|
+
|
|
|
|
+Command and event names are part of the wire ABI, but type names are
|
|
|
|
+not. Therefore, looking up a type by its name in the QAPI schema is
|
|
|
|
+wrong. Look up the command or event, 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" and "ret-type". 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".
|
|
|
|
+
|
|
|
|
+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": ":empty", "ret-type": "SchemaInfoList" }
|
|
|
|
+
|
|
|
|
+ Type ":empty" is an 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 called ":obj-NAME-arg",
|
|
|
|
+where NAME is the command or event's name.
|
|
|
|
+
|
|
|
|
+Example: the SchemaInfo for EVENT_C from section Events
|
|
|
|
+
|
|
|
|
+ { "name": "EVENT_C", "meta-type": "event",
|
|
|
|
+ "arg-type": ":obj-EVENT_C-arg" }
|
|
|
|
+
|
|
|
|
+ Type ":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.
|
|
|
|
+
|
|
|
|
+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).
|
|
|
|
+
|
|
|
|
+Example: the SchemaInfo for flat union BlockdevOptions from section
|
|
|
|
+Union types
|
|
|
|
+
|
|
|
|
+ { "name": "BlockdevOptions", "meta-type": "object",
|
|
|
|
+ "members": [
|
|
|
|
+ { "name": "driver", "type": "BlockdevDriver" },
|
|
|
|
+ { "name": "readonly", "type": "bool"} ],
|
|
|
|
+ "tag": "driver",
|
|
|
|
+ "variants": [
|
|
|
|
+ { "case": "file", "type": "FileOptions" },
|
|
|
|
+ { "case": "qcow2", "type": "Qcow2Options" } ] }
|
|
|
|
+
|
|
|
|
+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).
|
|
|
|
+Such a type's name is made by appending "Kind" to the simple union's
|
|
|
|
+name.
|
|
|
|
+
|
|
|
|
+A simple union implicitly defines an object type for each of its
|
|
|
|
+variants. The type's name is ":obj-NAME-wrapper", where NAME is the
|
|
|
|
+name of the name of the variant's type.
|
|
|
|
+
|
|
|
|
+Example: the SchemaInfo for simple union BlockdevOptions from section
|
|
|
|
+Union types
|
|
|
|
+
|
|
|
|
+ { "name": "BlockdevOptions", "meta-type": "object",
|
|
|
|
+ "members": [
|
|
|
|
+ { "name": "kind", "type": "BlockdevOptionsKind" } ],
|
|
|
|
+ "tag": "type",
|
|
|
|
+ "variants": [
|
|
|
|
+ { "case": "file", "type": ":obj-FileOptions-wrapper" },
|
|
|
|
+ { "case": "qcow2", "type": ":obj-Qcow2Options-wrapper" } ] }
|
|
|
|
+
|
|
|
|
+ Enumeration type "BlockdevOptionsKind" and the object types
|
|
|
|
+ ":obj-FileOptions-wrapper", ":obj-Qcow2Options-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.
|
|
|
|
+
|
|
|
|
+Example: the SchemaInfo for BlockRef from section Alternate types
|
|
|
|
+
|
|
|
|
+ { "name": "BlockRef", "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. An array type's name is made by
|
|
|
|
+appending "List" to its element type's name.
|
|
|
|
+
|
|
|
|
+Example: the SchemaInfo for ['str']
|
|
|
|
+
|
|
|
|
+ { "name": "strList", "meta-type": "array",
|
|
|
|
+ "element-type": "str" }
|
|
|
|
+
|
|
|
|
+The SchemaInfo for an enumeration type has meta-type "enum" and
|
|
|
|
+variant member "values".
|
|
|
|
+
|
|
|
|
+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.
|
|
|
|
+
|
|
|
|
+
|
|
== Code generation ==
|
|
== Code generation ==
|
|
|
|
|
|
-Schemas are fed into 3 scripts to generate all the code/files that, paired
|
|
|
|
-with the core QAPI libraries, comprise 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, and map the
|
|
|
|
-response back to a Client JSON Protocol response to be returned to the user.
|
|
|
|
|
|
+Schemas are fed into four scripts to generate all the code/files that,
|
|
|
|
+paired with the core QAPI libraries, comprise 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, and map the response back to a Client JSON Protocol
|
|
|
|
+response to be returned to the user.
|
|
|
|
|
|
As an example, we'll use the following schema, which describes a single
|
|
As an example, we'll use the following schema, which describes a single
|
|
complex user-defined type (which will produce a C struct, along with a list
|
|
complex user-defined type (which will produce a C struct, along with a list
|
|
@@ -856,3 +1049,37 @@ Example:
|
|
extern const char *const example_QAPIEvent_lookup[];
|
|
extern const char *const example_QAPIEvent_lookup[];
|
|
|
|
|
|
#endif
|
|
#endif
|
|
|
|
+
|
|
|
|
+=== scripts/qapi-introspect.py ===
|
|
|
|
+
|
|
|
|
+Used to generate the introspection C code for a schema. The following
|
|
|
|
+files are created:
|
|
|
|
+
|
|
|
|
+$(prefix)qmp-introspect.c - Defines a string holding a JSON
|
|
|
|
+ description of the schema.
|
|
|
|
+$(prefix)qmp-introspect.h - Declares the above string.
|
|
|
|
+
|
|
|
|
+Example:
|
|
|
|
+
|
|
|
|
+ $ python scripts/qapi-introspect.py --output-dir="qapi-generated"
|
|
|
|
+ --prefix="example-" example-schema.json
|
|
|
|
+ $ cat qapi-generated/example-qmp-introspect.c
|
|
|
|
+[Uninteresting stuff omitted...]
|
|
|
|
+
|
|
|
|
+ const char example_qmp_schema_json[] = "["
|
|
|
|
+ "{\"arg-type\": \":empty\", \"meta-type\": \"event\", \"name\": \"MY_EVENT\"}, "
|
|
|
|
+ "{\"json-type\": \"int\", \"meta-type\": \"builtin\", \"name\": \"int\"}, "
|
|
|
|
+ "{\"json-type\": \"string\", \"meta-type\": \"builtin\", \"name\": \"str\"}, "
|
|
|
|
+ "{\"members\": [], \"meta-type\": \"object\", \"name\": \":empty\"}, "
|
|
|
|
+ "{\"members\": [{\"name\": \"arg1\", \"type\": \"UserDefOne\"}], \"meta-type\": \"object\", \"name\": \":obj-my-command-arg\"}, "
|
|
|
|
+ "{\"members\": [{\"name\": \"integer\", \"type\": \"int\"}, {\"name\": \"string\", \"type\": \"str\"}], \"meta-type\": \"object\", \"name\": \"UserDefOne\"}, "
|
|
|
|
+ "{\"arg-type\": \":obj-my-command-arg\", \"meta-type\": \"command\", \"name\": \"my-command\", \"ret-type\": \"UserDefOne\"}]";
|
|
|
|
+ $ cat qapi-generated/example-qmp-introspect.h
|
|
|
|
+[Uninteresting stuff omitted...]
|
|
|
|
+
|
|
|
|
+ #ifndef EXAMPLE_QMP_INTROSPECT_H
|
|
|
|
+ #define EXAMPLE_QMP_INTROSPECT_H
|
|
|
|
+
|
|
|
|
+ extern const char example_qmp_schema_json[];
|
|
|
|
+
|
|
|
|
+ #endif
|