From: Anthony Liguori <anthony@codemonkey.ws>
To: Markus Armbruster <armbru@redhat.com>
Cc: Kevin Wolf <kwolf@redhat.com>, qemu-devel <qemu-devel@nongnu.org>,
Luiz Capitulino <lcapitulino@redhat.com>
Subject: [Qemu-devel] Re: What's QAPI?
Date: Tue, 15 Feb 2011 10:15:17 -0600 [thread overview]
Message-ID: <4D5AA695.6050301@codemonkey.ws> (raw)
In-Reply-To: <m3tyg58k86.fsf@blackfin.pond.sub.org>
On 02/15/2011 08:07 AM, Markus Armbruster wrote:
> Anthony Liguori<anthony@codemonkey.ws> writes:
>
>
>> Hi,
>>
>> In my QAPI branch[1], I've now got almost every existing QMP command
>> converted with (hopefully) all of the hard problems solved. There is
>> only one remaining thing to attack before posting for inclusion and
>> that's events. Here's my current thinking about what to do.
>>
> Have you put your thinking behind the QAPI branch in writing anywhere?
> Ideally in comparable detail as your discussion of events in QAPI (which
> I snipped).
>
http://wiki.qemu.org/Features/QAPI
Inlined here in case anyone wants to discuss:
== Implementation ==
QAPI uses a schema/IDL written in JSON to automatically generate the
types and
marshalling information for QMP commands. It is used to generate both the
server side marshalling interfaces and a client library.
A typical function definition looks like this:
##
# @change:
#
# This command is multiple commands multiplexed together. Generally
speaking,
# it should not be used in favor of the single purpose alternatives
such as
# @change-vnc-listen, @change-vnc-password, and @change-blockdev.
#
# @device: This is normally the name of a block device but it may also
be 'vnc'.
# when it's 'vnc', then sub command depends on @target
#
# @target: If @device is a block device, then this is the new filename.
# If @device is 'vnc', then if the value 'password' selects
the vnc
# change password command. Otherwise, this specifies a new
server URI
# address to listen to for VNC connections.
#
# @arg: If @device is a block device, then this is an optional
format to open
# the device with.
# If @device is 'vnc' and @target is 'password', this is the
new VNC
# password to set. If this argument is an empty string, then
no future
# logins will be allowed.
#
# Returns: Nothing on success.
# If @device is not a valid block device, DeviceNotFound
# If @format is not a valid block format, InvalidBlockFormat
# If the new block device is encrypted, DeviceEncrypted.
Note that
# if this error is returned, the device has been opened
successfully
# and an additional call to @block_passwd is required to set the
# device's password. The behavior of reads and writes to the
block
# device between when these calls are executed is undefined.
#
# Notes: It is strongly recommended that this interface is not used
especially
# for changing block devices.
#
# Since: 0.14.0
##
[ 'change', {'device': 'str', 'target': 'str'}, {'arg': 'str'}, 'none' ]
The comments above the function are written in gtk-doc format and meant
to be
extracted to generate both protocol documentation and libqmp documentation.
The first element of the list is the command name, in this case, 'change'.
The second element of the list is a dictionary containing the required
arguments
for the function. The key is the argument name and the value is the
type. The
type can be a string or a complex type (see section on Typing).
The third element is a dictionary of optional arguments that follows the
same
rules as the required arguments.
The final list element is the return type of the function. 'none' is a
special
type representing a void return value.
== QMP Server ==
This definition will generate the following signature in qemu/qmp.h:
void qmp_change(const char *device, const char *target, bool has_arg,
const char *arg, Error **errp);
Which is then implemented in the appropriate place in QEMU. The optional
arguments always are prefixed with a boolean argument to indicate
whether the
option has been specified. The final argument is a pointer to an Error
object
in the fashion of GError. The caller of this function is will check for a
non-NULL error object to determine if the function failed. errp can be
set to
NULL if the caller does not care about failure.
Currently, Error is roughly identical to QError with the exception that
it only
supports simple key/value arguments.
== Complex Types ==
Some commands take or return complex types. It's usually a good idea to
define
complex types outside of the function definition. An example of a command
that returns a complex type is below:
##
# @VersionInfo:
#
# A description of QEMU's version.
#
# @qemu.major: The major version of QEMU
#
# @qemu.minor: The minor version of QEMU
#
# @qemu.micro: The micro version of QEMU. By current convention, a micro
# version of 50 signifies a development branch. A micro
version
# greater than or equal to 90 signifies a release
candidate for
# the next minor version. A micro version of less than 50
# signifies a stable release.
#
# @package: QEMU will always set this field to an empty string.
Downstream
# versions of QEMU should set this to a non-empty
string. The
# exact format depends on the downstream however it highly
# recommended that a unique name is used.
#
# Since: 0.14.0
##
{ 'VersionInfo': {'qemu': {'major': 'int', 'minor': 'int', 'micro':
'int'},
'package': 'str'} }
##
# @query-version:
#
# Returns the current version of QEMU.
#
# Returns: A @VersionInfo object describing the current version of QEMU.
#
# Since: 0.14.0
##
[ 'query-version', {}, {}, 'VersionInfo' ]
The syntax the use of a dictionary instead of a list is an indication of a
typedef. Within QEMU, This will generate the following code in
qemu/qmp-types.h:
typedef struct VersionInfo
{
struct {
int64_t major;
int64_t minor;
int64_t micro;
} qemu;
const char *package;
struct VersionInfo *next;
} VersionInfo;
The use of a next pointer is to enable support for returning lists of
complex
types. The query-version command will generate the following signature:
// qemu/qmp-types.h
VersionInfo *qmp_alloc_version_info(void);
void qmp_free_version_info(VersionInfo *obj);
// qemu/qmp.h
VersionInfo *qmp_query_version(Error **errp);
A typical implementation might look something like:
VersionInfo *qmp_query_version(Error **errp)
{
VersionInfo *info = qmp_alloc_version_info();
info->qemu.major = 0;
info->qemu.minor = 14;
info->qemu.micro = 92;
info->package = qemu_strdup(" (qemu-kvm)");
return info;
}
== Optional Structure Members ==
Optional structure members can be specified by using a '*' as a prefix
to the
member name. For example:
##
# @BlockDeviceInfo:
#
# Information about the backing device for a block device.
#
# @file: the filename of the backing device
#
# @ro: true if the backing device was open read-only
#
# @drv: the name of the block format used to open the backing dvice
#
# @backing_file: #optional the name of the backing file (for
copy-on-write)
#
# @encrypted: true if the backing device is encrypted
#
# Since: 0.14.0
#
# Notes: This interface is only found in @BlockInfo.
##
{ 'BlockDeviceInfo': { 'file': 'str', 'ro': 'bool', 'drv': 'str',
'*backing_file': 'str', 'encrypted': 'bool' } }
A typical implementation may look like:
BlockDeviceInfo *qmp_query_block_device_info(const char *device, Error
**errp)
{
BlockDeviceInfo *info;
BlockDriverState *bs;
Error *local_err = NULL;
bs = bdrv_find(device, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return NULL;
}
info->file = qemu_strdup(bs->filename);
info->ro = bs->readonly;
info->drv = qemu_strdup(bs->drv);
info->encrypted = bs->encrypted;
if (bs->backing_file[0]) {
info->has_backing_file = true;
info->backing_file = qemu_strdup(info->backing_file);
}
return info;
}
== Enumeration Types ==
QAPI also supports enumeration types. The following syntax is used:
{ 'VirtioNetTxStrategy': ['bh', 'timer'] }
A list of strings signifies a enumeration type. The enumeration type will
generate the following code in qemu/qmp-types.h:
typedef enum VirtioNetTxStrategy
{
VNTS_BH = 0,
VNTS_TIMER,
} VirtioNetTxStrategy;
Any use of the type in QEMU or in libqmp will use the enumeration. At the
moment, the integer values of the enumeration are sent over the wire in
order to
better support languages like Python that don't have enumeration types.
String to enumeration conversion functions will also be generated.
// qemu/qmp-types.h
VirtioNetTxStrategy qmp_virtio_net_tx_strategy_from_str(const char *str,
Error **errp);
char *qmp_virtio_net_tx_strategy_to_str(VirtioNetTxStrategy value,
Error **errp);
== Client Library ==
A client library will also be generated that makes use of qmp-types.h. The
client library functions are very similar to the QEMU functions except they
reside in libqmp.h, use a different prefix, and take a QmpSession argument.
For instance, 'query-version' will generate:
VersionInfo *libqmp_query_version(QmpSession *sess, Error **errp);
== QMP Server Discovery ==
QAPI has a standard mechanism to discover QMP servers. By default, a QMP
session is always created in ~/.qemu/name-$name.sock or
~/.qemu/pid-$pid.sock.
libqmp provides functions to enumerate the running guests and connect to
a guest
by name or pid.
Regards,
Anthony Liguori
> [...]
>
>
prev parent reply other threads:[~2011-02-15 16:15 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-02-13 18:08 [Qemu-devel] [RFC] qapi: events in QMP Anthony Liguori
2011-02-13 18:15 ` Anthony Liguori
2011-02-14 9:50 ` [Qemu-devel] " Kevin Wolf
2011-02-14 12:03 ` Anthony Liguori
2011-02-14 12:32 ` Kevin Wolf
2011-02-14 12:45 ` Luiz Capitulino
2011-02-14 14:39 ` Anthony Liguori
2011-02-14 18:34 ` Luiz Capitulino
2011-02-14 19:34 ` Anthony Liguori
2011-02-14 19:58 ` Luiz Capitulino
2011-02-14 20:01 ` Luiz Capitulino
2011-02-14 20:15 ` Anthony Liguori
2011-02-15 13:35 ` Luiz Capitulino
2011-02-15 14:54 ` Markus Armbruster
2011-02-15 9:20 ` Kevin Wolf
2011-02-15 13:38 ` Luiz Capitulino
2011-02-16 0:59 ` Anthony Liguori
2011-02-16 8:50 ` Kevin Wolf
2011-02-16 13:43 ` Anthony Liguori
2011-02-16 14:15 ` Kevin Wolf
2011-02-16 14:32 ` Anthony Liguori
2011-02-16 14:32 ` Anthony Liguori
2011-02-14 21:14 ` Anthony Liguori
2011-02-14 13:28 ` Luiz Capitulino
2011-02-14 13:33 ` Daniel P. Berrange
2011-02-14 14:24 ` Anthony Liguori
2011-02-14 14:32 ` Anthony Liguori
2011-02-15 14:07 ` What's QAPI? (was: [Qemu-devel] [RFC] qapi: events in QMP) Markus Armbruster
2011-02-15 14:13 ` [Qemu-devel] Re: What's QAPI? Anthony Liguori
2011-02-15 16:15 ` Anthony Liguori [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4D5AA695.6050301@codemonkey.ws \
--to=anthony@codemonkey.ws \
--cc=armbru@redhat.com \
--cc=kwolf@redhat.com \
--cc=lcapitulino@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).