QAPI patches for 2017-09-01
-----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJZrTlXAAoJEDhwtADrkYZT570P/20EQATHuRMGcO9QIParHqZL dh3yyBMEoSPNJx/dK2M1psT9vQgfcQ9+W6ouzW8nmu70bmY+NpwwlJfr9DadXE/q C9ht8ULL6pNfJ4bfLB8SqWqG6WUuyZJEWc3x3dCVuU4921hprwyAkWFEXiw73ThN Gay4zRooxZSR0pHsuh5wrlUl7iF7UHy/UO1yRvIUWvYMQ4PLyMzF/+o2hP4MvPNe l/b5B2XYiioMlJOjmi2/kRABOUywt4YWSXTxRi7f9VxWmKa5B8rbeMmxaX5zH3zB b4Ik8UdYAvW47iKilGQa1JlLqK24tgnA6monzMfQwhCdUtBTHu3rf8jJrvRai1fl R8vitLy1JJ93GPzVUAknSNOdkNBD5QnEvqn/ZGxvKpEQIHaPURoyOD50i9/NFR0n 6d8WSv2403zZsE6c+JkmeOm0zRhoE3Bkhcg8G9QYhGJu8meCsOVmR+afoBtzrOB9 ziB7dpWyAMwCioY25vHVD2vtMT/YlZX7Ic+vuWKtagFLt6lHROnSraon/iLdXYj3 Dmeb+sdBXL8vUXBK1c5P+ifKqgF6asz918wJgc5aucPWY3xY6lEN9wCGXqJuVw5Q B3FSIMCIAJhW8KpzmHObRJU1Enj2StkWBymWWNIu5f323v1u7hK57TXYw9HqDETj cL599N7VasD5azXLjlxk =eUZW -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2017-09-01-v3' into staging QAPI patches for 2017-09-01 # gpg: Signature made Mon 04 Sep 2017 12:30:31 BST # gpg: using RSA key 0x3870B400EB918653 # gpg: Good signature from "Markus Armbruster <armbru@redhat.com>" # gpg: aka "Markus Armbruster <armbru@pond.sub.org>" # Primary key fingerprint: 354B C8B3 D7EB 2A6B 6867 4E5F 3870 B400 EB91 8653 * remotes/armbru/tags/pull-qapi-2017-09-01-v3: (47 commits) qapi: drop the sentinel in enum array qapi: Change data type of the FOO_lookup generated for enum FOO qapi: Convert indirect uses of FOO_lookup[...] to qapi_enum_lookup() qapi: Mechanically convert FOO_lookup[...] to FOO_str(...) qapi: Generate FOO_str() macro for QAPI enum FOO qapi: Avoid unnecessary use of enum lookup table's sentinel qapi: Use qapi_enum_parse() in input_type_enum() crypto: Use qapi_enum_parse() in qcrypto_block_luks_name_lookup() quorum: Use qapi_enum_parse() in quorum_open() block: Use qemu_enum_parse() in blkdebug_debug_breakpoint() hmp: Use qapi_enum_parse() in hmp_migrate_set_parameter() hmp: Use qapi_enum_parse() in hmp_migrate_set_capability() tpm: Clean up model registration & lookup tpm: Clean up driver registration & lookup qapi: Drop superfluous qapi_enum_parse() parameter max qapi: Update qapi-code-gen.txt examples to match current code qapi-schema: Improve section headings qapi-schema: Move queries from common.json to qapi-schema.json qapi-schema: Make block-core.json self-contained qapi-schema: Fold event.json back into qapi-schema.json ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
98bfaac788
16
MAINTAINERS
16
MAINTAINERS
@ -1231,6 +1231,7 @@ S: Supported
|
||||
F: blockdev.c
|
||||
F: block/qapi.c
|
||||
F: qapi/block*.json
|
||||
F: qapi/transaction.json
|
||||
T: git git://repo.or.cz/qemu/armbru.git block-next
|
||||
|
||||
Dirty Bitmaps
|
||||
@ -1253,6 +1254,7 @@ M: Marc-André Lureau <marcandre.lureau@redhat.com>
|
||||
S: Maintained
|
||||
F: chardev/
|
||||
F: include/chardev/
|
||||
F: qapi/char.json
|
||||
|
||||
Character Devices (Braille)
|
||||
M: Samuel Thibault <samuel.thibault@ens-lyon.org>
|
||||
@ -1319,12 +1321,14 @@ F: include/ui/spice-display.h
|
||||
F: ui/spice-*.c
|
||||
F: audio/spiceaudio.c
|
||||
F: hw/display/qxl*
|
||||
F: qapi/ui.json
|
||||
|
||||
Graphics
|
||||
M: Gerd Hoffmann <kraxel@redhat.com>
|
||||
S: Odd Fixes
|
||||
F: ui/
|
||||
F: include/ui/
|
||||
F: qapi/ui.json
|
||||
|
||||
Cocoa graphics
|
||||
M: Peter Maydell <peter.maydell@linaro.org>
|
||||
@ -1338,6 +1342,7 @@ F: cpus.c
|
||||
F: util/main-loop.c
|
||||
F: util/qemu-timer.c
|
||||
F: vl.c
|
||||
F: qapi/run-state.json
|
||||
|
||||
Human Monitor (HMP)
|
||||
M: Dr. David Alan Gilbert <dgilbert@redhat.com>
|
||||
@ -1354,6 +1359,7 @@ S: Maintained
|
||||
F: net/
|
||||
F: include/net/
|
||||
T: git git://github.com/jasowang/qemu.git net
|
||||
F: qapi/net.json
|
||||
|
||||
Netmap network backend
|
||||
M: Luigi Rizzo <rizzo@iet.unipi.it>
|
||||
@ -1480,6 +1486,14 @@ F: scripts/tracetool/
|
||||
F: docs/tracing.txt
|
||||
T: git git://github.com/stefanha/qemu.git tracing
|
||||
|
||||
TPM
|
||||
S: Orphan
|
||||
F: tpm.c
|
||||
F: hw/tpm/*
|
||||
F: include/hw/acpi/tpm.h
|
||||
F: include/sysemu/tpm*
|
||||
F: qapi/tpm.json
|
||||
|
||||
Checkpatch
|
||||
S: Odd Fixes
|
||||
F: scripts/checkpatch.pl
|
||||
@ -1493,6 +1507,7 @@ F: migration/
|
||||
F: scripts/vmstate-static-checker.py
|
||||
F: tests/vmstate-static-checker-data/
|
||||
F: docs/migration.txt
|
||||
F: qapi/migration.json
|
||||
|
||||
Seccomp
|
||||
M: Eduardo Otubo <otubo@redhat.com>
|
||||
@ -1535,6 +1550,7 @@ M: Paolo Bonzini <pbonzini@redhat.com>
|
||||
S: Maintained
|
||||
F: include/qemu/sockets.h
|
||||
F: util/qemu-sockets.c
|
||||
F: qapi/sockets.json
|
||||
|
||||
Throttling infrastructure
|
||||
M: Alberto Garcia <berto@igalia.com>
|
||||
|
15
Makefile
15
Makefile
@ -410,9 +410,18 @@ $(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
|
||||
|
||||
qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \
|
||||
$(SRC_PATH)/qapi/block.json $(SRC_PATH)/qapi/block-core.json \
|
||||
$(SRC_PATH)/qapi/event.json $(SRC_PATH)/qapi/introspect.json \
|
||||
$(SRC_PATH)/qapi/crypto.json $(SRC_PATH)/qapi/rocker.json \
|
||||
$(SRC_PATH)/qapi/trace.json
|
||||
$(SRC_PATH)/qapi/char.json \
|
||||
$(SRC_PATH)/qapi/crypto.json \
|
||||
$(SRC_PATH)/qapi/introspect.json \
|
||||
$(SRC_PATH)/qapi/migration.json \
|
||||
$(SRC_PATH)/qapi/net.json \
|
||||
$(SRC_PATH)/qapi/rocker.json \
|
||||
$(SRC_PATH)/qapi/run-state.json \
|
||||
$(SRC_PATH)/qapi/sockets.json \
|
||||
$(SRC_PATH)/qapi/tpm.json \
|
||||
$(SRC_PATH)/qapi/trace.json \
|
||||
$(SRC_PATH)/qapi/transaction.json \
|
||||
$(SRC_PATH)/qapi/ui.json
|
||||
|
||||
qapi-types.c qapi-types.h :\
|
||||
$(qapi-modules) $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
|
||||
|
@ -304,7 +304,7 @@ host_memory_backend_memory_complete(UserCreatable *uc, Error **errp)
|
||||
return;
|
||||
} else if (maxnode == 0 && backend->policy != MPOL_DEFAULT) {
|
||||
error_setg(errp, "host-nodes must be set for policy %s",
|
||||
HostMemPolicy_lookup[backend->policy]);
|
||||
HostMemPolicy_str(backend->policy));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -395,7 +395,7 @@ host_memory_backend_class_init(ObjectClass *oc, void *data)
|
||||
host_memory_backend_set_host_nodes,
|
||||
NULL, NULL, &error_abort);
|
||||
object_class_property_add_enum(oc, "policy", "HostMemPolicy",
|
||||
HostMemPolicy_lookup,
|
||||
&HostMemPolicy_lookup,
|
||||
host_memory_backend_get_policy,
|
||||
host_memory_backend_set_policy, &error_abort);
|
||||
object_class_property_add_str(oc, "id", get_id, set_id, &error_abort);
|
||||
|
4
block.c
4
block.c
@ -42,7 +42,6 @@
|
||||
#include "qapi-event.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qemu/id.h"
|
||||
#include "qapi/util.h"
|
||||
|
||||
#ifdef CONFIG_BSD
|
||||
#include <sys/ioctl.h>
|
||||
@ -1333,9 +1332,8 @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
|
||||
detect_zeroes = qemu_opt_get(opts, "detect-zeroes");
|
||||
if (detect_zeroes) {
|
||||
BlockdevDetectZeroesOptions value =
|
||||
qapi_enum_parse(BlockdevDetectZeroesOptions_lookup,
|
||||
qapi_enum_parse(&BlockdevDetectZeroesOptions_lookup,
|
||||
detect_zeroes,
|
||||
BLOCKDEV_DETECT_ZEROES_OPTIONS__MAX,
|
||||
BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF,
|
||||
&local_err);
|
||||
if (local_err) {
|
||||
|
@ -596,7 +596,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
||||
error_setg(errp,
|
||||
"a sync_bitmap was provided to backup_run, "
|
||||
"but received an incompatible sync_mode (%s)",
|
||||
MirrorSyncMode_lookup[sync_mode]);
|
||||
MirrorSyncMode_str(sync_mode));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -149,20 +149,6 @@ static QemuOptsList *config_groups[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
static int get_event_by_name(const char *name, BlkdebugEvent *event)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < BLKDBG__MAX; i++) {
|
||||
if (!strcmp(BlkdebugEvent_lookup[i], name)) {
|
||||
*event = i;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct add_rule_data {
|
||||
BDRVBlkdebugState *s;
|
||||
int action;
|
||||
@ -173,7 +159,7 @@ static int add_rule(void *opaque, QemuOpts *opts, Error **errp)
|
||||
struct add_rule_data *d = opaque;
|
||||
BDRVBlkdebugState *s = d->s;
|
||||
const char* event_name;
|
||||
BlkdebugEvent event;
|
||||
int event;
|
||||
struct BlkdebugRule *rule;
|
||||
int64_t sector;
|
||||
|
||||
@ -182,8 +168,9 @@ static int add_rule(void *opaque, QemuOpts *opts, Error **errp)
|
||||
if (!event_name) {
|
||||
error_setg(errp, "Missing event name for rule");
|
||||
return -1;
|
||||
} else if (get_event_by_name(event_name, &event) < 0) {
|
||||
error_setg(errp, "Invalid event name \"%s\"", event_name);
|
||||
}
|
||||
event = qapi_enum_parse(&BlkdebugEvent_lookup, event_name, -1, errp);
|
||||
if (event < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -743,13 +730,13 @@ static int blkdebug_debug_breakpoint(BlockDriverState *bs, const char *event,
|
||||
{
|
||||
BDRVBlkdebugState *s = bs->opaque;
|
||||
struct BlkdebugRule *rule;
|
||||
BlkdebugEvent blkdebug_event;
|
||||
int blkdebug_event;
|
||||
|
||||
if (get_event_by_name(event, &blkdebug_event) < 0) {
|
||||
blkdebug_event = qapi_enum_parse(&BlkdebugEvent_lookup, event, -1, NULL);
|
||||
if (blkdebug_event < 0) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
|
||||
rule = g_malloc(sizeof(*rule));
|
||||
*rule = (struct BlkdebugRule) {
|
||||
.event = blkdebug_event,
|
||||
|
@ -31,7 +31,6 @@
|
||||
#include "block/thread-pool.h"
|
||||
#include "qemu/iov.h"
|
||||
#include "block/raw-aio.h"
|
||||
#include "qapi/util.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
|
||||
#if defined(__APPLE__) && (__MACH__)
|
||||
@ -438,8 +437,9 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
|
||||
aio_default = (bdrv_flags & BDRV_O_NATIVE_AIO)
|
||||
? BLOCKDEV_AIO_OPTIONS_NATIVE
|
||||
: BLOCKDEV_AIO_OPTIONS_THREADS;
|
||||
aio = qapi_enum_parse(BlockdevAioOptions_lookup, qemu_opt_get(opts, "aio"),
|
||||
BLOCKDEV_AIO_OPTIONS__MAX, aio_default, &local_err);
|
||||
aio = qapi_enum_parse(&BlockdevAioOptions_lookup,
|
||||
qemu_opt_get(opts, "aio"),
|
||||
aio_default, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
ret = -EINVAL;
|
||||
@ -447,8 +447,9 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
|
||||
}
|
||||
s->use_linux_aio = (aio == BLOCKDEV_AIO_OPTIONS_NATIVE);
|
||||
|
||||
locking = qapi_enum_parse(OnOffAuto_lookup, qemu_opt_get(opts, "locking"),
|
||||
ON_OFF_AUTO__MAX, ON_OFF_AUTO_AUTO, &local_err);
|
||||
locking = qapi_enum_parse(&OnOffAuto_lookup,
|
||||
qemu_opt_get(opts, "locking"),
|
||||
ON_OFF_AUTO_AUTO, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
ret = -EINVAL;
|
||||
@ -1725,7 +1726,7 @@ static int raw_regular_truncate(int fd, int64_t offset, PreallocMode prealloc,
|
||||
default:
|
||||
result = -ENOTSUP;
|
||||
error_setg(errp, "Unsupported preallocation mode: %s",
|
||||
PreallocMode_lookup[prealloc]);
|
||||
PreallocMode_str(prealloc));
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1760,7 +1761,7 @@ static int raw_truncate(BlockDriverState *bs, int64_t offset,
|
||||
|
||||
if (prealloc != PREALLOC_MODE_OFF) {
|
||||
error_setg(errp, "Preallocation mode '%s' unsupported for this "
|
||||
"non-regular file", PreallocMode_lookup[prealloc]);
|
||||
"non-regular file", PreallocMode_str(prealloc));
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
@ -1974,9 +1975,8 @@ static int raw_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
BDRV_SECTOR_SIZE);
|
||||
nocow = qemu_opt_get_bool(opts, BLOCK_OPT_NOCOW, false);
|
||||
buf = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);
|
||||
prealloc = qapi_enum_parse(PreallocMode_lookup, buf,
|
||||
PREALLOC_MODE__MAX, PREALLOC_MODE_OFF,
|
||||
&local_err);
|
||||
prealloc = qapi_enum_parse(&PreallocMode_lookup, buf,
|
||||
PREALLOC_MODE_OFF, &local_err);
|
||||
g_free(buf);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
|
@ -31,7 +31,6 @@
|
||||
#include "block/thread-pool.h"
|
||||
#include "qemu/iov.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
#include "qapi/util.h"
|
||||
#include <windows.h>
|
||||
#include <winioctl.h>
|
||||
|
||||
@ -303,8 +302,8 @@ static bool get_aio_option(QemuOpts *opts, int flags, Error **errp)
|
||||
|
||||
aio_default = (flags & BDRV_O_NATIVE_AIO) ? BLOCKDEV_AIO_OPTIONS_NATIVE
|
||||
: BLOCKDEV_AIO_OPTIONS_THREADS;
|
||||
aio = qapi_enum_parse(BlockdevAioOptions_lookup, qemu_opt_get(opts, "aio"),
|
||||
BLOCKDEV_AIO_OPTIONS__MAX, aio_default, errp);
|
||||
aio = qapi_enum_parse(&BlockdevAioOptions_lookup, qemu_opt_get(opts, "aio"),
|
||||
aio_default, errp);
|
||||
|
||||
switch (aio) {
|
||||
case BLOCKDEV_AIO_OPTIONS_NATIVE:
|
||||
@ -470,7 +469,7 @@ static int raw_truncate(BlockDriverState *bs, int64_t offset,
|
||||
|
||||
if (prealloc != PREALLOC_MODE_OFF) {
|
||||
error_setg(errp, "Unsupported preallocation mode '%s'",
|
||||
PreallocMode_lookup[prealloc]);
|
||||
PreallocMode_str(prealloc));
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include "block/block_int.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "qapi/util.h"
|
||||
#include "qemu/uri.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/cutils.h"
|
||||
@ -544,8 +543,7 @@ static int qemu_gluster_parse_json(BlockdevOptionsGluster *gconf,
|
||||
if (!strcmp(ptr, "tcp")) {
|
||||
ptr = "inet"; /* accept legacy "tcp" */
|
||||
}
|
||||
type = qapi_enum_parse(SocketAddressType_lookup, ptr,
|
||||
SOCKET_ADDRESS_TYPE__MAX, -1, NULL);
|
||||
type = qapi_enum_parse(&SocketAddressType_lookup, ptr, -1, NULL);
|
||||
if (type != SOCKET_ADDRESS_TYPE_INET
|
||||
&& type != SOCKET_ADDRESS_TYPE_UNIX) {
|
||||
error_setg(&local_err,
|
||||
@ -1002,8 +1000,7 @@ static int qemu_gluster_create(const char *filename,
|
||||
BDRV_SECTOR_SIZE);
|
||||
|
||||
tmp = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);
|
||||
prealloc = qapi_enum_parse(PreallocMode_lookup, tmp,
|
||||
PREALLOC_MODE__MAX, PREALLOC_MODE_OFF,
|
||||
prealloc = qapi_enum_parse(&PreallocMode_lookup, tmp, PREALLOC_MODE_OFF,
|
||||
&local_err);
|
||||
g_free(tmp);
|
||||
if (local_err) {
|
||||
@ -1050,7 +1047,7 @@ static int qemu_gluster_create(const char *filename,
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
error_setg(errp, "Unsupported preallocation mode: %s",
|
||||
PreallocMode_lookup[prealloc]);
|
||||
PreallocMode_str(prealloc));
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1102,7 +1099,7 @@ static int qemu_gluster_truncate(BlockDriverState *bs, int64_t offset,
|
||||
|
||||
if (prealloc != PREALLOC_MODE_OFF) {
|
||||
error_setg(errp, "Unsupported preallocation mode '%s'",
|
||||
PreallocMode_lookup[prealloc]);
|
||||
PreallocMode_str(prealloc));
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
|
@ -2087,7 +2087,7 @@ static int iscsi_truncate(BlockDriverState *bs, int64_t offset,
|
||||
|
||||
if (prealloc != PREALLOC_MODE_OFF) {
|
||||
error_setg(errp, "Unsupported preallocation mode '%s'",
|
||||
PreallocMode_lookup[prealloc]);
|
||||
PreallocMode_str(prealloc));
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
|
@ -772,7 +772,7 @@ static int nfs_file_truncate(BlockDriverState *bs, int64_t offset,
|
||||
|
||||
if (prealloc != PREALLOC_MODE_OFF) {
|
||||
error_setg(errp, "Unsupported preallocation mode '%s'",
|
||||
PreallocMode_lookup[prealloc]);
|
||||
PreallocMode_str(prealloc));
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,6 @@
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/bswap.h"
|
||||
#include "qemu/bitmap.h"
|
||||
#include "qapi/util.h"
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
@ -69,13 +68,14 @@ typedef enum ParallelsPreallocMode {
|
||||
PRL_PREALLOC_MODE__MAX = 2,
|
||||
} ParallelsPreallocMode;
|
||||
|
||||
static const char *prealloc_mode_lookup[] = {
|
||||
"falloc",
|
||||
"truncate",
|
||||
NULL,
|
||||
static QEnumLookup prealloc_mode_lookup = {
|
||||
.array = (const char *const[]) {
|
||||
"falloc",
|
||||
"truncate",
|
||||
},
|
||||
.size = PRL_PREALLOC_MODE__MAX
|
||||
};
|
||||
|
||||
|
||||
typedef struct BDRVParallelsState {
|
||||
/** Locking is conservative, the lock protects
|
||||
* - image file extending (truncate, fallocate)
|
||||
@ -696,8 +696,9 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
qemu_opt_get_size_del(opts, PARALLELS_OPT_PREALLOC_SIZE, 0);
|
||||
s->prealloc_size = MAX(s->tracks, s->prealloc_size >> BDRV_SECTOR_BITS);
|
||||
buf = qemu_opt_get_del(opts, PARALLELS_OPT_PREALLOC_MODE);
|
||||
s->prealloc_mode = qapi_enum_parse(prealloc_mode_lookup, buf,
|
||||
PRL_PREALLOC_MODE__MAX, PRL_PREALLOC_MODE_FALLOCATE, &local_err);
|
||||
s->prealloc_mode = qapi_enum_parse(&prealloc_mode_lookup, buf,
|
||||
PRL_PREALLOC_MODE_FALLOCATE,
|
||||
&local_err);
|
||||
g_free(buf);
|
||||
if (local_err != NULL) {
|
||||
goto fail_options;
|
||||
|
@ -30,7 +30,6 @@
|
||||
#include "qemu/error-report.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "qapi/qmp/qbool.h"
|
||||
#include "qapi/util.h"
|
||||
#include "qapi/qmp/types.h"
|
||||
#include "qapi-event.h"
|
||||
#include "trace.h"
|
||||
@ -2716,7 +2715,7 @@ static int qcow2_create2(const char *filename, int64_t total_size,
|
||||
int64_t prealloc_size =
|
||||
qcow2_calc_prealloc_size(total_size, cluster_size, refcount_order);
|
||||
qemu_opt_set_number(opts, BLOCK_OPT_SIZE, prealloc_size, &error_abort);
|
||||
qemu_opt_set(opts, BLOCK_OPT_PREALLOC, PreallocMode_lookup[prealloc],
|
||||
qemu_opt_set(opts, BLOCK_OPT_PREALLOC, PreallocMode_str(prealloc),
|
||||
&error_abort);
|
||||
}
|
||||
|
||||
@ -2916,9 +2915,8 @@ static int qcow2_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
goto finish;
|
||||
}
|
||||
buf = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);
|
||||
prealloc = qapi_enum_parse(PreallocMode_lookup, buf,
|
||||
PREALLOC_MODE__MAX, PREALLOC_MODE_OFF,
|
||||
&local_err);
|
||||
prealloc = qapi_enum_parse(&PreallocMode_lookup, buf,
|
||||
PREALLOC_MODE_OFF, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
ret = -EINVAL;
|
||||
@ -3082,7 +3080,7 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
|
||||
prealloc != PREALLOC_MODE_FALLOC && prealloc != PREALLOC_MODE_FULL)
|
||||
{
|
||||
error_setg(errp, "Unsupported preallocation mode '%s'",
|
||||
PreallocMode_lookup[prealloc]);
|
||||
PreallocMode_str(prealloc));
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
@ -3607,9 +3605,8 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
|
||||
}
|
||||
|
||||
optstr = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);
|
||||
prealloc = qapi_enum_parse(PreallocMode_lookup, optstr,
|
||||
PREALLOC_MODE__MAX, PREALLOC_MODE_OFF,
|
||||
&local_err);
|
||||
prealloc = qapi_enum_parse(&PreallocMode_lookup, optstr,
|
||||
PREALLOC_MODE_OFF, &local_err);
|
||||
g_free(optstr);
|
||||
if (local_err) {
|
||||
goto err;
|
||||
|
@ -1399,7 +1399,7 @@ static int bdrv_qed_truncate(BlockDriverState *bs, int64_t offset,
|
||||
|
||||
if (prealloc != PREALLOC_MODE_OFF) {
|
||||
error_setg(errp, "Unsupported preallocation mode '%s'",
|
||||
PreallocMode_lookup[prealloc]);
|
||||
PreallocMode_str(prealloc));
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
|
@ -867,30 +867,13 @@ static QemuOptsList quorum_runtime_opts = {
|
||||
},
|
||||
};
|
||||
|
||||
static int parse_read_pattern(const char *opt)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!opt) {
|
||||
/* Set quorum as default */
|
||||
return QUORUM_READ_PATTERN_QUORUM;
|
||||
}
|
||||
|
||||
for (i = 0; i < QUORUM_READ_PATTERN__MAX; i++) {
|
||||
if (!strcmp(opt, QuorumReadPattern_lookup[i])) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
Error **errp)
|
||||
{
|
||||
BDRVQuorumState *s = bs->opaque;
|
||||
Error *local_err = NULL;
|
||||
QemuOpts *opts = NULL;
|
||||
const char *pattern_str;
|
||||
bool *opened;
|
||||
int i;
|
||||
int ret = 0;
|
||||
@ -925,7 +908,13 @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = parse_read_pattern(qemu_opt_get(opts, QUORUM_OPT_READ_PATTERN));
|
||||
pattern_str = qemu_opt_get(opts, QUORUM_OPT_READ_PATTERN);
|
||||
if (!pattern_str) {
|
||||
ret = QUORUM_READ_PATTERN_QUORUM;
|
||||
} else {
|
||||
ret = qapi_enum_parse(&QuorumReadPattern_lookup, pattern_str,
|
||||
-EINVAL, NULL);
|
||||
}
|
||||
if (ret < 0) {
|
||||
error_setg(&local_err, "Please set read-pattern as fifo or quorum");
|
||||
goto exit;
|
||||
|
@ -944,7 +944,7 @@ static int qemu_rbd_truncate(BlockDriverState *bs, int64_t offset,
|
||||
|
||||
if (prealloc != PREALLOC_MODE_OFF) {
|
||||
error_setg(errp, "Unsupported preallocation mode '%s'",
|
||||
PreallocMode_lookup[prealloc]);
|
||||
PreallocMode_str(prealloc));
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
|
@ -2176,7 +2176,7 @@ static int sd_truncate(BlockDriverState *bs, int64_t offset,
|
||||
|
||||
if (prealloc != PREALLOC_MODE_OFF) {
|
||||
error_setg(errp, "Unsupported preallocation mode '%s'",
|
||||
PreallocMode_lookup[prealloc]);
|
||||
PreallocMode_str(prealloc));
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,6 @@
|
||||
#include "qapi-visit.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "qapi/qobject-output-visitor.h"
|
||||
#include "qapi/util.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "block/block_int.h"
|
||||
#include "qmp-commands.h"
|
||||
@ -438,9 +437,8 @@ static void extract_common_blockdev_options(QemuOpts *opts, int *bdrv_flags,
|
||||
|
||||
if (detect_zeroes) {
|
||||
*detect_zeroes =
|
||||
qapi_enum_parse(BlockdevDetectZeroesOptions_lookup,
|
||||
qapi_enum_parse(&BlockdevDetectZeroesOptions_lookup,
|
||||
qemu_opt_get(opts, "detect-zeroes"),
|
||||
BLOCKDEV_DETECT_ZEROES_OPTIONS__MAX,
|
||||
BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF,
|
||||
&local_error);
|
||||
if (local_error) {
|
||||
@ -1468,8 +1466,8 @@ static int action_check_completion_mode(BlkActionState *s, Error **errp)
|
||||
error_setg(errp,
|
||||
"Action '%s' does not support Transaction property "
|
||||
"completion-mode = %s",
|
||||
TransactionActionKind_lookup[s->action->type],
|
||||
ActionCompletionMode_lookup[s->txn_props->completion_mode]);
|
||||
TransactionActionKind_str(s->action->type),
|
||||
ActionCompletionMode_str(s->txn_props->completion_mode));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -208,7 +208,7 @@ static char *child_job_get_parent_desc(BdrvChild *c)
|
||||
{
|
||||
BlockJob *job = c->opaque;
|
||||
return g_strdup_printf("%s job '%s'",
|
||||
BlockJobType_lookup[job->driver->job_type],
|
||||
BlockJobType_str(job->driver->job_type),
|
||||
job->id);
|
||||
}
|
||||
|
||||
@ -553,7 +553,7 @@ BlockJobInfo *block_job_query(BlockJob *job, Error **errp)
|
||||
return NULL;
|
||||
}
|
||||
info = g_new0(BlockJobInfo, 1);
|
||||
info->type = g_strdup(BlockJobType_lookup[job->driver->job_type]);
|
||||
info->type = g_strdup(BlockJobType_str(job->driver->job_type));
|
||||
info->device = g_strdup(job->id);
|
||||
info->len = job->len;
|
||||
info->busy = job->busy;
|
||||
@ -666,7 +666,7 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
|
||||
job->refcnt = 1;
|
||||
|
||||
error_setg(&job->blocker, "block device is in use by block job: %s",
|
||||
BlockJobType_lookup[driver->job_type]);
|
||||
BlockJobType_str(driver->job_type));
|
||||
block_job_add_bdrv(job, "main node", bs, 0, BLK_PERM_ALL, &error_abort);
|
||||
bs->job = job;
|
||||
|
||||
|
@ -931,7 +931,7 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
|
||||
ChardevReturn *ret;
|
||||
Chardev *chr;
|
||||
|
||||
cc = char_get_class(ChardevBackendKind_lookup[backend->type], errp);
|
||||
cc = char_get_class(ChardevBackendKind_str(backend->type), errp);
|
||||
if (!cc) {
|
||||
return NULL;
|
||||
}
|
||||
@ -989,7 +989,7 @@ ChardevReturn *qmp_chardev_change(const char *id, ChardevBackend *backend,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cc = char_get_class(ChardevBackendKind_lookup[backend->type], errp);
|
||||
cc = char_get_class(ChardevBackendKind_str(backend->type), errp);
|
||||
if (!cc) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -257,47 +257,41 @@ qcrypto_block_luks_cipher_alg_lookup(QCryptoCipherAlgorithm alg,
|
||||
}
|
||||
|
||||
error_setg(errp, "Algorithm '%s' not supported",
|
||||
QCryptoCipherAlgorithm_lookup[alg]);
|
||||
QCryptoCipherAlgorithm_str(alg));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* XXX replace with qapi_enum_parse() in future, when we can
|
||||
* make that function emit a more friendly error message */
|
||||
static int qcrypto_block_luks_name_lookup(const char *name,
|
||||
const char *const *map,
|
||||
size_t maplen,
|
||||
const QEnumLookup *map,
|
||||
const char *type,
|
||||
Error **errp)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < maplen; i++) {
|
||||
if (g_str_equal(map[i], name)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
int ret = qapi_enum_parse(map, name, -1, NULL);
|
||||
|
||||
error_setg(errp, "%s %s not supported", type, name);
|
||||
return 0;
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "%s %s not supported", type, name);
|
||||
return 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define qcrypto_block_luks_cipher_mode_lookup(name, errp) \
|
||||
qcrypto_block_luks_name_lookup(name, \
|
||||
QCryptoCipherMode_lookup, \
|
||||
QCRYPTO_CIPHER_MODE__MAX, \
|
||||
&QCryptoCipherMode_lookup, \
|
||||
"Cipher mode", \
|
||||
errp)
|
||||
|
||||
#define qcrypto_block_luks_hash_name_lookup(name, errp) \
|
||||
qcrypto_block_luks_name_lookup(name, \
|
||||
QCryptoHashAlgorithm_lookup, \
|
||||
QCRYPTO_HASH_ALG__MAX, \
|
||||
&QCryptoHashAlgorithm_lookup, \
|
||||
"Hash algorithm", \
|
||||
errp)
|
||||
|
||||
#define qcrypto_block_luks_ivgen_name_lookup(name, errp) \
|
||||
qcrypto_block_luks_name_lookup(name, \
|
||||
QCryptoIVGenAlgorithm_lookup, \
|
||||
QCRYPTO_IVGEN_ALG__MAX, \
|
||||
&QCryptoIVGenAlgorithm_lookup, \
|
||||
"IV generator", \
|
||||
errp)
|
||||
|
||||
@ -398,7 +392,7 @@ qcrypto_block_luks_essiv_cipher(QCryptoCipherAlgorithm cipher,
|
||||
break;
|
||||
default:
|
||||
error_setg(errp, "Cipher %s not supported with essiv",
|
||||
QCryptoCipherAlgorithm_lookup[cipher]);
|
||||
QCryptoCipherAlgorithm_str(cipher));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -968,16 +962,16 @@ qcrypto_block_luks_create(QCryptoBlock *block,
|
||||
goto error;
|
||||
}
|
||||
|
||||
cipher_mode = QCryptoCipherMode_lookup[luks_opts.cipher_mode];
|
||||
ivgen_alg = QCryptoIVGenAlgorithm_lookup[luks_opts.ivgen_alg];
|
||||
cipher_mode = QCryptoCipherMode_str(luks_opts.cipher_mode);
|
||||
ivgen_alg = QCryptoIVGenAlgorithm_str(luks_opts.ivgen_alg);
|
||||
if (luks_opts.has_ivgen_hash_alg) {
|
||||
ivgen_hash_alg = QCryptoHashAlgorithm_lookup[luks_opts.ivgen_hash_alg];
|
||||
ivgen_hash_alg = QCryptoHashAlgorithm_str(luks_opts.ivgen_hash_alg);
|
||||
cipher_mode_spec = g_strdup_printf("%s-%s:%s", cipher_mode, ivgen_alg,
|
||||
ivgen_hash_alg);
|
||||
} else {
|
||||
cipher_mode_spec = g_strdup_printf("%s-%s", cipher_mode, ivgen_alg);
|
||||
}
|
||||
hash_alg = QCryptoHashAlgorithm_lookup[luks_opts.hash_alg];
|
||||
hash_alg = QCryptoHashAlgorithm_str(luks_opts.hash_alg);
|
||||
|
||||
|
||||
if (strlen(cipher_alg) >= QCRYPTO_BLOCK_LUKS_CIPHER_NAME_LEN) {
|
||||
|
@ -61,7 +61,7 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
|
||||
if (options->format >= G_N_ELEMENTS(qcrypto_block_drivers) ||
|
||||
!qcrypto_block_drivers[options->format]) {
|
||||
error_setg(errp, "Unsupported block driver %s",
|
||||
QCryptoBlockFormat_lookup[options->format]);
|
||||
QCryptoBlockFormat_str(options->format));
|
||||
g_free(block);
|
||||
return NULL;
|
||||
}
|
||||
@ -92,7 +92,7 @@ QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options,
|
||||
if (options->format >= G_N_ELEMENTS(qcrypto_block_drivers) ||
|
||||
!qcrypto_block_drivers[options->format]) {
|
||||
error_setg(errp, "Unsupported block driver %s",
|
||||
QCryptoBlockFormat_lookup[options->format]);
|
||||
QCryptoBlockFormat_str(options->format));
|
||||
g_free(block);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ qcrypto_afalg_cipher_format_name(QCryptoCipherAlgorithm alg,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mode_name = QCryptoCipherMode_lookup[mode];
|
||||
mode_name = QCryptoCipherMode_str(mode);
|
||||
name = g_strdup_printf("%s(%s)", mode_name, alg_name);
|
||||
|
||||
return name;
|
||||
|
@ -247,7 +247,7 @@ qcrypto_cipher_init_aes(QCryptoCipherMode mode,
|
||||
mode != QCRYPTO_CIPHER_MODE_ECB &&
|
||||
mode != QCRYPTO_CIPHER_MODE_XTS) {
|
||||
error_setg(errp, "Unsupported cipher mode %s",
|
||||
QCryptoCipherMode_lookup[mode]);
|
||||
QCryptoCipherMode_str(mode));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -379,7 +379,7 @@ qcrypto_cipher_init_des_rfb(QCryptoCipherMode mode,
|
||||
|
||||
if (mode != QCRYPTO_CIPHER_MODE_ECB) {
|
||||
error_setg(errp, "Unsupported cipher mode %s",
|
||||
QCryptoCipherMode_lookup[mode]);
|
||||
QCryptoCipherMode_str(mode));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -440,7 +440,7 @@ static QCryptoCipherBuiltin *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
|
||||
break;
|
||||
default:
|
||||
error_setg(errp, "Unsupported cipher mode %s",
|
||||
QCryptoCipherMode_lookup[mode]);
|
||||
QCryptoCipherMode_str(mode));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -460,7 +460,7 @@ static QCryptoCipherBuiltin *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
|
||||
default:
|
||||
error_setg(errp,
|
||||
"Unsupported cipher algorithm %s",
|
||||
QCryptoCipherAlgorithm_lookup[alg]);
|
||||
QCryptoCipherAlgorithm_str(alg));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -105,7 +105,7 @@ static QCryptoCipherGcrypt *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
|
||||
break;
|
||||
default:
|
||||
error_setg(errp, "Unsupported cipher mode %s",
|
||||
QCryptoCipherMode_lookup[mode]);
|
||||
QCryptoCipherMode_str(mode));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -160,7 +160,7 @@ static QCryptoCipherGcrypt *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
|
||||
|
||||
default:
|
||||
error_setg(errp, "Unsupported cipher algorithm %s",
|
||||
QCryptoCipherAlgorithm_lookup[alg]);
|
||||
QCryptoCipherAlgorithm_str(alg));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -281,7 +281,7 @@ static QCryptoCipherNettle *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
|
||||
break;
|
||||
default:
|
||||
error_setg(errp, "Unsupported cipher mode %s",
|
||||
QCryptoCipherMode_lookup[mode]);
|
||||
QCryptoCipherMode_str(mode));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -420,7 +420,7 @@ static QCryptoCipherNettle *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
|
||||
|
||||
default:
|
||||
error_setg(errp, "Unsupported cipher algorithm %s",
|
||||
QCryptoCipherAlgorithm_lookup[alg]);
|
||||
QCryptoCipherAlgorithm_str(alg));
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -491,7 +491,7 @@ qcrypto_nettle_cipher_encrypt(QCryptoCipher *cipher,
|
||||
|
||||
default:
|
||||
error_setg(errp, "Unsupported cipher mode %s",
|
||||
QCryptoCipherMode_lookup[cipher->mode]);
|
||||
QCryptoCipherMode_str(cipher->mode));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@ -537,7 +537,7 @@ qcrypto_nettle_cipher_decrypt(QCryptoCipher *cipher,
|
||||
|
||||
default:
|
||||
error_setg(errp, "Unsupported cipher mode %s",
|
||||
QCryptoCipherMode_lookup[cipher->mode]);
|
||||
QCryptoCipherMode_str(cipher->mode));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -52,7 +52,7 @@ void *qcrypto_hmac_ctx_new(QCryptoHashAlgorithm alg,
|
||||
|
||||
if (!qcrypto_hmac_supports(alg)) {
|
||||
error_setg(errp, "Unsupported hmac algorithm %s",
|
||||
QCryptoHashAlgorithm_lookup[alg]);
|
||||
QCryptoHashAlgorithm_str(alg));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ void *qcrypto_hmac_ctx_new(QCryptoHashAlgorithm alg,
|
||||
|
||||
if (!qcrypto_hmac_supports(alg)) {
|
||||
error_setg(errp, "Unsupported hmac algorithm %s",
|
||||
QCryptoHashAlgorithm_lookup[alg]);
|
||||
QCryptoHashAlgorithm_str(alg));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -106,7 +106,7 @@ void *qcrypto_hmac_ctx_new(QCryptoHashAlgorithm alg,
|
||||
|
||||
if (!qcrypto_hmac_supports(alg)) {
|
||||
error_setg(errp, "Unsupported hmac algorithm %s",
|
||||
QCryptoHashAlgorithm_lookup[alg]);
|
||||
QCryptoHashAlgorithm_str(alg));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ int qcrypto_pbkdf2(QCryptoHashAlgorithm hash,
|
||||
hash_map[hash] == GCRY_MD_NONE) {
|
||||
error_setg_errno(errp, ENOSYS,
|
||||
"PBKDF does not support hash algorithm %s",
|
||||
QCryptoHashAlgorithm_lookup[hash]);
|
||||
QCryptoHashAlgorithm_str(hash));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -110,7 +110,7 @@ int qcrypto_pbkdf2(QCryptoHashAlgorithm hash,
|
||||
default:
|
||||
error_setg_errno(errp, ENOSYS,
|
||||
"PBKDF does not support hash algorithm %s",
|
||||
QCryptoHashAlgorithm_lookup[hash]);
|
||||
QCryptoHashAlgorithm_str(hash));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -378,7 +378,7 @@ qcrypto_secret_class_init(ObjectClass *oc, void *data)
|
||||
NULL);
|
||||
object_class_property_add_enum(oc, "format",
|
||||
"QCryptoSecretFormat",
|
||||
QCryptoSecretFormat_lookup,
|
||||
&QCryptoSecretFormat_lookup,
|
||||
qcrypto_secret_prop_get_format,
|
||||
qcrypto_secret_prop_set_format,
|
||||
NULL);
|
||||
|
@ -233,7 +233,7 @@ qcrypto_tls_creds_class_init(ObjectClass *oc, void *data)
|
||||
NULL);
|
||||
object_class_property_add_enum(oc, "endpoint",
|
||||
"QCryptoTLSCredsEndpoint",
|
||||
QCryptoTLSCredsEndpoint_lookup,
|
||||
&QCryptoTLSCredsEndpoint_lookup,
|
||||
qcrypto_tls_creds_prop_get_endpoint,
|
||||
qcrypto_tls_creds_prop_set_endpoint,
|
||||
NULL);
|
||||
|
@ -957,6 +957,8 @@ Example:
|
||||
|
||||
typedef struct UserDefOneList UserDefOneList;
|
||||
|
||||
typedef struct q_obj_my_command_arg q_obj_my_command_arg;
|
||||
|
||||
struct UserDefOne {
|
||||
int64_t integer;
|
||||
bool has_string;
|
||||
@ -972,6 +974,10 @@ Example:
|
||||
|
||||
void qapi_free_UserDefOneList(UserDefOneList *obj);
|
||||
|
||||
struct q_obj_my_command_arg {
|
||||
UserDefOneList *arg1;
|
||||
};
|
||||
|
||||
#endif
|
||||
$ cat qapi-generated/example-qapi-types.c
|
||||
[Uninteresting stuff omitted...]
|
||||
@ -1036,6 +1042,8 @@ Example:
|
||||
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
|
||||
$ cat qapi-generated/example-qapi-visit.c
|
||||
[Uninteresting stuff omitted...]
|
||||
@ -1104,6 +1112,9 @@ Example:
|
||||
}
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
visit_check_list(v, &err);
|
||||
}
|
||||
visit_end_list(v, (void **)obj);
|
||||
if (err && visit_is_input(v)) {
|
||||
qapi_free_UserDefOneList(*obj);
|
||||
@ -1113,6 +1124,19 @@ Example:
|
||||
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);
|
||||
}
|
||||
|
||||
=== scripts/qapi-commands.py ===
|
||||
|
||||
Used to generate the marshaling/dispatch functions for the commands
|
||||
@ -1145,9 +1169,12 @@ Example:
|
||||
|
||||
#include "example-qapi-types.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
#include "qapi/qmp/dispatch.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
void example_qmp_init_marshal(QmpCommandList *cmds);
|
||||
UserDefOne *qmp_my_command(UserDefOneList *arg1, Error **errp);
|
||||
void qmp_marshal_my_command(QDict *args, QObject **ret, Error **errp);
|
||||
|
||||
#endif
|
||||
$ cat qapi-generated/example-qmp-marshal.c
|
||||
@ -1170,19 +1197,19 @@ Example:
|
||||
visit_free(v);
|
||||
}
|
||||
|
||||
static void qmp_marshal_my_command(QDict *args, QObject **ret, Error **errp)
|
||||
void qmp_marshal_my_command(QDict *args, QObject **ret, Error **errp)
|
||||
{
|
||||
Error *err = NULL;
|
||||
UserDefOne *retval;
|
||||
Visitor *v;
|
||||
UserDefOneList *arg1 = NULL;
|
||||
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_UserDefOneList(v, "arg1", &arg1, &err);
|
||||
visit_type_q_obj_my_command_arg_members(v, &arg, &err);
|
||||
if (!err) {
|
||||
visit_check_struct(v, &err);
|
||||
}
|
||||
@ -1191,7 +1218,7 @@ Example:
|
||||
goto out;
|
||||
}
|
||||
|
||||
retval = qmp_my_command(arg1, &err);
|
||||
retval = qmp_my_command(arg.arg1, &err);
|
||||
if (err) {
|
||||
goto out;
|
||||
}
|
||||
@ -1203,17 +1230,18 @@ Example:
|
||||
visit_free(v);
|
||||
v = qapi_dealloc_visitor_new();
|
||||
visit_start_struct(v, NULL, NULL, 0, NULL);
|
||||
visit_type_UserDefOneList(v, "arg1", &arg1, NULL);
|
||||
visit_type_q_obj_my_command_arg_members(v, &arg, NULL);
|
||||
visit_end_struct(v, NULL);
|
||||
visit_free(v);
|
||||
}
|
||||
|
||||
static void qmp_init_marshal(void)
|
||||
void example_qmp_init_marshal(QmpCommandList *cmds)
|
||||
{
|
||||
qmp_register_command("my-command", qmp_marshal_my_command, QCO_NO_OPTIONS);
|
||||
}
|
||||
QTAILQ_INIT(cmds);
|
||||
|
||||
qapi_init(qmp_init_marshal);
|
||||
qmp_register_command(cmds, "my-command",
|
||||
qmp_marshal_my_command, QCO_NO_OPTIONS);
|
||||
}
|
||||
|
||||
=== scripts/qapi-event.py ===
|
||||
|
||||
@ -1247,6 +1275,9 @@ Example:
|
||||
EXAMPLE_QAPI_EVENT__MAX = 1,
|
||||
} example_QAPIEvent;
|
||||
|
||||
#define example_QAPIEvent_str(val) \
|
||||
qapi_enum_lookup(example_QAPIEvent_lookup, (val))
|
||||
|
||||
extern const char *const example_QAPIEvent_lookup[];
|
||||
|
||||
#endif
|
||||
@ -1258,6 +1289,7 @@ Example:
|
||||
QDict *qmp;
|
||||
Error *err = NULL;
|
||||
QMPEventFuncEmit emit;
|
||||
|
||||
emit = qmp_event_get_func_emit();
|
||||
if (!emit) {
|
||||
return;
|
||||
|
220
hmp.c
220
hmp.c
@ -31,7 +31,6 @@
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "qapi/string-input-visitor.h"
|
||||
#include "qapi/string-output-visitor.h"
|
||||
#include "qapi/util.h"
|
||||
#include "qapi-visit.h"
|
||||
#include "qom/object_interfaces.h"
|
||||
#include "ui/console.h"
|
||||
@ -107,7 +106,7 @@ void hmp_info_status(Monitor *mon, const QDict *qdict)
|
||||
info->singlestep ? " (single step mode)" : "");
|
||||
|
||||
if (!info->running && info->status != RUN_STATE_PAUSED) {
|
||||
monitor_printf(mon, " (%s)", RunState_lookup[info->status]);
|
||||
monitor_printf(mon, " (%s)", RunState_str(info->status));
|
||||
}
|
||||
|
||||
monitor_printf(mon, "\n");
|
||||
@ -172,7 +171,7 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict)
|
||||
monitor_printf(mon, "capabilities: ");
|
||||
for (cap = caps; cap; cap = cap->next) {
|
||||
monitor_printf(mon, "%s: %s ",
|
||||
MigrationCapability_lookup[cap->value->capability],
|
||||
MigrationCapability_str(cap->value->capability),
|
||||
cap->value->state ? "on" : "off");
|
||||
}
|
||||
monitor_printf(mon, "\n");
|
||||
@ -180,7 +179,7 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict)
|
||||
|
||||
if (info->has_status) {
|
||||
monitor_printf(mon, "Migration status: %s",
|
||||
MigrationStatus_lookup[info->status]);
|
||||
MigrationStatus_str(info->status));
|
||||
if (info->status == MIGRATION_STATUS_FAILED &&
|
||||
info->has_error_desc) {
|
||||
monitor_printf(mon, " (%s)\n", info->error_desc);
|
||||
@ -278,7 +277,7 @@ void hmp_info_migrate_capabilities(Monitor *mon, const QDict *qdict)
|
||||
if (caps) {
|
||||
for (cap = caps; cap; cap = cap->next) {
|
||||
monitor_printf(mon, "%s: %s\n",
|
||||
MigrationCapability_lookup[cap->value->capability],
|
||||
MigrationCapability_str(cap->value->capability),
|
||||
cap->value->state ? "on" : "off");
|
||||
}
|
||||
}
|
||||
@ -295,48 +294,48 @@ void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict)
|
||||
if (params) {
|
||||
assert(params->has_compress_level);
|
||||
monitor_printf(mon, "%s: %" PRId64 "\n",
|
||||
MigrationParameter_lookup[MIGRATION_PARAMETER_COMPRESS_LEVEL],
|
||||
MigrationParameter_str(MIGRATION_PARAMETER_COMPRESS_LEVEL),
|
||||
params->compress_level);
|
||||
assert(params->has_compress_threads);
|
||||
monitor_printf(mon, "%s: %" PRId64 "\n",
|
||||
MigrationParameter_lookup[MIGRATION_PARAMETER_COMPRESS_THREADS],
|
||||
MigrationParameter_str(MIGRATION_PARAMETER_COMPRESS_THREADS),
|
||||
params->compress_threads);
|
||||
assert(params->has_decompress_threads);
|
||||
monitor_printf(mon, "%s: %" PRId64 "\n",
|
||||
MigrationParameter_lookup[MIGRATION_PARAMETER_DECOMPRESS_THREADS],
|
||||
MigrationParameter_str(MIGRATION_PARAMETER_DECOMPRESS_THREADS),
|
||||
params->decompress_threads);
|
||||
assert(params->has_cpu_throttle_initial);
|
||||
monitor_printf(mon, "%s: %" PRId64 "\n",
|
||||
MigrationParameter_lookup[MIGRATION_PARAMETER_CPU_THROTTLE_INITIAL],
|
||||
MigrationParameter_str(MIGRATION_PARAMETER_CPU_THROTTLE_INITIAL),
|
||||
params->cpu_throttle_initial);
|
||||
assert(params->has_cpu_throttle_increment);
|
||||
monitor_printf(mon, "%s: %" PRId64 "\n",
|
||||
MigrationParameter_lookup[MIGRATION_PARAMETER_CPU_THROTTLE_INCREMENT],
|
||||
MigrationParameter_str(MIGRATION_PARAMETER_CPU_THROTTLE_INCREMENT),
|
||||
params->cpu_throttle_increment);
|
||||
assert(params->has_tls_creds);
|
||||
monitor_printf(mon, "%s: '%s'\n",
|
||||
MigrationParameter_lookup[MIGRATION_PARAMETER_TLS_CREDS],
|
||||
MigrationParameter_str(MIGRATION_PARAMETER_TLS_CREDS),
|
||||
params->tls_creds);
|
||||
assert(params->has_tls_hostname);
|
||||
monitor_printf(mon, "%s: '%s'\n",
|
||||
MigrationParameter_lookup[MIGRATION_PARAMETER_TLS_HOSTNAME],
|
||||
MigrationParameter_str(MIGRATION_PARAMETER_TLS_HOSTNAME),
|
||||
params->tls_hostname);
|
||||
assert(params->has_max_bandwidth);
|
||||
monitor_printf(mon, "%s: %" PRId64 " bytes/second\n",
|
||||
MigrationParameter_lookup[MIGRATION_PARAMETER_MAX_BANDWIDTH],
|
||||
MigrationParameter_str(MIGRATION_PARAMETER_MAX_BANDWIDTH),
|
||||
params->max_bandwidth);
|
||||
assert(params->has_downtime_limit);
|
||||
monitor_printf(mon, "%s: %" PRId64 " milliseconds\n",
|
||||
MigrationParameter_lookup[MIGRATION_PARAMETER_DOWNTIME_LIMIT],
|
||||
MigrationParameter_str(MIGRATION_PARAMETER_DOWNTIME_LIMIT),
|
||||
params->downtime_limit);
|
||||
assert(params->has_x_checkpoint_delay);
|
||||
monitor_printf(mon, "%s: %" PRId64 "\n",
|
||||
MigrationParameter_lookup[MIGRATION_PARAMETER_X_CHECKPOINT_DELAY],
|
||||
MigrationParameter_str(MIGRATION_PARAMETER_X_CHECKPOINT_DELAY),
|
||||
params->x_checkpoint_delay);
|
||||
assert(params->has_block_incremental);
|
||||
monitor_printf(mon, "%s: %s\n",
|
||||
MigrationParameter_lookup[MIGRATION_PARAMETER_BLOCK_INCREMENTAL],
|
||||
params->block_incremental ? "on" : "off");
|
||||
MigrationParameter_str(MIGRATION_PARAMETER_BLOCK_INCREMENTAL),
|
||||
params->block_incremental ? "on" : "off");
|
||||
}
|
||||
|
||||
qapi_free_MigrationParameters(params);
|
||||
@ -432,7 +431,7 @@ static void print_block_info(Monitor *mon, BlockInfo *info,
|
||||
}
|
||||
if (info->has_io_status && info->io_status != BLOCK_DEVICE_IO_STATUS_OK) {
|
||||
monitor_printf(mon, " I/O status: %s\n",
|
||||
BlockDeviceIoStatus_lookup[info->io_status]);
|
||||
BlockDeviceIoStatus_str(info->io_status));
|
||||
}
|
||||
|
||||
if (info->removable) {
|
||||
@ -462,7 +461,7 @@ static void print_block_info(Monitor *mon, BlockInfo *info,
|
||||
|
||||
if (inserted->detect_zeroes != BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF) {
|
||||
monitor_printf(mon, " Detect zeroes: %s\n",
|
||||
BlockdevDetectZeroesOptions_lookup[inserted->detect_zeroes]);
|
||||
BlockdevDetectZeroesOptions_str(inserted->detect_zeroes));
|
||||
}
|
||||
|
||||
if (inserted->bps || inserted->bps_rd || inserted->bps_wr ||
|
||||
@ -613,7 +612,7 @@ static void hmp_info_VncBasicInfo(Monitor *mon, VncBasicInfo *info,
|
||||
name,
|
||||
info->host,
|
||||
info->service,
|
||||
NetworkAddressFamily_lookup[info->family],
|
||||
NetworkAddressFamily_str(info->family),
|
||||
info->websocket ? " (Websocket)" : "");
|
||||
}
|
||||
|
||||
@ -623,8 +622,8 @@ static void hmp_info_vnc_authcrypt(Monitor *mon, const char *indent,
|
||||
VncVencryptSubAuth *vencrypt)
|
||||
{
|
||||
monitor_printf(mon, "%sAuth: %s (Sub: %s)\n", indent,
|
||||
VncPrimaryAuth_lookup[auth],
|
||||
vencrypt ? VncVencryptSubAuth_lookup[*vencrypt] : "none");
|
||||
VncPrimaryAuth_str(auth),
|
||||
vencrypt ? VncVencryptSubAuth_str(*vencrypt) : "none");
|
||||
}
|
||||
|
||||
static void hmp_info_vnc_clients(Monitor *mon, VncClientInfoList *client)
|
||||
@ -739,7 +738,7 @@ void hmp_info_spice(Monitor *mon, const QDict *qdict)
|
||||
monitor_printf(mon, " auth: %s\n", info->auth);
|
||||
monitor_printf(mon, " compiled: %s\n", info->compiled_version);
|
||||
monitor_printf(mon, " mouse-mode: %s\n",
|
||||
SpiceQueryMouseMode_lookup[info->mouse_mode]);
|
||||
SpiceQueryMouseMode_str(info->mouse_mode));
|
||||
|
||||
if (!info->has_channels || info->channels == NULL) {
|
||||
monitor_printf(mon, "Channels: none\n");
|
||||
@ -1010,10 +1009,10 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict)
|
||||
for (info = info_list; info; info = info->next) {
|
||||
TPMInfo *ti = info->value;
|
||||
monitor_printf(mon, " tpm%d: model=%s\n",
|
||||
c, TpmModel_lookup[ti->model]);
|
||||
c, TpmModel_str(ti->model));
|
||||
|
||||
monitor_printf(mon, " \\ %s: type=%s",
|
||||
ti->id, TpmTypeOptionsKind_lookup[ti->options->type]);
|
||||
ti->id, TpmTypeOptionsKind_str(ti->options->type));
|
||||
|
||||
switch (ti->options->type) {
|
||||
case TPM_TYPE_OPTIONS_KIND_PASSTHROUGH:
|
||||
@ -1527,23 +1526,20 @@ void hmp_migrate_set_capability(Monitor *mon, const QDict *qdict)
|
||||
bool state = qdict_get_bool(qdict, "state");
|
||||
Error *err = NULL;
|
||||
MigrationCapabilityStatusList *caps = g_malloc0(sizeof(*caps));
|
||||
int i;
|
||||
int val;
|
||||
|
||||
for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
|
||||
if (strcmp(cap, MigrationCapability_lookup[i]) == 0) {
|
||||
caps->value = g_malloc0(sizeof(*caps->value));
|
||||
caps->value->capability = i;
|
||||
caps->value->state = state;
|
||||
caps->next = NULL;
|
||||
qmp_migrate_set_capabilities(caps, &err);
|
||||
break;
|
||||
}
|
||||
val = qapi_enum_parse(&MigrationCapability_lookup, cap, -1, &err);
|
||||
if (val < 0) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (i == MIGRATION_CAPABILITY__MAX) {
|
||||
error_setg(&err, QERR_INVALID_PARAMETER, cap);
|
||||
}
|
||||
caps->value = g_malloc0(sizeof(*caps->value));
|
||||
caps->value->capability = val;
|
||||
caps->value->state = state;
|
||||
caps->next = NULL;
|
||||
qmp_migrate_set_capabilities(caps, &err);
|
||||
|
||||
end:
|
||||
qapi_free_MigrationCapabilityStatusList(caps);
|
||||
|
||||
if (err) {
|
||||
@ -1559,84 +1555,82 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
|
||||
MigrateSetParameters *p = g_new0(MigrateSetParameters, 1);
|
||||
uint64_t valuebw = 0;
|
||||
Error *err = NULL;
|
||||
int i, ret;
|
||||
int val, ret;
|
||||
|
||||
for (i = 0; i < MIGRATION_PARAMETER__MAX; i++) {
|
||||
if (strcmp(param, MigrationParameter_lookup[i]) == 0) {
|
||||
switch (i) {
|
||||
case MIGRATION_PARAMETER_COMPRESS_LEVEL:
|
||||
p->has_compress_level = true;
|
||||
visit_type_int(v, param, &p->compress_level, &err);
|
||||
break;
|
||||
case MIGRATION_PARAMETER_COMPRESS_THREADS:
|
||||
p->has_compress_threads = true;
|
||||
visit_type_int(v, param, &p->compress_threads, &err);
|
||||
break;
|
||||
case MIGRATION_PARAMETER_DECOMPRESS_THREADS:
|
||||
p->has_decompress_threads = true;
|
||||
visit_type_int(v, param, &p->decompress_threads, &err);
|
||||
break;
|
||||
case MIGRATION_PARAMETER_CPU_THROTTLE_INITIAL:
|
||||
p->has_cpu_throttle_initial = true;
|
||||
visit_type_int(v, param, &p->cpu_throttle_initial, &err);
|
||||
break;
|
||||
case MIGRATION_PARAMETER_CPU_THROTTLE_INCREMENT:
|
||||
p->has_cpu_throttle_increment = true;
|
||||
visit_type_int(v, param, &p->cpu_throttle_increment, &err);
|
||||
break;
|
||||
case MIGRATION_PARAMETER_TLS_CREDS:
|
||||
p->has_tls_creds = true;
|
||||
p->tls_creds = g_new0(StrOrNull, 1);
|
||||
p->tls_creds->type = QTYPE_QSTRING;
|
||||
visit_type_str(v, param, &p->tls_creds->u.s, &err);
|
||||
break;
|
||||
case MIGRATION_PARAMETER_TLS_HOSTNAME:
|
||||
p->has_tls_hostname = true;
|
||||
p->tls_hostname = g_new0(StrOrNull, 1);
|
||||
p->tls_hostname->type = QTYPE_QSTRING;
|
||||
visit_type_str(v, param, &p->tls_hostname->u.s, &err);
|
||||
break;
|
||||
case MIGRATION_PARAMETER_MAX_BANDWIDTH:
|
||||
p->has_max_bandwidth = true;
|
||||
/*
|
||||
* Can't use visit_type_size() here, because it
|
||||
* defaults to Bytes rather than Mebibytes.
|
||||
*/
|
||||
ret = qemu_strtosz_MiB(valuestr, NULL, &valuebw);
|
||||
if (ret < 0 || valuebw > INT64_MAX
|
||||
|| (size_t)valuebw != valuebw) {
|
||||
error_setg(&err, "Invalid size %s", valuestr);
|
||||
break;
|
||||
}
|
||||
p->max_bandwidth = valuebw;
|
||||
break;
|
||||
case MIGRATION_PARAMETER_DOWNTIME_LIMIT:
|
||||
p->has_downtime_limit = true;
|
||||
visit_type_int(v, param, &p->downtime_limit, &err);
|
||||
break;
|
||||
case MIGRATION_PARAMETER_X_CHECKPOINT_DELAY:
|
||||
p->has_x_checkpoint_delay = true;
|
||||
visit_type_int(v, param, &p->x_checkpoint_delay, &err);
|
||||
break;
|
||||
case MIGRATION_PARAMETER_BLOCK_INCREMENTAL:
|
||||
p->has_block_incremental = true;
|
||||
visit_type_bool(v, param, &p->block_incremental, &err);
|
||||
break;
|
||||
}
|
||||
val = qapi_enum_parse(&MigrationParameter_lookup, param, -1, &err);
|
||||
if (val < 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
qmp_migrate_set_parameters(p, &err);
|
||||
switch (val) {
|
||||
case MIGRATION_PARAMETER_COMPRESS_LEVEL:
|
||||
p->has_compress_level = true;
|
||||
visit_type_int(v, param, &p->compress_level, &err);
|
||||
break;
|
||||
case MIGRATION_PARAMETER_COMPRESS_THREADS:
|
||||
p->has_compress_threads = true;
|
||||
visit_type_int(v, param, &p->compress_threads, &err);
|
||||
break;
|
||||
case MIGRATION_PARAMETER_DECOMPRESS_THREADS:
|
||||
p->has_decompress_threads = true;
|
||||
visit_type_int(v, param, &p->decompress_threads, &err);
|
||||
break;
|
||||
case MIGRATION_PARAMETER_CPU_THROTTLE_INITIAL:
|
||||
p->has_cpu_throttle_initial = true;
|
||||
visit_type_int(v, param, &p->cpu_throttle_initial, &err);
|
||||
break;
|
||||
case MIGRATION_PARAMETER_CPU_THROTTLE_INCREMENT:
|
||||
p->has_cpu_throttle_increment = true;
|
||||
visit_type_int(v, param, &p->cpu_throttle_increment, &err);
|
||||
break;
|
||||
case MIGRATION_PARAMETER_TLS_CREDS:
|
||||
p->has_tls_creds = true;
|
||||
p->tls_creds = g_new0(StrOrNull, 1);
|
||||
p->tls_creds->type = QTYPE_QSTRING;
|
||||
visit_type_str(v, param, &p->tls_creds->u.s, &err);
|
||||
break;
|
||||
case MIGRATION_PARAMETER_TLS_HOSTNAME:
|
||||
p->has_tls_hostname = true;
|
||||
p->tls_hostname = g_new0(StrOrNull, 1);
|
||||
p->tls_hostname->type = QTYPE_QSTRING;
|
||||
visit_type_str(v, param, &p->tls_hostname->u.s, &err);
|
||||
break;
|
||||
case MIGRATION_PARAMETER_MAX_BANDWIDTH:
|
||||
p->has_max_bandwidth = true;
|
||||
/*
|
||||
* Can't use visit_type_size() here, because it
|
||||
* defaults to Bytes rather than Mebibytes.
|
||||
*/
|
||||
ret = qemu_strtosz_MiB(valuestr, NULL, &valuebw);
|
||||
if (ret < 0 || valuebw > INT64_MAX
|
||||
|| (size_t)valuebw != valuebw) {
|
||||
error_setg(&err, "Invalid size %s", valuestr);
|
||||
break;
|
||||
}
|
||||
p->max_bandwidth = valuebw;
|
||||
break;
|
||||
case MIGRATION_PARAMETER_DOWNTIME_LIMIT:
|
||||
p->has_downtime_limit = true;
|
||||
visit_type_int(v, param, &p->downtime_limit, &err);
|
||||
break;
|
||||
case MIGRATION_PARAMETER_X_CHECKPOINT_DELAY:
|
||||
p->has_x_checkpoint_delay = true;
|
||||
visit_type_int(v, param, &p->x_checkpoint_delay, &err);
|
||||
break;
|
||||
case MIGRATION_PARAMETER_BLOCK_INCREMENTAL:
|
||||
p->has_block_incremental = true;
|
||||
visit_type_bool(v, param, &p->block_incremental, &err);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if (i == MIGRATION_PARAMETER__MAX) {
|
||||
error_setg(&err, QERR_INVALID_PARAMETER, param);
|
||||
if (err) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
qmp_migrate_set_parameters(p, &err);
|
||||
|
||||
cleanup:
|
||||
qapi_free_MigrateSetParameters(p);
|
||||
visit_free(v);
|
||||
@ -1741,8 +1735,8 @@ void hmp_change(Monitor *mon, const QDict *qdict)
|
||||
} else {
|
||||
if (read_only) {
|
||||
read_only_mode =
|
||||
qapi_enum_parse(BlockdevChangeReadOnlyMode_lookup,
|
||||
read_only, BLOCKDEV_CHANGE_READ_ONLY_MODE__MAX,
|
||||
qapi_enum_parse(&BlockdevChangeReadOnlyMode_lookup,
|
||||
read_only,
|
||||
BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN, &err);
|
||||
if (err) {
|
||||
hmp_handle_error(mon, &err);
|
||||
@ -2374,7 +2368,7 @@ void hmp_info_memdev(Monitor *mon, const QDict *qdict)
|
||||
monitor_printf(mon, " prealloc: %s\n",
|
||||
m->value->prealloc ? "true" : "false");
|
||||
monitor_printf(mon, " policy: %s\n",
|
||||
HostMemPolicy_lookup[m->value->policy]);
|
||||
HostMemPolicy_str(m->value->policy));
|
||||
visit_complete(v, &str);
|
||||
monitor_printf(mon, " host nodes: %s\n", str);
|
||||
|
||||
@ -2405,7 +2399,7 @@ void hmp_info_memory_devices(Monitor *mon, const QDict *qdict)
|
||||
di = value->u.dimm.data;
|
||||
|
||||
monitor_printf(mon, "Memory device [%s]: \"%s\"\n",
|
||||
MemoryDeviceInfoKind_lookup[value->type],
|
||||
MemoryDeviceInfoKind_str(value->type),
|
||||
di->id ? di->id : "");
|
||||
monitor_printf(mon, " addr: 0x%" PRIx64 "\n", di->addr);
|
||||
monitor_printf(mon, " slot: %" PRId64 "\n", di->slot);
|
||||
@ -2799,7 +2793,7 @@ void hmp_info_dump(Monitor *mon, const QDict *qdict)
|
||||
DumpQueryResult *result = qmp_query_dump(NULL);
|
||||
|
||||
assert(result && result->status < DUMP_STATUS__MAX);
|
||||
monitor_printf(mon, "Status: %s\n", DumpStatus_lookup[result->status]);
|
||||
monitor_printf(mon, "Status: %s\n", DumpStatus_str(result->status));
|
||||
|
||||
if (result->status == DUMP_STATUS_ACTIVE) {
|
||||
float percent = 0;
|
||||
|
@ -392,9 +392,9 @@ static int pick_geometry(FDrive *drv)
|
||||
FLOPPY_DPRINTF("User requested floppy drive type '%s', "
|
||||
"but inserted medium appears to be a "
|
||||
"%"PRId64" sector '%s' type\n",
|
||||
FloppyDriveType_lookup[drv->drive],
|
||||
FloppyDriveType_str(drv->drive),
|
||||
nb_sectors,
|
||||
FloppyDriveType_lookup[parse->drive]);
|
||||
FloppyDriveType_str(parse->drive));
|
||||
}
|
||||
match = type_match;
|
||||
}
|
||||
@ -403,7 +403,7 @@ static int pick_geometry(FDrive *drv)
|
||||
if (match == -1) {
|
||||
error_setg(&error_abort, "No candidate geometries present in table "
|
||||
" for floppy drive type '%s'",
|
||||
FloppyDriveType_lookup[drv->drive]);
|
||||
FloppyDriveType_str(drv->drive));
|
||||
}
|
||||
|
||||
parse = &(fd_formats[match]);
|
||||
|
@ -848,7 +848,7 @@ static void sunkbd_handle_event(DeviceState *dev, QemuConsole *src,
|
||||
assert(evt->type == INPUT_EVENT_KIND_KEY);
|
||||
key = evt->u.key.data;
|
||||
qcode = qemu_input_key_value_to_qcode(key->key);
|
||||
trace_escc_sunkbd_event_in(qcode, QKeyCode_lookup[qcode],
|
||||
trace_escc_sunkbd_event_in(qcode, QKeyCode_str(qcode),
|
||||
key->down);
|
||||
|
||||
if (qcode == Q_KEY_CODE_CAPS_LOCK) {
|
||||
|
@ -72,7 +72,9 @@ static void set_enum(Object *obj, Visitor *v, const char *name, void *opaque,
|
||||
|
||||
static void set_default_value_enum(Object *obj, const Property *prop)
|
||||
{
|
||||
object_property_set_str(obj, prop->info->enum_table[prop->defval.i],
|
||||
object_property_set_str(obj,
|
||||
qapi_enum_lookup(prop->info->enum_table,
|
||||
prop->defval.i),
|
||||
prop->name, &error_abort);
|
||||
}
|
||||
|
||||
@ -585,7 +587,7 @@ const PropertyInfo qdev_prop_macaddr = {
|
||||
const PropertyInfo qdev_prop_on_off_auto = {
|
||||
.name = "OnOffAuto",
|
||||
.description = "on/off/auto",
|
||||
.enum_table = OnOffAuto_lookup,
|
||||
.enum_table = &OnOffAuto_lookup,
|
||||
.get = get_enum,
|
||||
.set = set_enum,
|
||||
.set_default_value = set_default_value_enum,
|
||||
@ -597,7 +599,7 @@ QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
|
||||
|
||||
const PropertyInfo qdev_prop_losttickpolicy = {
|
||||
.name = "LostTickPolicy",
|
||||
.enum_table = LostTickPolicy_lookup,
|
||||
.enum_table = &LostTickPolicy_lookup,
|
||||
.get = get_enum,
|
||||
.set = set_enum,
|
||||
.set_default_value = set_default_value_enum,
|
||||
@ -611,7 +613,7 @@ const PropertyInfo qdev_prop_blockdev_on_error = {
|
||||
.name = "BlockdevOnError",
|
||||
.description = "Error handling policy, "
|
||||
"report/ignore/enospc/stop/auto",
|
||||
.enum_table = BlockdevOnError_lookup,
|
||||
.enum_table = &BlockdevOnError_lookup,
|
||||
.get = get_enum,
|
||||
.set = set_enum,
|
||||
.set_default_value = set_default_value_enum,
|
||||
@ -625,7 +627,7 @@ const PropertyInfo qdev_prop_bios_chs_trans = {
|
||||
.name = "BiosAtaTranslation",
|
||||
.description = "Logical CHS translation algorithm, "
|
||||
"auto/none/lba/large/rechs",
|
||||
.enum_table = BiosAtaTranslation_lookup,
|
||||
.enum_table = &BiosAtaTranslation_lookup,
|
||||
.get = get_enum,
|
||||
.set = set_enum,
|
||||
.set_default_value = set_default_value_enum,
|
||||
@ -637,7 +639,7 @@ const PropertyInfo qdev_prop_fdc_drive_type = {
|
||||
.name = "FdcDriveType",
|
||||
.description = "FDC drive type, "
|
||||
"144/288/120/none/auto",
|
||||
.enum_table = FloppyDriveType_lookup,
|
||||
.enum_table = &FloppyDriveType_lookup,
|
||||
.get = get_enum,
|
||||
.set = set_enum,
|
||||
.set_default_value = set_default_value_enum,
|
||||
@ -1095,7 +1097,8 @@ void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
|
||||
Property *prop;
|
||||
|
||||
prop = qdev_prop_find(dev, name);
|
||||
object_property_set_str(OBJECT(dev), prop->info->enum_table[value],
|
||||
object_property_set_str(OBJECT(dev),
|
||||
qapi_enum_lookup(prop->info->enum_table, value),
|
||||
name, &error_abort);
|
||||
}
|
||||
|
||||
|
@ -209,7 +209,7 @@ static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
|
||||
} else {
|
||||
if (key->down) {
|
||||
fprintf(stderr, "%s: unmapped key: %d [%s]\n", __func__,
|
||||
qcode, QKeyCode_lookup[qcode]);
|
||||
qcode, QKeyCode_str(qcode));
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -224,7 +224,7 @@ static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
|
||||
if (btn->down) {
|
||||
fprintf(stderr, "%s: unmapped button: %d [%s]\n", __func__,
|
||||
btn->button,
|
||||
InputButton_lookup[btn->button]);
|
||||
InputButton_str(btn->button));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -249,7 +249,7 @@ struct Property {
|
||||
struct PropertyInfo {
|
||||
const char *name;
|
||||
const char *description;
|
||||
const char * const *enum_table;
|
||||
const QEnumLookup *enum_table;
|
||||
int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len);
|
||||
void (*set_default_value)(Object *obj, const Property *prop);
|
||||
void (*create)(Object *obj, Property *prop, Error **errp);
|
||||
|
@ -53,13 +53,15 @@ void qdict_destroy_obj(QObject *obj);
|
||||
#define qdict_put(qdict, key, obj) \
|
||||
qdict_put_obj(qdict, key, QOBJECT(obj))
|
||||
|
||||
/* Helpers for int, bool, and string */
|
||||
/* Helpers for int, bool, null, and string */
|
||||
#define qdict_put_int(qdict, key, value) \
|
||||
qdict_put(qdict, key, qnum_from_int(value))
|
||||
#define qdict_put_bool(qdict, key, value) \
|
||||
qdict_put(qdict, key, qbool_from_bool(value))
|
||||
#define qdict_put_str(qdict, key, value) \
|
||||
qdict_put(qdict, key, qstring_from_str(value))
|
||||
#define qdict_put_null(qdict, key) \
|
||||
qdict_put(qdict, key, qnull())
|
||||
|
||||
/* High level helpers */
|
||||
double qdict_get_double(const QDict *qdict, const char *key);
|
||||
|
54
include/qapi/qmp/qlit.h
Normal file
54
include/qapi/qmp/qlit.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright IBM, Corp. 2009
|
||||
* Copyright (c) 2013, 2015, 2017 Red Hat Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <aliguori@us.ibm.com>
|
||||
* Markus Armbruster <armbru@redhat.com>
|
||||
* Marc-André Lureau <marcandre.lureau@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
#ifndef QLIT_H
|
||||
#define QLIT_H
|
||||
|
||||
#include "qapi-types.h"
|
||||
#include "qobject.h"
|
||||
|
||||
typedef struct QLitDictEntry QLitDictEntry;
|
||||
typedef struct QLitObject QLitObject;
|
||||
|
||||
struct QLitObject {
|
||||
int type;
|
||||
union {
|
||||
bool qbool;
|
||||
int64_t qnum;
|
||||
const char *qstr;
|
||||
QLitDictEntry *qdict;
|
||||
QLitObject *qlist;
|
||||
} value;
|
||||
};
|
||||
|
||||
struct QLitDictEntry {
|
||||
const char *key;
|
||||
QLitObject value;
|
||||
};
|
||||
|
||||
#define QLIT_QNULL \
|
||||
{ .type = QTYPE_QNULL }
|
||||
#define QLIT_QBOOL(val) \
|
||||
{ .type = QTYPE_QBOOL, .value.qbool = (val) }
|
||||
#define QLIT_QNUM(val) \
|
||||
{ .type = QTYPE_QNUM, .value.qnum = (val) }
|
||||
#define QLIT_QSTR(val) \
|
||||
{ .type = QTYPE_QSTRING, .value.qstr = (val) }
|
||||
#define QLIT_QDICT(val) \
|
||||
{ .type = QTYPE_QDICT, .value.qdict = (val) }
|
||||
#define QLIT_QLIST(val) \
|
||||
{ .type = QTYPE_QLIST, .value.qlist = (val) }
|
||||
|
||||
bool qlit_equal_qobject(const QLitObject *lhs, const QObject *rhs);
|
||||
|
||||
#endif /* QLIT_H */
|
@ -23,6 +23,27 @@ typedef enum {
|
||||
QNUM_DOUBLE
|
||||
} QNumKind;
|
||||
|
||||
/*
|
||||
* QNum encapsulates how our dialect of JSON fills in the blanks left
|
||||
* by the JSON specification (RFC 7159) regarding numbers.
|
||||
*
|
||||
* Conceptually, we treat number as an abstract type with three
|
||||
* concrete subtypes: floating-point, signed integer, unsigned
|
||||
* integer. QNum implements this as a discriminated union of double,
|
||||
* int64_t, uint64_t.
|
||||
*
|
||||
* The JSON parser picks the subtype as follows. If the number has a
|
||||
* decimal point or an exponent, it is floating-point. Else if it
|
||||
* fits into int64_t, it's signed integer. Else if it fits into
|
||||
* uint64_t, it's unsigned integer. Else it's floating-point.
|
||||
*
|
||||
* Any number can serve as double: qnum_get_double() converts under
|
||||
* the hood.
|
||||
*
|
||||
* An integer can serve as signed / unsigned integer as long as it is
|
||||
* in range: qnum_get_try_int() / qnum_get_try_uint() check range and
|
||||
* convert under the hood.
|
||||
*/
|
||||
typedef struct QNum {
|
||||
QObject base;
|
||||
QNumKind kind;
|
||||
|
@ -11,8 +11,14 @@
|
||||
#ifndef QAPI_UTIL_H
|
||||
#define QAPI_UTIL_H
|
||||
|
||||
int qapi_enum_parse(const char * const lookup[], const char *buf,
|
||||
int max, int def, Error **errp);
|
||||
typedef struct QEnumLookup {
|
||||
const char *const *array;
|
||||
int size;
|
||||
} QEnumLookup;
|
||||
|
||||
const char *qapi_enum_lookup(const QEnumLookup *lookup, int val);
|
||||
int qapi_enum_parse(const QEnumLookup *lookup, const char *buf,
|
||||
int def, Error **errp);
|
||||
|
||||
int parse_qapi_name(const char *name, bool complete);
|
||||
|
||||
|
@ -469,7 +469,7 @@ bool visit_optional(Visitor *v, const char *name, bool *present);
|
||||
* that visit_type_str() must have no unwelcome side effects.
|
||||
*/
|
||||
void visit_type_enum(Visitor *v, const char *name, int *obj,
|
||||
const char *const strings[], Error **errp);
|
||||
const QEnumLookup *lookup, Error **errp);
|
||||
|
||||
/*
|
||||
* Check if visitor is an input visitor.
|
||||
|
@ -1415,14 +1415,14 @@ void object_class_property_add_bool(ObjectClass *klass, const char *name,
|
||||
*/
|
||||
void object_property_add_enum(Object *obj, const char *name,
|
||||
const char *typename,
|
||||
const char * const *strings,
|
||||
const QEnumLookup *lookup,
|
||||
int (*get)(Object *, Error **),
|
||||
void (*set)(Object *, int, Error **),
|
||||
Error **errp);
|
||||
|
||||
void object_class_property_add_enum(ObjectClass *klass, const char *name,
|
||||
const char *typename,
|
||||
const char * const *strings,
|
||||
const QEnumLookup *lookup,
|
||||
int (*get)(Object *, Error **),
|
||||
void (*set)(Object *, int, Error **),
|
||||
Error **errp);
|
||||
|
@ -226,7 +226,7 @@ TPMVersion tpm_backend_get_tpm_version(TPMBackend *s);
|
||||
TPMBackend *qemu_find_tpm(const char *id);
|
||||
|
||||
const TPMDriverOps *tpm_get_backend_driver(const char *type);
|
||||
int tpm_register_model(enum TpmModel model);
|
||||
int tpm_register_driver(const TPMDriverOps *tdo);
|
||||
void tpm_register_model(enum TpmModel model);
|
||||
void tpm_register_driver(const TPMDriverOps *tdo);
|
||||
|
||||
#endif
|
||||
|
@ -34,7 +34,7 @@ static void colo_failover_bh(void *opaque)
|
||||
FAILOVER_STATUS_ACTIVE);
|
||||
if (old_state != FAILOVER_STATUS_REQUIRE) {
|
||||
error_report("Unknown error for failover, old_state = %s",
|
||||
FailoverStatus_lookup[old_state]);
|
||||
FailoverStatus_str(old_state));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -64,7 +64,7 @@ FailoverStatus failover_set_state(FailoverStatus old_state,
|
||||
|
||||
old = atomic_cmpxchg(&failover_state, old_state, new_state);
|
||||
if (old == old_state) {
|
||||
trace_colo_failover_set_state(FailoverStatus_lookup[new_state]);
|
||||
trace_colo_failover_set_state(FailoverStatus_str(new_state));
|
||||
}
|
||||
return old;
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ static void secondary_vm_do_failover(void)
|
||||
FAILOVER_STATUS_RELAUNCH);
|
||||
if (old_state != FAILOVER_STATUS_ACTIVE) {
|
||||
error_report("Unknown error while do failover for secondary VM,"
|
||||
"old_state: %s", FailoverStatus_lookup[old_state]);
|
||||
"old_state: %s", FailoverStatus_str(old_state));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -91,7 +91,7 @@ static void secondary_vm_do_failover(void)
|
||||
FAILOVER_STATUS_COMPLETED);
|
||||
if (old_state != FAILOVER_STATUS_ACTIVE) {
|
||||
error_report("Incorrect state (%s) while doing failover for "
|
||||
"secondary VM", FailoverStatus_lookup[old_state]);
|
||||
"secondary VM", FailoverStatus_str(old_state));
|
||||
return;
|
||||
}
|
||||
/* Notify COLO incoming thread that failover work is finished */
|
||||
@ -126,7 +126,7 @@ static void primary_vm_do_failover(void)
|
||||
FAILOVER_STATUS_COMPLETED);
|
||||
if (old_state != FAILOVER_STATUS_ACTIVE) {
|
||||
error_report("Incorrect state (%s) while doing failover for Primary VM",
|
||||
FailoverStatus_lookup[old_state]);
|
||||
FailoverStatus_str(old_state));
|
||||
return;
|
||||
}
|
||||
/* Notify COLO thread that failover work is finished */
|
||||
@ -222,7 +222,7 @@ static void colo_send_message(QEMUFile *f, COLOMessage msg,
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Can't send COLO message");
|
||||
}
|
||||
trace_colo_send_message(COLOMessage_lookup[msg]);
|
||||
trace_colo_send_message(COLOMessage_str(msg));
|
||||
}
|
||||
|
||||
static void colo_send_message_value(QEMUFile *f, COLOMessage msg,
|
||||
@ -242,7 +242,7 @@ static void colo_send_message_value(QEMUFile *f, COLOMessage msg,
|
||||
ret = qemu_file_get_error(f);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Failed to send value for message:%s",
|
||||
COLOMessage_lookup[msg]);
|
||||
COLOMessage_str(msg));
|
||||
}
|
||||
}
|
||||
|
||||
@ -261,7 +261,7 @@ static COLOMessage colo_receive_message(QEMUFile *f, Error **errp)
|
||||
error_setg(errp, "%s: Invalid message", __func__);
|
||||
return msg;
|
||||
}
|
||||
trace_colo_receive_message(COLOMessage_lookup[msg]);
|
||||
trace_colo_receive_message(COLOMessage_str(msg));
|
||||
return msg;
|
||||
}
|
||||
|
||||
@ -299,7 +299,7 @@ static uint64_t colo_receive_message_value(QEMUFile *f, uint32_t expect_msg,
|
||||
ret = qemu_file_get_error(f);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Failed to get value for COLO message: %s",
|
||||
COLOMessage_lookup[expect_msg]);
|
||||
COLOMessage_str(expect_msg));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include "qemu/cutils.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/util.h"
|
||||
#include "migration.h"
|
||||
#include "migration/global_state.h"
|
||||
#include "migration/vmstate.h"
|
||||
@ -42,7 +41,7 @@ int global_state_store(void)
|
||||
|
||||
void global_state_store_running(void)
|
||||
{
|
||||
const char *state = RunState_lookup[RUN_STATE_RUNNING];
|
||||
const char *state = RunState_str(RUN_STATE_RUNNING);
|
||||
strncpy((char *)global_state.runstate,
|
||||
state, sizeof(global_state.runstate));
|
||||
}
|
||||
@ -89,8 +88,7 @@ static int global_state_post_load(void *opaque, int version_id)
|
||||
s->received = true;
|
||||
trace_migrate_global_state_post_load(runstate);
|
||||
|
||||
r = qapi_enum_parse(RunState_lookup, runstate, RUN_STATE__MAX,
|
||||
-1, &local_err);
|
||||
r = qapi_enum_parse(&RunState_lookup, runstate, -1, &local_err);
|
||||
|
||||
if (r == -1) {
|
||||
if (local_err) {
|
||||
|
@ -31,7 +31,6 @@
|
||||
#include "migration/vmstate.h"
|
||||
#include "block/block.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "qapi/util.h"
|
||||
#include "qemu/rcu.h"
|
||||
#include "block.h"
|
||||
#include "postcopy-ram.h"
|
||||
|
20
monitor.c
20
monitor.c
@ -928,7 +928,7 @@ EventInfoList *qmp_query_events(Error **errp)
|
||||
QAPIEvent e;
|
||||
|
||||
for (e = 0 ; e < QAPI_EVENT__MAX ; e++) {
|
||||
const char *event_name = QAPIEvent_lookup[e];
|
||||
const char *event_name = QAPIEvent_str(e);
|
||||
assert(event_name != NULL);
|
||||
info = g_malloc0(sizeof(*info));
|
||||
info->value = g_malloc0(sizeof(*info->value));
|
||||
@ -3249,8 +3249,8 @@ void netdev_add_completion(ReadLineState *rs, int nb_args, const char *str)
|
||||
}
|
||||
len = strlen(str);
|
||||
readline_set_completion_index(rs, len);
|
||||
for (i = 0; NetClientDriver_lookup[i]; i++) {
|
||||
add_completion_option(rs, str, NetClientDriver_lookup[i]);
|
||||
for (i = 0; i < NET_CLIENT_DRIVER__MAX; i++) {
|
||||
add_completion_option(rs, str, NetClientDriver_str(i));
|
||||
}
|
||||
}
|
||||
|
||||
@ -3434,8 +3434,8 @@ void sendkey_completion(ReadLineState *rs, int nb_args, const char *str)
|
||||
len = strlen(str);
|
||||
readline_set_completion_index(rs, len);
|
||||
for (i = 0; i < Q_KEY_CODE__MAX; i++) {
|
||||
if (!strncmp(str, QKeyCode_lookup[i], len)) {
|
||||
readline_add_completion(rs, QKeyCode_lookup[i]);
|
||||
if (!strncmp(str, QKeyCode_str(i), len)) {
|
||||
readline_add_completion(rs, QKeyCode_str(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3537,8 +3537,8 @@ void watchdog_action_completion(ReadLineState *rs, int nb_args, const char *str)
|
||||
return;
|
||||
}
|
||||
readline_set_completion_index(rs, strlen(str));
|
||||
for (i = 0; WatchdogExpirationAction_lookup[i]; i++) {
|
||||
add_completion_option(rs, str, WatchdogExpirationAction_lookup[i]);
|
||||
for (i = 0; i < WATCHDOG_EXPIRATION_ACTION__MAX; i++) {
|
||||
add_completion_option(rs, str, WatchdogExpirationAction_str(i));
|
||||
}
|
||||
}
|
||||
|
||||
@ -3552,7 +3552,7 @@ void migrate_set_capability_completion(ReadLineState *rs, int nb_args,
|
||||
if (nb_args == 2) {
|
||||
int i;
|
||||
for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
|
||||
const char *name = MigrationCapability_lookup[i];
|
||||
const char *name = MigrationCapability_str(i);
|
||||
if (!strncmp(str, name, len)) {
|
||||
readline_add_completion(rs, name);
|
||||
}
|
||||
@ -3573,7 +3573,7 @@ void migrate_set_parameter_completion(ReadLineState *rs, int nb_args,
|
||||
if (nb_args == 2) {
|
||||
int i;
|
||||
for (i = 0; i < MIGRATION_PARAMETER__MAX; i++) {
|
||||
const char *name = MigrationParameter_lookup[i];
|
||||
const char *name = MigrationParameter_str(i);
|
||||
if (!strncmp(str, name, len)) {
|
||||
readline_add_completion(rs, name);
|
||||
}
|
||||
@ -3852,7 +3852,7 @@ static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens)
|
||||
qdict = qdict_get_qdict(qobject_to_qdict(rsp), "error");
|
||||
if (qdict
|
||||
&& !g_strcmp0(qdict_get_try_str(qdict, "class"),
|
||||
QapiErrorClass_lookup[ERROR_CLASS_COMMAND_NOT_FOUND])) {
|
||||
QapiErrorClass_str(ERROR_CLASS_COMMAND_NOT_FOUND))) {
|
||||
/* Provide a more useful error message */
|
||||
qdict_del(qdict, "desc");
|
||||
qdict_put_str(qdict, "desc", "Expecting capabilities negotiation"
|
||||
|
@ -179,7 +179,7 @@ static void netfilter_init(Object *obj)
|
||||
netfilter_get_netdev_id, netfilter_set_netdev_id,
|
||||
NULL);
|
||||
object_property_add_enum(obj, "queue", "NetFilterDirection",
|
||||
NetFilterDirection_lookup,
|
||||
&NetFilterDirection_lookup,
|
||||
netfilter_get_direction, netfilter_set_direction,
|
||||
NULL);
|
||||
object_property_add_str(obj, "status",
|
||||
|
@ -1064,7 +1064,7 @@ static int net_client_init1(const void *object, bool is_netdev, Error **errp)
|
||||
/* FIXME drop when all init functions store an Error */
|
||||
if (errp && !*errp) {
|
||||
error_setg(errp, QERR_DEVICE_INIT_FAILED,
|
||||
NetClientDriver_lookup[netdev->type]);
|
||||
NetClientDriver_str(netdev->type));
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@ -1288,7 +1288,7 @@ void print_net_client(Monitor *mon, NetClientState *nc)
|
||||
|
||||
monitor_printf(mon, "%s: index=%d,type=%s,%s\n", nc->name,
|
||||
nc->queue_index,
|
||||
NetClientDriver_lookup[nc->info->type],
|
||||
NetClientDriver_str(nc->info->type),
|
||||
nc->info_str);
|
||||
if (!QTAILQ_EMPTY(&nc->filters)) {
|
||||
monitor_printf(mon, "filters:\n");
|
||||
|
3872
qapi-schema.json
3872
qapi-schema.json
File diff suppressed because it is too large
Load Diff
@ -1,11 +1,12 @@
|
||||
# -*- Mode: Python -*-
|
||||
|
||||
##
|
||||
# == QAPI block core definitions (vm unrelated)
|
||||
# == Block core (VM unrelated)
|
||||
##
|
||||
|
||||
# QAPI common definitions
|
||||
{ 'include': 'common.json' }
|
||||
{ 'include': 'crypto.json' }
|
||||
{ 'include': 'sockets.json' }
|
||||
|
||||
##
|
||||
# @SnapshotInfo:
|
||||
|
@ -1,14 +1,13 @@
|
||||
# -*- Mode: Python -*-
|
||||
|
||||
##
|
||||
# = QAPI block definitions
|
||||
# = Block devices
|
||||
##
|
||||
|
||||
# QAPI block core definitions
|
||||
{ 'include': 'block-core.json' }
|
||||
|
||||
##
|
||||
# == QAPI block definitions (vm unrelated)
|
||||
# == Additional block stuff (VM related)
|
||||
##
|
||||
|
||||
##
|
||||
@ -277,3 +276,71 @@
|
||||
##
|
||||
{ 'enum': 'QuorumOpType',
|
||||
'data': [ 'read', 'write', 'flush' ] }
|
||||
|
||||
##
|
||||
# @QUORUM_FAILURE:
|
||||
#
|
||||
# Emitted by the Quorum block driver if it fails to establish a quorum
|
||||
#
|
||||
# @reference: device name if defined else node name
|
||||
#
|
||||
# @sector-num: number of the first sector of the failed read operation
|
||||
#
|
||||
# @sectors-count: failed read operation sector count
|
||||
#
|
||||
# Note: This event is rate-limited.
|
||||
#
|
||||
# Since: 2.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "QUORUM_FAILURE",
|
||||
# "data": { "reference": "usr1", "sector-num": 345435, "sectors-count": 5 },
|
||||
# "timestamp": { "seconds": 1344522075, "microseconds": 745528 } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'QUORUM_FAILURE',
|
||||
'data': { 'reference': 'str', 'sector-num': 'int', 'sectors-count': 'int' } }
|
||||
|
||||
##
|
||||
# @QUORUM_REPORT_BAD:
|
||||
#
|
||||
# Emitted to report a corruption of a Quorum file
|
||||
#
|
||||
# @type: quorum operation type (Since 2.6)
|
||||
#
|
||||
# @error: error message. Only present on failure. This field
|
||||
# contains a human-readable error message. There are no semantics other
|
||||
# than that the block layer reported an error and clients should not
|
||||
# try to interpret the error string.
|
||||
#
|
||||
# @node-name: the graph node name of the block driver state
|
||||
#
|
||||
# @sector-num: number of the first sector of the failed read operation
|
||||
#
|
||||
# @sectors-count: failed read operation sector count
|
||||
#
|
||||
# Note: This event is rate-limited.
|
||||
#
|
||||
# Since: 2.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# 1. Read operation
|
||||
#
|
||||
# { "event": "QUORUM_REPORT_BAD",
|
||||
# "data": { "node-name": "node0", "sector-num": 345435, "sectors-count": 5,
|
||||
# "type": "read" },
|
||||
# "timestamp": { "seconds": 1344522075, "microseconds": 745528 } }
|
||||
#
|
||||
# 2. Flush operation
|
||||
#
|
||||
# { "event": "QUORUM_REPORT_BAD",
|
||||
# "data": { "node-name": "node0", "sector-num": 0, "sectors-count": 2097120,
|
||||
# "type": "flush", "error": "Broken pipe" },
|
||||
# "timestamp": { "seconds": 1456406829, "microseconds": 291763 } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'QUORUM_REPORT_BAD',
|
||||
'data': { 'type': 'QuorumOpType', '*error': 'str', 'node-name': 'str',
|
||||
'sector-num': 'int', 'sectors-count': 'int' } }
|
||||
|
538
qapi/char.json
Normal file
538
qapi/char.json
Normal file
@ -0,0 +1,538 @@
|
||||
# -*- Mode: Python -*-
|
||||
#
|
||||
|
||||
##
|
||||
# = Character devices
|
||||
##
|
||||
|
||||
{ 'include': 'sockets.json' }
|
||||
|
||||
##
|
||||
# @ChardevInfo:
|
||||
#
|
||||
# Information about a character device.
|
||||
#
|
||||
# @label: the label of the character device
|
||||
#
|
||||
# @filename: the filename of the character device
|
||||
#
|
||||
# @frontend-open: shows whether the frontend device attached to this backend
|
||||
# (eg. with the chardev=... option) is in open or closed state
|
||||
# (since 2.1)
|
||||
#
|
||||
# Notes: @filename is encoded using the QEMU command line character device
|
||||
# encoding. See the QEMU man page for details.
|
||||
#
|
||||
# Since: 0.14.0
|
||||
##
|
||||
{ 'struct': 'ChardevInfo', 'data': {'label': 'str',
|
||||
'filename': 'str',
|
||||
'frontend-open': 'bool'} }
|
||||
|
||||
##
|
||||
# @query-chardev:
|
||||
#
|
||||
# Returns information about current character devices.
|
||||
#
|
||||
# Returns: a list of @ChardevInfo
|
||||
#
|
||||
# Since: 0.14.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# -> { "execute": "query-chardev" }
|
||||
# <- {
|
||||
# "return": [
|
||||
# {
|
||||
# "label": "charchannel0",
|
||||
# "filename": "unix:/var/lib/libvirt/qemu/seabios.rhel6.agent,server",
|
||||
# "frontend-open": false
|
||||
# },
|
||||
# {
|
||||
# "label": "charmonitor",
|
||||
# "filename": "unix:/var/lib/libvirt/qemu/seabios.rhel6.monitor,server",
|
||||
# "frontend-open": true
|
||||
# },
|
||||
# {
|
||||
# "label": "charserial0",
|
||||
# "filename": "pty:/dev/pts/2",
|
||||
# "frontend-open": true
|
||||
# }
|
||||
# ]
|
||||
# }
|
||||
#
|
||||
##
|
||||
{ 'command': 'query-chardev', 'returns': ['ChardevInfo'] }
|
||||
|
||||
##
|
||||
# @ChardevBackendInfo:
|
||||
#
|
||||
# Information about a character device backend
|
||||
#
|
||||
# @name: The backend name
|
||||
#
|
||||
# Since: 2.0
|
||||
##
|
||||
{ 'struct': 'ChardevBackendInfo', 'data': {'name': 'str'} }
|
||||
|
||||
##
|
||||
# @query-chardev-backends:
|
||||
#
|
||||
# Returns information about character device backends.
|
||||
#
|
||||
# Returns: a list of @ChardevBackendInfo
|
||||
#
|
||||
# Since: 2.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# -> { "execute": "query-chardev-backends" }
|
||||
# <- {
|
||||
# "return":[
|
||||
# {
|
||||
# "name":"udp"
|
||||
# },
|
||||
# {
|
||||
# "name":"tcp"
|
||||
# },
|
||||
# {
|
||||
# "name":"unix"
|
||||
# },
|
||||
# {
|
||||
# "name":"spiceport"
|
||||
# }
|
||||
# ]
|
||||
# }
|
||||
#
|
||||
##
|
||||
{ 'command': 'query-chardev-backends', 'returns': ['ChardevBackendInfo'] }
|
||||
|
||||
##
|
||||
# @DataFormat:
|
||||
#
|
||||
# An enumeration of data format.
|
||||
#
|
||||
# @utf8: Data is a UTF-8 string (RFC 3629)
|
||||
#
|
||||
# @base64: Data is Base64 encoded binary (RFC 3548)
|
||||
#
|
||||
# Since: 1.4
|
||||
##
|
||||
{ 'enum': 'DataFormat',
|
||||
'data': [ 'utf8', 'base64' ] }
|
||||
|
||||
##
|
||||
# @ringbuf-write:
|
||||
#
|
||||
# Write to a ring buffer character device.
|
||||
#
|
||||
# @device: the ring buffer character device name
|
||||
#
|
||||
# @data: data to write
|
||||
#
|
||||
# @format: data encoding (default 'utf8').
|
||||
# - base64: data must be base64 encoded text. Its binary
|
||||
# decoding gets written.
|
||||
# - utf8: data's UTF-8 encoding is written
|
||||
# - data itself is always Unicode regardless of format, like
|
||||
# any other string.
|
||||
#
|
||||
# Returns: Nothing on success
|
||||
#
|
||||
# Since: 1.4
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# -> { "execute": "ringbuf-write",
|
||||
# "arguments": { "device": "foo",
|
||||
# "data": "abcdefgh",
|
||||
# "format": "utf8" } }
|
||||
# <- { "return": {} }
|
||||
#
|
||||
##
|
||||
{ 'command': 'ringbuf-write',
|
||||
'data': {'device': 'str', 'data': 'str',
|
||||
'*format': 'DataFormat'} }
|
||||
|
||||
##
|
||||
# @ringbuf-read:
|
||||
#
|
||||
# Read from a ring buffer character device.
|
||||
#
|
||||
# @device: the ring buffer character device name
|
||||
#
|
||||
# @size: how many bytes to read at most
|
||||
#
|
||||
# @format: data encoding (default 'utf8').
|
||||
# - base64: the data read is returned in base64 encoding.
|
||||
# - utf8: the data read is interpreted as UTF-8.
|
||||
# Bug: can screw up when the buffer contains invalid UTF-8
|
||||
# sequences, NUL characters, after the ring buffer lost
|
||||
# data, and when reading stops because the size limit is
|
||||
# reached.
|
||||
# - The return value is always Unicode regardless of format,
|
||||
# like any other string.
|
||||
#
|
||||
# Returns: data read from the device
|
||||
#
|
||||
# Since: 1.4
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# -> { "execute": "ringbuf-read",
|
||||
# "arguments": { "device": "foo",
|
||||
# "size": 1000,
|
||||
# "format": "utf8" } }
|
||||
# <- { "return": "abcdefgh" }
|
||||
#
|
||||
##
|
||||
{ 'command': 'ringbuf-read',
|
||||
'data': {'device': 'str', 'size': 'int', '*format': 'DataFormat'},
|
||||
'returns': 'str' }
|
||||
|
||||
##
|
||||
# @ChardevCommon:
|
||||
#
|
||||
# Configuration shared across all chardev backends
|
||||
#
|
||||
# @logfile: The name of a logfile to save output
|
||||
# @logappend: true to append instead of truncate
|
||||
# (default to false to truncate)
|
||||
#
|
||||
# Since: 2.6
|
||||
##
|
||||
{ 'struct': 'ChardevCommon', 'data': { '*logfile': 'str',
|
||||
'*logappend': 'bool' } }
|
||||
|
||||
##
|
||||
# @ChardevFile:
|
||||
#
|
||||
# Configuration info for file chardevs.
|
||||
#
|
||||
# @in: The name of the input file
|
||||
# @out: The name of the output file
|
||||
# @append: Open the file in append mode (default false to
|
||||
# truncate) (Since 2.6)
|
||||
#
|
||||
# Since: 1.4
|
||||
##
|
||||
{ 'struct': 'ChardevFile', 'data': { '*in' : 'str',
|
||||
'out' : 'str',
|
||||
'*append': 'bool' },
|
||||
'base': 'ChardevCommon' }
|
||||
|
||||
##
|
||||
# @ChardevHostdev:
|
||||
#
|
||||
# Configuration info for device and pipe chardevs.
|
||||
#
|
||||
# @device: The name of the special file for the device,
|
||||
# i.e. /dev/ttyS0 on Unix or COM1: on Windows
|
||||
#
|
||||
# Since: 1.4
|
||||
##
|
||||
{ 'struct': 'ChardevHostdev', 'data': { 'device' : 'str' },
|
||||
'base': 'ChardevCommon' }
|
||||
|
||||
##
|
||||
# @ChardevSocket:
|
||||
#
|
||||
# Configuration info for (stream) socket chardevs.
|
||||
#
|
||||
# @addr: socket address to listen on (server=true)
|
||||
# or connect to (server=false)
|
||||
# @tls-creds: the ID of the TLS credentials object (since 2.6)
|
||||
# @server: create server socket (default: true)
|
||||
# @wait: wait for incoming connection on server
|
||||
# sockets (default: false).
|
||||
# @nodelay: set TCP_NODELAY socket option (default: false)
|
||||
# @telnet: enable telnet protocol on server
|
||||
# sockets (default: false)
|
||||
# @tn3270: enable tn3270 protocol on server
|
||||
# sockets (default: false) (Since: 2.10)
|
||||
# @reconnect: For a client socket, if a socket is disconnected,
|
||||
# then attempt a reconnect after the given number of seconds.
|
||||
# Setting this to zero disables this function. (default: 0)
|
||||
# (Since: 2.2)
|
||||
#
|
||||
# Since: 1.4
|
||||
##
|
||||
{ 'struct': 'ChardevSocket', 'data': { 'addr' : 'SocketAddressLegacy',
|
||||
'*tls-creds' : 'str',
|
||||
'*server' : 'bool',
|
||||
'*wait' : 'bool',
|
||||
'*nodelay' : 'bool',
|
||||
'*telnet' : 'bool',
|
||||
'*tn3270' : 'bool',
|
||||
'*reconnect' : 'int' },
|
||||
'base': 'ChardevCommon' }
|
||||
|
||||
##
|
||||
# @ChardevUdp:
|
||||
#
|
||||
# Configuration info for datagram socket chardevs.
|
||||
#
|
||||
# @remote: remote address
|
||||
# @local: local address
|
||||
#
|
||||
# Since: 1.5
|
||||
##
|
||||
{ 'struct': 'ChardevUdp', 'data': { 'remote' : 'SocketAddressLegacy',
|
||||
'*local' : 'SocketAddressLegacy' },
|
||||
'base': 'ChardevCommon' }
|
||||
|
||||
##
|
||||
# @ChardevMux:
|
||||
#
|
||||
# Configuration info for mux chardevs.
|
||||
#
|
||||
# @chardev: name of the base chardev.
|
||||
#
|
||||
# Since: 1.5
|
||||
##
|
||||
{ 'struct': 'ChardevMux', 'data': { 'chardev' : 'str' },
|
||||
'base': 'ChardevCommon' }
|
||||
|
||||
##
|
||||
# @ChardevStdio:
|
||||
#
|
||||
# Configuration info for stdio chardevs.
|
||||
#
|
||||
# @signal: Allow signals (such as SIGINT triggered by ^C)
|
||||
# be delivered to qemu. Default: true in -nographic mode,
|
||||
# false otherwise.
|
||||
#
|
||||
# Since: 1.5
|
||||
##
|
||||
{ 'struct': 'ChardevStdio', 'data': { '*signal' : 'bool' },
|
||||
'base': 'ChardevCommon' }
|
||||
|
||||
|
||||
##
|
||||
# @ChardevSpiceChannel:
|
||||
#
|
||||
# Configuration info for spice vm channel chardevs.
|
||||
#
|
||||
# @type: kind of channel (for example vdagent).
|
||||
#
|
||||
# Since: 1.5
|
||||
##
|
||||
{ 'struct': 'ChardevSpiceChannel', 'data': { 'type' : 'str' },
|
||||
'base': 'ChardevCommon' }
|
||||
|
||||
##
|
||||
# @ChardevSpicePort:
|
||||
#
|
||||
# Configuration info for spice port chardevs.
|
||||
#
|
||||
# @fqdn: name of the channel (see docs/spice-port-fqdn.txt)
|
||||
#
|
||||
# Since: 1.5
|
||||
##
|
||||
{ 'struct': 'ChardevSpicePort', 'data': { 'fqdn' : 'str' },
|
||||
'base': 'ChardevCommon' }
|
||||
|
||||
##
|
||||
# @ChardevVC:
|
||||
#
|
||||
# Configuration info for virtual console chardevs.
|
||||
#
|
||||
# @width: console width, in pixels
|
||||
# @height: console height, in pixels
|
||||
# @cols: console width, in chars
|
||||
# @rows: console height, in chars
|
||||
#
|
||||
# Since: 1.5
|
||||
##
|
||||
{ 'struct': 'ChardevVC', 'data': { '*width' : 'int',
|
||||
'*height' : 'int',
|
||||
'*cols' : 'int',
|
||||
'*rows' : 'int' },
|
||||
'base': 'ChardevCommon' }
|
||||
|
||||
##
|
||||
# @ChardevRingbuf:
|
||||
#
|
||||
# Configuration info for ring buffer chardevs.
|
||||
#
|
||||
# @size: ring buffer size, must be power of two, default is 65536
|
||||
#
|
||||
# Since: 1.5
|
||||
##
|
||||
{ 'struct': 'ChardevRingbuf', 'data': { '*size' : 'int' },
|
||||
'base': 'ChardevCommon' }
|
||||
|
||||
##
|
||||
# @ChardevBackend:
|
||||
#
|
||||
# Configuration info for the new chardev backend.
|
||||
#
|
||||
# Since: 1.4 (testdev since 2.2, wctablet since 2.9)
|
||||
##
|
||||
{ 'union': 'ChardevBackend', 'data': { 'file' : 'ChardevFile',
|
||||
'serial' : 'ChardevHostdev',
|
||||
'parallel': 'ChardevHostdev',
|
||||
'pipe' : 'ChardevHostdev',
|
||||
'socket' : 'ChardevSocket',
|
||||
'udp' : 'ChardevUdp',
|
||||
'pty' : 'ChardevCommon',
|
||||
'null' : 'ChardevCommon',
|
||||
'mux' : 'ChardevMux',
|
||||
'msmouse': 'ChardevCommon',
|
||||
'wctablet' : 'ChardevCommon',
|
||||
'braille': 'ChardevCommon',
|
||||
'testdev': 'ChardevCommon',
|
||||
'stdio' : 'ChardevStdio',
|
||||
'console': 'ChardevCommon',
|
||||
'spicevmc' : 'ChardevSpiceChannel',
|
||||
'spiceport' : 'ChardevSpicePort',
|
||||
'vc' : 'ChardevVC',
|
||||
'ringbuf': 'ChardevRingbuf',
|
||||
# next one is just for compatibility
|
||||
'memory' : 'ChardevRingbuf' } }
|
||||
|
||||
##
|
||||
# @ChardevReturn:
|
||||
#
|
||||
# Return info about the chardev backend just created.
|
||||
#
|
||||
# @pty: name of the slave pseudoterminal device, present if
|
||||
# and only if a chardev of type 'pty' was created
|
||||
#
|
||||
# Since: 1.4
|
||||
##
|
||||
{ 'struct' : 'ChardevReturn', 'data': { '*pty' : 'str' } }
|
||||
|
||||
##
|
||||
# @chardev-add:
|
||||
#
|
||||
# Add a character device backend
|
||||
#
|
||||
# @id: the chardev's ID, must be unique
|
||||
# @backend: backend type and parameters
|
||||
#
|
||||
# Returns: ChardevReturn.
|
||||
#
|
||||
# Since: 1.4
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# -> { "execute" : "chardev-add",
|
||||
# "arguments" : { "id" : "foo",
|
||||
# "backend" : { "type" : "null", "data" : {} } } }
|
||||
# <- { "return": {} }
|
||||
#
|
||||
# -> { "execute" : "chardev-add",
|
||||
# "arguments" : { "id" : "bar",
|
||||
# "backend" : { "type" : "file",
|
||||
# "data" : { "out" : "/tmp/bar.log" } } } }
|
||||
# <- { "return": {} }
|
||||
#
|
||||
# -> { "execute" : "chardev-add",
|
||||
# "arguments" : { "id" : "baz",
|
||||
# "backend" : { "type" : "pty", "data" : {} } } }
|
||||
# <- { "return": { "pty" : "/dev/pty/42" } }
|
||||
#
|
||||
##
|
||||
{ 'command': 'chardev-add', 'data': {'id' : 'str',
|
||||
'backend' : 'ChardevBackend' },
|
||||
'returns': 'ChardevReturn' }
|
||||
|
||||
##
|
||||
# @chardev-change:
|
||||
#
|
||||
# Change a character device backend
|
||||
#
|
||||
# @id: the chardev's ID, must exist
|
||||
# @backend: new backend type and parameters
|
||||
#
|
||||
# Returns: ChardevReturn.
|
||||
#
|
||||
# Since: 2.10
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# -> { "execute" : "chardev-change",
|
||||
# "arguments" : { "id" : "baz",
|
||||
# "backend" : { "type" : "pty", "data" : {} } } }
|
||||
# <- { "return": { "pty" : "/dev/pty/42" } }
|
||||
#
|
||||
# -> {"execute" : "chardev-change",
|
||||
# "arguments" : {
|
||||
# "id" : "charchannel2",
|
||||
# "backend" : {
|
||||
# "type" : "socket",
|
||||
# "data" : {
|
||||
# "addr" : {
|
||||
# "type" : "unix" ,
|
||||
# "data" : {
|
||||
# "path" : "/tmp/charchannel2.socket"
|
||||
# }
|
||||
# },
|
||||
# "server" : true,
|
||||
# "wait" : false }}}}
|
||||
# <- {"return": {}}
|
||||
#
|
||||
##
|
||||
{ 'command': 'chardev-change', 'data': {'id' : 'str',
|
||||
'backend' : 'ChardevBackend' },
|
||||
'returns': 'ChardevReturn' }
|
||||
|
||||
##
|
||||
# @chardev-remove:
|
||||
#
|
||||
# Remove a character device backend
|
||||
#
|
||||
# @id: the chardev's ID, must exist and not be in use
|
||||
#
|
||||
# Returns: Nothing on success
|
||||
#
|
||||
# Since: 1.4
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# -> { "execute": "chardev-remove", "arguments": { "id" : "foo" } }
|
||||
# <- { "return": {} }
|
||||
#
|
||||
##
|
||||
{ 'command': 'chardev-remove', 'data': {'id': 'str'} }
|
||||
|
||||
##
|
||||
# @chardev-send-break:
|
||||
#
|
||||
# Send a break to a character device
|
||||
#
|
||||
# @id: the chardev's ID, must exist
|
||||
#
|
||||
# Returns: Nothing on success
|
||||
#
|
||||
# Since: 2.10
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# -> { "execute": "chardev-send-break", "arguments": { "id" : "foo" } }
|
||||
# <- { "return": {} }
|
||||
#
|
||||
##
|
||||
{ 'command': 'chardev-send-break', 'data': {'id': 'str'} }
|
||||
|
||||
##
|
||||
# @VSERPORT_CHANGE:
|
||||
#
|
||||
# Emitted when the guest opens or closes a virtio-serial port.
|
||||
#
|
||||
# @id: device identifier of the virtio-serial port
|
||||
#
|
||||
# @open: true if the guest has opened the virtio-serial port
|
||||
#
|
||||
# Since: 2.1
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "VSERPORT_CHANGE",
|
||||
# "data": { "id": "channel0", "open": true },
|
||||
# "timestamp": { "seconds": 1401385907, "microseconds": 422329 } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'VSERPORT_CHANGE',
|
||||
'data': { 'id': 'str', 'open': 'bool' } }
|
132
qapi/common.json
132
qapi/common.json
@ -1,7 +1,7 @@
|
||||
# -*- Mode: Python -*-
|
||||
|
||||
##
|
||||
# = QAPI common definitions
|
||||
# = Common data types
|
||||
##
|
||||
|
||||
##
|
||||
@ -29,107 +29,18 @@
|
||||
'DeviceNotActive', 'DeviceNotFound', 'KVMMissingCap' ] }
|
||||
|
||||
##
|
||||
# @VersionTriple:
|
||||
# @IoOperationType:
|
||||
#
|
||||
# A three-part version number.
|
||||
# An enumeration of the I/O operation types
|
||||
#
|
||||
# @major: The major version number.
|
||||
# @read: read operation
|
||||
#
|
||||
# @minor: The minor version number.
|
||||
# @write: write operation
|
||||
#
|
||||
# @micro: The micro version number.
|
||||
#
|
||||
# Since: 2.4
|
||||
# Since: 2.1
|
||||
##
|
||||
{ 'struct': 'VersionTriple',
|
||||
'data': {'major': 'int', 'minor': 'int', 'micro': 'int'} }
|
||||
|
||||
|
||||
##
|
||||
# @VersionInfo:
|
||||
#
|
||||
# A description of QEMU's version.
|
||||
#
|
||||
# @qemu: The 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
|
||||
##
|
||||
{ 'struct': 'VersionInfo',
|
||||
'data': {'qemu': 'VersionTriple', 'package': 'str'} }
|
||||
|
||||
##
|
||||
# @query-version:
|
||||
#
|
||||
# Returns the current version of QEMU.
|
||||
#
|
||||
# Returns: A @VersionInfo object describing the current version of QEMU.
|
||||
#
|
||||
# Since: 0.14.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# -> { "execute": "query-version" }
|
||||
# <- {
|
||||
# "return":{
|
||||
# "qemu":{
|
||||
# "major":0,
|
||||
# "minor":11,
|
||||
# "micro":5
|
||||
# },
|
||||
# "package":""
|
||||
# }
|
||||
# }
|
||||
#
|
||||
##
|
||||
{ 'command': 'query-version', 'returns': 'VersionInfo' }
|
||||
|
||||
##
|
||||
# @CommandInfo:
|
||||
#
|
||||
# Information about a QMP command
|
||||
#
|
||||
# @name: The command name
|
||||
#
|
||||
# Since: 0.14.0
|
||||
##
|
||||
{ 'struct': 'CommandInfo', 'data': {'name': 'str'} }
|
||||
|
||||
##
|
||||
# @query-commands:
|
||||
#
|
||||
# Return a list of supported QMP commands by this server
|
||||
#
|
||||
# Returns: A list of @CommandInfo for all supported commands
|
||||
#
|
||||
# Since: 0.14.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# -> { "execute": "query-commands" }
|
||||
# <- {
|
||||
# "return":[
|
||||
# {
|
||||
# "name":"query-balloon"
|
||||
# },
|
||||
# {
|
||||
# "name":"system_powerdown"
|
||||
# }
|
||||
# ]
|
||||
# }
|
||||
#
|
||||
# Note: This example has been shortened as the real response is too long.
|
||||
#
|
||||
##
|
||||
{ 'command': 'query-commands', 'returns': ['CommandInfo'] }
|
||||
{ 'enum': 'IoOperationType',
|
||||
'data': [ 'read', 'write' ] }
|
||||
|
||||
##
|
||||
# @OnOffAuto:
|
||||
@ -162,3 +73,30 @@
|
||||
##
|
||||
{ 'enum': 'OnOffSplit',
|
||||
'data': [ 'on', 'off', 'split' ] }
|
||||
|
||||
##
|
||||
# @String:
|
||||
#
|
||||
# A fat type wrapping 'str', to be embedded in lists.
|
||||
#
|
||||
# Since: 1.2
|
||||
##
|
||||
{ 'struct': 'String',
|
||||
'data': {
|
||||
'str': 'str' } }
|
||||
|
||||
##
|
||||
# @StrOrNull:
|
||||
#
|
||||
# This is a string value or the explicit lack of a string (null
|
||||
# pointer in C). Intended for cases when 'optional absent' already
|
||||
# has a different meaning.
|
||||
#
|
||||
# @s: the string value
|
||||
# @n: no string value
|
||||
#
|
||||
# Since: 2.10
|
||||
##
|
||||
{ 'alternate': 'StrOrNull',
|
||||
'data': { 's': 'str',
|
||||
'n': 'null' } }
|
||||
|
@ -2,7 +2,7 @@
|
||||
#
|
||||
|
||||
##
|
||||
# = QAPI crypto definitions
|
||||
# = Cryptography
|
||||
##
|
||||
|
||||
##
|
||||
|
646
qapi/event.json
646
qapi/event.json
@ -1,646 +0,0 @@
|
||||
# -*- Mode: Python -*-
|
||||
|
||||
##
|
||||
# = Other events
|
||||
##
|
||||
|
||||
##
|
||||
# @SHUTDOWN:
|
||||
#
|
||||
# Emitted when the virtual machine has shut down, indicating that qemu is
|
||||
# about to exit.
|
||||
#
|
||||
# @guest: If true, the shutdown was triggered by a guest request (such as
|
||||
# a guest-initiated ACPI shutdown request or other hardware-specific action)
|
||||
# rather than a host request (such as sending qemu a SIGINT). (since 2.10)
|
||||
#
|
||||
# Note: If the command-line option "-no-shutdown" has been specified, qemu will
|
||||
# not exit, and a STOP event will eventually follow the SHUTDOWN event
|
||||
#
|
||||
# Since: 0.12.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "SHUTDOWN", "data": { "guest": true },
|
||||
# "timestamp": { "seconds": 1267040730, "microseconds": 682951 } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'SHUTDOWN', 'data': { 'guest': 'bool' } }
|
||||
|
||||
##
|
||||
# @POWERDOWN:
|
||||
#
|
||||
# Emitted when the virtual machine is powered down through the power control
|
||||
# system, such as via ACPI.
|
||||
#
|
||||
# Since: 0.12.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "POWERDOWN",
|
||||
# "timestamp": { "seconds": 1267040730, "microseconds": 682951 } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'POWERDOWN' }
|
||||
|
||||
##
|
||||
# @RESET:
|
||||
#
|
||||
# Emitted when the virtual machine is reset
|
||||
#
|
||||
# @guest: If true, the reset was triggered by a guest request (such as
|
||||
# a guest-initiated ACPI reboot request or other hardware-specific action)
|
||||
# rather than a host request (such as the QMP command system_reset).
|
||||
# (since 2.10)
|
||||
#
|
||||
# Since: 0.12.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "RESET", "data": { "guest": false },
|
||||
# "timestamp": { "seconds": 1267041653, "microseconds": 9518 } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'RESET', 'data': { 'guest': 'bool' } }
|
||||
|
||||
##
|
||||
# @STOP:
|
||||
#
|
||||
# Emitted when the virtual machine is stopped
|
||||
#
|
||||
# Since: 0.12.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "STOP",
|
||||
# "timestamp": { "seconds": 1267041730, "microseconds": 281295 } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'STOP' }
|
||||
|
||||
##
|
||||
# @RESUME:
|
||||
#
|
||||
# Emitted when the virtual machine resumes execution
|
||||
#
|
||||
# Since: 0.12.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "RESUME",
|
||||
# "timestamp": { "seconds": 1271770767, "microseconds": 582542 } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'RESUME' }
|
||||
|
||||
##
|
||||
# @SUSPEND:
|
||||
#
|
||||
# Emitted when guest enters a hardware suspension state, for example, S3 state,
|
||||
# which is sometimes called standby state
|
||||
#
|
||||
# Since: 1.1
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "SUSPEND",
|
||||
# "timestamp": { "seconds": 1344456160, "microseconds": 309119 } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'SUSPEND' }
|
||||
|
||||
##
|
||||
# @SUSPEND_DISK:
|
||||
#
|
||||
# Emitted when guest enters a hardware suspension state with data saved on
|
||||
# disk, for example, S4 state, which is sometimes called hibernate state
|
||||
#
|
||||
# Note: QEMU shuts down (similar to event @SHUTDOWN) when entering this state
|
||||
#
|
||||
# Since: 1.2
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "SUSPEND_DISK",
|
||||
# "timestamp": { "seconds": 1344456160, "microseconds": 309119 } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'SUSPEND_DISK' }
|
||||
|
||||
##
|
||||
# @WAKEUP:
|
||||
#
|
||||
# Emitted when the guest has woken up from suspend state and is running
|
||||
#
|
||||
# Since: 1.1
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "WAKEUP",
|
||||
# "timestamp": { "seconds": 1344522075, "microseconds": 745528 } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'WAKEUP' }
|
||||
|
||||
##
|
||||
# @RTC_CHANGE:
|
||||
#
|
||||
# Emitted when the guest changes the RTC time.
|
||||
#
|
||||
# @offset: offset between base RTC clock (as specified by -rtc base), and
|
||||
# new RTC clock value
|
||||
#
|
||||
# Note: This event is rate-limited.
|
||||
#
|
||||
# Since: 0.13.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "RTC_CHANGE",
|
||||
# "data": { "offset": 78 },
|
||||
# "timestamp": { "seconds": 1267020223, "microseconds": 435656 } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'RTC_CHANGE',
|
||||
'data': { 'offset': 'int' } }
|
||||
|
||||
##
|
||||
# @WATCHDOG:
|
||||
#
|
||||
# Emitted when the watchdog device's timer is expired
|
||||
#
|
||||
# @action: action that has been taken
|
||||
#
|
||||
# Note: If action is "reset", "shutdown", or "pause" the WATCHDOG event is
|
||||
# followed respectively by the RESET, SHUTDOWN, or STOP events
|
||||
#
|
||||
# Note: This event is rate-limited.
|
||||
#
|
||||
# Since: 0.13.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "WATCHDOG",
|
||||
# "data": { "action": "reset" },
|
||||
# "timestamp": { "seconds": 1267061043, "microseconds": 959568 } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'WATCHDOG',
|
||||
'data': { 'action': 'WatchdogExpirationAction' } }
|
||||
|
||||
##
|
||||
# @DEVICE_DELETED:
|
||||
#
|
||||
# Emitted whenever the device removal completion is acknowledged by the guest.
|
||||
# At this point, it's safe to reuse the specified device ID. Device removal can
|
||||
# be initiated by the guest or by HMP/QMP commands.
|
||||
#
|
||||
# @device: device name
|
||||
#
|
||||
# @path: device path
|
||||
#
|
||||
# Since: 1.5
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "DEVICE_DELETED",
|
||||
# "data": { "device": "virtio-net-pci-0",
|
||||
# "path": "/machine/peripheral/virtio-net-pci-0" },
|
||||
# "timestamp": { "seconds": 1265044230, "microseconds": 450486 } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'DEVICE_DELETED',
|
||||
'data': { '*device': 'str', 'path': 'str' } }
|
||||
|
||||
##
|
||||
# @NIC_RX_FILTER_CHANGED:
|
||||
#
|
||||
# Emitted once until the 'query-rx-filter' command is executed, the first event
|
||||
# will always be emitted
|
||||
#
|
||||
# @name: net client name
|
||||
#
|
||||
# @path: device path
|
||||
#
|
||||
# Since: 1.6
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "NIC_RX_FILTER_CHANGED",
|
||||
# "data": { "name": "vnet0",
|
||||
# "path": "/machine/peripheral/vnet0/virtio-backend" },
|
||||
# "timestamp": { "seconds": 1368697518, "microseconds": 326866 } }
|
||||
# }
|
||||
#
|
||||
##
|
||||
{ 'event': 'NIC_RX_FILTER_CHANGED',
|
||||
'data': { '*name': 'str', 'path': 'str' } }
|
||||
|
||||
##
|
||||
# @VNC_CONNECTED:
|
||||
#
|
||||
# Emitted when a VNC client establishes a connection
|
||||
#
|
||||
# @server: server information
|
||||
#
|
||||
# @client: client information
|
||||
#
|
||||
# Note: This event is emitted before any authentication takes place, thus
|
||||
# the authentication ID is not provided
|
||||
#
|
||||
# Since: 0.13.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "VNC_CONNECTED",
|
||||
# "data": {
|
||||
# "server": { "auth": "sasl", "family": "ipv4",
|
||||
# "service": "5901", "host": "0.0.0.0" },
|
||||
# "client": { "family": "ipv4", "service": "58425",
|
||||
# "host": "127.0.0.1" } },
|
||||
# "timestamp": { "seconds": 1262976601, "microseconds": 975795 } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'VNC_CONNECTED',
|
||||
'data': { 'server': 'VncServerInfo',
|
||||
'client': 'VncBasicInfo' } }
|
||||
|
||||
##
|
||||
# @VNC_INITIALIZED:
|
||||
#
|
||||
# Emitted after authentication takes place (if any) and the VNC session is
|
||||
# made active
|
||||
#
|
||||
# @server: server information
|
||||
#
|
||||
# @client: client information
|
||||
#
|
||||
# Since: 0.13.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "VNC_INITIALIZED",
|
||||
# "data": {
|
||||
# "server": { "auth": "sasl", "family": "ipv4",
|
||||
# "service": "5901", "host": "0.0.0.0"},
|
||||
# "client": { "family": "ipv4", "service": "46089",
|
||||
# "host": "127.0.0.1", "sasl_username": "luiz" } },
|
||||
# "timestamp": { "seconds": 1263475302, "microseconds": 150772 } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'VNC_INITIALIZED',
|
||||
'data': { 'server': 'VncServerInfo',
|
||||
'client': 'VncClientInfo' } }
|
||||
|
||||
##
|
||||
# @VNC_DISCONNECTED:
|
||||
#
|
||||
# Emitted when the connection is closed
|
||||
#
|
||||
# @server: server information
|
||||
#
|
||||
# @client: client information
|
||||
#
|
||||
# Since: 0.13.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "VNC_DISCONNECTED",
|
||||
# "data": {
|
||||
# "server": { "auth": "sasl", "family": "ipv4",
|
||||
# "service": "5901", "host": "0.0.0.0" },
|
||||
# "client": { "family": "ipv4", "service": "58425",
|
||||
# "host": "127.0.0.1", "sasl_username": "luiz" } },
|
||||
# "timestamp": { "seconds": 1262976601, "microseconds": 975795 } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'VNC_DISCONNECTED',
|
||||
'data': { 'server': 'VncServerInfo',
|
||||
'client': 'VncClientInfo' } }
|
||||
|
||||
##
|
||||
# @SPICE_CONNECTED:
|
||||
#
|
||||
# Emitted when a SPICE client establishes a connection
|
||||
#
|
||||
# @server: server information
|
||||
#
|
||||
# @client: client information
|
||||
#
|
||||
# Since: 0.14.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "timestamp": {"seconds": 1290688046, "microseconds": 388707},
|
||||
# "event": "SPICE_CONNECTED",
|
||||
# "data": {
|
||||
# "server": { "port": "5920", "family": "ipv4", "host": "127.0.0.1"},
|
||||
# "client": {"port": "52873", "family": "ipv4", "host": "127.0.0.1"}
|
||||
# }}
|
||||
#
|
||||
##
|
||||
{ 'event': 'SPICE_CONNECTED',
|
||||
'data': { 'server': 'SpiceBasicInfo',
|
||||
'client': 'SpiceBasicInfo' } }
|
||||
|
||||
##
|
||||
# @SPICE_INITIALIZED:
|
||||
#
|
||||
# Emitted after initial handshake and authentication takes place (if any)
|
||||
# and the SPICE channel is up and running
|
||||
#
|
||||
# @server: server information
|
||||
#
|
||||
# @client: client information
|
||||
#
|
||||
# Since: 0.14.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "timestamp": {"seconds": 1290688046, "microseconds": 417172},
|
||||
# "event": "SPICE_INITIALIZED",
|
||||
# "data": {"server": {"auth": "spice", "port": "5921",
|
||||
# "family": "ipv4", "host": "127.0.0.1"},
|
||||
# "client": {"port": "49004", "family": "ipv4", "channel-type": 3,
|
||||
# "connection-id": 1804289383, "host": "127.0.0.1",
|
||||
# "channel-id": 0, "tls": true}
|
||||
# }}
|
||||
#
|
||||
##
|
||||
{ 'event': 'SPICE_INITIALIZED',
|
||||
'data': { 'server': 'SpiceServerInfo',
|
||||
'client': 'SpiceChannel' } }
|
||||
|
||||
##
|
||||
# @SPICE_DISCONNECTED:
|
||||
#
|
||||
# Emitted when the SPICE connection is closed
|
||||
#
|
||||
# @server: server information
|
||||
#
|
||||
# @client: client information
|
||||
#
|
||||
# Since: 0.14.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "timestamp": {"seconds": 1290688046, "microseconds": 388707},
|
||||
# "event": "SPICE_DISCONNECTED",
|
||||
# "data": {
|
||||
# "server": { "port": "5920", "family": "ipv4", "host": "127.0.0.1"},
|
||||
# "client": {"port": "52873", "family": "ipv4", "host": "127.0.0.1"}
|
||||
# }}
|
||||
#
|
||||
##
|
||||
{ 'event': 'SPICE_DISCONNECTED',
|
||||
'data': { 'server': 'SpiceBasicInfo',
|
||||
'client': 'SpiceBasicInfo' } }
|
||||
|
||||
##
|
||||
# @SPICE_MIGRATE_COMPLETED:
|
||||
#
|
||||
# Emitted when SPICE migration has completed
|
||||
#
|
||||
# Since: 1.3
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "timestamp": {"seconds": 1290688046, "microseconds": 417172},
|
||||
# "event": "SPICE_MIGRATE_COMPLETED" }
|
||||
#
|
||||
##
|
||||
{ 'event': 'SPICE_MIGRATE_COMPLETED' }
|
||||
|
||||
##
|
||||
# @MIGRATION:
|
||||
#
|
||||
# Emitted when a migration event happens
|
||||
#
|
||||
# @status: @MigrationStatus describing the current migration status.
|
||||
#
|
||||
# Since: 2.4
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- {"timestamp": {"seconds": 1432121972, "microseconds": 744001},
|
||||
# "event": "MIGRATION",
|
||||
# "data": {"status": "completed"} }
|
||||
#
|
||||
##
|
||||
{ 'event': 'MIGRATION',
|
||||
'data': {'status': 'MigrationStatus'}}
|
||||
|
||||
##
|
||||
# @MIGRATION_PASS:
|
||||
#
|
||||
# Emitted from the source side of a migration at the start of each pass
|
||||
# (when it syncs the dirty bitmap)
|
||||
#
|
||||
# @pass: An incrementing count (starting at 1 on the first pass)
|
||||
#
|
||||
# Since: 2.6
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# { "timestamp": {"seconds": 1449669631, "microseconds": 239225},
|
||||
# "event": "MIGRATION_PASS", "data": {"pass": 2} }
|
||||
#
|
||||
##
|
||||
{ 'event': 'MIGRATION_PASS',
|
||||
'data': { 'pass': 'int' } }
|
||||
|
||||
##
|
||||
# @ACPI_DEVICE_OST:
|
||||
#
|
||||
# Emitted when guest executes ACPI _OST method.
|
||||
#
|
||||
# @info: ACPIOSTInfo type as described in qapi-schema.json
|
||||
#
|
||||
# Since: 2.1
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "ACPI_DEVICE_OST",
|
||||
# "data": { "device": "d1", "slot": "0",
|
||||
# "slot-type": "DIMM", "source": 1, "status": 0 } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'ACPI_DEVICE_OST',
|
||||
'data': { 'info': 'ACPIOSTInfo' } }
|
||||
|
||||
##
|
||||
# @BALLOON_CHANGE:
|
||||
#
|
||||
# Emitted when the guest changes the actual BALLOON level. This value is
|
||||
# equivalent to the @actual field return by the 'query-balloon' command
|
||||
#
|
||||
# @actual: actual level of the guest memory balloon in bytes
|
||||
#
|
||||
# Note: this event is rate-limited.
|
||||
#
|
||||
# Since: 1.2
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "BALLOON_CHANGE",
|
||||
# "data": { "actual": 944766976 },
|
||||
# "timestamp": { "seconds": 1267020223, "microseconds": 435656 } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'BALLOON_CHANGE',
|
||||
'data': { 'actual': 'int' } }
|
||||
|
||||
##
|
||||
# @GUEST_PANICKED:
|
||||
#
|
||||
# Emitted when guest OS panic is detected
|
||||
#
|
||||
# @action: action that has been taken, currently always "pause"
|
||||
#
|
||||
# @info: information about a panic (since 2.9)
|
||||
#
|
||||
# Since: 1.5
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "GUEST_PANICKED",
|
||||
# "data": { "action": "pause" } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'GUEST_PANICKED',
|
||||
'data': { 'action': 'GuestPanicAction', '*info': 'GuestPanicInformation' } }
|
||||
|
||||
##
|
||||
# @QUORUM_FAILURE:
|
||||
#
|
||||
# Emitted by the Quorum block driver if it fails to establish a quorum
|
||||
#
|
||||
# @reference: device name if defined else node name
|
||||
#
|
||||
# @sector-num: number of the first sector of the failed read operation
|
||||
#
|
||||
# @sectors-count: failed read operation sector count
|
||||
#
|
||||
# Note: This event is rate-limited.
|
||||
#
|
||||
# Since: 2.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "QUORUM_FAILURE",
|
||||
# "data": { "reference": "usr1", "sector-num": 345435, "sectors-count": 5 },
|
||||
# "timestamp": { "seconds": 1344522075, "microseconds": 745528 } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'QUORUM_FAILURE',
|
||||
'data': { 'reference': 'str', 'sector-num': 'int', 'sectors-count': 'int' } }
|
||||
|
||||
##
|
||||
# @QUORUM_REPORT_BAD:
|
||||
#
|
||||
# Emitted to report a corruption of a Quorum file
|
||||
#
|
||||
# @type: quorum operation type (Since 2.6)
|
||||
#
|
||||
# @error: error message. Only present on failure. This field
|
||||
# contains a human-readable error message. There are no semantics other
|
||||
# than that the block layer reported an error and clients should not
|
||||
# try to interpret the error string.
|
||||
#
|
||||
# @node-name: the graph node name of the block driver state
|
||||
#
|
||||
# @sector-num: number of the first sector of the failed read operation
|
||||
#
|
||||
# @sectors-count: failed read operation sector count
|
||||
#
|
||||
# Note: This event is rate-limited.
|
||||
#
|
||||
# Since: 2.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# 1. Read operation
|
||||
#
|
||||
# { "event": "QUORUM_REPORT_BAD",
|
||||
# "data": { "node-name": "node0", "sector-num": 345435, "sectors-count": 5,
|
||||
# "type": "read" },
|
||||
# "timestamp": { "seconds": 1344522075, "microseconds": 745528 } }
|
||||
#
|
||||
# 2. Flush operation
|
||||
#
|
||||
# { "event": "QUORUM_REPORT_BAD",
|
||||
# "data": { "node-name": "node0", "sector-num": 0, "sectors-count": 2097120,
|
||||
# "type": "flush", "error": "Broken pipe" },
|
||||
# "timestamp": { "seconds": 1456406829, "microseconds": 291763 } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'QUORUM_REPORT_BAD',
|
||||
'data': { 'type': 'QuorumOpType', '*error': 'str', 'node-name': 'str',
|
||||
'sector-num': 'int', 'sectors-count': 'int' } }
|
||||
|
||||
##
|
||||
# @VSERPORT_CHANGE:
|
||||
#
|
||||
# Emitted when the guest opens or closes a virtio-serial port.
|
||||
#
|
||||
# @id: device identifier of the virtio-serial port
|
||||
#
|
||||
# @open: true if the guest has opened the virtio-serial port
|
||||
#
|
||||
# Since: 2.1
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "VSERPORT_CHANGE",
|
||||
# "data": { "id": "channel0", "open": true },
|
||||
# "timestamp": { "seconds": 1401385907, "microseconds": 422329 } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'VSERPORT_CHANGE',
|
||||
'data': { 'id': 'str', 'open': 'bool' } }
|
||||
|
||||
##
|
||||
# @MEM_UNPLUG_ERROR:
|
||||
#
|
||||
# Emitted when memory hot unplug error occurs.
|
||||
#
|
||||
# @device: device name
|
||||
#
|
||||
# @msg: Informative message
|
||||
#
|
||||
# Since: 2.4
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "MEM_UNPLUG_ERROR"
|
||||
# "data": { "device": "dimm1",
|
||||
# "msg": "acpi: device unplug for unsupported device"
|
||||
# },
|
||||
# "timestamp": { "seconds": 1265044230, "microseconds": 450486 } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'MEM_UNPLUG_ERROR',
|
||||
'data': { 'device': 'str', 'msg': 'str' } }
|
||||
|
||||
##
|
||||
# @DUMP_COMPLETED:
|
||||
#
|
||||
# Emitted when background dump has completed
|
||||
#
|
||||
# @result: DumpQueryResult type described in qapi-schema.json.
|
||||
#
|
||||
# @error: human-readable error string that provides
|
||||
# hint on why dump failed. Only presents on failure. The
|
||||
# user should not try to interpret the error string.
|
||||
#
|
||||
# Since: 2.6
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# { "event": "DUMP_COMPLETED",
|
||||
# "data": {"result": {"total": 1090650112, "status": "completed",
|
||||
# "completed": 1090650112} } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'DUMP_COMPLETED' ,
|
||||
'data': { 'result': 'DumpQueryResult', '*error': 'str' } }
|
@ -1,7 +1,5 @@
|
||||
# -*- Mode: Python -*-
|
||||
#
|
||||
# QAPI/QMP introspection
|
||||
#
|
||||
# Copyright (C) 2015 Red Hat, Inc.
|
||||
#
|
||||
# Authors:
|
||||
@ -10,6 +8,10 @@
|
||||
# This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
# See the COPYING file in the top-level directory.
|
||||
|
||||
##
|
||||
# = QMP introspection
|
||||
##
|
||||
|
||||
##
|
||||
# @query-qmp-schema:
|
||||
#
|
||||
|
1085
qapi/migration.json
Normal file
1085
qapi/migration.json
Normal file
File diff suppressed because it is too large
Load Diff
706
qapi/net.json
Normal file
706
qapi/net.json
Normal file
@ -0,0 +1,706 @@
|
||||
# -*- Mode: Python -*-
|
||||
#
|
||||
|
||||
##
|
||||
# = Net devices
|
||||
##
|
||||
|
||||
{ 'include': 'common.json' }
|
||||
|
||||
##
|
||||
# @set_link:
|
||||
#
|
||||
# Sets the link status of a virtual network adapter.
|
||||
#
|
||||
# @name: the device name of the virtual network adapter
|
||||
#
|
||||
# @up: true to set the link status to be up
|
||||
#
|
||||
# Returns: Nothing on success
|
||||
# If @name is not a valid network device, DeviceNotFound
|
||||
#
|
||||
# Since: 0.14.0
|
||||
#
|
||||
# Notes: Not all network adapters support setting link status. This command
|
||||
# will succeed even if the network adapter does not support link status
|
||||
# notification.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# -> { "execute": "set_link",
|
||||
# "arguments": { "name": "e1000.0", "up": false } }
|
||||
# <- { "return": {} }
|
||||
#
|
||||
##
|
||||
{ 'command': 'set_link', 'data': {'name': 'str', 'up': 'bool'} }
|
||||
|
||||
##
|
||||
# @netdev_add:
|
||||
#
|
||||
# Add a network backend.
|
||||
#
|
||||
# @type: the type of network backend. Current valid values are 'user', 'tap',
|
||||
# 'vde', 'socket', 'dump' and 'bridge'
|
||||
#
|
||||
# @id: the name of the new network backend
|
||||
#
|
||||
# Additional arguments depend on the type.
|
||||
#
|
||||
# TODO: This command effectively bypasses QAPI completely due to its
|
||||
# "additional arguments" business. It shouldn't have been added to
|
||||
# the schema in this form. It should be qapified properly, or
|
||||
# replaced by a properly qapified command.
|
||||
#
|
||||
# Since: 0.14.0
|
||||
#
|
||||
# Returns: Nothing on success
|
||||
# If @type is not a valid network backend, DeviceNotFound
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# -> { "execute": "netdev_add",
|
||||
# "arguments": { "type": "user", "id": "netdev1",
|
||||
# "dnssearch": "example.org" } }
|
||||
# <- { "return": {} }
|
||||
#
|
||||
##
|
||||
{ 'command': 'netdev_add',
|
||||
'data': {'type': 'str', 'id': 'str'},
|
||||
'gen': false } # so we can get the additional arguments
|
||||
|
||||
##
|
||||
# @netdev_del:
|
||||
#
|
||||
# Remove a network backend.
|
||||
#
|
||||
# @id: the name of the network backend to remove
|
||||
#
|
||||
# Returns: Nothing on success
|
||||
# If @id is not a valid network backend, DeviceNotFound
|
||||
#
|
||||
# Since: 0.14.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# -> { "execute": "netdev_del", "arguments": { "id": "netdev1" } }
|
||||
# <- { "return": {} }
|
||||
#
|
||||
##
|
||||
{ 'command': 'netdev_del', 'data': {'id': 'str'} }
|
||||
|
||||
##
|
||||
# @NetdevNoneOptions:
|
||||
#
|
||||
# Use it alone to have zero network devices.
|
||||
#
|
||||
# Since: 1.2
|
||||
##
|
||||
{ 'struct': 'NetdevNoneOptions',
|
||||
'data': { } }
|
||||
|
||||
##
|
||||
# @NetLegacyNicOptions:
|
||||
#
|
||||
# Create a new Network Interface Card.
|
||||
#
|
||||
# @netdev: id of -netdev to connect to
|
||||
#
|
||||
# @macaddr: MAC address
|
||||
#
|
||||
# @model: device model (e1000, rtl8139, virtio etc.)
|
||||
#
|
||||
# @addr: PCI device address
|
||||
#
|
||||
# @vectors: number of MSI-x vectors, 0 to disable MSI-X
|
||||
#
|
||||
# Since: 1.2
|
||||
##
|
||||
{ 'struct': 'NetLegacyNicOptions',
|
||||
'data': {
|
||||
'*netdev': 'str',
|
||||
'*macaddr': 'str',
|
||||
'*model': 'str',
|
||||
'*addr': 'str',
|
||||
'*vectors': 'uint32' } }
|
||||
|
||||
##
|
||||
# @NetdevUserOptions:
|
||||
#
|
||||
# Use the user mode network stack which requires no administrator privilege to
|
||||
# run.
|
||||
#
|
||||
# @hostname: client hostname reported by the builtin DHCP server
|
||||
#
|
||||
# @restrict: isolate the guest from the host
|
||||
#
|
||||
# @ipv4: whether to support IPv4, default true for enabled
|
||||
# (since 2.6)
|
||||
#
|
||||
# @ipv6: whether to support IPv6, default true for enabled
|
||||
# (since 2.6)
|
||||
#
|
||||
# @ip: legacy parameter, use net= instead
|
||||
#
|
||||
# @net: IP network address that the guest will see, in the
|
||||
# form addr[/netmask] The netmask is optional, and can be
|
||||
# either in the form a.b.c.d or as a number of valid top-most
|
||||
# bits. Default is 10.0.2.0/24.
|
||||
#
|
||||
# @host: guest-visible address of the host
|
||||
#
|
||||
# @tftp: root directory of the built-in TFTP server
|
||||
#
|
||||
# @bootfile: BOOTP filename, for use with tftp=
|
||||
#
|
||||
# @dhcpstart: the first of the 16 IPs the built-in DHCP server can
|
||||
# assign
|
||||
#
|
||||
# @dns: guest-visible address of the virtual nameserver
|
||||
#
|
||||
# @dnssearch: list of DNS suffixes to search, passed as DHCP option
|
||||
# to the guest
|
||||
#
|
||||
# @ipv6-prefix: IPv6 network prefix (default is fec0::) (since
|
||||
# 2.6). The network prefix is given in the usual
|
||||
# hexadecimal IPv6 address notation.
|
||||
#
|
||||
# @ipv6-prefixlen: IPv6 network prefix length (default is 64)
|
||||
# (since 2.6)
|
||||
#
|
||||
# @ipv6-host: guest-visible IPv6 address of the host (since 2.6)
|
||||
#
|
||||
# @ipv6-dns: guest-visible IPv6 address of the virtual
|
||||
# nameserver (since 2.6)
|
||||
#
|
||||
# @smb: root directory of the built-in SMB server
|
||||
#
|
||||
# @smbserver: IP address of the built-in SMB server
|
||||
#
|
||||
# @hostfwd: redirect incoming TCP or UDP host connections to guest
|
||||
# endpoints
|
||||
#
|
||||
# @guestfwd: forward guest TCP connections
|
||||
#
|
||||
# Since: 1.2
|
||||
##
|
||||
{ 'struct': 'NetdevUserOptions',
|
||||
'data': {
|
||||
'*hostname': 'str',
|
||||
'*restrict': 'bool',
|
||||
'*ipv4': 'bool',
|
||||
'*ipv6': 'bool',
|
||||
'*ip': 'str',
|
||||
'*net': 'str',
|
||||
'*host': 'str',
|
||||
'*tftp': 'str',
|
||||
'*bootfile': 'str',
|
||||
'*dhcpstart': 'str',
|
||||
'*dns': 'str',
|
||||
'*dnssearch': ['String'],
|
||||
'*ipv6-prefix': 'str',
|
||||
'*ipv6-prefixlen': 'int',
|
||||
'*ipv6-host': 'str',
|
||||
'*ipv6-dns': 'str',
|
||||
'*smb': 'str',
|
||||
'*smbserver': 'str',
|
||||
'*hostfwd': ['String'],
|
||||
'*guestfwd': ['String'] } }
|
||||
|
||||
##
|
||||
# @NetdevTapOptions:
|
||||
#
|
||||
# Connect the host TAP network interface name to the VLAN.
|
||||
#
|
||||
# @ifname: interface name
|
||||
#
|
||||
# @fd: file descriptor of an already opened tap
|
||||
#
|
||||
# @fds: multiple file descriptors of already opened multiqueue capable
|
||||
# tap
|
||||
#
|
||||
# @script: script to initialize the interface
|
||||
#
|
||||
# @downscript: script to shut down the interface
|
||||
#
|
||||
# @br: bridge name (since 2.8)
|
||||
#
|
||||
# @helper: command to execute to configure bridge
|
||||
#
|
||||
# @sndbuf: send buffer limit. Understands [TGMKkb] suffixes.
|
||||
#
|
||||
# @vnet_hdr: enable the IFF_VNET_HDR flag on the tap interface
|
||||
#
|
||||
# @vhost: enable vhost-net network accelerator
|
||||
#
|
||||
# @vhostfd: file descriptor of an already opened vhost net device
|
||||
#
|
||||
# @vhostfds: file descriptors of multiple already opened vhost net
|
||||
# devices
|
||||
#
|
||||
# @vhostforce: vhost on for non-MSIX virtio guests
|
||||
#
|
||||
# @queues: number of queues to be created for multiqueue capable tap
|
||||
#
|
||||
# @poll-us: maximum number of microseconds that could
|
||||
# be spent on busy polling for tap (since 2.7)
|
||||
#
|
||||
# Since: 1.2
|
||||
##
|
||||
{ 'struct': 'NetdevTapOptions',
|
||||
'data': {
|
||||
'*ifname': 'str',
|
||||
'*fd': 'str',
|
||||
'*fds': 'str',
|
||||
'*script': 'str',
|
||||
'*downscript': 'str',
|
||||
'*br': 'str',
|
||||
'*helper': 'str',
|
||||
'*sndbuf': 'size',
|
||||
'*vnet_hdr': 'bool',
|
||||
'*vhost': 'bool',
|
||||
'*vhostfd': 'str',
|
||||
'*vhostfds': 'str',
|
||||
'*vhostforce': 'bool',
|
||||
'*queues': 'uint32',
|
||||
'*poll-us': 'uint32'} }
|
||||
|
||||
##
|
||||
# @NetdevSocketOptions:
|
||||
#
|
||||
# Connect the VLAN to a remote VLAN in another QEMU virtual machine using a TCP
|
||||
# socket connection.
|
||||
#
|
||||
# @fd: file descriptor of an already opened socket
|
||||
#
|
||||
# @listen: port number, and optional hostname, to listen on
|
||||
#
|
||||
# @connect: port number, and optional hostname, to connect to
|
||||
#
|
||||
# @mcast: UDP multicast address and port number
|
||||
#
|
||||
# @localaddr: source address and port for multicast and udp packets
|
||||
#
|
||||
# @udp: UDP unicast address and port number
|
||||
#
|
||||
# Since: 1.2
|
||||
##
|
||||
{ 'struct': 'NetdevSocketOptions',
|
||||
'data': {
|
||||
'*fd': 'str',
|
||||
'*listen': 'str',
|
||||
'*connect': 'str',
|
||||
'*mcast': 'str',
|
||||
'*localaddr': 'str',
|
||||
'*udp': 'str' } }
|
||||
|
||||
##
|
||||
# @NetdevL2TPv3Options:
|
||||
#
|
||||
# Connect the VLAN to Ethernet over L2TPv3 Static tunnel
|
||||
#
|
||||
# @src: source address
|
||||
#
|
||||
# @dst: destination address
|
||||
#
|
||||
# @srcport: source port - mandatory for udp, optional for ip
|
||||
#
|
||||
# @dstport: destination port - mandatory for udp, optional for ip
|
||||
#
|
||||
# @ipv6: force the use of ipv6
|
||||
#
|
||||
# @udp: use the udp version of l2tpv3 encapsulation
|
||||
#
|
||||
# @cookie64: use 64 bit coookies
|
||||
#
|
||||
# @counter: have sequence counter
|
||||
#
|
||||
# @pincounter: pin sequence counter to zero -
|
||||
# workaround for buggy implementations or
|
||||
# networks with packet reorder
|
||||
#
|
||||
# @txcookie: 32 or 64 bit transmit cookie
|
||||
#
|
||||
# @rxcookie: 32 or 64 bit receive cookie
|
||||
#
|
||||
# @txsession: 32 bit transmit session
|
||||
#
|
||||
# @rxsession: 32 bit receive session - if not specified
|
||||
# set to the same value as transmit
|
||||
#
|
||||
# @offset: additional offset - allows the insertion of
|
||||
# additional application-specific data before the packet payload
|
||||
#
|
||||
# Since: 2.1
|
||||
##
|
||||
{ 'struct': 'NetdevL2TPv3Options',
|
||||
'data': {
|
||||
'src': 'str',
|
||||
'dst': 'str',
|
||||
'*srcport': 'str',
|
||||
'*dstport': 'str',
|
||||
'*ipv6': 'bool',
|
||||
'*udp': 'bool',
|
||||
'*cookie64': 'bool',
|
||||
'*counter': 'bool',
|
||||
'*pincounter': 'bool',
|
||||
'*txcookie': 'uint64',
|
||||
'*rxcookie': 'uint64',
|
||||
'txsession': 'uint32',
|
||||
'*rxsession': 'uint32',
|
||||
'*offset': 'uint32' } }
|
||||
|
||||
##
|
||||
# @NetdevVdeOptions:
|
||||
#
|
||||
# Connect the VLAN to a vde switch running on the host.
|
||||
#
|
||||
# @sock: socket path
|
||||
#
|
||||
# @port: port number
|
||||
#
|
||||
# @group: group owner of socket
|
||||
#
|
||||
# @mode: permissions for socket
|
||||
#
|
||||
# Since: 1.2
|
||||
##
|
||||
{ 'struct': 'NetdevVdeOptions',
|
||||
'data': {
|
||||
'*sock': 'str',
|
||||
'*port': 'uint16',
|
||||
'*group': 'str',
|
||||
'*mode': 'uint16' } }
|
||||
|
||||
##
|
||||
# @NetdevDumpOptions:
|
||||
#
|
||||
# Dump VLAN network traffic to a file.
|
||||
#
|
||||
# @len: per-packet size limit (64k default). Understands [TGMKkb]
|
||||
# suffixes.
|
||||
#
|
||||
# @file: dump file path (default is qemu-vlan0.pcap)
|
||||
#
|
||||
# Since: 1.2
|
||||
##
|
||||
{ 'struct': 'NetdevDumpOptions',
|
||||
'data': {
|
||||
'*len': 'size',
|
||||
'*file': 'str' } }
|
||||
|
||||
##
|
||||
# @NetdevBridgeOptions:
|
||||
#
|
||||
# Connect a host TAP network interface to a host bridge device.
|
||||
#
|
||||
# @br: bridge name
|
||||
#
|
||||
# @helper: command to execute to configure bridge
|
||||
#
|
||||
# Since: 1.2
|
||||
##
|
||||
{ 'struct': 'NetdevBridgeOptions',
|
||||
'data': {
|
||||
'*br': 'str',
|
||||
'*helper': 'str' } }
|
||||
|
||||
##
|
||||
# @NetdevHubPortOptions:
|
||||
#
|
||||
# Connect two or more net clients through a software hub.
|
||||
#
|
||||
# @hubid: hub identifier number
|
||||
#
|
||||
# Since: 1.2
|
||||
##
|
||||
{ 'struct': 'NetdevHubPortOptions',
|
||||
'data': {
|
||||
'hubid': 'int32' } }
|
||||
|
||||
##
|
||||
# @NetdevNetmapOptions:
|
||||
#
|
||||
# Connect a client to a netmap-enabled NIC or to a VALE switch port
|
||||
#
|
||||
# @ifname: Either the name of an existing network interface supported by
|
||||
# netmap, or the name of a VALE port (created on the fly).
|
||||
# A VALE port name is in the form 'valeXXX:YYY', where XXX and
|
||||
# YYY are non-negative integers. XXX identifies a switch and
|
||||
# YYY identifies a port of the switch. VALE ports having the
|
||||
# same XXX are therefore connected to the same switch.
|
||||
#
|
||||
# @devname: path of the netmap device (default: '/dev/netmap').
|
||||
#
|
||||
# Since: 2.0
|
||||
##
|
||||
{ 'struct': 'NetdevNetmapOptions',
|
||||
'data': {
|
||||
'ifname': 'str',
|
||||
'*devname': 'str' } }
|
||||
|
||||
##
|
||||
# @NetdevVhostUserOptions:
|
||||
#
|
||||
# Vhost-user network backend
|
||||
#
|
||||
# @chardev: name of a unix socket chardev
|
||||
#
|
||||
# @vhostforce: vhost on for non-MSIX virtio guests (default: false).
|
||||
#
|
||||
# @queues: number of queues to be created for multiqueue vhost-user
|
||||
# (default: 1) (Since 2.5)
|
||||
#
|
||||
# Since: 2.1
|
||||
##
|
||||
{ 'struct': 'NetdevVhostUserOptions',
|
||||
'data': {
|
||||
'chardev': 'str',
|
||||
'*vhostforce': 'bool',
|
||||
'*queues': 'int' } }
|
||||
|
||||
##
|
||||
# @NetClientDriver:
|
||||
#
|
||||
# Available netdev drivers.
|
||||
#
|
||||
# Since: 2.7
|
||||
##
|
||||
{ 'enum': 'NetClientDriver',
|
||||
'data': [ 'none', 'nic', 'user', 'tap', 'l2tpv3', 'socket', 'vde', 'dump',
|
||||
'bridge', 'hubport', 'netmap', 'vhost-user' ] }
|
||||
|
||||
##
|
||||
# @Netdev:
|
||||
#
|
||||
# Captures the configuration of a network device.
|
||||
#
|
||||
# @id: identifier for monitor commands.
|
||||
#
|
||||
# @type: Specify the driver used for interpreting remaining arguments.
|
||||
#
|
||||
# Since: 1.2
|
||||
#
|
||||
# 'l2tpv3' - since 2.1
|
||||
##
|
||||
{ 'union': 'Netdev',
|
||||
'base': { 'id': 'str', 'type': 'NetClientDriver' },
|
||||
'discriminator': 'type',
|
||||
'data': {
|
||||
'none': 'NetdevNoneOptions',
|
||||
'nic': 'NetLegacyNicOptions',
|
||||
'user': 'NetdevUserOptions',
|
||||
'tap': 'NetdevTapOptions',
|
||||
'l2tpv3': 'NetdevL2TPv3Options',
|
||||
'socket': 'NetdevSocketOptions',
|
||||
'vde': 'NetdevVdeOptions',
|
||||
'dump': 'NetdevDumpOptions',
|
||||
'bridge': 'NetdevBridgeOptions',
|
||||
'hubport': 'NetdevHubPortOptions',
|
||||
'netmap': 'NetdevNetmapOptions',
|
||||
'vhost-user': 'NetdevVhostUserOptions' } }
|
||||
|
||||
##
|
||||
# @NetLegacy:
|
||||
#
|
||||
# Captures the configuration of a network device; legacy.
|
||||
#
|
||||
# @vlan: vlan number
|
||||
#
|
||||
# @id: identifier for monitor commands
|
||||
#
|
||||
# @name: identifier for monitor commands, ignored if @id is present
|
||||
#
|
||||
# @opts: device type specific properties (legacy)
|
||||
#
|
||||
# Since: 1.2
|
||||
##
|
||||
{ 'struct': 'NetLegacy',
|
||||
'data': {
|
||||
'*vlan': 'int32',
|
||||
'*id': 'str',
|
||||
'*name': 'str',
|
||||
'opts': 'NetLegacyOptions' } }
|
||||
|
||||
##
|
||||
# @NetLegacyOptionsType:
|
||||
#
|
||||
# Since: 1.2
|
||||
##
|
||||
{ 'enum': 'NetLegacyOptionsType',
|
||||
'data': ['none', 'nic', 'user', 'tap', 'l2tpv3', 'socket', 'vde',
|
||||
'dump', 'bridge', 'netmap', 'vhost-user'] }
|
||||
|
||||
##
|
||||
# @NetLegacyOptions:
|
||||
#
|
||||
# Like Netdev, but for use only by the legacy command line options
|
||||
#
|
||||
# Since: 1.2
|
||||
##
|
||||
{ 'union': 'NetLegacyOptions',
|
||||
'base': { 'type': 'NetLegacyOptionsType' },
|
||||
'discriminator': 'type',
|
||||
'data': {
|
||||
'none': 'NetdevNoneOptions',
|
||||
'nic': 'NetLegacyNicOptions',
|
||||
'user': 'NetdevUserOptions',
|
||||
'tap': 'NetdevTapOptions',
|
||||
'l2tpv3': 'NetdevL2TPv3Options',
|
||||
'socket': 'NetdevSocketOptions',
|
||||
'vde': 'NetdevVdeOptions',
|
||||
'dump': 'NetdevDumpOptions',
|
||||
'bridge': 'NetdevBridgeOptions',
|
||||
'netmap': 'NetdevNetmapOptions',
|
||||
'vhost-user': 'NetdevVhostUserOptions' } }
|
||||
|
||||
##
|
||||
# @NetFilterDirection:
|
||||
#
|
||||
# Indicates whether a netfilter is attached to a netdev's transmit queue or
|
||||
# receive queue or both.
|
||||
#
|
||||
# @all: the filter is attached both to the receive and the transmit
|
||||
# queue of the netdev (default).
|
||||
#
|
||||
# @rx: the filter is attached to the receive queue of the netdev,
|
||||
# where it will receive packets sent to the netdev.
|
||||
#
|
||||
# @tx: the filter is attached to the transmit queue of the netdev,
|
||||
# where it will receive packets sent by the netdev.
|
||||
#
|
||||
# Since: 2.5
|
||||
##
|
||||
{ 'enum': 'NetFilterDirection',
|
||||
'data': [ 'all', 'rx', 'tx' ] }
|
||||
|
||||
##
|
||||
# @RxState:
|
||||
#
|
||||
# Packets receiving state
|
||||
#
|
||||
# @normal: filter assigned packets according to the mac-table
|
||||
#
|
||||
# @none: don't receive any assigned packet
|
||||
#
|
||||
# @all: receive all assigned packets
|
||||
#
|
||||
# Since: 1.6
|
||||
##
|
||||
{ 'enum': 'RxState', 'data': [ 'normal', 'none', 'all' ] }
|
||||
|
||||
##
|
||||
# @RxFilterInfo:
|
||||
#
|
||||
# Rx-filter information for a NIC.
|
||||
#
|
||||
# @name: net client name
|
||||
#
|
||||
# @promiscuous: whether promiscuous mode is enabled
|
||||
#
|
||||
# @multicast: multicast receive state
|
||||
#
|
||||
# @unicast: unicast receive state
|
||||
#
|
||||
# @vlan: vlan receive state (Since 2.0)
|
||||
#
|
||||
# @broadcast-allowed: whether to receive broadcast
|
||||
#
|
||||
# @multicast-overflow: multicast table is overflowed or not
|
||||
#
|
||||
# @unicast-overflow: unicast table is overflowed or not
|
||||
#
|
||||
# @main-mac: the main macaddr string
|
||||
#
|
||||
# @vlan-table: a list of active vlan id
|
||||
#
|
||||
# @unicast-table: a list of unicast macaddr string
|
||||
#
|
||||
# @multicast-table: a list of multicast macaddr string
|
||||
#
|
||||
# Since: 1.6
|
||||
##
|
||||
{ 'struct': 'RxFilterInfo',
|
||||
'data': {
|
||||
'name': 'str',
|
||||
'promiscuous': 'bool',
|
||||
'multicast': 'RxState',
|
||||
'unicast': 'RxState',
|
||||
'vlan': 'RxState',
|
||||
'broadcast-allowed': 'bool',
|
||||
'multicast-overflow': 'bool',
|
||||
'unicast-overflow': 'bool',
|
||||
'main-mac': 'str',
|
||||
'vlan-table': ['int'],
|
||||
'unicast-table': ['str'],
|
||||
'multicast-table': ['str'] }}
|
||||
|
||||
##
|
||||
# @query-rx-filter:
|
||||
#
|
||||
# Return rx-filter information for all NICs (or for the given NIC).
|
||||
#
|
||||
# @name: net client name
|
||||
#
|
||||
# Returns: list of @RxFilterInfo for all NICs (or for the given NIC).
|
||||
# Returns an error if the given @name doesn't exist, or given
|
||||
# NIC doesn't support rx-filter querying, or given net client
|
||||
# isn't a NIC.
|
||||
#
|
||||
# Since: 1.6
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# -> { "execute": "query-rx-filter", "arguments": { "name": "vnet0" } }
|
||||
# <- { "return": [
|
||||
# {
|
||||
# "promiscuous": true,
|
||||
# "name": "vnet0",
|
||||
# "main-mac": "52:54:00:12:34:56",
|
||||
# "unicast": "normal",
|
||||
# "vlan": "normal",
|
||||
# "vlan-table": [
|
||||
# 4,
|
||||
# 0
|
||||
# ],
|
||||
# "unicast-table": [
|
||||
# ],
|
||||
# "multicast": "normal",
|
||||
# "multicast-overflow": false,
|
||||
# "unicast-overflow": false,
|
||||
# "multicast-table": [
|
||||
# "01:00:5e:00:00:01",
|
||||
# "33:33:00:00:00:01",
|
||||
# "33:33:ff:12:34:56"
|
||||
# ],
|
||||
# "broadcast-allowed": false
|
||||
# }
|
||||
# ]
|
||||
# }
|
||||
#
|
||||
##
|
||||
{ 'command': 'query-rx-filter', 'data': { '*name': 'str' },
|
||||
'returns': ['RxFilterInfo'] }
|
||||
|
||||
##
|
||||
# @NIC_RX_FILTER_CHANGED:
|
||||
#
|
||||
# Emitted once until the 'query-rx-filter' command is executed, the first event
|
||||
# will always be emitted
|
||||
#
|
||||
# @name: net client name
|
||||
#
|
||||
# @path: device path
|
||||
#
|
||||
# Since: 1.6
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "NIC_RX_FILTER_CHANGED",
|
||||
# "data": { "name": "vnet0",
|
||||
# "path": "/machine/peripheral/vnet0/virtio-backend" },
|
||||
# "timestamp": { "seconds": 1368697518, "microseconds": 326866 } }
|
||||
# }
|
||||
#
|
||||
##
|
||||
{ 'event': 'NIC_RX_FILTER_CHANGED',
|
||||
'data': { '*name': 'str', 'path': 'str' } }
|
@ -13,10 +13,16 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qapi/util.h"
|
||||
|
||||
int qapi_enum_parse(const char * const lookup[], const char *buf,
|
||||
int max, int def, Error **errp)
|
||||
const char *qapi_enum_lookup(const QEnumLookup *lookup, int val)
|
||||
{
|
||||
assert(val >= 0 && val < lookup->size);
|
||||
|
||||
return lookup->array[val];
|
||||
}
|
||||
|
||||
int qapi_enum_parse(const QEnumLookup *lookup, const char *buf,
|
||||
int def, Error **errp)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -24,8 +30,8 @@ int qapi_enum_parse(const char * const lookup[], const char *buf,
|
||||
return def;
|
||||
}
|
||||
|
||||
for (i = 0; i < max; i++) {
|
||||
if (!strcmp(buf, lookup[i])) {
|
||||
for (i = 0; i < lookup->size; i++) {
|
||||
if (!strcmp(buf, lookup->array[i])) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
@ -333,27 +333,29 @@ void visit_type_null(Visitor *v, const char *name, QNull **obj,
|
||||
}
|
||||
|
||||
static void output_type_enum(Visitor *v, const char *name, int *obj,
|
||||
const char *const strings[], Error **errp)
|
||||
const QEnumLookup *lookup, Error **errp)
|
||||
{
|
||||
int i = 0;
|
||||
int value = *obj;
|
||||
char *enum_str;
|
||||
|
||||
while (strings[i++] != NULL);
|
||||
if (value < 0 || value >= i - 1) {
|
||||
/*
|
||||
* TODO why is this an error, not an assertion? If assertion:
|
||||
* delete, and rely on qapi_enum_lookup()
|
||||
*/
|
||||
if (value < 0 || value >= lookup->size) {
|
||||
error_setg(errp, QERR_INVALID_PARAMETER, name ? name : "null");
|
||||
return;
|
||||
}
|
||||
|
||||
enum_str = (char *)strings[value];
|
||||
enum_str = (char *)qapi_enum_lookup(lookup, value);
|
||||
visit_type_str(v, name, &enum_str, errp);
|
||||
}
|
||||
|
||||
static void input_type_enum(Visitor *v, const char *name, int *obj,
|
||||
const char *const strings[], Error **errp)
|
||||
const QEnumLookup *lookup, Error **errp)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
int64_t value = 0;
|
||||
int64_t value;
|
||||
char *enum_str;
|
||||
|
||||
visit_type_str(v, name, &enum_str, &local_err);
|
||||
@ -362,14 +364,8 @@ static void input_type_enum(Visitor *v, const char *name, int *obj,
|
||||
return;
|
||||
}
|
||||
|
||||
while (strings[value] != NULL) {
|
||||
if (strcmp(strings[value], enum_str) == 0) {
|
||||
break;
|
||||
}
|
||||
value++;
|
||||
}
|
||||
|
||||
if (strings[value] == NULL) {
|
||||
value = qapi_enum_parse(lookup, enum_str, -1, NULL);
|
||||
if (value < 0) {
|
||||
error_setg(errp, QERR_INVALID_PARAMETER, enum_str);
|
||||
g_free(enum_str);
|
||||
return;
|
||||
@ -380,16 +376,16 @@ static void input_type_enum(Visitor *v, const char *name, int *obj,
|
||||
}
|
||||
|
||||
void visit_type_enum(Visitor *v, const char *name, int *obj,
|
||||
const char *const strings[], Error **errp)
|
||||
const QEnumLookup *lookup, Error **errp)
|
||||
{
|
||||
assert(obj && strings);
|
||||
assert(obj && lookup);
|
||||
trace_visit_type_enum(v, name, obj);
|
||||
switch (v->type) {
|
||||
case VISITOR_INPUT:
|
||||
input_type_enum(v, name, obj, strings, errp);
|
||||
input_type_enum(v, name, obj, lookup, errp);
|
||||
break;
|
||||
case VISITOR_OUTPUT:
|
||||
output_type_enum(v, name, obj, strings, errp);
|
||||
output_type_enum(v, name, obj, lookup, errp);
|
||||
break;
|
||||
case VISITOR_CLONE:
|
||||
/* nothing further to do, scalar value was already copied by
|
||||
|
@ -118,7 +118,7 @@ static QObject *do_qmp_dispatch(QmpCommandList *cmds, QObject *request,
|
||||
QObject *qmp_build_error_object(Error *err)
|
||||
{
|
||||
return qobject_from_jsonf("{ 'class': %s, 'desc': %s }",
|
||||
QapiErrorClass_lookup[error_get_class(err)],
|
||||
QapiErrorClass_str(error_get_class(err)),
|
||||
error_get_pretty(err));
|
||||
}
|
||||
|
||||
|
352
qapi/run-state.json
Normal file
352
qapi/run-state.json
Normal file
@ -0,0 +1,352 @@
|
||||
# -*- Mode: Python -*-
|
||||
#
|
||||
|
||||
##
|
||||
# = VM run state
|
||||
##
|
||||
|
||||
##
|
||||
# @RunState:
|
||||
#
|
||||
# An enumeration of VM run states.
|
||||
#
|
||||
# @debug: QEMU is running on a debugger
|
||||
#
|
||||
# @finish-migrate: guest is paused to finish the migration process
|
||||
#
|
||||
# @inmigrate: guest is paused waiting for an incoming migration. Note
|
||||
# that this state does not tell whether the machine will start at the
|
||||
# end of the migration. This depends on the command-line -S option and
|
||||
# any invocation of 'stop' or 'cont' that has happened since QEMU was
|
||||
# started.
|
||||
#
|
||||
# @internal-error: An internal error that prevents further guest execution
|
||||
# has occurred
|
||||
#
|
||||
# @io-error: the last IOP has failed and the device is configured to pause
|
||||
# on I/O errors
|
||||
#
|
||||
# @paused: guest has been paused via the 'stop' command
|
||||
#
|
||||
# @postmigrate: guest is paused following a successful 'migrate'
|
||||
#
|
||||
# @prelaunch: QEMU was started with -S and guest has not started
|
||||
#
|
||||
# @restore-vm: guest is paused to restore VM state
|
||||
#
|
||||
# @running: guest is actively running
|
||||
#
|
||||
# @save-vm: guest is paused to save the VM state
|
||||
#
|
||||
# @shutdown: guest is shut down (and -no-shutdown is in use)
|
||||
#
|
||||
# @suspended: guest is suspended (ACPI S3)
|
||||
#
|
||||
# @watchdog: the watchdog action is configured to pause and has been triggered
|
||||
#
|
||||
# @guest-panicked: guest has been panicked as a result of guest OS panic
|
||||
#
|
||||
# @colo: guest is paused to save/restore VM state under colo checkpoint,
|
||||
# VM can not get into this state unless colo capability is enabled
|
||||
# for migration. (since 2.8)
|
||||
##
|
||||
{ 'enum': 'RunState',
|
||||
'data': [ 'debug', 'inmigrate', 'internal-error', 'io-error', 'paused',
|
||||
'postmigrate', 'prelaunch', 'finish-migrate', 'restore-vm',
|
||||
'running', 'save-vm', 'shutdown', 'suspended', 'watchdog',
|
||||
'guest-panicked', 'colo' ] }
|
||||
|
||||
##
|
||||
# @StatusInfo:
|
||||
#
|
||||
# Information about VCPU run state
|
||||
#
|
||||
# @running: true if all VCPUs are runnable, false if not runnable
|
||||
#
|
||||
# @singlestep: true if VCPUs are in single-step mode
|
||||
#
|
||||
# @status: the virtual machine @RunState
|
||||
#
|
||||
# Since: 0.14.0
|
||||
#
|
||||
# Notes: @singlestep is enabled through the GDB stub
|
||||
##
|
||||
{ 'struct': 'StatusInfo',
|
||||
'data': {'running': 'bool', 'singlestep': 'bool', 'status': 'RunState'} }
|
||||
|
||||
##
|
||||
# @query-status:
|
||||
#
|
||||
# Query the run status of all VCPUs
|
||||
#
|
||||
# Returns: @StatusInfo reflecting all VCPUs
|
||||
#
|
||||
# Since: 0.14.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# -> { "execute": "query-status" }
|
||||
# <- { "return": { "running": true,
|
||||
# "singlestep": false,
|
||||
# "status": "running" } }
|
||||
#
|
||||
##
|
||||
{ 'command': 'query-status', 'returns': 'StatusInfo' }
|
||||
|
||||
##
|
||||
# @SHUTDOWN:
|
||||
#
|
||||
# Emitted when the virtual machine has shut down, indicating that qemu is
|
||||
# about to exit.
|
||||
#
|
||||
# @guest: If true, the shutdown was triggered by a guest request (such as
|
||||
# a guest-initiated ACPI shutdown request or other hardware-specific action)
|
||||
# rather than a host request (such as sending qemu a SIGINT). (since 2.10)
|
||||
#
|
||||
# Note: If the command-line option "-no-shutdown" has been specified, qemu will
|
||||
# not exit, and a STOP event will eventually follow the SHUTDOWN event
|
||||
#
|
||||
# Since: 0.12.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "SHUTDOWN", "data": { "guest": true },
|
||||
# "timestamp": { "seconds": 1267040730, "microseconds": 682951 } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'SHUTDOWN', 'data': { 'guest': 'bool' } }
|
||||
|
||||
##
|
||||
# @POWERDOWN:
|
||||
#
|
||||
# Emitted when the virtual machine is powered down through the power control
|
||||
# system, such as via ACPI.
|
||||
#
|
||||
# Since: 0.12.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "POWERDOWN",
|
||||
# "timestamp": { "seconds": 1267040730, "microseconds": 682951 } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'POWERDOWN' }
|
||||
|
||||
##
|
||||
# @RESET:
|
||||
#
|
||||
# Emitted when the virtual machine is reset
|
||||
#
|
||||
# @guest: If true, the reset was triggered by a guest request (such as
|
||||
# a guest-initiated ACPI reboot request or other hardware-specific action)
|
||||
# rather than a host request (such as the QMP command system_reset).
|
||||
# (since 2.10)
|
||||
#
|
||||
# Since: 0.12.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "RESET", "data": { "guest": false },
|
||||
# "timestamp": { "seconds": 1267041653, "microseconds": 9518 } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'RESET', 'data': { 'guest': 'bool' } }
|
||||
|
||||
##
|
||||
# @STOP:
|
||||
#
|
||||
# Emitted when the virtual machine is stopped
|
||||
#
|
||||
# Since: 0.12.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "STOP",
|
||||
# "timestamp": { "seconds": 1267041730, "microseconds": 281295 } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'STOP' }
|
||||
|
||||
##
|
||||
# @RESUME:
|
||||
#
|
||||
# Emitted when the virtual machine resumes execution
|
||||
#
|
||||
# Since: 0.12.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "RESUME",
|
||||
# "timestamp": { "seconds": 1271770767, "microseconds": 582542 } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'RESUME' }
|
||||
|
||||
##
|
||||
# @SUSPEND:
|
||||
#
|
||||
# Emitted when guest enters a hardware suspension state, for example, S3 state,
|
||||
# which is sometimes called standby state
|
||||
#
|
||||
# Since: 1.1
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "SUSPEND",
|
||||
# "timestamp": { "seconds": 1344456160, "microseconds": 309119 } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'SUSPEND' }
|
||||
|
||||
##
|
||||
# @SUSPEND_DISK:
|
||||
#
|
||||
# Emitted when guest enters a hardware suspension state with data saved on
|
||||
# disk, for example, S4 state, which is sometimes called hibernate state
|
||||
#
|
||||
# Note: QEMU shuts down (similar to event @SHUTDOWN) when entering this state
|
||||
#
|
||||
# Since: 1.2
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "SUSPEND_DISK",
|
||||
# "timestamp": { "seconds": 1344456160, "microseconds": 309119 } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'SUSPEND_DISK' }
|
||||
|
||||
##
|
||||
# @WAKEUP:
|
||||
#
|
||||
# Emitted when the guest has woken up from suspend state and is running
|
||||
#
|
||||
# Since: 1.1
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "WAKEUP",
|
||||
# "timestamp": { "seconds": 1344522075, "microseconds": 745528 } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'WAKEUP' }
|
||||
|
||||
##
|
||||
# @WATCHDOG:
|
||||
#
|
||||
# Emitted when the watchdog device's timer is expired
|
||||
#
|
||||
# @action: action that has been taken
|
||||
#
|
||||
# Note: If action is "reset", "shutdown", or "pause" the WATCHDOG event is
|
||||
# followed respectively by the RESET, SHUTDOWN, or STOP events
|
||||
#
|
||||
# Note: This event is rate-limited.
|
||||
#
|
||||
# Since: 0.13.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "WATCHDOG",
|
||||
# "data": { "action": "reset" },
|
||||
# "timestamp": { "seconds": 1267061043, "microseconds": 959568 } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'WATCHDOG',
|
||||
'data': { 'action': 'WatchdogExpirationAction' } }
|
||||
|
||||
##
|
||||
# @WatchdogExpirationAction:
|
||||
#
|
||||
# An enumeration of the actions taken when the watchdog device's timer is
|
||||
# expired
|
||||
#
|
||||
# @reset: system resets
|
||||
#
|
||||
# @shutdown: system shutdown, note that it is similar to @powerdown, which
|
||||
# tries to set to system status and notify guest
|
||||
#
|
||||
# @poweroff: system poweroff, the emulator program exits
|
||||
#
|
||||
# @pause: system pauses, similar to @stop
|
||||
#
|
||||
# @debug: system enters debug state
|
||||
#
|
||||
# @none: nothing is done
|
||||
#
|
||||
# @inject-nmi: a non-maskable interrupt is injected into the first VCPU (all
|
||||
# VCPUS on x86) (since 2.4)
|
||||
#
|
||||
# Since: 2.1
|
||||
##
|
||||
{ 'enum': 'WatchdogExpirationAction',
|
||||
'data': [ 'reset', 'shutdown', 'poweroff', 'pause', 'debug', 'none',
|
||||
'inject-nmi' ] }
|
||||
|
||||
##
|
||||
# @GUEST_PANICKED:
|
||||
#
|
||||
# Emitted when guest OS panic is detected
|
||||
#
|
||||
# @action: action that has been taken, currently always "pause"
|
||||
#
|
||||
# @info: information about a panic (since 2.9)
|
||||
#
|
||||
# Since: 1.5
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "GUEST_PANICKED",
|
||||
# "data": { "action": "pause" } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'GUEST_PANICKED',
|
||||
'data': { 'action': 'GuestPanicAction', '*info': 'GuestPanicInformation' } }
|
||||
|
||||
##
|
||||
# @GuestPanicAction:
|
||||
#
|
||||
# An enumeration of the actions taken when guest OS panic is detected
|
||||
#
|
||||
# @pause: system pauses
|
||||
#
|
||||
# Since: 2.1 (poweroff since 2.8)
|
||||
##
|
||||
{ 'enum': 'GuestPanicAction',
|
||||
'data': [ 'pause', 'poweroff' ] }
|
||||
|
||||
##
|
||||
# @GuestPanicInformationType:
|
||||
#
|
||||
# An enumeration of the guest panic information types
|
||||
#
|
||||
# Since: 2.9
|
||||
##
|
||||
{ 'enum': 'GuestPanicInformationType',
|
||||
'data': [ 'hyper-v'] }
|
||||
|
||||
##
|
||||
# @GuestPanicInformation:
|
||||
#
|
||||
# Information about a guest panic
|
||||
#
|
||||
# Since: 2.9
|
||||
##
|
||||
{'union': 'GuestPanicInformation',
|
||||
'base': {'type': 'GuestPanicInformationType'},
|
||||
'discriminator': 'type',
|
||||
'data': { 'hyper-v': 'GuestPanicInformationHyperV' } }
|
||||
|
||||
##
|
||||
# @GuestPanicInformationHyperV:
|
||||
#
|
||||
# Hyper-V specific guest panic information (HV crash MSRs)
|
||||
#
|
||||
# Since: 2.9
|
||||
##
|
||||
{'struct': 'GuestPanicInformationHyperV',
|
||||
'data': { 'arg1': 'uint64',
|
||||
'arg2': 'uint64',
|
||||
'arg3': 'uint64',
|
||||
'arg4': 'uint64',
|
||||
'arg5': 'uint64' } }
|
147
qapi/sockets.json
Normal file
147
qapi/sockets.json
Normal file
@ -0,0 +1,147 @@
|
||||
# -*- Mode: Python -*-
|
||||
|
||||
##
|
||||
# = Socket data types
|
||||
##
|
||||
|
||||
{ 'include': 'common.json' }
|
||||
|
||||
##
|
||||
# @NetworkAddressFamily:
|
||||
#
|
||||
# The network address family
|
||||
#
|
||||
# @ipv4: IPV4 family
|
||||
#
|
||||
# @ipv6: IPV6 family
|
||||
#
|
||||
# @unix: unix socket
|
||||
#
|
||||
# @vsock: vsock family (since 2.8)
|
||||
#
|
||||
# @unknown: otherwise
|
||||
#
|
||||
# Since: 2.1
|
||||
##
|
||||
{ 'enum': 'NetworkAddressFamily',
|
||||
'data': [ 'ipv4', 'ipv6', 'unix', 'vsock', 'unknown' ] }
|
||||
|
||||
##
|
||||
# @InetSocketAddressBase:
|
||||
#
|
||||
# @host: host part of the address
|
||||
# @port: port part of the address
|
||||
##
|
||||
{ 'struct': 'InetSocketAddressBase',
|
||||
'data': {
|
||||
'host': 'str',
|
||||
'port': 'str' } }
|
||||
|
||||
##
|
||||
# @InetSocketAddress:
|
||||
#
|
||||
# Captures a socket address or address range in the Internet namespace.
|
||||
#
|
||||
# @numeric: true if the host/port are guaranteed to be numeric,
|
||||
# false if name resolution should be attempted. Defaults to false.
|
||||
# (Since 2.9)
|
||||
#
|
||||
# @to: If present, this is range of possible addresses, with port
|
||||
# between @port and @to.
|
||||
#
|
||||
# @ipv4: whether to accept IPv4 addresses, default try both IPv4 and IPv6
|
||||
#
|
||||
# @ipv6: whether to accept IPv6 addresses, default try both IPv4 and IPv6
|
||||
#
|
||||
# Since: 1.3
|
||||
##
|
||||
{ 'struct': 'InetSocketAddress',
|
||||
'base': 'InetSocketAddressBase',
|
||||
'data': {
|
||||
'*numeric': 'bool',
|
||||
'*to': 'uint16',
|
||||
'*ipv4': 'bool',
|
||||
'*ipv6': 'bool' } }
|
||||
|
||||
##
|
||||
# @UnixSocketAddress:
|
||||
#
|
||||
# Captures a socket address in the local ("Unix socket") namespace.
|
||||
#
|
||||
# @path: filesystem path to use
|
||||
#
|
||||
# Since: 1.3
|
||||
##
|
||||
{ 'struct': 'UnixSocketAddress',
|
||||
'data': {
|
||||
'path': 'str' } }
|
||||
|
||||
##
|
||||
# @VsockSocketAddress:
|
||||
#
|
||||
# Captures a socket address in the vsock namespace.
|
||||
#
|
||||
# @cid: unique host identifier
|
||||
# @port: port
|
||||
#
|
||||
# Note: string types are used to allow for possible future hostname or
|
||||
# service resolution support.
|
||||
#
|
||||
# Since: 2.8
|
||||
##
|
||||
{ 'struct': 'VsockSocketAddress',
|
||||
'data': {
|
||||
'cid': 'str',
|
||||
'port': 'str' } }
|
||||
|
||||
##
|
||||
# @SocketAddressLegacy:
|
||||
#
|
||||
# Captures the address of a socket, which could also be a named file descriptor
|
||||
#
|
||||
# Note: This type is deprecated in favor of SocketAddress. The
|
||||
# difference between SocketAddressLegacy and SocketAddress is that the
|
||||
# latter is a flat union rather than a simple union. Flat is nicer
|
||||
# because it avoids nesting on the wire, i.e. that form has fewer {}.
|
||||
|
||||
#
|
||||
# Since: 1.3
|
||||
##
|
||||
{ 'union': 'SocketAddressLegacy',
|
||||
'data': {
|
||||
'inet': 'InetSocketAddress',
|
||||
'unix': 'UnixSocketAddress',
|
||||
'vsock': 'VsockSocketAddress',
|
||||
'fd': 'String' } }
|
||||
|
||||
##
|
||||
# @SocketAddressType:
|
||||
#
|
||||
# Available SocketAddress types
|
||||
#
|
||||
# @inet: Internet address
|
||||
#
|
||||
# @unix: Unix domain socket
|
||||
#
|
||||
# Since: 2.9
|
||||
##
|
||||
{ 'enum': 'SocketAddressType',
|
||||
'data': [ 'inet', 'unix', 'vsock', 'fd' ] }
|
||||
|
||||
##
|
||||
# @SocketAddress:
|
||||
#
|
||||
# Captures the address of a socket, which could also be a named file
|
||||
# descriptor
|
||||
#
|
||||
# @type: Transport type
|
||||
#
|
||||
# Since: 2.9
|
||||
##
|
||||
{ 'union': 'SocketAddress',
|
||||
'base': { 'type': 'SocketAddressType' },
|
||||
'discriminator': 'type',
|
||||
'data': { 'inet': 'InetSocketAddress',
|
||||
'unix': 'UnixSocketAddress',
|
||||
'vsock': 'VsockSocketAddress',
|
||||
'fd': 'String' } }
|
137
qapi/tpm.json
Normal file
137
qapi/tpm.json
Normal file
@ -0,0 +1,137 @@
|
||||
# -*- Mode: Python -*-
|
||||
#
|
||||
|
||||
##
|
||||
# = TPM (trusted platform module) devices
|
||||
##
|
||||
|
||||
##
|
||||
# @TpmModel:
|
||||
#
|
||||
# An enumeration of TPM models
|
||||
#
|
||||
# @tpm-tis: TPM TIS model
|
||||
#
|
||||
# Since: 1.5
|
||||
##
|
||||
{ 'enum': 'TpmModel', 'data': [ 'tpm-tis' ] }
|
||||
|
||||
##
|
||||
# @query-tpm-models:
|
||||
#
|
||||
# Return a list of supported TPM models
|
||||
#
|
||||
# Returns: a list of TpmModel
|
||||
#
|
||||
# Since: 1.5
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# -> { "execute": "query-tpm-models" }
|
||||
# <- { "return": [ "tpm-tis" ] }
|
||||
#
|
||||
##
|
||||
{ 'command': 'query-tpm-models', 'returns': ['TpmModel'] }
|
||||
|
||||
##
|
||||
# @TpmType:
|
||||
#
|
||||
# An enumeration of TPM types
|
||||
#
|
||||
# @passthrough: TPM passthrough type
|
||||
#
|
||||
# Since: 1.5
|
||||
##
|
||||
{ 'enum': 'TpmType', 'data': [ 'passthrough' ] }
|
||||
|
||||
##
|
||||
# @query-tpm-types:
|
||||
#
|
||||
# Return a list of supported TPM types
|
||||
#
|
||||
# Returns: a list of TpmType
|
||||
#
|
||||
# Since: 1.5
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# -> { "execute": "query-tpm-types" }
|
||||
# <- { "return": [ "passthrough" ] }
|
||||
#
|
||||
##
|
||||
{ 'command': 'query-tpm-types', 'returns': ['TpmType'] }
|
||||
|
||||
##
|
||||
# @TPMPassthroughOptions:
|
||||
#
|
||||
# Information about the TPM passthrough type
|
||||
#
|
||||
# @path: string describing the path used for accessing the TPM device
|
||||
#
|
||||
# @cancel-path: string showing the TPM's sysfs cancel file
|
||||
# for cancellation of TPM commands while they are executing
|
||||
#
|
||||
# Since: 1.5
|
||||
##
|
||||
{ 'struct': 'TPMPassthroughOptions', 'data': { '*path' : 'str',
|
||||
'*cancel-path' : 'str'} }
|
||||
|
||||
##
|
||||
# @TpmTypeOptions:
|
||||
#
|
||||
# A union referencing different TPM backend types' configuration options
|
||||
#
|
||||
# @type: 'passthrough' The configuration options for the TPM passthrough type
|
||||
#
|
||||
# Since: 1.5
|
||||
##
|
||||
{ 'union': 'TpmTypeOptions',
|
||||
'data': { 'passthrough' : 'TPMPassthroughOptions' } }
|
||||
|
||||
##
|
||||
# @TPMInfo:
|
||||
#
|
||||
# Information about the TPM
|
||||
#
|
||||
# @id: The Id of the TPM
|
||||
#
|
||||
# @model: The TPM frontend model
|
||||
#
|
||||
# @options: The TPM (backend) type configuration options
|
||||
#
|
||||
# Since: 1.5
|
||||
##
|
||||
{ 'struct': 'TPMInfo',
|
||||
'data': {'id': 'str',
|
||||
'model': 'TpmModel',
|
||||
'options': 'TpmTypeOptions' } }
|
||||
|
||||
##
|
||||
# @query-tpm:
|
||||
#
|
||||
# Return information about the TPM device
|
||||
#
|
||||
# Returns: @TPMInfo on success
|
||||
#
|
||||
# Since: 1.5
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# -> { "execute": "query-tpm" }
|
||||
# <- { "return":
|
||||
# [
|
||||
# { "model": "tpm-tis",
|
||||
# "options":
|
||||
# { "type": "passthrough",
|
||||
# "data":
|
||||
# { "cancel-path": "/sys/class/misc/tpm0/device/cancel",
|
||||
# "path": "/dev/tpm0"
|
||||
# }
|
||||
# },
|
||||
# "id": "tpm0"
|
||||
# }
|
||||
# ]
|
||||
# }
|
||||
#
|
||||
##
|
||||
{ 'command': 'query-tpm', 'returns': ['TPMInfo'] }
|
@ -6,7 +6,7 @@
|
||||
# See the COPYING file in the top-level directory.
|
||||
|
||||
##
|
||||
# = Tracing commands
|
||||
# = Tracing
|
||||
##
|
||||
|
||||
##
|
||||
|
158
qapi/transaction.json
Normal file
158
qapi/transaction.json
Normal file
@ -0,0 +1,158 @@
|
||||
# -*- Mode: Python -*-
|
||||
#
|
||||
|
||||
##
|
||||
# = Transactions
|
||||
##
|
||||
|
||||
{ 'include': 'block.json' }
|
||||
|
||||
##
|
||||
# @Abort:
|
||||
#
|
||||
# This action can be used to test transaction failure.
|
||||
#
|
||||
# Since: 1.6
|
||||
##
|
||||
{ 'struct': 'Abort',
|
||||
'data': { } }
|
||||
|
||||
##
|
||||
# @ActionCompletionMode:
|
||||
#
|
||||
# An enumeration of Transactional completion modes.
|
||||
#
|
||||
# @individual: Do not attempt to cancel any other Actions if any Actions fail
|
||||
# after the Transaction request succeeds. All Actions that
|
||||
# can complete successfully will do so without waiting on others.
|
||||
# This is the default.
|
||||
#
|
||||
# @grouped: If any Action fails after the Transaction succeeds, cancel all
|
||||
# Actions. Actions do not complete until all Actions are ready to
|
||||
# complete. May be rejected by Actions that do not support this
|
||||
# completion mode.
|
||||
#
|
||||
# Since: 2.5
|
||||
##
|
||||
{ 'enum': 'ActionCompletionMode',
|
||||
'data': [ 'individual', 'grouped' ] }
|
||||
|
||||
##
|
||||
# @TransactionAction:
|
||||
#
|
||||
# A discriminated record of operations that can be performed with
|
||||
# @transaction. Action @type can be:
|
||||
#
|
||||
# - @abort: since 1.6
|
||||
# - @block-dirty-bitmap-add: since 2.5
|
||||
# - @block-dirty-bitmap-clear: since 2.5
|
||||
# - @blockdev-backup: since 2.3
|
||||
# - @blockdev-snapshot: since 2.5
|
||||
# - @blockdev-snapshot-internal-sync: since 1.7
|
||||
# - @blockdev-snapshot-sync: since 1.1
|
||||
# - @drive-backup: since 1.6
|
||||
#
|
||||
# Since: 1.1
|
||||
##
|
||||
{ 'union': 'TransactionAction',
|
||||
'data': {
|
||||
'abort': 'Abort',
|
||||
'block-dirty-bitmap-add': 'BlockDirtyBitmapAdd',
|
||||
'block-dirty-bitmap-clear': 'BlockDirtyBitmap',
|
||||
'blockdev-backup': 'BlockdevBackup',
|
||||
'blockdev-snapshot': 'BlockdevSnapshot',
|
||||
'blockdev-snapshot-internal-sync': 'BlockdevSnapshotInternal',
|
||||
'blockdev-snapshot-sync': 'BlockdevSnapshotSync',
|
||||
'drive-backup': 'DriveBackup'
|
||||
} }
|
||||
|
||||
##
|
||||
# @TransactionProperties:
|
||||
#
|
||||
# Optional arguments to modify the behavior of a Transaction.
|
||||
#
|
||||
# @completion-mode: Controls how jobs launched asynchronously by
|
||||
# Actions will complete or fail as a group.
|
||||
# See @ActionCompletionMode for details.
|
||||
#
|
||||
# Since: 2.5
|
||||
##
|
||||
{ 'struct': 'TransactionProperties',
|
||||
'data': {
|
||||
'*completion-mode': 'ActionCompletionMode'
|
||||
}
|
||||
}
|
||||
|
||||
##
|
||||
# @transaction:
|
||||
#
|
||||
# Executes a number of transactionable QMP commands atomically. If any
|
||||
# operation fails, then the entire set of actions will be abandoned and the
|
||||
# appropriate error returned.
|
||||
#
|
||||
# For external snapshots, the dictionary contains the device, the file to use for
|
||||
# the new snapshot, and the format. The default format, if not specified, is
|
||||
# qcow2.
|
||||
#
|
||||
# Each new snapshot defaults to being created by QEMU (wiping any
|
||||
# contents if the file already exists), but it is also possible to reuse
|
||||
# an externally-created file. In the latter case, you should ensure that
|
||||
# the new image file has the same contents as the current one; QEMU cannot
|
||||
# perform any meaningful check. Typically this is achieved by using the
|
||||
# current image file as the backing file for the new image.
|
||||
#
|
||||
# On failure, the original disks pre-snapshot attempt will be used.
|
||||
#
|
||||
# For internal snapshots, the dictionary contains the device and the snapshot's
|
||||
# name. If an internal snapshot matching name already exists, the request will
|
||||
# be rejected. Only some image formats support it, for example, qcow2, rbd,
|
||||
# and sheepdog.
|
||||
#
|
||||
# On failure, qemu will try delete the newly created internal snapshot in the
|
||||
# transaction. When an I/O error occurs during deletion, the user needs to fix
|
||||
# it later with qemu-img or other command.
|
||||
#
|
||||
# @actions: List of @TransactionAction;
|
||||
# information needed for the respective operations.
|
||||
#
|
||||
# @properties: structure of additional options to control the
|
||||
# execution of the transaction. See @TransactionProperties
|
||||
# for additional detail.
|
||||
#
|
||||
# Returns: nothing on success
|
||||
#
|
||||
# Errors depend on the operations of the transaction
|
||||
#
|
||||
# Note: The transaction aborts on the first failure. Therefore, there will be
|
||||
# information on only one failed operation returned in an error condition, and
|
||||
# subsequent actions will not have been attempted.
|
||||
#
|
||||
# Since: 1.1
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# -> { "execute": "transaction",
|
||||
# "arguments": { "actions": [
|
||||
# { "type": "blockdev-snapshot-sync", "data" : { "device": "ide-hd0",
|
||||
# "snapshot-file": "/some/place/my-image",
|
||||
# "format": "qcow2" } },
|
||||
# { "type": "blockdev-snapshot-sync", "data" : { "node-name": "myfile",
|
||||
# "snapshot-file": "/some/place/my-image2",
|
||||
# "snapshot-node-name": "node3432",
|
||||
# "mode": "existing",
|
||||
# "format": "qcow2" } },
|
||||
# { "type": "blockdev-snapshot-sync", "data" : { "device": "ide-hd1",
|
||||
# "snapshot-file": "/some/place/my-image2",
|
||||
# "mode": "existing",
|
||||
# "format": "qcow2" } },
|
||||
# { "type": "blockdev-snapshot-internal-sync", "data" : {
|
||||
# "device": "ide-hd2",
|
||||
# "name": "snapshot0" } } ] } }
|
||||
# <- { "return": {} }
|
||||
#
|
||||
##
|
||||
{ 'command': 'transaction',
|
||||
'data': { 'actions': [ 'TransactionAction' ],
|
||||
'*properties': 'TransactionProperties'
|
||||
}
|
||||
}
|
977
qapi/ui.json
Normal file
977
qapi/ui.json
Normal file
@ -0,0 +1,977 @@
|
||||
# -*- Mode: Python -*-
|
||||
#
|
||||
|
||||
##
|
||||
# = Remote desktop
|
||||
##
|
||||
|
||||
{ 'include': 'sockets.json' }
|
||||
|
||||
##
|
||||
# @set_password:
|
||||
#
|
||||
# Sets the password of a remote display session.
|
||||
#
|
||||
# @protocol: `vnc' to modify the VNC server password
|
||||
# `spice' to modify the Spice server password
|
||||
#
|
||||
# @password: the new password
|
||||
#
|
||||
# @connected: how to handle existing clients when changing the
|
||||
# password. If nothing is specified, defaults to `keep'
|
||||
# `fail' to fail the command if clients are connected
|
||||
# `disconnect' to disconnect existing clients
|
||||
# `keep' to maintain existing clients
|
||||
#
|
||||
# Returns: Nothing on success
|
||||
# If Spice is not enabled, DeviceNotFound
|
||||
#
|
||||
# Since: 0.14.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# -> { "execute": "set_password", "arguments": { "protocol": "vnc",
|
||||
# "password": "secret" } }
|
||||
# <- { "return": {} }
|
||||
#
|
||||
##
|
||||
{ 'command': 'set_password',
|
||||
'data': {'protocol': 'str', 'password': 'str', '*connected': 'str'} }
|
||||
|
||||
##
|
||||
# @expire_password:
|
||||
#
|
||||
# Expire the password of a remote display server.
|
||||
#
|
||||
# @protocol: the name of the remote display protocol `vnc' or `spice'
|
||||
#
|
||||
# @time: when to expire the password.
|
||||
# `now' to expire the password immediately
|
||||
# `never' to cancel password expiration
|
||||
# `+INT' where INT is the number of seconds from now (integer)
|
||||
# `INT' where INT is the absolute time in seconds
|
||||
#
|
||||
# Returns: Nothing on success
|
||||
# If @protocol is `spice' and Spice is not active, DeviceNotFound
|
||||
#
|
||||
# Since: 0.14.0
|
||||
#
|
||||
# Notes: Time is relative to the server and currently there is no way to
|
||||
# coordinate server time with client time. It is not recommended to
|
||||
# use the absolute time version of the @time parameter unless you're
|
||||
# sure you are on the same machine as the QEMU instance.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# -> { "execute": "expire_password", "arguments": { "protocol": "vnc",
|
||||
# "time": "+60" } }
|
||||
# <- { "return": {} }
|
||||
#
|
||||
##
|
||||
{ 'command': 'expire_password', 'data': {'protocol': 'str', 'time': 'str'} }
|
||||
|
||||
##
|
||||
# @screendump:
|
||||
#
|
||||
# Write a PPM of the VGA screen to a file.
|
||||
#
|
||||
# @filename: the path of a new PPM file to store the image
|
||||
#
|
||||
# Returns: Nothing on success
|
||||
#
|
||||
# Since: 0.14.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# -> { "execute": "screendump",
|
||||
# "arguments": { "filename": "/tmp/image" } }
|
||||
# <- { "return": {} }
|
||||
#
|
||||
##
|
||||
{ 'command': 'screendump', 'data': {'filename': 'str'} }
|
||||
|
||||
##
|
||||
# == Spice
|
||||
##
|
||||
|
||||
##
|
||||
# @SpiceBasicInfo:
|
||||
#
|
||||
# The basic information for SPICE network connection
|
||||
#
|
||||
# @host: IP address
|
||||
#
|
||||
# @port: port number
|
||||
#
|
||||
# @family: address family
|
||||
#
|
||||
# Since: 2.1
|
||||
##
|
||||
{ 'struct': 'SpiceBasicInfo',
|
||||
'data': { 'host': 'str',
|
||||
'port': 'str',
|
||||
'family': 'NetworkAddressFamily' } }
|
||||
|
||||
##
|
||||
# @SpiceServerInfo:
|
||||
#
|
||||
# Information about a SPICE server
|
||||
#
|
||||
# @auth: authentication method
|
||||
#
|
||||
# Since: 2.1
|
||||
##
|
||||
{ 'struct': 'SpiceServerInfo',
|
||||
'base': 'SpiceBasicInfo',
|
||||
'data': { '*auth': 'str' } }
|
||||
|
||||
##
|
||||
# @SpiceChannel:
|
||||
#
|
||||
# Information about a SPICE client channel.
|
||||
#
|
||||
# @connection-id: SPICE connection id number. All channels with the same id
|
||||
# belong to the same SPICE session.
|
||||
#
|
||||
# @channel-type: SPICE channel type number. "1" is the main control
|
||||
# channel, filter for this one if you want to track spice
|
||||
# sessions only
|
||||
#
|
||||
# @channel-id: SPICE channel ID number. Usually "0", might be different when
|
||||
# multiple channels of the same type exist, such as multiple
|
||||
# display channels in a multihead setup
|
||||
#
|
||||
# @tls: true if the channel is encrypted, false otherwise.
|
||||
#
|
||||
# Since: 0.14.0
|
||||
##
|
||||
{ 'struct': 'SpiceChannel',
|
||||
'base': 'SpiceBasicInfo',
|
||||
'data': {'connection-id': 'int', 'channel-type': 'int', 'channel-id': 'int',
|
||||
'tls': 'bool'} }
|
||||
|
||||
##
|
||||
# @SpiceQueryMouseMode:
|
||||
#
|
||||
# An enumeration of Spice mouse states.
|
||||
#
|
||||
# @client: Mouse cursor position is determined by the client.
|
||||
#
|
||||
# @server: Mouse cursor position is determined by the server.
|
||||
#
|
||||
# @unknown: No information is available about mouse mode used by
|
||||
# the spice server.
|
||||
#
|
||||
# Note: spice/enums.h has a SpiceMouseMode already, hence the name.
|
||||
#
|
||||
# Since: 1.1
|
||||
##
|
||||
{ 'enum': 'SpiceQueryMouseMode',
|
||||
'data': [ 'client', 'server', 'unknown' ] }
|
||||
|
||||
##
|
||||
# @SpiceInfo:
|
||||
#
|
||||
# Information about the SPICE session.
|
||||
#
|
||||
# @enabled: true if the SPICE server is enabled, false otherwise
|
||||
#
|
||||
# @migrated: true if the last guest migration completed and spice
|
||||
# migration had completed as well. false otherwise. (since 1.4)
|
||||
#
|
||||
# @host: The hostname the SPICE server is bound to. This depends on
|
||||
# the name resolution on the host and may be an IP address.
|
||||
#
|
||||
# @port: The SPICE server's port number.
|
||||
#
|
||||
# @compiled-version: SPICE server version.
|
||||
#
|
||||
# @tls-port: The SPICE server's TLS port number.
|
||||
#
|
||||
# @auth: the current authentication type used by the server
|
||||
# 'none' if no authentication is being used
|
||||
# 'spice' uses SASL or direct TLS authentication, depending on command
|
||||
# line options
|
||||
#
|
||||
# @mouse-mode: The mode in which the mouse cursor is displayed currently. Can
|
||||
# be determined by the client or the server, or unknown if spice
|
||||
# server doesn't provide this information. (since: 1.1)
|
||||
#
|
||||
# @channels: a list of @SpiceChannel for each active spice channel
|
||||
#
|
||||
# Since: 0.14.0
|
||||
##
|
||||
{ 'struct': 'SpiceInfo',
|
||||
'data': {'enabled': 'bool', 'migrated': 'bool', '*host': 'str', '*port': 'int',
|
||||
'*tls-port': 'int', '*auth': 'str', '*compiled-version': 'str',
|
||||
'mouse-mode': 'SpiceQueryMouseMode', '*channels': ['SpiceChannel']} }
|
||||
|
||||
##
|
||||
# @query-spice:
|
||||
#
|
||||
# Returns information about the current SPICE server
|
||||
#
|
||||
# Returns: @SpiceInfo
|
||||
#
|
||||
# Since: 0.14.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# -> { "execute": "query-spice" }
|
||||
# <- { "return": {
|
||||
# "enabled": true,
|
||||
# "auth": "spice",
|
||||
# "port": 5920,
|
||||
# "tls-port": 5921,
|
||||
# "host": "0.0.0.0",
|
||||
# "channels": [
|
||||
# {
|
||||
# "port": "54924",
|
||||
# "family": "ipv4",
|
||||
# "channel-type": 1,
|
||||
# "connection-id": 1804289383,
|
||||
# "host": "127.0.0.1",
|
||||
# "channel-id": 0,
|
||||
# "tls": true
|
||||
# },
|
||||
# {
|
||||
# "port": "36710",
|
||||
# "family": "ipv4",
|
||||
# "channel-type": 4,
|
||||
# "connection-id": 1804289383,
|
||||
# "host": "127.0.0.1",
|
||||
# "channel-id": 0,
|
||||
# "tls": false
|
||||
# },
|
||||
# [ ... more channels follow ... ]
|
||||
# ]
|
||||
# }
|
||||
# }
|
||||
#
|
||||
##
|
||||
{ 'command': 'query-spice', 'returns': 'SpiceInfo' }
|
||||
|
||||
##
|
||||
# @SPICE_CONNECTED:
|
||||
#
|
||||
# Emitted when a SPICE client establishes a connection
|
||||
#
|
||||
# @server: server information
|
||||
#
|
||||
# @client: client information
|
||||
#
|
||||
# Since: 0.14.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "timestamp": {"seconds": 1290688046, "microseconds": 388707},
|
||||
# "event": "SPICE_CONNECTED",
|
||||
# "data": {
|
||||
# "server": { "port": "5920", "family": "ipv4", "host": "127.0.0.1"},
|
||||
# "client": {"port": "52873", "family": "ipv4", "host": "127.0.0.1"}
|
||||
# }}
|
||||
#
|
||||
##
|
||||
{ 'event': 'SPICE_CONNECTED',
|
||||
'data': { 'server': 'SpiceBasicInfo',
|
||||
'client': 'SpiceBasicInfo' } }
|
||||
|
||||
##
|
||||
# @SPICE_INITIALIZED:
|
||||
#
|
||||
# Emitted after initial handshake and authentication takes place (if any)
|
||||
# and the SPICE channel is up and running
|
||||
#
|
||||
# @server: server information
|
||||
#
|
||||
# @client: client information
|
||||
#
|
||||
# Since: 0.14.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "timestamp": {"seconds": 1290688046, "microseconds": 417172},
|
||||
# "event": "SPICE_INITIALIZED",
|
||||
# "data": {"server": {"auth": "spice", "port": "5921",
|
||||
# "family": "ipv4", "host": "127.0.0.1"},
|
||||
# "client": {"port": "49004", "family": "ipv4", "channel-type": 3,
|
||||
# "connection-id": 1804289383, "host": "127.0.0.1",
|
||||
# "channel-id": 0, "tls": true}
|
||||
# }}
|
||||
#
|
||||
##
|
||||
{ 'event': 'SPICE_INITIALIZED',
|
||||
'data': { 'server': 'SpiceServerInfo',
|
||||
'client': 'SpiceChannel' } }
|
||||
|
||||
##
|
||||
# @SPICE_DISCONNECTED:
|
||||
#
|
||||
# Emitted when the SPICE connection is closed
|
||||
#
|
||||
# @server: server information
|
||||
#
|
||||
# @client: client information
|
||||
#
|
||||
# Since: 0.14.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "timestamp": {"seconds": 1290688046, "microseconds": 388707},
|
||||
# "event": "SPICE_DISCONNECTED",
|
||||
# "data": {
|
||||
# "server": { "port": "5920", "family": "ipv4", "host": "127.0.0.1"},
|
||||
# "client": {"port": "52873", "family": "ipv4", "host": "127.0.0.1"}
|
||||
# }}
|
||||
#
|
||||
##
|
||||
{ 'event': 'SPICE_DISCONNECTED',
|
||||
'data': { 'server': 'SpiceBasicInfo',
|
||||
'client': 'SpiceBasicInfo' } }
|
||||
|
||||
##
|
||||
# @SPICE_MIGRATE_COMPLETED:
|
||||
#
|
||||
# Emitted when SPICE migration has completed
|
||||
#
|
||||
# Since: 1.3
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "timestamp": {"seconds": 1290688046, "microseconds": 417172},
|
||||
# "event": "SPICE_MIGRATE_COMPLETED" }
|
||||
#
|
||||
##
|
||||
{ 'event': 'SPICE_MIGRATE_COMPLETED' }
|
||||
|
||||
##
|
||||
# == VNC
|
||||
##
|
||||
|
||||
##
|
||||
# @VncBasicInfo:
|
||||
#
|
||||
# The basic information for vnc network connection
|
||||
#
|
||||
# @host: IP address
|
||||
#
|
||||
# @service: The service name of the vnc port. This may depend on the host
|
||||
# system's service database so symbolic names should not be relied
|
||||
# on.
|
||||
#
|
||||
# @family: address family
|
||||
#
|
||||
# @websocket: true in case the socket is a websocket (since 2.3).
|
||||
#
|
||||
# Since: 2.1
|
||||
##
|
||||
{ 'struct': 'VncBasicInfo',
|
||||
'data': { 'host': 'str',
|
||||
'service': 'str',
|
||||
'family': 'NetworkAddressFamily',
|
||||
'websocket': 'bool' } }
|
||||
|
||||
##
|
||||
# @VncServerInfo:
|
||||
#
|
||||
# The network connection information for server
|
||||
#
|
||||
# @auth: authentication method used for
|
||||
# the plain (non-websocket) VNC server
|
||||
#
|
||||
# Since: 2.1
|
||||
##
|
||||
{ 'struct': 'VncServerInfo',
|
||||
'base': 'VncBasicInfo',
|
||||
'data': { '*auth': 'str' } }
|
||||
|
||||
##
|
||||
# @VncClientInfo:
|
||||
#
|
||||
# Information about a connected VNC client.
|
||||
#
|
||||
# @x509_dname: If x509 authentication is in use, the Distinguished
|
||||
# Name of the client.
|
||||
#
|
||||
# @sasl_username: If SASL authentication is in use, the SASL username
|
||||
# used for authentication.
|
||||
#
|
||||
# Since: 0.14.0
|
||||
##
|
||||
{ 'struct': 'VncClientInfo',
|
||||
'base': 'VncBasicInfo',
|
||||
'data': { '*x509_dname': 'str', '*sasl_username': 'str' } }
|
||||
|
||||
##
|
||||
# @VncInfo:
|
||||
#
|
||||
# Information about the VNC session.
|
||||
#
|
||||
# @enabled: true if the VNC server is enabled, false otherwise
|
||||
#
|
||||
# @host: The hostname the VNC server is bound to. This depends on
|
||||
# the name resolution on the host and may be an IP address.
|
||||
#
|
||||
# @family: 'ipv6' if the host is listening for IPv6 connections
|
||||
# 'ipv4' if the host is listening for IPv4 connections
|
||||
# 'unix' if the host is listening on a unix domain socket
|
||||
# 'unknown' otherwise
|
||||
#
|
||||
# @service: The service name of the server's port. This may depends
|
||||
# on the host system's service database so symbolic names should not
|
||||
# be relied on.
|
||||
#
|
||||
# @auth: the current authentication type used by the server
|
||||
# 'none' if no authentication is being used
|
||||
# 'vnc' if VNC authentication is being used
|
||||
# 'vencrypt+plain' if VEncrypt is used with plain text authentication
|
||||
# 'vencrypt+tls+none' if VEncrypt is used with TLS and no authentication
|
||||
# 'vencrypt+tls+vnc' if VEncrypt is used with TLS and VNC authentication
|
||||
# 'vencrypt+tls+plain' if VEncrypt is used with TLS and plain text auth
|
||||
# 'vencrypt+x509+none' if VEncrypt is used with x509 and no auth
|
||||
# 'vencrypt+x509+vnc' if VEncrypt is used with x509 and VNC auth
|
||||
# 'vencrypt+x509+plain' if VEncrypt is used with x509 and plain text auth
|
||||
# 'vencrypt+tls+sasl' if VEncrypt is used with TLS and SASL auth
|
||||
# 'vencrypt+x509+sasl' if VEncrypt is used with x509 and SASL auth
|
||||
#
|
||||
# @clients: a list of @VncClientInfo of all currently connected clients
|
||||
#
|
||||
# Since: 0.14.0
|
||||
##
|
||||
{ 'struct': 'VncInfo',
|
||||
'data': {'enabled': 'bool', '*host': 'str',
|
||||
'*family': 'NetworkAddressFamily',
|
||||
'*service': 'str', '*auth': 'str', '*clients': ['VncClientInfo']} }
|
||||
|
||||
##
|
||||
# @VncPrimaryAuth:
|
||||
#
|
||||
# vnc primary authentication method.
|
||||
#
|
||||
# Since: 2.3
|
||||
##
|
||||
{ 'enum': 'VncPrimaryAuth',
|
||||
'data': [ 'none', 'vnc', 'ra2', 'ra2ne', 'tight', 'ultra',
|
||||
'tls', 'vencrypt', 'sasl' ] }
|
||||
|
||||
##
|
||||
# @VncVencryptSubAuth:
|
||||
#
|
||||
# vnc sub authentication method with vencrypt.
|
||||
#
|
||||
# Since: 2.3
|
||||
##
|
||||
{ 'enum': 'VncVencryptSubAuth',
|
||||
'data': [ 'plain',
|
||||
'tls-none', 'x509-none',
|
||||
'tls-vnc', 'x509-vnc',
|
||||
'tls-plain', 'x509-plain',
|
||||
'tls-sasl', 'x509-sasl' ] }
|
||||
|
||||
|
||||
##
|
||||
# @VncServerInfo2:
|
||||
#
|
||||
# The network connection information for server
|
||||
#
|
||||
# @auth: The current authentication type used by the servers
|
||||
#
|
||||
# @vencrypt: The vencrypt sub authentication type used by the
|
||||
# servers, only specified in case auth == vencrypt.
|
||||
#
|
||||
# Since: 2.9
|
||||
##
|
||||
{ 'struct': 'VncServerInfo2',
|
||||
'base': 'VncBasicInfo',
|
||||
'data': { 'auth' : 'VncPrimaryAuth',
|
||||
'*vencrypt' : 'VncVencryptSubAuth' } }
|
||||
|
||||
|
||||
##
|
||||
# @VncInfo2:
|
||||
#
|
||||
# Information about a vnc server
|
||||
#
|
||||
# @id: vnc server name.
|
||||
#
|
||||
# @server: A list of @VncBasincInfo describing all listening sockets.
|
||||
# The list can be empty (in case the vnc server is disabled).
|
||||
# It also may have multiple entries: normal + websocket,
|
||||
# possibly also ipv4 + ipv6 in the future.
|
||||
#
|
||||
# @clients: A list of @VncClientInfo of all currently connected clients.
|
||||
# The list can be empty, for obvious reasons.
|
||||
#
|
||||
# @auth: The current authentication type used by the non-websockets servers
|
||||
#
|
||||
# @vencrypt: The vencrypt authentication type used by the servers,
|
||||
# only specified in case auth == vencrypt.
|
||||
#
|
||||
# @display: The display device the vnc server is linked to.
|
||||
#
|
||||
# Since: 2.3
|
||||
##
|
||||
{ 'struct': 'VncInfo2',
|
||||
'data': { 'id' : 'str',
|
||||
'server' : ['VncServerInfo2'],
|
||||
'clients' : ['VncClientInfo'],
|
||||
'auth' : 'VncPrimaryAuth',
|
||||
'*vencrypt' : 'VncVencryptSubAuth',
|
||||
'*display' : 'str' } }
|
||||
|
||||
##
|
||||
# @query-vnc:
|
||||
#
|
||||
# Returns information about the current VNC server
|
||||
#
|
||||
# Returns: @VncInfo
|
||||
#
|
||||
# Since: 0.14.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# -> { "execute": "query-vnc" }
|
||||
# <- { "return": {
|
||||
# "enabled":true,
|
||||
# "host":"0.0.0.0",
|
||||
# "service":"50402",
|
||||
# "auth":"vnc",
|
||||
# "family":"ipv4",
|
||||
# "clients":[
|
||||
# {
|
||||
# "host":"127.0.0.1",
|
||||
# "service":"50401",
|
||||
# "family":"ipv4"
|
||||
# }
|
||||
# ]
|
||||
# }
|
||||
# }
|
||||
#
|
||||
##
|
||||
{ 'command': 'query-vnc', 'returns': 'VncInfo' }
|
||||
|
||||
##
|
||||
# @query-vnc-servers:
|
||||
#
|
||||
# Returns a list of vnc servers. The list can be empty.
|
||||
#
|
||||
# Returns: a list of @VncInfo2
|
||||
#
|
||||
# Since: 2.3
|
||||
##
|
||||
{ 'command': 'query-vnc-servers', 'returns': ['VncInfo2'] }
|
||||
|
||||
##
|
||||
# @change-vnc-password:
|
||||
#
|
||||
# Change the VNC server password.
|
||||
#
|
||||
# @password: the new password to use with VNC authentication
|
||||
#
|
||||
# Since: 1.1
|
||||
#
|
||||
# Notes: An empty password in this command will set the password to the empty
|
||||
# string. Existing clients are unaffected by executing this command.
|
||||
##
|
||||
{ 'command': 'change-vnc-password', 'data': {'password': 'str'} }
|
||||
|
||||
##
|
||||
# @VNC_CONNECTED:
|
||||
#
|
||||
# Emitted when a VNC client establishes a connection
|
||||
#
|
||||
# @server: server information
|
||||
#
|
||||
# @client: client information
|
||||
#
|
||||
# Note: This event is emitted before any authentication takes place, thus
|
||||
# the authentication ID is not provided
|
||||
#
|
||||
# Since: 0.13.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "VNC_CONNECTED",
|
||||
# "data": {
|
||||
# "server": { "auth": "sasl", "family": "ipv4",
|
||||
# "service": "5901", "host": "0.0.0.0" },
|
||||
# "client": { "family": "ipv4", "service": "58425",
|
||||
# "host": "127.0.0.1" } },
|
||||
# "timestamp": { "seconds": 1262976601, "microseconds": 975795 } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'VNC_CONNECTED',
|
||||
'data': { 'server': 'VncServerInfo',
|
||||
'client': 'VncBasicInfo' } }
|
||||
|
||||
##
|
||||
# @VNC_INITIALIZED:
|
||||
#
|
||||
# Emitted after authentication takes place (if any) and the VNC session is
|
||||
# made active
|
||||
#
|
||||
# @server: server information
|
||||
#
|
||||
# @client: client information
|
||||
#
|
||||
# Since: 0.13.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "VNC_INITIALIZED",
|
||||
# "data": {
|
||||
# "server": { "auth": "sasl", "family": "ipv4",
|
||||
# "service": "5901", "host": "0.0.0.0"},
|
||||
# "client": { "family": "ipv4", "service": "46089",
|
||||
# "host": "127.0.0.1", "sasl_username": "luiz" } },
|
||||
# "timestamp": { "seconds": 1263475302, "microseconds": 150772 } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'VNC_INITIALIZED',
|
||||
'data': { 'server': 'VncServerInfo',
|
||||
'client': 'VncClientInfo' } }
|
||||
|
||||
##
|
||||
# @VNC_DISCONNECTED:
|
||||
#
|
||||
# Emitted when the connection is closed
|
||||
#
|
||||
# @server: server information
|
||||
#
|
||||
# @client: client information
|
||||
#
|
||||
# Since: 0.13.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# <- { "event": "VNC_DISCONNECTED",
|
||||
# "data": {
|
||||
# "server": { "auth": "sasl", "family": "ipv4",
|
||||
# "service": "5901", "host": "0.0.0.0" },
|
||||
# "client": { "family": "ipv4", "service": "58425",
|
||||
# "host": "127.0.0.1", "sasl_username": "luiz" } },
|
||||
# "timestamp": { "seconds": 1262976601, "microseconds": 975795 } }
|
||||
#
|
||||
##
|
||||
{ 'event': 'VNC_DISCONNECTED',
|
||||
'data': { 'server': 'VncServerInfo',
|
||||
'client': 'VncClientInfo' } }
|
||||
|
||||
##
|
||||
# = Input
|
||||
##
|
||||
|
||||
##
|
||||
# @MouseInfo:
|
||||
#
|
||||
# Information about a mouse device.
|
||||
#
|
||||
# @name: the name of the mouse device
|
||||
#
|
||||
# @index: the index of the mouse device
|
||||
#
|
||||
# @current: true if this device is currently receiving mouse events
|
||||
#
|
||||
# @absolute: true if this device supports absolute coordinates as input
|
||||
#
|
||||
# Since: 0.14.0
|
||||
##
|
||||
{ 'struct': 'MouseInfo',
|
||||
'data': {'name': 'str', 'index': 'int', 'current': 'bool',
|
||||
'absolute': 'bool'} }
|
||||
|
||||
##
|
||||
# @query-mice:
|
||||
#
|
||||
# Returns information about each active mouse device
|
||||
#
|
||||
# Returns: a list of @MouseInfo for each device
|
||||
#
|
||||
# Since: 0.14.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# -> { "execute": "query-mice" }
|
||||
# <- { "return": [
|
||||
# {
|
||||
# "name":"QEMU Microsoft Mouse",
|
||||
# "index":0,
|
||||
# "current":false,
|
||||
# "absolute":false
|
||||
# },
|
||||
# {
|
||||
# "name":"QEMU PS/2 Mouse",
|
||||
# "index":1,
|
||||
# "current":true,
|
||||
# "absolute":true
|
||||
# }
|
||||
# ]
|
||||
# }
|
||||
#
|
||||
##
|
||||
{ 'command': 'query-mice', 'returns': ['MouseInfo'] }
|
||||
|
||||
##
|
||||
# @QKeyCode:
|
||||
#
|
||||
# An enumeration of key name.
|
||||
#
|
||||
# This is used by the @send-key command.
|
||||
#
|
||||
# @unmapped: since 2.0
|
||||
# @pause: since 2.0
|
||||
# @ro: since 2.4
|
||||
# @kp_comma: since 2.4
|
||||
# @kp_equals: since 2.6
|
||||
# @power: since 2.6
|
||||
# @hiragana: since 2.9
|
||||
# @henkan: since 2.9
|
||||
# @yen: since 2.9
|
||||
#
|
||||
# @sleep: since 2.10
|
||||
# @wake: since 2.10
|
||||
# @audionext: since 2.10
|
||||
# @audioprev: since 2.10
|
||||
# @audiostop: since 2.10
|
||||
# @audioplay: since 2.10
|
||||
# @audiomute: since 2.10
|
||||
# @volumeup: since 2.10
|
||||
# @volumedown: since 2.10
|
||||
# @mediaselect: since 2.10
|
||||
# @mail: since 2.10
|
||||
# @calculator: since 2.10
|
||||
# @computer: since 2.10
|
||||
# @ac_home: since 2.10
|
||||
# @ac_back: since 2.10
|
||||
# @ac_forward: since 2.10
|
||||
# @ac_refresh: since 2.10
|
||||
# @ac_bookmarks: since 2.10
|
||||
# altgr, altgr_r: dropped in 2.10
|
||||
#
|
||||
# Since: 1.3.0
|
||||
#
|
||||
##
|
||||
{ 'enum': 'QKeyCode',
|
||||
'data': [ 'unmapped',
|
||||
'shift', 'shift_r', 'alt', 'alt_r', 'ctrl',
|
||||
'ctrl_r', 'menu', 'esc', '1', '2', '3', '4', '5', '6', '7', '8',
|
||||
'9', '0', 'minus', 'equal', 'backspace', 'tab', 'q', 'w', 'e',
|
||||
'r', 't', 'y', 'u', 'i', 'o', 'p', 'bracket_left', 'bracket_right',
|
||||
'ret', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'semicolon',
|
||||
'apostrophe', 'grave_accent', 'backslash', 'z', 'x', 'c', 'v', 'b',
|
||||
'n', 'm', 'comma', 'dot', 'slash', 'asterisk', 'spc', 'caps_lock',
|
||||
'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'f10',
|
||||
'num_lock', 'scroll_lock', 'kp_divide', 'kp_multiply',
|
||||
'kp_subtract', 'kp_add', 'kp_enter', 'kp_decimal', 'sysrq', 'kp_0',
|
||||
'kp_1', 'kp_2', 'kp_3', 'kp_4', 'kp_5', 'kp_6', 'kp_7', 'kp_8',
|
||||
'kp_9', 'less', 'f11', 'f12', 'print', 'home', 'pgup', 'pgdn', 'end',
|
||||
'left', 'up', 'down', 'right', 'insert', 'delete', 'stop', 'again',
|
||||
'props', 'undo', 'front', 'copy', 'open', 'paste', 'find', 'cut',
|
||||
'lf', 'help', 'meta_l', 'meta_r', 'compose', 'pause',
|
||||
'ro', 'hiragana', 'henkan', 'yen',
|
||||
'kp_comma', 'kp_equals', 'power', 'sleep', 'wake',
|
||||
'audionext', 'audioprev', 'audiostop', 'audioplay', 'audiomute',
|
||||
'volumeup', 'volumedown', 'mediaselect',
|
||||
'mail', 'calculator', 'computer',
|
||||
'ac_home', 'ac_back', 'ac_forward', 'ac_refresh', 'ac_bookmarks' ] }
|
||||
|
||||
##
|
||||
# @KeyValue:
|
||||
#
|
||||
# Represents a keyboard key.
|
||||
#
|
||||
# Since: 1.3.0
|
||||
##
|
||||
{ 'union': 'KeyValue',
|
||||
'data': {
|
||||
'number': 'int',
|
||||
'qcode': 'QKeyCode' } }
|
||||
|
||||
##
|
||||
# @send-key:
|
||||
#
|
||||
# Send keys to guest.
|
||||
#
|
||||
# @keys: An array of @KeyValue elements. All @KeyValues in this array are
|
||||
# simultaneously sent to the guest. A @KeyValue.number value is sent
|
||||
# directly to the guest, while @KeyValue.qcode must be a valid
|
||||
# @QKeyCode value
|
||||
#
|
||||
# @hold-time: time to delay key up events, milliseconds. Defaults
|
||||
# to 100
|
||||
#
|
||||
# Returns: Nothing on success
|
||||
# If key is unknown or redundant, InvalidParameter
|
||||
#
|
||||
# Since: 1.3.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# -> { "execute": "send-key",
|
||||
# "arguments": { "keys": [ { "type": "qcode", "data": "ctrl" },
|
||||
# { "type": "qcode", "data": "alt" },
|
||||
# { "type": "qcode", "data": "delete" } ] } }
|
||||
# <- { "return": {} }
|
||||
#
|
||||
##
|
||||
{ 'command': 'send-key',
|
||||
'data': { 'keys': ['KeyValue'], '*hold-time': 'int' } }
|
||||
|
||||
##
|
||||
# @InputButton:
|
||||
#
|
||||
# Button of a pointer input device (mouse, tablet).
|
||||
#
|
||||
# @side: front side button of a 5-button mouse (since 2.9)
|
||||
#
|
||||
# @extra: rear side button of a 5-button mouse (since 2.9)
|
||||
#
|
||||
# Since: 2.0
|
||||
##
|
||||
{ 'enum' : 'InputButton',
|
||||
'data' : [ 'left', 'middle', 'right', 'wheel-up', 'wheel-down', 'side',
|
||||
'extra' ] }
|
||||
|
||||
##
|
||||
# @InputAxis:
|
||||
#
|
||||
# Position axis of a pointer input device (mouse, tablet).
|
||||
#
|
||||
# Since: 2.0
|
||||
##
|
||||
{ 'enum' : 'InputAxis',
|
||||
'data' : [ 'x', 'y' ] }
|
||||
|
||||
##
|
||||
# @InputKeyEvent:
|
||||
#
|
||||
# Keyboard input event.
|
||||
#
|
||||
# @key: Which key this event is for.
|
||||
# @down: True for key-down and false for key-up events.
|
||||
#
|
||||
# Since: 2.0
|
||||
##
|
||||
{ 'struct' : 'InputKeyEvent',
|
||||
'data' : { 'key' : 'KeyValue',
|
||||
'down' : 'bool' } }
|
||||
|
||||
##
|
||||
# @InputBtnEvent:
|
||||
#
|
||||
# Pointer button input event.
|
||||
#
|
||||
# @button: Which button this event is for.
|
||||
# @down: True for key-down and false for key-up events.
|
||||
#
|
||||
# Since: 2.0
|
||||
##
|
||||
{ 'struct' : 'InputBtnEvent',
|
||||
'data' : { 'button' : 'InputButton',
|
||||
'down' : 'bool' } }
|
||||
|
||||
##
|
||||
# @InputMoveEvent:
|
||||
#
|
||||
# Pointer motion input event.
|
||||
#
|
||||
# @axis: Which axis is referenced by @value.
|
||||
# @value: Pointer position. For absolute coordinates the
|
||||
# valid range is 0 -> 0x7ffff
|
||||
#
|
||||
# Since: 2.0
|
||||
##
|
||||
{ 'struct' : 'InputMoveEvent',
|
||||
'data' : { 'axis' : 'InputAxis',
|
||||
'value' : 'int' } }
|
||||
|
||||
##
|
||||
# @InputEvent:
|
||||
#
|
||||
# Input event union.
|
||||
#
|
||||
# @type: the input type, one of:
|
||||
# - 'key': Input event of Keyboard
|
||||
# - 'btn': Input event of pointer buttons
|
||||
# - 'rel': Input event of relative pointer motion
|
||||
# - 'abs': Input event of absolute pointer motion
|
||||
#
|
||||
# Since: 2.0
|
||||
##
|
||||
{ 'union' : 'InputEvent',
|
||||
'data' : { 'key' : 'InputKeyEvent',
|
||||
'btn' : 'InputBtnEvent',
|
||||
'rel' : 'InputMoveEvent',
|
||||
'abs' : 'InputMoveEvent' } }
|
||||
|
||||
##
|
||||
# @input-send-event:
|
||||
#
|
||||
# Send input event(s) to guest.
|
||||
#
|
||||
# @device: display device to send event(s) to.
|
||||
# @head: head to send event(s) to, in case the
|
||||
# display device supports multiple scanouts.
|
||||
# @events: List of InputEvent union.
|
||||
#
|
||||
# Returns: Nothing on success.
|
||||
#
|
||||
# The @device and @head parameters can be used to send the input event
|
||||
# to specific input devices in case (a) multiple input devices of the
|
||||
# same kind are added to the virtual machine and (b) you have
|
||||
# configured input routing (see docs/multiseat.txt) for those input
|
||||
# devices. The parameters work exactly like the device and head
|
||||
# properties of input devices. If @device is missing, only devices
|
||||
# that have no input routing config are admissible. If @device is
|
||||
# specified, both input devices with and without input routing config
|
||||
# are admissible, but devices with input routing config take
|
||||
# precedence.
|
||||
#
|
||||
# Since: 2.6
|
||||
#
|
||||
# Note: The consoles are visible in the qom tree, under
|
||||
# /backend/console[$index]. They have a device link and head property,
|
||||
# so it is possible to map which console belongs to which device and
|
||||
# display.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# 1. Press left mouse button.
|
||||
#
|
||||
# -> { "execute": "input-send-event",
|
||||
# "arguments": { "device": "video0",
|
||||
# "events": [ { "type": "btn",
|
||||
# "data" : { "down": true, "button": "left" } } ] } }
|
||||
# <- { "return": {} }
|
||||
#
|
||||
# -> { "execute": "input-send-event",
|
||||
# "arguments": { "device": "video0",
|
||||
# "events": [ { "type": "btn",
|
||||
# "data" : { "down": false, "button": "left" } } ] } }
|
||||
# <- { "return": {} }
|
||||
#
|
||||
# 2. Press ctrl-alt-del.
|
||||
#
|
||||
# -> { "execute": "input-send-event",
|
||||
# "arguments": { "events": [
|
||||
# { "type": "key", "data" : { "down": true,
|
||||
# "key": {"type": "qcode", "data": "ctrl" } } },
|
||||
# { "type": "key", "data" : { "down": true,
|
||||
# "key": {"type": "qcode", "data": "alt" } } },
|
||||
# { "type": "key", "data" : { "down": true,
|
||||
# "key": {"type": "qcode", "data": "delete" } } } ] } }
|
||||
# <- { "return": {} }
|
||||
#
|
||||
# 3. Move mouse pointer to absolute coordinates (20000, 400).
|
||||
#
|
||||
# -> { "execute": "input-send-event" ,
|
||||
# "arguments": { "events": [
|
||||
# { "type": "abs", "data" : { "axis": "x", "value" : 20000 } },
|
||||
# { "type": "abs", "data" : { "axis": "y", "value" : 400 } } ] } }
|
||||
# <- { "return": {} }
|
||||
#
|
||||
##
|
||||
{ 'command': 'input-send-event',
|
||||
'data': { '*device': 'str',
|
||||
'*head' : 'int',
|
||||
'events' : [ 'InputEvent' ] } }
|
@ -26,7 +26,6 @@
|
||||
|
||||
#include "qemu-version.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/util.h"
|
||||
#include "qapi-visit.h"
|
||||
#include "qapi/qobject-output-visitor.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
@ -3490,9 +3489,8 @@ static int img_resize(int argc, char **argv)
|
||||
image_opts = true;
|
||||
break;
|
||||
case OPTION_PREALLOCATION:
|
||||
prealloc = qapi_enum_parse(PreallocMode_lookup, optarg,
|
||||
PREALLOC_MODE__MAX, PREALLOC_MODE__MAX,
|
||||
NULL);
|
||||
prealloc = qapi_enum_parse(&PreallocMode_lookup, optarg,
|
||||
PREALLOC_MODE__MAX, NULL);
|
||||
if (prealloc == PREALLOC_MODE__MAX) {
|
||||
error_report("Invalid preallocation mode '%s'", optarg);
|
||||
return 1;
|
||||
|
@ -34,7 +34,6 @@
|
||||
#include "qemu/log.h"
|
||||
#include "qemu/systemd.h"
|
||||
#include "block/snapshot.h"
|
||||
#include "qapi/util.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
#include "qom/object_interfaces.h"
|
||||
#include "io/channel-socket.h"
|
||||
@ -639,9 +638,8 @@ int main(int argc, char **argv)
|
||||
break;
|
||||
case QEMU_NBD_OPT_DETECT_ZEROES:
|
||||
detect_zeroes =
|
||||
qapi_enum_parse(BlockdevDetectZeroesOptions_lookup,
|
||||
qapi_enum_parse(&BlockdevDetectZeroesOptions_lookup,
|
||||
optarg,
|
||||
BLOCKDEV_DETECT_ZEROES_OPTIONS__MAX,
|
||||
BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF,
|
||||
&local_err);
|
||||
if (local_err) {
|
||||
|
@ -1,2 +1,2 @@
|
||||
util-obj-y = qnull.o qnum.o qstring.o qdict.o qlist.o qbool.o
|
||||
util-obj-y = qnull.o qnum.o qstring.o qdict.o qlist.o qbool.o qlit.o
|
||||
util-obj-y += qjson.o qobject.o json-lexer.o json-streamer.o json-parser.o
|
||||
|
84
qobject/qlit.c
Normal file
84
qobject/qlit.c
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* QLit literal qobject
|
||||
*
|
||||
* Copyright IBM, Corp. 2009
|
||||
* Copyright (c) 2013, 2015, 2017 Red Hat Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <aliguori@us.ibm.com>
|
||||
* Markus Armbruster <armbru@redhat.com>
|
||||
* Marc-André Lureau <marcandre.lureau@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#include "qapi/qmp/qlit.h"
|
||||
#include "qapi/qmp/types.h"
|
||||
|
||||
static bool qlit_equal_qdict(const QLitObject *lhs, const QDict *qdict)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; lhs->value.qdict[i].key; i++) {
|
||||
QObject *obj = qdict_get(qdict, lhs->value.qdict[i].key);
|
||||
|
||||
if (!qlit_equal_qobject(&lhs->value.qdict[i].value, obj)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Note: the literal qdict must not contain duplicates, this is
|
||||
* considered a programming error and it isn't checked here. */
|
||||
if (qdict_size(qdict) != i) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool qlit_equal_qlist(const QLitObject *lhs, const QList *qlist)
|
||||
{
|
||||
QListEntry *e;
|
||||
int i = 0;
|
||||
|
||||
QLIST_FOREACH_ENTRY(qlist, e) {
|
||||
QObject *obj = qlist_entry_obj(e);
|
||||
|
||||
if (!qlit_equal_qobject(&lhs->value.qlist[i], obj)) {
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
return !e && lhs->value.qlist[i].type == QTYPE_NONE;
|
||||
}
|
||||
|
||||
bool qlit_equal_qobject(const QLitObject *lhs, const QObject *rhs)
|
||||
{
|
||||
if (!rhs || lhs->type != qobject_type(rhs)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (lhs->type) {
|
||||
case QTYPE_QBOOL:
|
||||
return lhs->value.qbool == qbool_get_bool(qobject_to_qbool(rhs));
|
||||
case QTYPE_QNUM:
|
||||
return lhs->value.qnum == qnum_get_int(qobject_to_qnum(rhs));
|
||||
case QTYPE_QSTRING:
|
||||
return (strcmp(lhs->value.qstr,
|
||||
qstring_get_str(qobject_to_qstring(rhs))) == 0);
|
||||
case QTYPE_QDICT:
|
||||
return qlit_equal_qdict(lhs, qobject_to_qdict(rhs));
|
||||
case QTYPE_QLIST:
|
||||
return qlit_equal_qlist(lhs, qobject_to_qlist(rhs));
|
||||
case QTYPE_QNULL:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
16
qom/object.c
16
qom/object.c
@ -1246,7 +1246,7 @@ uint64_t object_property_get_uint(Object *obj, const char *name,
|
||||
}
|
||||
|
||||
typedef struct EnumProperty {
|
||||
const char * const *strings;
|
||||
const QEnumLookup *lookup;
|
||||
int (*get)(Object *, Error **);
|
||||
void (*set)(Object *, int, Error **);
|
||||
} EnumProperty;
|
||||
@ -1284,7 +1284,7 @@ int object_property_get_enum(Object *obj, const char *name,
|
||||
visit_complete(v, &str);
|
||||
visit_free(v);
|
||||
v = string_input_visitor_new(str);
|
||||
visit_type_enum(v, name, &ret, enumprop->strings, errp);
|
||||
visit_type_enum(v, name, &ret, enumprop->lookup, errp);
|
||||
|
||||
g_free(str);
|
||||
visit_free(v);
|
||||
@ -1950,7 +1950,7 @@ static void property_get_enum(Object *obj, Visitor *v, const char *name,
|
||||
return;
|
||||
}
|
||||
|
||||
visit_type_enum(v, name, &value, prop->strings, errp);
|
||||
visit_type_enum(v, name, &value, prop->lookup, errp);
|
||||
}
|
||||
|
||||
static void property_set_enum(Object *obj, Visitor *v, const char *name,
|
||||
@ -1960,7 +1960,7 @@ static void property_set_enum(Object *obj, Visitor *v, const char *name,
|
||||
int value;
|
||||
Error *err = NULL;
|
||||
|
||||
visit_type_enum(v, name, &value, prop->strings, &err);
|
||||
visit_type_enum(v, name, &value, prop->lookup, &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
@ -1977,7 +1977,7 @@ static void property_release_enum(Object *obj, const char *name,
|
||||
|
||||
void object_property_add_enum(Object *obj, const char *name,
|
||||
const char *typename,
|
||||
const char * const *strings,
|
||||
const QEnumLookup *lookup,
|
||||
int (*get)(Object *, Error **),
|
||||
void (*set)(Object *, int, Error **),
|
||||
Error **errp)
|
||||
@ -1985,7 +1985,7 @@ void object_property_add_enum(Object *obj, const char *name,
|
||||
Error *local_err = NULL;
|
||||
EnumProperty *prop = g_malloc(sizeof(*prop));
|
||||
|
||||
prop->strings = strings;
|
||||
prop->lookup = lookup;
|
||||
prop->get = get;
|
||||
prop->set = set;
|
||||
|
||||
@ -2002,7 +2002,7 @@ void object_property_add_enum(Object *obj, const char *name,
|
||||
|
||||
void object_class_property_add_enum(ObjectClass *klass, const char *name,
|
||||
const char *typename,
|
||||
const char * const *strings,
|
||||
const QEnumLookup *lookup,
|
||||
int (*get)(Object *, Error **),
|
||||
void (*set)(Object *, int, Error **),
|
||||
Error **errp)
|
||||
@ -2010,7 +2010,7 @@ void object_class_property_add_enum(ObjectClass *klass, const char *name,
|
||||
Error *local_err = NULL;
|
||||
EnumProperty *prop = g_malloc(sizeof(*prop));
|
||||
|
||||
prop->strings = strings;
|
||||
prop->lookup = lookup;
|
||||
prop->get = get;
|
||||
prop->set = set;
|
||||
|
||||
|
@ -20,6 +20,9 @@ expression Obj, Key, E;
|
||||
|
|
||||
- qdict_put(Obj, Key, qstring_from_str(E));
|
||||
+ qdict_put_str(Obj, Key, E);
|
||||
|
|
||||
- qdict_put(Obj, Key, qnull());
|
||||
+ qdict_put_null(Obj, Key);
|
||||
)
|
||||
|
||||
// Use QList macros where they make sense
|
||||
|
@ -217,6 +217,7 @@ fdef.write(mcgen('''
|
||||
|
||||
fdecl.write(mcgen('''
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/util.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
#include "%(prefix)sqapi-types.h"
|
||||
|
||||
|
@ -292,6 +292,10 @@ fdef.write(mcgen('''
|
||||
''',
|
||||
prefix=prefix))
|
||||
|
||||
fdecl.write(mcgen('''
|
||||
#include "qapi/util.h"
|
||||
'''))
|
||||
|
||||
schema = QAPISchema(input_file)
|
||||
gen = QAPISchemaGenTypeVisitor()
|
||||
schema.visit(gen)
|
||||
|
@ -153,7 +153,7 @@ def gen_visit_enum(name):
|
||||
void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s *obj, Error **errp)
|
||||
{
|
||||
int value = *obj;
|
||||
visit_type_enum(v, name, &value, %(c_name)s_lookup, errp);
|
||||
visit_type_enum(v, name, &value, &%(c_name)s_lookup, errp);
|
||||
*obj = value;
|
||||
}
|
||||
''',
|
||||
|
@ -825,11 +825,11 @@ def check_alternate(expr, info):
|
||||
else:
|
||||
conflicting.add('QTYPE_QNUM')
|
||||
conflicting.add('QTYPE_QBOOL')
|
||||
if conflicting & set(types_seen):
|
||||
raise QAPISemError(info, "Alternate '%s' member '%s' can't "
|
||||
"be distinguished from member '%s'"
|
||||
% (name, key, types_seen[qtype]))
|
||||
for qt in conflicting:
|
||||
if qt in types_seen:
|
||||
raise QAPISemError(info, "Alternate '%s' member '%s' can't "
|
||||
"be distinguished from member '%s'"
|
||||
% (name, key, types_seen[qt]))
|
||||
types_seen[qt] = key
|
||||
|
||||
|
||||
@ -1849,22 +1849,23 @@ def guardend(name):
|
||||
def gen_enum_lookup(name, values, prefix=None):
|
||||
ret = mcgen('''
|
||||
|
||||
const char *const %(c_name)s_lookup[] = {
|
||||
const QEnumLookup %(c_name)s_lookup = {
|
||||
.array = (const char *const[]) {
|
||||
''',
|
||||
c_name=c_name(name))
|
||||
for value in values:
|
||||
index = c_enum_const(name, value, prefix)
|
||||
ret += mcgen('''
|
||||
[%(index)s] = "%(value)s",
|
||||
[%(index)s] = "%(value)s",
|
||||
''',
|
||||
index=index, value=value)
|
||||
|
||||
max_index = c_enum_const(name, '_MAX', prefix)
|
||||
ret += mcgen('''
|
||||
[%(max_index)s] = NULL,
|
||||
},
|
||||
.size = %(max_index)s
|
||||
};
|
||||
''',
|
||||
max_index=max_index)
|
||||
max_index=c_enum_const(name, '_MAX', prefix))
|
||||
return ret
|
||||
|
||||
|
||||
@ -1894,7 +1895,10 @@ typedef enum %(c_name)s {
|
||||
|
||||
ret += mcgen('''
|
||||
|
||||
extern const char *const %(c_name)s_lookup[];
|
||||
#define %(c_name)s_str(val) \\
|
||||
qapi_enum_lookup(&%(c_name)s_lookup, (val))
|
||||
|
||||
extern const QEnumLookup %(c_name)s_lookup;
|
||||
''',
|
||||
c_name=c_name(name))
|
||||
return ret
|
||||
|
@ -2498,7 +2498,7 @@ static QDict *x86_cpu_static_props(void)
|
||||
|
||||
d = qdict_new();
|
||||
for (i = 0; props[i]; i++) {
|
||||
qdict_put(d, props[i], qnull());
|
||||
qdict_put_null(d, props[i]);
|
||||
}
|
||||
|
||||
for (w = 0; w < FEATURE_WORDS; w++) {
|
||||
@ -2508,7 +2508,7 @@ static QDict *x86_cpu_static_props(void)
|
||||
if (!fi->feat_names[bit]) {
|
||||
continue;
|
||||
}
|
||||
qdict_put(d, fi->feat_names[bit], qnull());
|
||||
qdict_put_null(d, fi->feat_names[bit]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,8 @@ check-unit-y += tests/check-qnull$(EXESUF)
|
||||
gcov-files-check-qnull-y = qobject/qnull.c
|
||||
check-unit-y += tests/check-qjson$(EXESUF)
|
||||
gcov-files-check-qjson-y = qobject/qjson.c
|
||||
check-unit-y += tests/check-qlit$(EXESUF)
|
||||
gcov-files-check-qlit-y = qobject/qlit.c
|
||||
check-unit-y += tests/test-qobject-output-visitor$(EXESUF)
|
||||
gcov-files-test-qobject-output-visitor-y = qapi/qobject-output-visitor.c
|
||||
check-unit-y += tests/test-clone-visitor$(EXESUF)
|
||||
@ -376,6 +378,8 @@ qapi-schema += alternate-conflict-dict.json
|
||||
qapi-schema += alternate-conflict-enum-bool.json
|
||||
qapi-schema += alternate-conflict-enum-int.json
|
||||
qapi-schema += alternate-conflict-string.json
|
||||
qapi-schema += alternate-conflict-bool-string.json
|
||||
qapi-schema += alternate-conflict-num-string.json
|
||||
qapi-schema += alternate-empty.json
|
||||
qapi-schema += alternate-nested.json
|
||||
qapi-schema += alternate-unknown.json
|
||||
@ -539,7 +543,7 @@ GENERATED_FILES += tests/test-qapi-types.h tests/test-qapi-visit.h \
|
||||
|
||||
test-obj-y = tests/check-qnum.o tests/check-qstring.o tests/check-qdict.o \
|
||||
tests/check-qlist.o tests/check-qnull.o \
|
||||
tests/check-qjson.o \
|
||||
tests/check-qjson.o tests/check-qlit.o \
|
||||
tests/test-coroutine.o tests/test-string-output-visitor.o \
|
||||
tests/test-string-input-visitor.o tests/test-qobject-output-visitor.o \
|
||||
tests/test-clone-visitor.o \
|
||||
@ -573,6 +577,7 @@ tests/check-qdict$(EXESUF): tests/check-qdict.o $(test-util-obj-y)
|
||||
tests/check-qlist$(EXESUF): tests/check-qlist.o $(test-util-obj-y)
|
||||
tests/check-qnull$(EXESUF): tests/check-qnull.o $(test-util-obj-y)
|
||||
tests/check-qjson$(EXESUF): tests/check-qjson.o $(test-util-obj-y)
|
||||
tests/check-qlit$(EXESUF): tests/check-qlit.o $(test-util-obj-y)
|
||||
tests/check-qom-interface$(EXESUF): tests/check-qom-interface.o $(test-qom-obj-y)
|
||||
tests/check-qom-proplist$(EXESUF): tests/check-qom-proplist.o $(test-qom-obj-y)
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qmp/types.h"
|
||||
#include "qapi/qmp/qjson.h"
|
||||
#include "qapi/qmp/qlit.h"
|
||||
#include "qemu-common.h"
|
||||
|
||||
static void escaped_string(void)
|
||||
@ -1059,123 +1060,28 @@ static void keyword_literal(void)
|
||||
QDECREF(null);
|
||||
}
|
||||
|
||||
typedef struct LiteralQDictEntry LiteralQDictEntry;
|
||||
typedef struct LiteralQObject LiteralQObject;
|
||||
|
||||
struct LiteralQObject
|
||||
{
|
||||
int type;
|
||||
union {
|
||||
int64_t qnum;
|
||||
const char *qstr;
|
||||
LiteralQDictEntry *qdict;
|
||||
LiteralQObject *qlist;
|
||||
} value;
|
||||
};
|
||||
|
||||
struct LiteralQDictEntry
|
||||
{
|
||||
const char *key;
|
||||
LiteralQObject value;
|
||||
};
|
||||
|
||||
#define QLIT_QNUM(val) (LiteralQObject){.type = QTYPE_QNUM, .value.qnum = (val)}
|
||||
#define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
|
||||
#define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
|
||||
#define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}
|
||||
|
||||
typedef struct QListCompareHelper
|
||||
{
|
||||
int index;
|
||||
LiteralQObject *objs;
|
||||
int result;
|
||||
} QListCompareHelper;
|
||||
|
||||
static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs);
|
||||
|
||||
static void compare_helper(QObject *obj, void *opaque)
|
||||
{
|
||||
QListCompareHelper *helper = opaque;
|
||||
|
||||
if (helper->result == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (helper->objs[helper->index].type == QTYPE_NONE) {
|
||||
helper->result = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
helper->result = compare_litqobj_to_qobj(&helper->objs[helper->index++], obj);
|
||||
}
|
||||
|
||||
static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs)
|
||||
{
|
||||
int64_t val;
|
||||
|
||||
if (!rhs || lhs->type != qobject_type(rhs)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (lhs->type) {
|
||||
case QTYPE_QNUM:
|
||||
g_assert(qnum_get_try_int(qobject_to_qnum(rhs), &val));
|
||||
return lhs->value.qnum == val;
|
||||
case QTYPE_QSTRING:
|
||||
return (strcmp(lhs->value.qstr, qstring_get_str(qobject_to_qstring(rhs))) == 0);
|
||||
case QTYPE_QDICT: {
|
||||
int i;
|
||||
|
||||
for (i = 0; lhs->value.qdict[i].key; i++) {
|
||||
QObject *obj = qdict_get(qobject_to_qdict(rhs), lhs->value.qdict[i].key);
|
||||
|
||||
if (!compare_litqobj_to_qobj(&lhs->value.qdict[i].value, obj)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
case QTYPE_QLIST: {
|
||||
QListCompareHelper helper;
|
||||
|
||||
helper.index = 0;
|
||||
helper.objs = lhs->value.qlist;
|
||||
helper.result = 1;
|
||||
|
||||
qlist_iter(qobject_to_qlist(rhs), compare_helper, &helper);
|
||||
|
||||
return helper.result;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void simple_dict(void)
|
||||
{
|
||||
int i;
|
||||
struct {
|
||||
const char *encoded;
|
||||
LiteralQObject decoded;
|
||||
QLitObject decoded;
|
||||
} test_cases[] = {
|
||||
{
|
||||
.encoded = "{\"foo\": 42, \"bar\": \"hello world\"}",
|
||||
.decoded = QLIT_QDICT(((LiteralQDictEntry[]){
|
||||
.decoded = QLIT_QDICT(((QLitDictEntry[]){
|
||||
{ "foo", QLIT_QNUM(42) },
|
||||
{ "bar", QLIT_QSTR("hello world") },
|
||||
{ }
|
||||
})),
|
||||
}, {
|
||||
.encoded = "{}",
|
||||
.decoded = QLIT_QDICT(((LiteralQDictEntry[]){
|
||||
.decoded = QLIT_QDICT(((QLitDictEntry[]){
|
||||
{ }
|
||||
})),
|
||||
}, {
|
||||
.encoded = "{\"foo\": 43}",
|
||||
.decoded = QLIT_QDICT(((LiteralQDictEntry[]){
|
||||
.decoded = QLIT_QDICT(((QLitDictEntry[]){
|
||||
{ "foo", QLIT_QNUM(43) },
|
||||
{ }
|
||||
})),
|
||||
@ -1188,13 +1094,13 @@ static void simple_dict(void)
|
||||
QString *str;
|
||||
|
||||
obj = qobject_from_json(test_cases[i].encoded, &error_abort);
|
||||
g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
|
||||
g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
|
||||
|
||||
str = qobject_to_json(obj);
|
||||
qobject_decref(obj);
|
||||
|
||||
obj = qobject_from_json(qstring_get_str(str), &error_abort);
|
||||
g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
|
||||
g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
|
||||
qobject_decref(obj);
|
||||
QDECREF(str);
|
||||
}
|
||||
@ -1257,11 +1163,11 @@ static void simple_list(void)
|
||||
int i;
|
||||
struct {
|
||||
const char *encoded;
|
||||
LiteralQObject decoded;
|
||||
QLitObject decoded;
|
||||
} test_cases[] = {
|
||||
{
|
||||
.encoded = "[43,42]",
|
||||
.decoded = QLIT_QLIST(((LiteralQObject[]){
|
||||
.decoded = QLIT_QLIST(((QLitObject[]){
|
||||
QLIT_QNUM(43),
|
||||
QLIT_QNUM(42),
|
||||
{ }
|
||||
@ -1269,21 +1175,21 @@ static void simple_list(void)
|
||||
},
|
||||
{
|
||||
.encoded = "[43]",
|
||||
.decoded = QLIT_QLIST(((LiteralQObject[]){
|
||||
.decoded = QLIT_QLIST(((QLitObject[]){
|
||||
QLIT_QNUM(43),
|
||||
{ }
|
||||
})),
|
||||
},
|
||||
{
|
||||
.encoded = "[]",
|
||||
.decoded = QLIT_QLIST(((LiteralQObject[]){
|
||||
.decoded = QLIT_QLIST(((QLitObject[]){
|
||||
{ }
|
||||
})),
|
||||
},
|
||||
{
|
||||
.encoded = "[{}]",
|
||||
.decoded = QLIT_QLIST(((LiteralQObject[]){
|
||||
QLIT_QDICT(((LiteralQDictEntry[]){
|
||||
.decoded = QLIT_QLIST(((QLitObject[]){
|
||||
QLIT_QDICT(((QLitDictEntry[]){
|
||||
{},
|
||||
})),
|
||||
{},
|
||||
@ -1297,13 +1203,13 @@ static void simple_list(void)
|
||||
QString *str;
|
||||
|
||||
obj = qobject_from_json(test_cases[i].encoded, &error_abort);
|
||||
g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
|
||||
g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
|
||||
|
||||
str = qobject_to_json(obj);
|
||||
qobject_decref(obj);
|
||||
|
||||
obj = qobject_from_json(qstring_get_str(str), &error_abort);
|
||||
g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
|
||||
g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
|
||||
qobject_decref(obj);
|
||||
QDECREF(str);
|
||||
}
|
||||
@ -1314,11 +1220,11 @@ static void simple_whitespace(void)
|
||||
int i;
|
||||
struct {
|
||||
const char *encoded;
|
||||
LiteralQObject decoded;
|
||||
QLitObject decoded;
|
||||
} test_cases[] = {
|
||||
{
|
||||
.encoded = " [ 43 , 42 ]",
|
||||
.decoded = QLIT_QLIST(((LiteralQObject[]){
|
||||
.decoded = QLIT_QLIST(((QLitObject[]){
|
||||
QLIT_QNUM(43),
|
||||
QLIT_QNUM(42),
|
||||
{ }
|
||||
@ -1326,12 +1232,12 @@ static void simple_whitespace(void)
|
||||
},
|
||||
{
|
||||
.encoded = " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
|
||||
.decoded = QLIT_QLIST(((LiteralQObject[]){
|
||||
.decoded = QLIT_QLIST(((QLitObject[]){
|
||||
QLIT_QNUM(43),
|
||||
QLIT_QDICT(((LiteralQDictEntry[]){
|
||||
QLIT_QDICT(((QLitDictEntry[]){
|
||||
{ "h", QLIT_QSTR("b") },
|
||||
{ }})),
|
||||
QLIT_QLIST(((LiteralQObject[]){
|
||||
QLIT_QLIST(((QLitObject[]){
|
||||
{ }})),
|
||||
QLIT_QNUM(42),
|
||||
{ }
|
||||
@ -1339,13 +1245,13 @@ static void simple_whitespace(void)
|
||||
},
|
||||
{
|
||||
.encoded = " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
|
||||
.decoded = QLIT_QLIST(((LiteralQObject[]){
|
||||
.decoded = QLIT_QLIST(((QLitObject[]){
|
||||
QLIT_QNUM(43),
|
||||
QLIT_QDICT(((LiteralQDictEntry[]){
|
||||
QLIT_QDICT(((QLitDictEntry[]){
|
||||
{ "h", QLIT_QSTR("b") },
|
||||
{ "a", QLIT_QNUM(32) },
|
||||
{ }})),
|
||||
QLIT_QLIST(((LiteralQObject[]){
|
||||
QLIT_QLIST(((QLitObject[]){
|
||||
{ }})),
|
||||
QLIT_QNUM(42),
|
||||
{ }
|
||||
@ -1359,13 +1265,13 @@ static void simple_whitespace(void)
|
||||
QString *str;
|
||||
|
||||
obj = qobject_from_json(test_cases[i].encoded, &error_abort);
|
||||
g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
|
||||
g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
|
||||
|
||||
str = qobject_to_json(obj);
|
||||
qobject_decref(obj);
|
||||
|
||||
obj = qobject_from_json(qstring_get_str(str), &error_abort);
|
||||
g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
|
||||
g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
|
||||
|
||||
qobject_decref(obj);
|
||||
QDECREF(str);
|
||||
@ -1376,10 +1282,10 @@ static void simple_varargs(void)
|
||||
{
|
||||
QObject *embedded_obj;
|
||||
QObject *obj;
|
||||
LiteralQObject decoded = QLIT_QLIST(((LiteralQObject[]){
|
||||
QLitObject decoded = QLIT_QLIST(((QLitObject[]){
|
||||
QLIT_QNUM(1),
|
||||
QLIT_QNUM(2),
|
||||
QLIT_QLIST(((LiteralQObject[]){
|
||||
QLIT_QLIST(((QLitObject[]){
|
||||
QLIT_QNUM(32),
|
||||
QLIT_QNUM(42),
|
||||
{}})),
|
||||
@ -1389,7 +1295,7 @@ static void simple_varargs(void)
|
||||
g_assert(embedded_obj != NULL);
|
||||
|
||||
obj = qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj);
|
||||
g_assert(compare_litqobj_to_qobj(&decoded, obj) == 1);
|
||||
g_assert(qlit_equal_qobject(&decoded, obj));
|
||||
|
||||
qobject_decref(obj);
|
||||
}
|
||||
|
74
tests/check-qlit.c
Normal file
74
tests/check-qlit.c
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* QLit unit-tests.
|
||||
*
|
||||
* Copyright (C) 2017 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.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#include "qapi/qmp/qbool.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
#include "qapi/qmp/qlit.h"
|
||||
#include "qapi/qmp/qnum.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
|
||||
static QLitObject qlit = QLIT_QDICT(((QLitDictEntry[]) {
|
||||
{ "foo", QLIT_QNUM(42) },
|
||||
{ "bar", QLIT_QSTR("hello world") },
|
||||
{ "baz", QLIT_QNULL },
|
||||
{ "bee", QLIT_QLIST(((QLitObject[]) {
|
||||
QLIT_QNUM(43),
|
||||
QLIT_QNUM(44),
|
||||
QLIT_QBOOL(true),
|
||||
{ },
|
||||
}))},
|
||||
{ },
|
||||
}));
|
||||
|
||||
static QLitObject qlit_foo = QLIT_QDICT(((QLitDictEntry[]) {
|
||||
{ "foo", QLIT_QNUM(42) },
|
||||
{ },
|
||||
}));
|
||||
|
||||
static QObject *make_qobject(void)
|
||||
{
|
||||
QDict *qdict = qdict_new();
|
||||
QList *list = qlist_new();
|
||||
|
||||
qdict_put_int(qdict, "foo", 42);
|
||||
qdict_put_str(qdict, "bar", "hello world");
|
||||
qdict_put_null(qdict, "baz");
|
||||
|
||||
qlist_append_int(list, 43);
|
||||
qlist_append_int(list, 44);
|
||||
qlist_append_bool(list, true);
|
||||
qdict_put(qdict, "bee", list);
|
||||
|
||||
return QOBJECT(qdict);
|
||||
}
|
||||
|
||||
static void qlit_equal_qobject_test(void)
|
||||
{
|
||||
QObject *qobj = make_qobject();
|
||||
|
||||
g_assert(qlit_equal_qobject(&qlit, qobj));
|
||||
|
||||
g_assert(!qlit_equal_qobject(&qlit_foo, qobj));
|
||||
|
||||
qdict_put(qobject_to_qdict(qobj), "bee", qlist_new());
|
||||
g_assert(!qlit_equal_qobject(&qlit, qobj));
|
||||
|
||||
qobject_decref(qobj);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
|
||||
g_test_add_func("/qlit/equal_qobject", qlit_equal_qobject_test);
|
||||
|
||||
return g_test_run();
|
||||
}
|
@ -46,11 +46,13 @@ enum DummyAnimal {
|
||||
DUMMY_LAST,
|
||||
};
|
||||
|
||||
static const char *const dummy_animal_map[DUMMY_LAST + 1] = {
|
||||
[DUMMY_FROG] = "frog",
|
||||
[DUMMY_ALLIGATOR] = "alligator",
|
||||
[DUMMY_PLATYPUS] = "platypus",
|
||||
[DUMMY_LAST] = NULL,
|
||||
const QEnumLookup dummy_animal_map = {
|
||||
.array = (const char *const[]) {
|
||||
[DUMMY_FROG] = "frog",
|
||||
[DUMMY_ALLIGATOR] = "alligator",
|
||||
[DUMMY_PLATYPUS] = "platypus",
|
||||
},
|
||||
.size = DUMMY_LAST
|
||||
};
|
||||
|
||||
struct DummyObject {
|
||||
@ -142,7 +144,7 @@ static void dummy_class_init(ObjectClass *cls, void *data)
|
||||
NULL);
|
||||
object_class_property_add_enum(cls, "av",
|
||||
"DummyAnimal",
|
||||
dummy_animal_map,
|
||||
&dummy_animal_map,
|
||||
dummy_get_av,
|
||||
dummy_set_av,
|
||||
NULL);
|
||||
|
1
tests/qapi-schema/alternate-conflict-bool-string.err
Normal file
1
tests/qapi-schema/alternate-conflict-bool-string.err
Normal file
@ -0,0 +1 @@
|
||||
tests/qapi-schema/alternate-conflict-bool-string.json:2: Alternate 'Alt' member 'two' can't be distinguished from member 'one'
|
1
tests/qapi-schema/alternate-conflict-bool-string.exit
Normal file
1
tests/qapi-schema/alternate-conflict-bool-string.exit
Normal file
@ -0,0 +1 @@
|
||||
1
|
4
tests/qapi-schema/alternate-conflict-bool-string.json
Normal file
4
tests/qapi-schema/alternate-conflict-bool-string.json
Normal file
@ -0,0 +1,4 @@
|
||||
# alternate branches of 'str' type conflict with all scalar types
|
||||
{ 'alternate': 'Alt',
|
||||
'data': { 'one': 'bool',
|
||||
'two': 'str' } }
|
1
tests/qapi-schema/alternate-conflict-num-string.err
Normal file
1
tests/qapi-schema/alternate-conflict-num-string.err
Normal file
@ -0,0 +1 @@
|
||||
tests/qapi-schema/alternate-conflict-num-string.json:2: Alternate 'Alt' member 'two' can't be distinguished from member 'one'
|
1
tests/qapi-schema/alternate-conflict-num-string.exit
Normal file
1
tests/qapi-schema/alternate-conflict-num-string.exit
Normal file
@ -0,0 +1 @@
|
||||
1
|
4
tests/qapi-schema/alternate-conflict-num-string.json
Normal file
4
tests/qapi-schema/alternate-conflict-num-string.json
Normal file
@ -0,0 +1,4 @@
|
||||
# alternate branches of 'str' type conflict with all scalar types
|
||||
{ 'alternate': 'Alt',
|
||||
'data': { 'one': 'number',
|
||||
'two': 'str' } }
|
0
tests/qapi-schema/alternate-conflict-num-string.out
Normal file
0
tests/qapi-schema/alternate-conflict-num-string.out
Normal file
181
tests/qmp-test.c
181
tests/qmp-test.c
@ -15,6 +15,7 @@
|
||||
#include "qapi-visit.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qobject-input-visitor.h"
|
||||
#include "qapi/util.h"
|
||||
#include "qapi/visitor.h"
|
||||
|
||||
const char common_args[] = "-nodefaults -machine none";
|
||||
@ -129,11 +130,189 @@ static void test_qmp_protocol(void)
|
||||
qtest_end();
|
||||
}
|
||||
|
||||
static int query_error_class(const char *cmd)
|
||||
{
|
||||
static struct {
|
||||
const char *cmd;
|
||||
int err_class;
|
||||
} fails[] = {
|
||||
/* Success depends on build configuration: */
|
||||
#ifndef CONFIG_SPICE
|
||||
{ "query-spice", ERROR_CLASS_COMMAND_NOT_FOUND },
|
||||
#endif
|
||||
#ifndef CONFIG_VNC
|
||||
{ "query-vnc", ERROR_CLASS_GENERIC_ERROR },
|
||||
{ "query-vnc-servers", ERROR_CLASS_GENERIC_ERROR },
|
||||
#endif
|
||||
#ifndef CONFIG_REPLICATION
|
||||
{ "query-xen-replication-status", ERROR_CLASS_COMMAND_NOT_FOUND },
|
||||
#endif
|
||||
/* Likewise, and require special QEMU command-line arguments: */
|
||||
{ "query-acpi-ospm-status", ERROR_CLASS_GENERIC_ERROR },
|
||||
{ "query-balloon", ERROR_CLASS_DEVICE_NOT_ACTIVE },
|
||||
{ "query-hotpluggable-cpus", ERROR_CLASS_GENERIC_ERROR },
|
||||
{ "query-vm-generation-id", ERROR_CLASS_GENERIC_ERROR },
|
||||
{ NULL, -1 }
|
||||
};
|
||||
int i;
|
||||
|
||||
for (i = 0; fails[i].cmd; i++) {
|
||||
if (!strcmp(cmd, fails[i].cmd)) {
|
||||
return fails[i].err_class;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void test_query(const void *data)
|
||||
{
|
||||
const char *cmd = data;
|
||||
int expected_error_class = query_error_class(cmd);
|
||||
QDict *resp, *error;
|
||||
const char *error_class;
|
||||
|
||||
qtest_start(common_args);
|
||||
|
||||
resp = qmp("{ 'execute': %s }", cmd);
|
||||
error = qdict_get_qdict(resp, "error");
|
||||
error_class = error ? qdict_get_str(error, "class") : NULL;
|
||||
|
||||
if (expected_error_class < 0) {
|
||||
g_assert(qdict_haskey(resp, "return"));
|
||||
} else {
|
||||
g_assert(error);
|
||||
g_assert_cmpint(qapi_enum_parse(&QapiErrorClass_lookup, error_class,
|
||||
-1, &error_abort),
|
||||
==, expected_error_class);
|
||||
}
|
||||
QDECREF(resp);
|
||||
|
||||
qtest_end();
|
||||
}
|
||||
|
||||
static bool query_is_blacklisted(const char *cmd)
|
||||
{
|
||||
const char *blacklist[] = {
|
||||
/* Not actually queries: */
|
||||
"add-fd",
|
||||
/* Success depends on target arch: */
|
||||
"query-cpu-definitions", /* arm, i386, ppc, s390x */
|
||||
"query-gic-capabilities", /* arm */
|
||||
/* Success depends on target-specific build configuration: */
|
||||
"query-pci", /* CONFIG_PCI */
|
||||
NULL
|
||||
};
|
||||
int i;
|
||||
|
||||
for (i = 0; blacklist[i]; i++) {
|
||||
if (!strcmp(cmd, blacklist[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
SchemaInfoList *list;
|
||||
GHashTable *hash;
|
||||
} QmpSchema;
|
||||
|
||||
static void qmp_schema_init(QmpSchema *schema)
|
||||
{
|
||||
QDict *resp;
|
||||
Visitor *qiv;
|
||||
SchemaInfoList *tail;
|
||||
|
||||
qtest_start(common_args);
|
||||
resp = qmp("{ 'execute': 'query-qmp-schema' }");
|
||||
|
||||
qiv = qobject_input_visitor_new(qdict_get(resp, "return"));
|
||||
visit_type_SchemaInfoList(qiv, NULL, &schema->list, &error_abort);
|
||||
visit_free(qiv);
|
||||
|
||||
QDECREF(resp);
|
||||
qtest_end();
|
||||
|
||||
schema->hash = g_hash_table_new(g_str_hash, g_str_equal);
|
||||
|
||||
/* Build @schema: hash table mapping entity name to SchemaInfo */
|
||||
for (tail = schema->list; tail; tail = tail->next) {
|
||||
g_hash_table_insert(schema->hash, tail->value->name, tail->value);
|
||||
}
|
||||
}
|
||||
|
||||
static SchemaInfo *qmp_schema_lookup(QmpSchema *schema, const char *name)
|
||||
{
|
||||
return g_hash_table_lookup(schema->hash, name);
|
||||
}
|
||||
|
||||
static void qmp_schema_cleanup(QmpSchema *schema)
|
||||
{
|
||||
qapi_free_SchemaInfoList(schema->list);
|
||||
g_hash_table_destroy(schema->hash);
|
||||
}
|
||||
|
||||
static bool object_type_has_mandatory_members(SchemaInfo *type)
|
||||
{
|
||||
SchemaInfoObjectMemberList *tail;
|
||||
|
||||
g_assert(type->meta_type == SCHEMA_META_TYPE_OBJECT);
|
||||
|
||||
for (tail = type->u.object.members; tail; tail = tail->next) {
|
||||
if (!tail->value->has_q_default) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void add_query_tests(QmpSchema *schema)
|
||||
{
|
||||
SchemaInfoList *tail;
|
||||
SchemaInfo *si, *arg_type, *ret_type;
|
||||
const char *test_name;
|
||||
|
||||
/* Test the query-like commands */
|
||||
for (tail = schema->list; tail; tail = tail->next) {
|
||||
si = tail->value;
|
||||
if (si->meta_type != SCHEMA_META_TYPE_COMMAND) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (query_is_blacklisted(si->name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
arg_type = qmp_schema_lookup(schema, si->u.command.arg_type);
|
||||
if (object_type_has_mandatory_members(arg_type)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ret_type = qmp_schema_lookup(schema, si->u.command.ret_type);
|
||||
if (ret_type->meta_type == SCHEMA_META_TYPE_OBJECT
|
||||
&& !ret_type->u.object.members) {
|
||||
continue;
|
||||
}
|
||||
|
||||
test_name = g_strdup_printf("qmp/%s", si->name);
|
||||
qtest_add_data_func(test_name, si->name, test_query);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QmpSchema schema;
|
||||
int ret;
|
||||
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
|
||||
qtest_add_func("qmp/protocol", test_qmp_protocol);
|
||||
qmp_schema_init(&schema);
|
||||
add_query_tests(&schema);
|
||||
|
||||
return g_test_run();
|
||||
ret = g_test_run();
|
||||
|
||||
qmp_schema_cleanup(&schema);
|
||||
return ret;
|
||||
}
|
||||
|
@ -12,7 +12,6 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/util.h"
|
||||
#include "test-qapi-types.h"
|
||||
|
||||
static void test_qapi_enum_parse(void)
|
||||
@ -20,25 +19,20 @@ static void test_qapi_enum_parse(void)
|
||||
Error *err = NULL;
|
||||
int ret;
|
||||
|
||||
ret = qapi_enum_parse(QType_lookup, NULL, QTYPE__MAX, QTYPE_NONE,
|
||||
&error_abort);
|
||||
ret = qapi_enum_parse(&QType_lookup, NULL, QTYPE_NONE, &error_abort);
|
||||
g_assert_cmpint(ret, ==, QTYPE_NONE);
|
||||
|
||||
ret = qapi_enum_parse(QType_lookup, "junk", QTYPE__MAX, -1,
|
||||
NULL);
|
||||
ret = qapi_enum_parse(&QType_lookup, "junk", -1, NULL);
|
||||
g_assert_cmpint(ret, ==, -1);
|
||||
|
||||
ret = qapi_enum_parse(QType_lookup, "junk", QTYPE__MAX, -1,
|
||||
&err);
|
||||
ret = qapi_enum_parse(&QType_lookup, "junk", -1, &err);
|
||||
error_free_or_abort(&err);
|
||||
|
||||
ret = qapi_enum_parse(QType_lookup, "none", QTYPE__MAX, -1,
|
||||
&error_abort);
|
||||
ret = qapi_enum_parse(&QType_lookup, "none", -1, &error_abort);
|
||||
g_assert_cmpint(ret, ==, QTYPE_NONE);
|
||||
|
||||
ret = qapi_enum_parse(QType_lookup, QType_lookup[QTYPE__MAX - 1],
|
||||
QTYPE__MAX, QTYPE__MAX - 1,
|
||||
&error_abort);
|
||||
ret = qapi_enum_parse(&QType_lookup, QType_str(QTYPE__MAX - 1),
|
||||
QTYPE__MAX - 1, &error_abort);
|
||||
g_assert_cmpint(ret, ==, QTYPE__MAX - 1);
|
||||
}
|
||||
|
||||
|
@ -382,10 +382,10 @@ static void test_visitor_in_enum(TestInputVisitorData *data,
|
||||
Visitor *v;
|
||||
EnumOne i;
|
||||
|
||||
for (i = 0; EnumOne_lookup[i]; i++) {
|
||||
for (i = 0; i < ENUM_ONE__MAX; i++) {
|
||||
EnumOne res = -1;
|
||||
|
||||
v = visitor_input_test_init(data, "%s", EnumOne_lookup[i]);
|
||||
v = visitor_input_test_init(data, "%s", EnumOne_str(i));
|
||||
|
||||
visit_type_EnumOne(v, NULL, &res, &error_abort);
|
||||
g_assert_cmpint(i, ==, res);
|
||||
@ -699,7 +699,7 @@ static void test_native_list_integer_helper(TestInputVisitorData *data,
|
||||
}
|
||||
}
|
||||
g_string_append_printf(gstr_union, "{ 'type': '%s', 'data': [ %s ] }",
|
||||
UserDefNativeListUnionKind_lookup[kind],
|
||||
UserDefNativeListUnionKind_str(kind),
|
||||
gstr_list->str);
|
||||
v = visitor_input_test_init_raw(data, gstr_union->str);
|
||||
|
||||
@ -1110,7 +1110,7 @@ static void test_visitor_in_fail_struct_missing(TestInputVisitorData *data,
|
||||
error_free_or_abort(&err);
|
||||
visit_optional(v, "optional", &present);
|
||||
g_assert(!present);
|
||||
visit_type_enum(v, "enum", &en, EnumOne_lookup, &err);
|
||||
visit_type_enum(v, "enum", &en, &EnumOne_lookup, &err);
|
||||
error_free_or_abort(&err);
|
||||
visit_type_int(v, "i64", &i64, &err);
|
||||
error_free_or_abort(&err);
|
||||
|
@ -133,7 +133,7 @@ static void test_visitor_out_enum(TestOutputVisitorData *data,
|
||||
|
||||
qstr = qobject_to_qstring(visitor_get(data));
|
||||
g_assert(qstr);
|
||||
g_assert_cmpstr(qstring_get_str(qstr), ==, EnumOne_lookup[i]);
|
||||
g_assert_cmpstr(qstring_get_str(qstr), ==, EnumOne_str(i));
|
||||
visitor_reset(data);
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user