docs: convert writing-qmp-commands.txt to writing-qmp-commands.rst
This does about the bare minimum, converting section headers to ReST ones and adding an indent for code blocks. Signed-off-by: John Snow <jsnow@redhat.com> Message-Id: <20210721165015.2180311-1-jsnow@redhat.com> Reviewed-by: Connor Kuehl <ckuehl@redhat.com> Signed-off-by: Markus Armbruster <armbru@redhat.com>
This commit is contained in:
parent
9c66762a60
commit
68e6dc594a
@ -43,3 +43,4 @@ modifying QEMU's source code.
|
||||
ebpf_rss
|
||||
vfio-migration
|
||||
qapi-code-gen
|
||||
writing-qmp-commands
|
||||
|
@ -1,4 +1,5 @@
|
||||
= How to write QMP commands using the QAPI framework =
|
||||
How to write QMP commands using the QAPI framework
|
||||
==================================================
|
||||
|
||||
This document is a step-by-step guide on how to write new QMP commands using
|
||||
the QAPI framework. It also shows how to implement new style HMP commands.
|
||||
@ -10,7 +11,9 @@ For an in-depth introduction to the QAPI framework, please refer to
|
||||
docs/devel/qapi-code-gen.txt. For documentation about the QMP protocol,
|
||||
start with docs/interop/qmp-intro.txt.
|
||||
|
||||
== Overview ==
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
Generally speaking, the following steps should be taken in order to write a
|
||||
new QMP command.
|
||||
@ -31,18 +34,20 @@ new QMP command.
|
||||
The following sections will demonstrate each of the steps above. We will start
|
||||
very simple and get more complex as we progress.
|
||||
|
||||
=== Testing ===
|
||||
|
||||
Testing
|
||||
-------
|
||||
|
||||
For all the examples in the next sections, the test setup is the same and is
|
||||
shown here.
|
||||
|
||||
First, QEMU should be started like this:
|
||||
First, QEMU should be started like this::
|
||||
|
||||
# qemu-system-TARGET [...] \
|
||||
-chardev socket,id=qmp,port=4444,host=localhost,server=on \
|
||||
-mon chardev=qmp,mode=control,pretty=on
|
||||
|
||||
Then, in a different terminal:
|
||||
Then, in a different terminal::
|
||||
|
||||
$ telnet localhost 4444
|
||||
Trying 127.0.0.1...
|
||||
@ -64,11 +69,11 @@ Escape character is '^]'.
|
||||
}
|
||||
|
||||
The above output is the QMP server saying you're connected. The server is
|
||||
actually in capabilities negotiation mode. To enter in command mode type:
|
||||
actually in capabilities negotiation mode. To enter in command mode type::
|
||||
|
||||
{ "execute": "qmp_capabilities" }
|
||||
|
||||
Then the server should respond:
|
||||
Then the server should respond::
|
||||
|
||||
{
|
||||
"return": {
|
||||
@ -79,7 +84,9 @@ Which is QMP's way of saying "the latest command executed OK and didn't return
|
||||
any data". Now you're ready to enter the QMP example commands as explained in
|
||||
the following sections.
|
||||
|
||||
== Writing a command that doesn't return data ==
|
||||
|
||||
Writing a command that doesn't return data
|
||||
------------------------------------------
|
||||
|
||||
That's the most simple QMP command that can be written. Usually, this kind of
|
||||
command carries some meaningful action in QEMU but here it will just print
|
||||
@ -90,7 +97,7 @@ return any data.
|
||||
|
||||
The first step is defining the command in the appropriate QAPI schema
|
||||
module. We pick module qapi/misc.json, and add the following line at
|
||||
the bottom:
|
||||
the bottom::
|
||||
|
||||
{ 'command': 'hello-world' }
|
||||
|
||||
@ -102,7 +109,7 @@ protocol data.
|
||||
The next step is to write the "hello-world" implementation. As explained
|
||||
earlier, it's preferable for commands to live in QEMU subsystems. But
|
||||
"hello-world" doesn't pertain to any, so we put its implementation in
|
||||
monitor/qmp-cmds.c:
|
||||
monitor/qmp-cmds.c::
|
||||
|
||||
void qmp_hello_world(Error **errp)
|
||||
{
|
||||
@ -111,10 +118,10 @@ void qmp_hello_world(Error **errp)
|
||||
|
||||
There are a few things to be noticed:
|
||||
|
||||
1. QMP command implementation functions must be prefixed with "qmp_"
|
||||
1. QMP command implementation functions must be prefixed with "qmp\_"
|
||||
2. qmp_hello_world() returns void, this is in accordance with the fact that the
|
||||
command doesn't return any data
|
||||
3. It takes an "Error **" argument. This is required. Later we will see how to
|
||||
3. It takes an "Error \*\*" argument. This is required. Later we will see how to
|
||||
return errors and take additional arguments. The Error argument should not
|
||||
be touched if the command doesn't return errors
|
||||
4. We won't add the function's prototype. That's automatically done by the QAPI
|
||||
@ -122,21 +129,23 @@ There are a few things to be noticed:
|
||||
because it's the easiest way to demonstrate a QMP command
|
||||
|
||||
You're done. Now build qemu, run it as suggested in the "Testing" section,
|
||||
and then type the following QMP command:
|
||||
and then type the following QMP command::
|
||||
|
||||
{ "execute": "hello-world" }
|
||||
|
||||
Then check the terminal running qemu and look for the "Hello, world" string. If
|
||||
you don't see it then something went wrong.
|
||||
|
||||
=== Arguments ===
|
||||
|
||||
Arguments
|
||||
~~~~~~~~~
|
||||
|
||||
Let's add an argument called "message" to our "hello-world" command. The new
|
||||
argument will contain the string to be printed to stdout. It's an optional
|
||||
argument, if it's not present we print our default "Hello, World" string.
|
||||
|
||||
The first change we have to do is to modify the command specification in the
|
||||
schema file to the following:
|
||||
schema file to the following::
|
||||
|
||||
{ 'command': 'hello-world', 'data': { '*message': 'str' } }
|
||||
|
||||
@ -147,7 +156,7 @@ for mandatory arguments). Finally, 'str' is the argument's type, which
|
||||
stands for "string". The QAPI also supports integers, booleans, enumerations
|
||||
and user defined types.
|
||||
|
||||
Now, let's update our C implementation in monitor/qmp-cmds.c:
|
||||
Now, let's update our C implementation in monitor/qmp-cmds.c::
|
||||
|
||||
void qmp_hello_world(bool has_message, const char *message, Error **errp)
|
||||
{
|
||||
@ -160,13 +169,13 @@ void qmp_hello_world(bool has_message, const char *message, Error **errp)
|
||||
|
||||
There are two important details to be noticed:
|
||||
|
||||
1. All optional arguments are accompanied by a 'has_' boolean, which is set
|
||||
1. All optional arguments are accompanied by a 'has\_' boolean, which is set
|
||||
if the optional argument is present or false otherwise
|
||||
2. The C implementation signature must follow the schema's argument ordering,
|
||||
which is defined by the "data" member
|
||||
|
||||
Time to test our new version of the "hello-world" command. Build qemu, run it as
|
||||
described in the "Testing" section and then send two commands:
|
||||
described in the "Testing" section and then send two commands::
|
||||
|
||||
{ "execute": "hello-world" }
|
||||
{
|
||||
@ -183,13 +192,15 @@ described in the "Testing" section and then send two commands:
|
||||
You should see "Hello, world" and "We love qemu" in the terminal running qemu,
|
||||
if you don't see these strings, then something went wrong.
|
||||
|
||||
=== Errors ===
|
||||
|
||||
Errors
|
||||
~~~~~~
|
||||
|
||||
QMP commands should use the error interface exported by the error.h header
|
||||
file. Basically, most errors are set by calling the error_setg() function.
|
||||
|
||||
Let's say we don't accept the string "message" to contain the word "love". If
|
||||
it does contain it, we want the "hello-world" command to return an error:
|
||||
it does contain it, we want the "hello-world" command to return an error::
|
||||
|
||||
void qmp_hello_world(bool has_message, const char *message, Error **errp)
|
||||
{
|
||||
@ -209,11 +220,11 @@ to pointer, which is passed to all QMP functions. The next argument is a human
|
||||
description of the error, this is a free-form printf-like string.
|
||||
|
||||
Let's test the example above. Build qemu, run it as defined in the "Testing"
|
||||
section, and then issue the following command:
|
||||
section, and then issue the following command::
|
||||
|
||||
{ "execute": "hello-world", "arguments": { "message": "all you need is love" } }
|
||||
|
||||
The QMP server's response should be:
|
||||
The QMP server's response should be::
|
||||
|
||||
{
|
||||
"error": {
|
||||
@ -234,13 +245,15 @@ to this rule:
|
||||
If the failure you want to report falls into one of the two cases above,
|
||||
use error_set() with a second argument of an ErrorClass value.
|
||||
|
||||
=== Command Documentation ===
|
||||
|
||||
Command Documentation
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
There's only one step missing to make "hello-world"'s implementation complete,
|
||||
and that's its documentation in the schema file.
|
||||
|
||||
There are many examples of such documentation in the schema file already, but
|
||||
here goes "hello-world"'s new entry for qapi/misc.json:
|
||||
here goes "hello-world"'s new entry for qapi/misc.json::
|
||||
|
||||
##
|
||||
# @hello-world:
|
||||
@ -261,7 +274,9 @@ here goes "hello-world"'s new entry for qapi/misc.json:
|
||||
Please, note that the "Returns" clause is optional if a command doesn't return
|
||||
any data nor any errors.
|
||||
|
||||
=== Implementing the HMP command ===
|
||||
|
||||
Implementing the HMP command
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Now that the QMP command is in place, we can also make it available in the human
|
||||
monitor (HMP).
|
||||
@ -270,7 +285,7 @@ With the introduction of the QAPI, HMP commands make QMP calls. Most of the
|
||||
time HMP commands are simple wrappers. All HMP commands implementation exist in
|
||||
the monitor/hmp-cmds.c file.
|
||||
|
||||
Here's the implementation of the "hello-world" HMP command:
|
||||
Here's the implementation of the "hello-world" HMP command::
|
||||
|
||||
void hmp_hello_world(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
@ -299,7 +314,7 @@ There are three important points to be noticed:
|
||||
QMP call
|
||||
|
||||
There's one last step to actually make the command available to monitor users,
|
||||
we should add it to the hmp-commands.hx file:
|
||||
we should add it to the hmp-commands.hx file::
|
||||
|
||||
{
|
||||
.name = "hello-world",
|
||||
@ -309,6 +324,8 @@ we should add it to the hmp-commands.hx file:
|
||||
.cmd = hmp_hello_world,
|
||||
},
|
||||
|
||||
::
|
||||
|
||||
STEXI
|
||||
@item hello_world @var{message}
|
||||
@findex hello_world
|
||||
@ -322,7 +339,9 @@ HMP's "help" command.
|
||||
Please, check the "-monitor" command-line option to know how to open a user
|
||||
monitor.
|
||||
|
||||
== Writing a command that returns data ==
|
||||
|
||||
Writing a command that returns data
|
||||
-----------------------------------
|
||||
|
||||
A QMP command is capable of returning any data the QAPI supports like integers,
|
||||
strings, booleans, enumerations and user defined types.
|
||||
@ -330,7 +349,9 @@ strings, booleans, enumerations and user defined types.
|
||||
In this section we will focus on user defined types. Please, check the QAPI
|
||||
documentation for information about the other types.
|
||||
|
||||
=== User Defined Types ===
|
||||
|
||||
User Defined Types
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
FIXME This example needs to be redone after commit 6d32717
|
||||
|
||||
@ -344,7 +365,7 @@ returned as a string, the latter is an integer in nanoseconds (which is not
|
||||
very useful in practice, as the timer has probably already fired when the
|
||||
information reaches the client).
|
||||
|
||||
The best way to return that data is to create a new QAPI type, as shown below:
|
||||
The best way to return that data is to create a new QAPI type, as shown below::
|
||||
|
||||
##
|
||||
# @QemuAlarmClock
|
||||
@ -364,7 +385,7 @@ The "type" keyword defines a new QAPI type. Its "data" member contains the
|
||||
type's members. In this example our members are the "clock-name" and the
|
||||
"next-deadline" one, which is optional.
|
||||
|
||||
Now let's define the query-alarm-clock command:
|
||||
Now let's define the query-alarm-clock command::
|
||||
|
||||
##
|
||||
# @query-alarm-clock
|
||||
@ -383,7 +404,7 @@ Notice the "returns" keyword. As its name suggests, it's used to define the
|
||||
data returned by a command.
|
||||
|
||||
It's time to implement the qmp_query_alarm_clock() function, you can put it
|
||||
in the qemu-timer.c file:
|
||||
in the qemu-timer.c file::
|
||||
|
||||
QemuAlarmClock *qmp_query_alarm_clock(Error **errp)
|
||||
{
|
||||
@ -423,7 +444,7 @@ There are a number of things to be noticed:
|
||||
6. You have to include "qapi/qapi-commands-misc.h" in qemu-timer.c
|
||||
|
||||
Time to test the new command. Build qemu, run it as described in the "Testing"
|
||||
section and try this:
|
||||
section and try this::
|
||||
|
||||
{ "execute": "query-alarm-clock" }
|
||||
{
|
||||
@ -433,9 +454,11 @@ section and try this:
|
||||
}
|
||||
}
|
||||
|
||||
==== The HMP command ====
|
||||
|
||||
Here's the HMP counterpart of the query-alarm-clock command:
|
||||
The HMP command
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Here's the HMP counterpart of the query-alarm-clock command::
|
||||
|
||||
void hmp_info_alarm_clock(Monitor *mon)
|
||||
{
|
||||
@ -471,7 +494,7 @@ it's good practice to always check for errors.
|
||||
|
||||
Another important detail is that HMP's "info" commands don't go into the
|
||||
hmp-commands.hx. Instead, they go into the info_cmds[] table, which is defined
|
||||
in the monitor/misc.c file. The entry for the "info alarmclock" follows:
|
||||
in the monitor/misc.c file. The entry for the "info alarmclock" follows::
|
||||
|
||||
{
|
||||
.name = "alarmclock",
|
||||
@ -483,13 +506,15 @@ in the monitor/misc.c file. The entry for the "info alarmclock" follows:
|
||||
|
||||
To test this, run qemu and type "info alarmclock" in the user monitor.
|
||||
|
||||
=== Returning Lists ===
|
||||
|
||||
Returning Lists
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
For this example, we're going to return all available methods for the timer
|
||||
alarm, which is pretty much what the command-line option "-clock ?" does,
|
||||
except that we're also going to inform which method is in use.
|
||||
|
||||
This first step is to define a new type:
|
||||
This first step is to define a new type::
|
||||
|
||||
##
|
||||
# @TimerAlarmMethod
|
||||
@ -506,7 +531,7 @@ This first step is to define a new type:
|
||||
'data': { 'method-name': 'str', 'current': 'bool' } }
|
||||
|
||||
The command will be called "query-alarm-methods", here is its schema
|
||||
specification:
|
||||
specification::
|
||||
|
||||
##
|
||||
# @query-alarm-methods
|
||||
@ -522,7 +547,7 @@ specification:
|
||||
Notice the syntax for returning lists "'returns': ['TimerAlarmMethod']", this
|
||||
should be read as "returns a list of TimerAlarmMethod instances".
|
||||
|
||||
The C implementation follows:
|
||||
The C implementation follows::
|
||||
|
||||
TimerAlarmMethodList *qmp_query_alarm_methods(Error **errp)
|
||||
{
|
||||
@ -557,7 +582,7 @@ first element of the alarm_timers array. Also notice that QAPI lists are handled
|
||||
by hand and we return the head of the list.
|
||||
|
||||
Now Build qemu, run it as explained in the "Testing" section and try our new
|
||||
command:
|
||||
command::
|
||||
|
||||
{ "execute": "query-alarm-methods" }
|
||||
{
|
||||
@ -574,7 +599,7 @@ command:
|
||||
}
|
||||
|
||||
The HMP counterpart is a bit more complex than previous examples because it
|
||||
has to traverse the list, it's shown below for reference:
|
||||
has to traverse the list, it's shown below for reference::
|
||||
|
||||
void hmp_info_alarm_methods(Monitor *mon)
|
||||
{
|
Loading…
x
Reference in New Issue
Block a user