| 
									
										
										
										
											2011-10-28 17:43:29 -02:00
										 |  |  | = 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. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This document doesn't discuss QMP protocol level details, nor does it dive | 
					
						
							|  |  |  | into the QAPI framework implementation. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | For an in-depth introduction to the QAPI framework, please refer to | 
					
						
							|  |  |  | docs/qapi-code-gen.txt. For documentation about the QMP protocol, please | 
					
						
							|  |  |  | check the files in QMP/. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | == Overview == | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Generally speaking, the following steps should be taken in order to write a | 
					
						
							|  |  |  | new QMP command. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 1. Write the command's and type(s) specification in the QAPI schema file | 
					
						
							|  |  |  |    (qapi-schema.json in the root source directory) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 2. Write the QMP command itself, which is a regular C function. Preferably, | 
					
						
							|  |  |  |    the command should be exported by some QEMU subsystem. But it can also be | 
					
						
							|  |  |  |    added to the qmp.c file | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 3. At this point the command can be tested under the QMP protocol | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 4. Write the HMP command equivalent. This is not required and should only be | 
					
						
							|  |  |  |    done if it does make sense to have the functionality in HMP. The HMP command | 
					
						
							|  |  |  |    is implemented in terms of the 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 === | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | For all the examples in the next sections, the test setup is the same and is | 
					
						
							|  |  |  | shown here. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | First, QEMU should be started as: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # /path/to/your/source/qemu [...] \ | 
					
						
							|  |  |  |     -chardev socket,id=qmp,port=4444,host=localhost,server \ | 
					
						
							|  |  |  |     -mon chardev=qmp,mode=control,pretty=on | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Then, in a different terminal: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | $ telnet localhost 4444 | 
					
						
							|  |  |  | Trying 127.0.0.1... | 
					
						
							|  |  |  | Connected to localhost. | 
					
						
							|  |  |  | Escape character is '^]'. | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     "QMP": { | 
					
						
							|  |  |  |         "version": { | 
					
						
							|  |  |  |             "qemu": { | 
					
						
							|  |  |  |                 "micro": 50,  | 
					
						
							|  |  |  |                 "minor": 15,  | 
					
						
							|  |  |  |                 "major": 0 | 
					
						
							|  |  |  |             },  | 
					
						
							|  |  |  |             "package": "" | 
					
						
							|  |  |  |         },  | 
					
						
							|  |  |  |         "capabilities": [ | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | { "execute": "qmp_capabilities" } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Then the server should respond: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     "return": { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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 == | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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 | 
					
						
							|  |  |  | "Hello, world" to the standard output. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Our command will be called "hello-world". It takes no arguments, nor does it | 
					
						
							|  |  |  | return any data. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The first step is to add the following line to the bottom of the | 
					
						
							|  |  |  | qapi-schema.json file: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | { 'command': 'hello-world' } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The "command" keyword defines a new QMP command. It's an JSON object. All | 
					
						
							|  |  |  | schema entries are JSON objects. The line above will instruct the QAPI to | 
					
						
							|  |  |  | generate any prototypes and the necessary code to marshal and unmarshal | 
					
						
							|  |  |  | 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 qmp.c: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void qmp_hello_world(Error **errp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     printf("Hello, world!\n"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | There are a few things to be noticed: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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 | 
					
						
							|  |  |  |    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 | 
					
						
							|  |  |  | 5. Printing to the terminal is discouraged for QMP commands, we do it here | 
					
						
							|  |  |  |    because it's the easiest way to demonstrate a QMP command | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Now a little hack is needed. As we're still using the old QMP server we need | 
					
						
							|  |  |  | to add the new command to its internal dispatch table. This step won't be | 
					
						
							|  |  |  | required in the near future. Open the qmp-commands.hx file and add the | 
					
						
							|  |  |  | following in the botton: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         .name       = "hello-world", | 
					
						
							|  |  |  |         .args_type  = "", | 
					
						
							|  |  |  |         .mhandler.cmd_new = qmp_marshal_input_hello_world, | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | You're done. Now build qemu, run it as suggested in the "Testing" section, | 
					
						
							|  |  |  | 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 === | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | { 'command': 'hello-world', 'data': { '*message': 'str' } } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Notice the new 'data' member in the schema. It's an JSON object whose each | 
					
						
							|  |  |  | element is an argument to the command in question. Also notice the asterisk, | 
					
						
							|  |  |  | it's used to mark the argument optional (that means that you shouldn't use it | 
					
						
							|  |  |  | 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 qmp.c: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void qmp_hello_world(bool has_message, const char *message, Error **errp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (has_message) { | 
					
						
							|  |  |  |         printf("%s\n", message); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         printf("Hello, world\n"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | There are two important details to be noticed: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The last step is to update the qmp-commands.hx file: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         .name       = "hello-world", | 
					
						
							|  |  |  |         .args_type  = "message:s?", | 
					
						
							|  |  |  |         .mhandler.cmd_new = qmp_marshal_input_hello_world, | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Notice that the "args_type" member got our "message" argument. The character | 
					
						
							|  |  |  | "s" stands for "string" and "?" means it's optional. This too must be ordered | 
					
						
							|  |  |  | according to the C implementation and schema file. You can look for more | 
					
						
							|  |  |  | examples in the qmp-commands.hx file if you need to define more arguments. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Again, this step won't be required in the future. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | { "execute": "hello-world" } | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     "return": { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | { "execute": "hello-world", "arguments": { "message": "We love qemu" } } | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     "return": { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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 === | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QMP commands should use the error interface exported by the error.h header | 
					
						
							| 
									
										
										
										
											2012-08-06 11:35:22 -03:00
										 |  |  | file. Basically, errors are set by calling the error_set() function. | 
					
						
							| 
									
										
										
										
											2011-10-28 17:43:29 -02:00
										 |  |  | 
 | 
					
						
							|  |  |  | Let's say we don't accept the string "message" to contain the word "love". If | 
					
						
							| 
									
										
										
										
											2012-08-06 11:35:22 -03:00
										 |  |  | it does contain it, we want the "hello-world" command to return an error: | 
					
						
							| 
									
										
										
										
											2011-10-28 17:43:29 -02:00
										 |  |  | 
 | 
					
						
							|  |  |  | void qmp_hello_world(bool has_message, const char *message, Error **errp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (has_message) { | 
					
						
							|  |  |  |         if (strstr(message, "love")) { | 
					
						
							| 
									
										
										
										
											2012-08-06 11:35:22 -03:00
										 |  |  |             error_set(errp, ERROR_CLASS_GENERIC_ERROR, | 
					
						
							|  |  |  |                       "the word 'love' is not allowed"); | 
					
						
							| 
									
										
										
										
											2011-10-28 17:43:29 -02:00
										 |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         printf("%s\n", message); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         printf("Hello, world\n"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-06 11:35:22 -03:00
										 |  |  | The first argument to the error_set() function is the Error pointer to pointer, | 
					
						
							|  |  |  | which is passed to all QMP functions. The second argument is a ErrorClass | 
					
						
							|  |  |  | value, which should be ERROR_CLASS_GENERIC_ERROR most of the time (more | 
					
						
							|  |  |  | details about error classes are given below). The third 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: | 
					
						
							| 
									
										
										
										
											2011-10-28 17:43:29 -02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-06 11:35:22 -03:00
										 |  |  | { "execute": "hello-world", "arguments": { "message": "all you need is love" } } | 
					
						
							| 
									
										
										
										
											2011-10-28 17:43:29 -02:00
										 |  |  | 
 | 
					
						
							|  |  |  | The QMP server's response should be: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     "error": { | 
					
						
							| 
									
										
										
										
											2012-08-06 11:35:22 -03:00
										 |  |  |         "class": "GenericError", | 
					
						
							|  |  |  |         "desc": "the word 'love' is not allowed" | 
					
						
							| 
									
										
										
										
											2011-10-28 17:43:29 -02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-06 11:35:22 -03:00
										 |  |  | As a general rule, all QMP errors should use ERROR_CLASS_GENERIC_ERROR. There | 
					
						
							|  |  |  | are two exceptions to this rule: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  1. A non-generic ErrorClass value exists* for the failure you want to report | 
					
						
							|  |  |  |     (eg. DeviceNotFound) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  2. Management applications have to take special action on the failure you | 
					
						
							|  |  |  |     want to report, hence you have to add a new ErrorClass value so that they | 
					
						
							|  |  |  |     can check for it | 
					
						
							| 
									
										
										
										
											2011-10-28 17:43:29 -02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-06 11:35:22 -03:00
										 |  |  | If the failure you want to report doesn't fall in one of the two cases above, | 
					
						
							|  |  |  | just report ERROR_CLASS_GENERIC_ERROR. | 
					
						
							| 
									
										
										
										
											2011-10-28 17:43:29 -02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-06 11:35:22 -03:00
										 |  |  |  * All existing ErrorClass values are defined in the qapi-schema.json file | 
					
						
							| 
									
										
										
										
											2011-10-28 17:43:29 -02:00
										 |  |  | 
 | 
					
						
							|  |  |  | === Command Documentation === | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | There's only one step missing to make "hello-world"'s implementation complete, | 
					
						
							|  |  |  | and that's its documentation in the schema file. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This is very important. No QMP command will be accepted in QEMU without proper | 
					
						
							|  |  |  | documentation. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | There are many examples of such documentation in the schema file already, but | 
					
						
							|  |  |  | here goes "hello-world"'s new entry for the qapi-schema.json file: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## | 
					
						
							|  |  |  | # @hello-world | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # Print a client provided string to the standard output stream. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # @message: #optional string to be printed | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # Returns: Nothing on success. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # Notes: if @message is not provided, the "Hello, world" string will | 
					
						
							|  |  |  | #        be printed instead | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # Since: <next qemu stable release, eg. 1.0> | 
					
						
							|  |  |  | ## | 
					
						
							|  |  |  | { 'command': 'hello-world', 'data': { '*message': 'str' } } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Please, note that the "Returns" clause is optional if a command doesn't return | 
					
						
							|  |  |  | any data nor any errors. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | === Implementing the HMP command === | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Now that the QMP command is in place, we can also make it available in the human | 
					
						
							|  |  |  | monitor (HMP). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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 hmp.c file. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Here's the implementation of the "hello-world" HMP command: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hmp_hello_world(Monitor *mon, const QDict *qdict) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const char *message = qdict_get_try_str(qdict, "message"); | 
					
						
							|  |  |  |     Error *errp = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     qmp_hello_world(!!message, message, &errp); | 
					
						
							|  |  |  |     if (error_is_set(&errp)) { | 
					
						
							|  |  |  |         monitor_printf(mon, "%s\n", error_get_pretty(errp)); | 
					
						
							|  |  |  |         error_free(errp); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Also, you have to add the function's prototype to the hmp.h file. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | There are three important points to be noticed: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 1. The "mon" and "qdict" arguments are mandatory for all HMP functions. The | 
					
						
							|  |  |  |    former is the monitor object. The latter is how the monitor passes | 
					
						
							|  |  |  |    arguments entered by the user to the command implementation | 
					
						
							|  |  |  | 2. hmp_hello_world() performs error checking. In this example we just print | 
					
						
							|  |  |  |    the error description to the user, but we could do more, like taking | 
					
						
							|  |  |  |    different actions depending on the error qmp_hello_world() returns | 
					
						
							|  |  |  | 3. The "errp" variable must be initialized to NULL before performing the | 
					
						
							|  |  |  |    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: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         .name       = "hello-world", | 
					
						
							|  |  |  |         .args_type  = "message:s?", | 
					
						
							|  |  |  |         .params     = "hello-world [message]", | 
					
						
							|  |  |  |         .help       = "Print message to the standard output", | 
					
						
							|  |  |  |         .mhandler.cmd = hmp_hello_world, | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | STEXI | 
					
						
							|  |  |  | @item hello_world @var{message} | 
					
						
							|  |  |  | @findex hello_world | 
					
						
							|  |  |  | Print message to the standard output | 
					
						
							|  |  |  | ETEXI | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | To test this you have to open a user monitor and issue the "hello-world" | 
					
						
							|  |  |  | command. It might be instructive to check the command's documentation with | 
					
						
							|  |  |  | 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 == | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | A QMP command is capable of returning any data the QAPI supports like integers, | 
					
						
							|  |  |  | 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 === | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | For this example we will write the query-alarm-clock command, which returns | 
					
						
							|  |  |  | information about QEMU's timer alarm. For more information about it, please | 
					
						
							|  |  |  | check the "-clock" command-line option. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | We want to return two pieces of information. The first one is the alarm clock's | 
					
						
							|  |  |  | name. The second one is when the next alarm will fire. The former information is | 
					
						
							|  |  |  | 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: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## | 
					
						
							|  |  |  | # @QemuAlarmClock | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # QEMU alarm clock information. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # @clock-name: The alarm clock method's name. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # @next-deadline: #optional The time (in nanoseconds) the next alarm will fire. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # Since: 1.0 | 
					
						
							|  |  |  | ## | 
					
						
							|  |  |  | { 'type': 'QemuAlarmClock', | 
					
						
							|  |  |  |   'data': { 'clock-name': 'str', '*next-deadline': 'int' } } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## | 
					
						
							|  |  |  | # @query-alarm-clock | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # Return information about QEMU's alarm clock. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # Returns a @QemuAlarmClock instance describing the alarm clock method | 
					
						
							|  |  |  | # being currently used by QEMU (this is usually set by the '-clock' | 
					
						
							|  |  |  | # command-line option). | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # Since: 1.0 | 
					
						
							|  |  |  | ## | 
					
						
							|  |  |  | { 'command': 'query-alarm-clock', 'returns': 'QemuAlarmClock' } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QemuAlarmClock *qmp_query_alarm_clock(Error **errp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QemuAlarmClock *clock; | 
					
						
							|  |  |  |     int64_t deadline; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     clock = g_malloc0(sizeof(*clock)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     deadline = qemu_next_alarm_deadline(); | 
					
						
							|  |  |  |     if (deadline > 0) { | 
					
						
							|  |  |  |         clock->has_next_deadline = true; | 
					
						
							|  |  |  |         clock->next_deadline = deadline; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     clock->clock_name = g_strdup(alarm_timer->name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return clock; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | There are a number of things to be noticed: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 1. The QemuAlarmClock type is automatically generated by the QAPI framework, | 
					
						
							|  |  |  |    its members correspond to the type's specification in the schema file | 
					
						
							|  |  |  | 2. As specified in the schema file, the function returns a QemuAlarmClock | 
					
						
							|  |  |  |    instance and takes no arguments (besides the "errp" one, which is mandatory | 
					
						
							|  |  |  |    for all QMP functions) | 
					
						
							|  |  |  | 3. The "clock" variable (which will point to our QAPI type instance) is | 
					
						
							|  |  |  |    allocated by the regular g_malloc0() function. Note that we chose to | 
					
						
							| 
									
										
										
										
											2012-01-08 19:35:09 +01:00
										 |  |  |    initialize the memory to zero. This is recommended for all QAPI types, as | 
					
						
							| 
									
										
										
										
											2011-10-28 17:43:29 -02:00
										 |  |  |    it helps avoiding bad surprises (specially with booleans) | 
					
						
							|  |  |  | 4. Remember that "next_deadline" is optional? All optional members have a | 
					
						
							|  |  |  |    'has_TYPE_NAME' member that should be properly set by the implementation, | 
					
						
							|  |  |  |    as shown above | 
					
						
							|  |  |  | 5. Even static strings, such as "alarm_timer->name", should be dynamically | 
					
						
							|  |  |  |    allocated by the implementation. This is so because the QAPI also generates | 
					
						
							|  |  |  |    a function to free its types and it cannot distinguish between dynamically | 
					
						
							|  |  |  |    or statically allocated strings | 
					
						
							|  |  |  | 6. You have to include the "qmp-commands.h" header file in qemu-timer.c, | 
					
						
							|  |  |  |    otherwise qemu won't build | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The last step is to add the correspoding entry in the qmp-commands.hx file: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         .name       = "query-alarm-clock", | 
					
						
							|  |  |  |         .args_type  = "", | 
					
						
							|  |  |  |         .mhandler.cmd_new = qmp_marshal_input_query_alarm_clock, | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Time to test the new command. Build qemu, run it as described in the "Testing" | 
					
						
							|  |  |  | section and try this: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | { "execute": "query-alarm-clock" } | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     "return": { | 
					
						
							|  |  |  |         "next-deadline": 2368219, | 
					
						
							|  |  |  |         "clock-name": "dynticks" | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ==== The HMP command ==== | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Here's the HMP counterpart of the query-alarm-clock command: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hmp_info_alarm_clock(Monitor *mon) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QemuAlarmClock *clock; | 
					
						
							|  |  |  |     Error *errp = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     clock = qmp_query_alarm_clock(&errp); | 
					
						
							|  |  |  |     if (error_is_set(&errp)) { | 
					
						
							|  |  |  |         monitor_printf(mon, "Could not query alarm clock information\n"); | 
					
						
							|  |  |  |         error_free(errp); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     monitor_printf(mon, "Alarm clock method in use: '%s'\n", clock->clock_name); | 
					
						
							|  |  |  |     if (clock->has_next_deadline) { | 
					
						
							|  |  |  |         monitor_printf(mon, "Next alarm will fire in %" PRId64 " nanoseconds\n", | 
					
						
							|  |  |  |                        clock->next_deadline); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    qapi_free_QemuAlarmClock(clock);  | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | It's important to notice that hmp_info_alarm_clock() calls | 
					
						
							|  |  |  | qapi_free_QemuAlarmClock() to free the data returned by qmp_query_alarm_clock(). | 
					
						
							|  |  |  | For user defined types, the QAPI will generate a qapi_free_QAPI_TYPE_NAME() | 
					
						
							|  |  |  | function and that's what you have to use to free the types you define and | 
					
						
							|  |  |  | qapi_free_QAPI_TYPE_NAMEList() for list types (explained in the next section). | 
					
						
							|  |  |  | If the QMP call returns a string, then you should g_free() to free it. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Also note that hmp_info_alarm_clock() performs error handling. That's not | 
					
						
							|  |  |  | strictly required if you're sure the QMP function doesn't return errors, but | 
					
						
							|  |  |  | 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.c file. The entry for the "info alarmclock" follows: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         .name       = "alarmclock", | 
					
						
							|  |  |  |         .args_type  = "", | 
					
						
							|  |  |  |         .params     = "", | 
					
						
							|  |  |  |         .help       = "show information about the alarm clock", | 
					
						
							|  |  |  |         .mhandler.info = hmp_info_alarm_clock, | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | To test this, run qemu and type "info alarmclock" in the user monitor. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | === 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: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## | 
					
						
							|  |  |  | # @TimerAlarmMethod | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # Timer alarm method information. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # @method-name: The method's name. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # @current: true if this alarm method is currently in use, false otherwise | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # Since: 1.0 | 
					
						
							|  |  |  | ## | 
					
						
							|  |  |  | { 'type': 'TimerAlarmMethod', | 
					
						
							|  |  |  |   'data': { 'method-name': 'str', 'current': 'bool' } } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The command will be called "query-alarm-methods", here is its schema | 
					
						
							|  |  |  | specification: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## | 
					
						
							|  |  |  | # @query-alarm-methods | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # Returns information about available alarm methods. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # Returns: a list of @TimerAlarmMethod for each method | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # Since: 1.0 | 
					
						
							|  |  |  | ## | 
					
						
							|  |  |  | { 'command': 'query-alarm-methods', 'returns': ['TimerAlarmMethod'] } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Notice the syntax for returning lists "'returns': ['TimerAlarmMethod']", this | 
					
						
							|  |  |  | should be read as "returns a list of TimerAlarmMethod instances". | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The C implementation follows: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TimerAlarmMethodList *qmp_query_alarm_methods(Error **errp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     TimerAlarmMethodList *method_list = NULL; | 
					
						
							|  |  |  |     const struct qemu_alarm_timer *p; | 
					
						
							|  |  |  |     bool current = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (p = alarm_timers; p->name; p++) { | 
					
						
							|  |  |  |         TimerAlarmMethodList *info = g_malloc0(sizeof(*info)); | 
					
						
							|  |  |  |         info->value = g_malloc0(sizeof(*info->value)); | 
					
						
							|  |  |  |         info->value->method_name = g_strdup(p->name); | 
					
						
							|  |  |  |         info->value->current = current; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         current = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         info->next = method_list; | 
					
						
							|  |  |  |         method_list = info; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return method_list; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The most important difference from the previous examples is the | 
					
						
							|  |  |  | TimerAlarmMethodList type, which is automatically generated by the QAPI from | 
					
						
							|  |  |  | the TimerAlarmMethod type. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Each list node is represented by a TimerAlarmMethodList instance. We have to | 
					
						
							|  |  |  | allocate it, and that's done inside the for loop: the "info" pointer points to | 
					
						
							|  |  |  | an allocated node. We also have to allocate the node's contents, which is | 
					
						
							|  |  |  | stored in its "value" member. In our example, the "value" member is a pointer | 
					
						
							|  |  |  | to an TimerAlarmMethod instance. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Notice that the "current" variable is used as "true" only in the first | 
					
						
							|  |  |  | interation of the loop. That's because the alarm timer method in use is the | 
					
						
							|  |  |  | first element of the alarm_timers array. Also notice that QAPI lists are handled | 
					
						
							|  |  |  | by hand and we return the head of the list. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | To test this you have to add the corresponding qmp-commands.hx entry: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         .name       = "query-alarm-methods", | 
					
						
							|  |  |  |         .args_type  = "", | 
					
						
							|  |  |  |         .mhandler.cmd_new = qmp_marshal_input_query_alarm_methods, | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Now Build qemu, run it as explained in the "Testing" section and try our new | 
					
						
							|  |  |  | command: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | { "execute": "query-alarm-methods" } | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     "return": [ | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             "current": false,  | 
					
						
							|  |  |  |             "method-name": "unix" | 
					
						
							|  |  |  |         },  | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             "current": true,  | 
					
						
							|  |  |  |             "method-name": "dynticks" | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The HMP counterpart is a bit more complex than previous examples because it | 
					
						
							|  |  |  | has to traverse the list, it's shown below for reference: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hmp_info_alarm_methods(Monitor *mon) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     TimerAlarmMethodList *method_list, *method; | 
					
						
							|  |  |  |     Error *errp = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     method_list = qmp_query_alarm_methods(&errp); | 
					
						
							|  |  |  |     if (error_is_set(&errp)) { | 
					
						
							|  |  |  |         monitor_printf(mon, "Could not query alarm methods\n"); | 
					
						
							|  |  |  |         error_free(errp); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (method = method_list; method; method = method->next) { | 
					
						
							|  |  |  |         monitor_printf(mon, "%c %s\n", method->value->current ? '*' : ' ', | 
					
						
							|  |  |  |                                        method->value->method_name); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     qapi_free_TimerAlarmMethodList(method_list); | 
					
						
							|  |  |  | } |