Merge remote branch 'qmp/for-anthony' into staging
This commit is contained in:
commit
48f57044e6
4
Makefile
4
Makefile
@ -255,10 +255,10 @@ TEXIFLAG=$(if $(V),,--quiet)
|
||||
qemu-options.texi: $(SRC_PATH)/qemu-options.hx
|
||||
$(call quiet-command,sh $(SRC_PATH)/hxtool -t < $< > $@," GEN $@")
|
||||
|
||||
qemu-monitor.texi: $(SRC_PATH)/qemu-monitor.hx
|
||||
qemu-monitor.texi: $(SRC_PATH)/hmp-commands.hx
|
||||
$(call quiet-command,sh $(SRC_PATH)/hxtool -t < $< > $@," GEN $@")
|
||||
|
||||
QMP/qmp-commands.txt: $(SRC_PATH)/qemu-monitor.hx
|
||||
QMP/qmp-commands.txt: $(SRC_PATH)/qmp-commands.hx
|
||||
$(call quiet-command,sh $(SRC_PATH)/hxtool -q < $< > $@," GEN $@")
|
||||
|
||||
qemu-img-cmds.texi: $(SRC_PATH)/qemu-img-cmds.hx
|
||||
|
@ -309,7 +309,7 @@ obj-alpha-y = alpha_palcode.o
|
||||
|
||||
main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
|
||||
|
||||
monitor.o: qemu-monitor.h
|
||||
monitor.o: hmp-commands.h qmp-commands.h
|
||||
|
||||
$(obj-y) $(obj-$(TARGET_BASE_ARCH)-y): $(GENERATED_HEADERS)
|
||||
|
||||
@ -330,13 +330,16 @@ $(QEMU_PROG): $(obj-y) $(obj-$(TARGET_BASE_ARCH)-y)
|
||||
gdbstub-xml.c: $(TARGET_XML_FILES) $(SRC_PATH)/feature_to_c.sh
|
||||
$(call quiet-command,rm -f $@ && $(SHELL) $(SRC_PATH)/feature_to_c.sh $@ $(TARGET_XML_FILES)," GEN $(TARGET_DIR)$@")
|
||||
|
||||
qemu-monitor.h: $(SRC_PATH)/qemu-monitor.hx
|
||||
hmp-commands.h: $(SRC_PATH)/hmp-commands.hx
|
||||
$(call quiet-command,sh $(SRC_PATH)/hxtool -h < $< > $@," GEN $(TARGET_DIR)$@")
|
||||
|
||||
qmp-commands.h: $(SRC_PATH)/qmp-commands.hx
|
||||
$(call quiet-command,sh $(SRC_PATH)/hxtool -h < $< > $@," GEN $(TARGET_DIR)$@")
|
||||
|
||||
clean:
|
||||
rm -f *.o *.a *~ $(PROGS) nwfpe/*.o fpu/*.o
|
||||
rm -f *.d */*.d tcg/*.o ide/*.o
|
||||
rm -f qemu-monitor.h gdbstub-xml.c
|
||||
rm -f hmp-commands.h qmp-commands.h gdbstub-xml.c
|
||||
|
||||
install: all
|
||||
ifneq ($(PROGS),)
|
||||
|
@ -82,10 +82,10 @@ doing any code change. This is so because:
|
||||
2. Review can improve your interface. Letting that happen before
|
||||
you implement it can save you work.
|
||||
|
||||
* The qmp-commands.txt file is generated from the qemu-monitor.hx one, which
|
||||
* The qmp-commands.txt file is generated from the qmp-commands.hx one, which
|
||||
is the file that should be edited.
|
||||
|
||||
Homepage
|
||||
--------
|
||||
|
||||
http://www.linux-kvm.org/page/MonitorProtocol
|
||||
http://wiki.qemu.org/QMP
|
||||
|
1216
hmp-commands.hx
Normal file
1216
hmp-commands.hx
Normal file
File diff suppressed because it is too large
Load Diff
@ -29,6 +29,10 @@
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
/* Disable guest-provided stats by now (https://bugzilla.redhat.com/show_bug.cgi?id=623903) */
|
||||
#define ENABLE_GUEST_STATS 0
|
||||
|
||||
|
||||
typedef struct VirtIOBalloon
|
||||
{
|
||||
VirtIODevice vdev;
|
||||
@ -83,12 +87,14 @@ static QObject *get_stats_qobject(VirtIOBalloon *dev)
|
||||
VIRTIO_BALLOON_PFN_SHIFT);
|
||||
|
||||
stat_put(dict, "actual", actual);
|
||||
#if ENABLE_GUEST_STATS
|
||||
stat_put(dict, "mem_swapped_in", dev->stats[VIRTIO_BALLOON_S_SWAP_IN]);
|
||||
stat_put(dict, "mem_swapped_out", dev->stats[VIRTIO_BALLOON_S_SWAP_OUT]);
|
||||
stat_put(dict, "major_page_faults", dev->stats[VIRTIO_BALLOON_S_MAJFLT]);
|
||||
stat_put(dict, "minor_page_faults", dev->stats[VIRTIO_BALLOON_S_MINFLT]);
|
||||
stat_put(dict, "free_mem", dev->stats[VIRTIO_BALLOON_S_MEMFREE]);
|
||||
stat_put(dict, "total_mem", dev->stats[VIRTIO_BALLOON_S_MEMTOT]);
|
||||
#endif
|
||||
|
||||
return QOBJECT(dict);
|
||||
}
|
||||
@ -214,7 +220,7 @@ static void virtio_balloon_to_target(void *opaque, ram_addr_t target,
|
||||
}
|
||||
dev->stats_callback = cb;
|
||||
dev->stats_opaque_callback_data = cb_data;
|
||||
if (dev->vdev.guest_features & (1 << VIRTIO_BALLOON_F_STATS_VQ)) {
|
||||
if (ENABLE_GUEST_STATS && (dev->vdev.guest_features & (1 << VIRTIO_BALLOON_F_STATS_VQ))) {
|
||||
virtqueue_push(dev->svq, &dev->stats_vq_elem, dev->stats_vq_offset);
|
||||
virtio_notify(&dev->vdev, dev->svq);
|
||||
} else {
|
||||
|
366
monitor.c
366
monitor.c
@ -189,6 +189,9 @@ static QLIST_HEAD(mon_list, Monitor) mon_list;
|
||||
static const mon_cmd_t mon_cmds[];
|
||||
static const mon_cmd_t info_cmds[];
|
||||
|
||||
static const mon_cmd_t qmp_cmds[];
|
||||
static const mon_cmd_t qmp_query_cmds[];
|
||||
|
||||
Monitor *cur_mon;
|
||||
Monitor *default_mon;
|
||||
|
||||
@ -328,21 +331,16 @@ static int GCC_FMT_ATTR(2, 3) monitor_fprintf(FILE *stream,
|
||||
|
||||
static void monitor_user_noop(Monitor *mon, const QObject *data) { }
|
||||
|
||||
static inline int monitor_handler_ported(const mon_cmd_t *cmd)
|
||||
static inline int handler_is_qobject(const mon_cmd_t *cmd)
|
||||
{
|
||||
return cmd->user_print != NULL;
|
||||
}
|
||||
|
||||
static inline bool monitor_handler_is_async(const mon_cmd_t *cmd)
|
||||
static inline bool handler_is_async(const mon_cmd_t *cmd)
|
||||
{
|
||||
return cmd->flags & MONITOR_CMD_ASYNC;
|
||||
}
|
||||
|
||||
static inline bool monitor_cmd_user_only(const mon_cmd_t *cmd)
|
||||
{
|
||||
return (cmd->flags & MONITOR_CMD_USER_ONLY);
|
||||
}
|
||||
|
||||
static inline int monitor_has_error(const Monitor *mon)
|
||||
{
|
||||
return mon->error != NULL;
|
||||
@ -352,7 +350,10 @@ static void monitor_json_emitter(Monitor *mon, const QObject *data)
|
||||
{
|
||||
QString *json;
|
||||
|
||||
json = qobject_to_json(data);
|
||||
if (mon->flags & MONITOR_USE_PRETTY)
|
||||
json = qobject_to_json_pretty(data);
|
||||
else
|
||||
json = qobject_to_json(data);
|
||||
assert(json != NULL);
|
||||
|
||||
qstring_append_chr(json, '\n');
|
||||
@ -634,13 +635,12 @@ static void user_async_info_handler(Monitor *mon, const mon_cmd_t *cmd)
|
||||
}
|
||||
}
|
||||
|
||||
static int do_info(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
||||
static void do_info(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
const mon_cmd_t *cmd;
|
||||
const char *item = qdict_get_try_str(qdict, "item");
|
||||
|
||||
if (!item) {
|
||||
assert(monitor_ctrl_mode(mon) == 0);
|
||||
goto help;
|
||||
}
|
||||
|
||||
@ -650,56 +650,27 @@ static int do_info(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
||||
}
|
||||
|
||||
if (cmd->name == NULL) {
|
||||
if (monitor_ctrl_mode(mon)) {
|
||||
qerror_report(QERR_COMMAND_NOT_FOUND, item);
|
||||
return -1;
|
||||
}
|
||||
goto help;
|
||||
}
|
||||
|
||||
if (monitor_ctrl_mode(mon) && monitor_cmd_user_only(cmd)) {
|
||||
qerror_report(QERR_COMMAND_NOT_FOUND, item);
|
||||
return -1;
|
||||
}
|
||||
if (handler_is_async(cmd)) {
|
||||
user_async_info_handler(mon, cmd);
|
||||
} else if (handler_is_qobject(cmd)) {
|
||||
QObject *info_data = NULL;
|
||||
|
||||
if (monitor_handler_is_async(cmd)) {
|
||||
if (monitor_ctrl_mode(mon)) {
|
||||
qmp_async_info_handler(mon, cmd);
|
||||
} else {
|
||||
user_async_info_handler(mon, cmd);
|
||||
}
|
||||
/*
|
||||
* Indicate that this command is asynchronous and will not return any
|
||||
* data (not even empty). Instead, the data will be returned via a
|
||||
* completion callback.
|
||||
*/
|
||||
*ret_data = qobject_from_jsonf("{ '__mon_async': 'return' }");
|
||||
} else if (monitor_handler_ported(cmd)) {
|
||||
cmd->mhandler.info_new(mon, ret_data);
|
||||
|
||||
if (!monitor_ctrl_mode(mon)) {
|
||||
/*
|
||||
* User Protocol function is called here, Monitor Protocol is
|
||||
* handled by monitor_call_handler()
|
||||
*/
|
||||
if (*ret_data)
|
||||
cmd->user_print(mon, *ret_data);
|
||||
cmd->mhandler.info_new(mon, &info_data);
|
||||
if (info_data) {
|
||||
cmd->user_print(mon, info_data);
|
||||
qobject_decref(info_data);
|
||||
}
|
||||
} else {
|
||||
if (monitor_ctrl_mode(mon)) {
|
||||
/* handler not converted yet */
|
||||
qerror_report(QERR_COMMAND_NOT_FOUND, item);
|
||||
return -1;
|
||||
} else {
|
||||
cmd->mhandler.info(mon);
|
||||
}
|
||||
cmd->mhandler.info(mon);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return;
|
||||
|
||||
help:
|
||||
help_cmd(mon, "info");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void do_info_version_print(Monitor *mon, const QObject *data)
|
||||
@ -773,19 +744,14 @@ static void do_info_commands(Monitor *mon, QObject **ret_data)
|
||||
|
||||
cmd_list = qlist_new();
|
||||
|
||||
for (cmd = mon_cmds; cmd->name != NULL; cmd++) {
|
||||
if (monitor_handler_ported(cmd) && !monitor_cmd_user_only(cmd) &&
|
||||
!compare_cmd(cmd->name, "info")) {
|
||||
qlist_append_obj(cmd_list, get_cmd_dict(cmd->name));
|
||||
}
|
||||
for (cmd = qmp_cmds; cmd->name != NULL; cmd++) {
|
||||
qlist_append_obj(cmd_list, get_cmd_dict(cmd->name));
|
||||
}
|
||||
|
||||
for (cmd = info_cmds; cmd->name != NULL; cmd++) {
|
||||
if (monitor_handler_ported(cmd) && !monitor_cmd_user_only(cmd)) {
|
||||
char buf[128];
|
||||
snprintf(buf, sizeof(buf), "query-%s", cmd->name);
|
||||
qlist_append_obj(cmd_list, get_cmd_dict(buf));
|
||||
}
|
||||
for (cmd = qmp_query_cmds; cmd->name != NULL; cmd++) {
|
||||
char buf[128];
|
||||
snprintf(buf, sizeof(buf), "query-%s", cmd->name);
|
||||
qlist_append_obj(cmd_list, get_cmd_dict(buf));
|
||||
}
|
||||
|
||||
*ret_data = QOBJECT(cmd_list);
|
||||
@ -2367,11 +2333,11 @@ int monitor_get_fd(Monitor *mon, const char *fdname)
|
||||
}
|
||||
|
||||
static const mon_cmd_t mon_cmds[] = {
|
||||
#include "qemu-monitor.h"
|
||||
#include "hmp-commands.h"
|
||||
{ NULL, NULL, },
|
||||
};
|
||||
|
||||
/* Please update qemu-monitor.hx when adding or changing commands */
|
||||
/* Please update hmp-commands.hx when adding or changing commands */
|
||||
static const mon_cmd_t info_cmds[] = {
|
||||
{
|
||||
.name = "version",
|
||||
@ -2381,14 +2347,6 @@ static const mon_cmd_t info_cmds[] = {
|
||||
.user_print = do_info_version_print,
|
||||
.mhandler.info_new = do_info_version,
|
||||
},
|
||||
{
|
||||
.name = "commands",
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
.help = "list QMP available commands",
|
||||
.user_print = monitor_user_noop,
|
||||
.mhandler.info_new = do_info_commands,
|
||||
},
|
||||
{
|
||||
.name = "network",
|
||||
.args_type = "",
|
||||
@ -2663,6 +2621,136 @@ static const mon_cmd_t info_cmds[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static const mon_cmd_t qmp_cmds[] = {
|
||||
#include "qmp-commands.h"
|
||||
{ /* NULL */ },
|
||||
};
|
||||
|
||||
static const mon_cmd_t qmp_query_cmds[] = {
|
||||
{
|
||||
.name = "version",
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
.help = "show the version of QEMU",
|
||||
.user_print = do_info_version_print,
|
||||
.mhandler.info_new = do_info_version,
|
||||
},
|
||||
{
|
||||
.name = "commands",
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
.help = "list QMP available commands",
|
||||
.user_print = monitor_user_noop,
|
||||
.mhandler.info_new = do_info_commands,
|
||||
},
|
||||
{
|
||||
.name = "chardev",
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
.help = "show the character devices",
|
||||
.user_print = qemu_chr_info_print,
|
||||
.mhandler.info_new = qemu_chr_info,
|
||||
},
|
||||
{
|
||||
.name = "block",
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
.help = "show the block devices",
|
||||
.user_print = bdrv_info_print,
|
||||
.mhandler.info_new = bdrv_info,
|
||||
},
|
||||
{
|
||||
.name = "blockstats",
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
.help = "show block device statistics",
|
||||
.user_print = bdrv_stats_print,
|
||||
.mhandler.info_new = bdrv_info_stats,
|
||||
},
|
||||
{
|
||||
.name = "cpus",
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
.help = "show infos for each CPU",
|
||||
.user_print = monitor_print_cpus,
|
||||
.mhandler.info_new = do_info_cpus,
|
||||
},
|
||||
{
|
||||
.name = "pci",
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
.help = "show PCI info",
|
||||
.user_print = do_pci_info_print,
|
||||
.mhandler.info_new = do_pci_info,
|
||||
},
|
||||
{
|
||||
.name = "kvm",
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
.help = "show KVM information",
|
||||
.user_print = do_info_kvm_print,
|
||||
.mhandler.info_new = do_info_kvm,
|
||||
},
|
||||
{
|
||||
.name = "status",
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
.help = "show the current VM status (running|paused)",
|
||||
.user_print = do_info_status_print,
|
||||
.mhandler.info_new = do_info_status,
|
||||
},
|
||||
{
|
||||
.name = "mice",
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
.help = "show which guest mouse is receiving events",
|
||||
.user_print = do_info_mice_print,
|
||||
.mhandler.info_new = do_info_mice,
|
||||
},
|
||||
{
|
||||
.name = "vnc",
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
.help = "show the vnc server status",
|
||||
.user_print = do_info_vnc_print,
|
||||
.mhandler.info_new = do_info_vnc,
|
||||
},
|
||||
{
|
||||
.name = "name",
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
.help = "show the current VM name",
|
||||
.user_print = do_info_name_print,
|
||||
.mhandler.info_new = do_info_name,
|
||||
},
|
||||
{
|
||||
.name = "uuid",
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
.help = "show the current VM UUID",
|
||||
.user_print = do_info_uuid_print,
|
||||
.mhandler.info_new = do_info_uuid,
|
||||
},
|
||||
{
|
||||
.name = "migrate",
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
.help = "show migration status",
|
||||
.user_print = do_info_migrate_print,
|
||||
.mhandler.info_new = do_info_migrate,
|
||||
},
|
||||
{
|
||||
.name = "balloon",
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
.help = "show balloon information",
|
||||
.user_print = monitor_print_balloon,
|
||||
.mhandler.info_async = do_info_balloon,
|
||||
.flags = MONITOR_CMD_ASYNC,
|
||||
},
|
||||
{ /* NULL */ },
|
||||
};
|
||||
|
||||
/*******************************************************************/
|
||||
|
||||
static const char *pch;
|
||||
@ -3369,11 +3457,12 @@ static int is_valid_option(const char *c, const char *typestr)
|
||||
return (typestr != NULL);
|
||||
}
|
||||
|
||||
static const mon_cmd_t *monitor_find_command(const char *cmdname)
|
||||
static const mon_cmd_t *search_dispatch_table(const mon_cmd_t *disp_table,
|
||||
const char *cmdname)
|
||||
{
|
||||
const mon_cmd_t *cmd;
|
||||
|
||||
for (cmd = mon_cmds; cmd->name != NULL; cmd++) {
|
||||
for (cmd = disp_table; cmd->name != NULL; cmd++) {
|
||||
if (compare_cmd(cmdname, cmd->name)) {
|
||||
return cmd;
|
||||
}
|
||||
@ -3382,6 +3471,21 @@ static const mon_cmd_t *monitor_find_command(const char *cmdname)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const mon_cmd_t *monitor_find_command(const char *cmdname)
|
||||
{
|
||||
return search_dispatch_table(mon_cmds, cmdname);
|
||||
}
|
||||
|
||||
static const mon_cmd_t *qmp_find_query_cmd(const char *info_item)
|
||||
{
|
||||
return search_dispatch_table(qmp_query_cmds, info_item);
|
||||
}
|
||||
|
||||
static const mon_cmd_t *qmp_find_cmd(const char *cmdname)
|
||||
{
|
||||
return search_dispatch_table(qmp_cmds, cmdname);
|
||||
}
|
||||
|
||||
static const mon_cmd_t *monitor_parse_command(Monitor *mon,
|
||||
const char *cmdline,
|
||||
QDict *qdict)
|
||||
@ -3730,15 +3834,6 @@ void monitor_set_error(Monitor *mon, QError *qerror)
|
||||
}
|
||||
}
|
||||
|
||||
static int is_async_return(const QObject *data)
|
||||
{
|
||||
if (data && qobject_type(data) == QTYPE_QDICT) {
|
||||
return qdict_haskey(qobject_to_qdict(data), "__mon_async");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void handler_audit(Monitor *mon, const mon_cmd_t *cmd, int ret)
|
||||
{
|
||||
if (monitor_ctrl_mode(mon)) {
|
||||
@ -3786,37 +3881,6 @@ static void handler_audit(Monitor *mon, const mon_cmd_t *cmd, int ret)
|
||||
}
|
||||
}
|
||||
|
||||
static void monitor_call_handler(Monitor *mon, const mon_cmd_t *cmd,
|
||||
const QDict *params)
|
||||
{
|
||||
int ret;
|
||||
QObject *data = NULL;
|
||||
|
||||
mon_print_count_init(mon);
|
||||
|
||||
ret = cmd->mhandler.cmd_new(mon, params, &data);
|
||||
handler_audit(mon, cmd, ret);
|
||||
|
||||
if (is_async_return(data)) {
|
||||
/*
|
||||
* Asynchronous commands have no initial return data but they can
|
||||
* generate errors. Data is returned via the async completion handler.
|
||||
*/
|
||||
if (monitor_ctrl_mode(mon) && monitor_has_error(mon)) {
|
||||
monitor_protocol_emitter(mon, NULL);
|
||||
}
|
||||
} else if (monitor_ctrl_mode(mon)) {
|
||||
/* Monitor Protocol */
|
||||
monitor_protocol_emitter(mon, data);
|
||||
} else {
|
||||
/* User Protocol */
|
||||
if (data)
|
||||
cmd->user_print(mon, data);
|
||||
}
|
||||
|
||||
qobject_decref(data);
|
||||
}
|
||||
|
||||
static void handle_user_command(Monitor *mon, const char *cmdline)
|
||||
{
|
||||
QDict *qdict;
|
||||
@ -3828,10 +3892,18 @@ static void handle_user_command(Monitor *mon, const char *cmdline)
|
||||
if (!cmd)
|
||||
goto out;
|
||||
|
||||
if (monitor_handler_is_async(cmd)) {
|
||||
if (handler_is_async(cmd)) {
|
||||
user_async_cmd_handler(mon, cmd, qdict);
|
||||
} else if (monitor_handler_ported(cmd)) {
|
||||
monitor_call_handler(mon, cmd, qdict);
|
||||
} else if (handler_is_qobject(cmd)) {
|
||||
QObject *data = NULL;
|
||||
|
||||
/* XXX: ignores the error code */
|
||||
cmd->mhandler.cmd_new(mon, qdict, &data);
|
||||
assert(!monitor_has_error(mon));
|
||||
if (data) {
|
||||
cmd->user_print(mon, data);
|
||||
qobject_decref(data);
|
||||
}
|
||||
} else {
|
||||
cmd->mhandler.cmd(mon, qdict);
|
||||
}
|
||||
@ -4321,6 +4393,38 @@ static QDict *qmp_check_input_obj(QObject *input_obj)
|
||||
return input_dict;
|
||||
}
|
||||
|
||||
static void qmp_call_query_cmd(Monitor *mon, const mon_cmd_t *cmd)
|
||||
{
|
||||
QObject *ret_data = NULL;
|
||||
|
||||
if (handler_is_async(cmd)) {
|
||||
qmp_async_info_handler(mon, cmd);
|
||||
if (monitor_has_error(mon)) {
|
||||
monitor_protocol_emitter(mon, NULL);
|
||||
}
|
||||
} else {
|
||||
cmd->mhandler.info_new(mon, &ret_data);
|
||||
if (ret_data) {
|
||||
monitor_protocol_emitter(mon, ret_data);
|
||||
qobject_decref(ret_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void qmp_call_cmd(Monitor *mon, const mon_cmd_t *cmd,
|
||||
const QDict *params)
|
||||
{
|
||||
int ret;
|
||||
QObject *data = NULL;
|
||||
|
||||
mon_print_count_init(mon);
|
||||
|
||||
ret = cmd->mhandler.cmd_new(mon, params, &data);
|
||||
handler_audit(mon, cmd, ret);
|
||||
monitor_protocol_emitter(mon, data);
|
||||
qobject_decref(data);
|
||||
}
|
||||
|
||||
static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
|
||||
{
|
||||
int err;
|
||||
@ -4328,8 +4432,9 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
|
||||
QDict *input, *args;
|
||||
const mon_cmd_t *cmd;
|
||||
Monitor *mon = cur_mon;
|
||||
const char *cmd_name, *info_item;
|
||||
const char *cmd_name, *query_cmd;
|
||||
|
||||
query_cmd = NULL;
|
||||
args = input = NULL;
|
||||
|
||||
obj = json_parser_parse(tokens, NULL);
|
||||
@ -4354,24 +4459,15 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX: We need this special case until we get info handlers
|
||||
* converted into 'query-' commands
|
||||
*/
|
||||
if (compare_cmd(cmd_name, "info")) {
|
||||
if (strstart(cmd_name, "query-", &query_cmd)) {
|
||||
cmd = qmp_find_query_cmd(query_cmd);
|
||||
} else {
|
||||
cmd = qmp_find_cmd(cmd_name);
|
||||
}
|
||||
|
||||
if (!cmd) {
|
||||
qerror_report(QERR_COMMAND_NOT_FOUND, cmd_name);
|
||||
goto err_out;
|
||||
} else if (strstart(cmd_name, "query-", &info_item)) {
|
||||
cmd = monitor_find_command("info");
|
||||
qdict_put_obj(input, "arguments",
|
||||
qobject_from_jsonf("{ 'item': %s }", info_item));
|
||||
} else {
|
||||
cmd = monitor_find_command(cmd_name);
|
||||
if (!cmd || !monitor_handler_ported(cmd)
|
||||
|| monitor_cmd_user_only(cmd)) {
|
||||
qerror_report(QERR_COMMAND_NOT_FOUND, cmd_name);
|
||||
goto err_out;
|
||||
}
|
||||
}
|
||||
|
||||
obj = qdict_get(input, "arguments");
|
||||
@ -4387,14 +4483,16 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
if (monitor_handler_is_async(cmd)) {
|
||||
if (query_cmd) {
|
||||
qmp_call_query_cmd(mon, cmd);
|
||||
} else if (handler_is_async(cmd)) {
|
||||
err = qmp_async_cmd_handler(mon, cmd, args);
|
||||
if (err) {
|
||||
/* emit the error response */
|
||||
goto err_out;
|
||||
}
|
||||
} else {
|
||||
monitor_call_handler(mon, cmd, args);
|
||||
qmp_call_cmd(mon, cmd, args);
|
||||
}
|
||||
|
||||
goto out;
|
||||
|
@ -14,10 +14,10 @@ extern Monitor *default_mon;
|
||||
#define MONITOR_IS_DEFAULT 0x01
|
||||
#define MONITOR_USE_READLINE 0x02
|
||||
#define MONITOR_USE_CONTROL 0x04
|
||||
#define MONITOR_USE_PRETTY 0x08
|
||||
|
||||
/* flags for monitor commands */
|
||||
#define MONITOR_CMD_ASYNC 0x0001
|
||||
#define MONITOR_CMD_USER_ONLY 0x0002
|
||||
|
||||
/* QMP events */
|
||||
typedef enum MonitorEvent {
|
||||
|
@ -283,6 +283,9 @@ static QemuOptsList qemu_mon_opts = {
|
||||
},{
|
||||
.name = "default",
|
||||
.type = QEMU_OPT_BOOL,
|
||||
},{
|
||||
.name = "pretty",
|
||||
.type = QEMU_OPT_BOOL,
|
||||
},
|
||||
{ /* end of list */ }
|
||||
},
|
||||
|
55
qjson.c
55
qjson.c
@ -72,43 +72,57 @@ QObject *qobject_from_jsonf(const char *string, ...)
|
||||
|
||||
typedef struct ToJsonIterState
|
||||
{
|
||||
int indent;
|
||||
int pretty;
|
||||
int count;
|
||||
QString *str;
|
||||
} ToJsonIterState;
|
||||
|
||||
static void to_json(const QObject *obj, QString *str);
|
||||
static void to_json(const QObject *obj, QString *str, int pretty, int indent);
|
||||
|
||||
static void to_json_dict_iter(const char *key, QObject *obj, void *opaque)
|
||||
{
|
||||
ToJsonIterState *s = opaque;
|
||||
QString *qkey;
|
||||
int j;
|
||||
|
||||
if (s->count) {
|
||||
if (s->count)
|
||||
qstring_append(s->str, ", ");
|
||||
|
||||
if (s->pretty) {
|
||||
qstring_append(s->str, "\n");
|
||||
for (j = 0 ; j < s->indent ; j++)
|
||||
qstring_append(s->str, " ");
|
||||
}
|
||||
|
||||
qkey = qstring_from_str(key);
|
||||
to_json(QOBJECT(qkey), s->str);
|
||||
to_json(QOBJECT(qkey), s->str, s->pretty, s->indent);
|
||||
QDECREF(qkey);
|
||||
|
||||
qstring_append(s->str, ": ");
|
||||
to_json(obj, s->str);
|
||||
to_json(obj, s->str, s->pretty, s->indent);
|
||||
s->count++;
|
||||
}
|
||||
|
||||
static void to_json_list_iter(QObject *obj, void *opaque)
|
||||
{
|
||||
ToJsonIterState *s = opaque;
|
||||
int j;
|
||||
|
||||
if (s->count) {
|
||||
if (s->count)
|
||||
qstring_append(s->str, ", ");
|
||||
|
||||
if (s->pretty) {
|
||||
qstring_append(s->str, "\n");
|
||||
for (j = 0 ; j < s->indent ; j++)
|
||||
qstring_append(s->str, " ");
|
||||
}
|
||||
|
||||
to_json(obj, s->str);
|
||||
to_json(obj, s->str, s->pretty, s->indent);
|
||||
s->count++;
|
||||
}
|
||||
|
||||
static void to_json(const QObject *obj, QString *str)
|
||||
static void to_json(const QObject *obj, QString *str, int pretty, int indent)
|
||||
{
|
||||
switch (qobject_type(obj)) {
|
||||
case QTYPE_QINT: {
|
||||
@ -193,8 +207,16 @@ static void to_json(const QObject *obj, QString *str)
|
||||
|
||||
s.count = 0;
|
||||
s.str = str;
|
||||
s.indent = indent + 1;
|
||||
s.pretty = pretty;
|
||||
qstring_append(str, "{");
|
||||
qdict_iter(val, to_json_dict_iter, &s);
|
||||
if (pretty) {
|
||||
int j;
|
||||
qstring_append(str, "\n");
|
||||
for (j = 0 ; j < indent ; j++)
|
||||
qstring_append(str, " ");
|
||||
}
|
||||
qstring_append(str, "}");
|
||||
break;
|
||||
}
|
||||
@ -204,8 +226,16 @@ static void to_json(const QObject *obj, QString *str)
|
||||
|
||||
s.count = 0;
|
||||
s.str = str;
|
||||
s.indent = indent + 1;
|
||||
s.pretty = pretty;
|
||||
qstring_append(str, "[");
|
||||
qlist_iter(val, (void *)to_json_list_iter, &s);
|
||||
if (pretty) {
|
||||
int j;
|
||||
qstring_append(str, "\n");
|
||||
for (j = 0 ; j < indent ; j++)
|
||||
qstring_append(str, " ");
|
||||
}
|
||||
qstring_append(str, "]");
|
||||
break;
|
||||
}
|
||||
@ -249,7 +279,16 @@ QString *qobject_to_json(const QObject *obj)
|
||||
{
|
||||
QString *str = qstring_new();
|
||||
|
||||
to_json(obj, str);
|
||||
to_json(obj, str, 0, 0);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
QString *qobject_to_json_pretty(const QObject *obj)
|
||||
{
|
||||
QString *str = qstring_new();
|
||||
|
||||
to_json(obj, str, 1, 0);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
1
qjson.h
1
qjson.h
@ -23,5 +23,6 @@ QObject *qobject_from_jsonf(const char *string, ...) GCC_FMT_ATTR(1, 2);
|
||||
QObject *qobject_from_jsonv(const char *string, va_list *ap) GCC_FMT_ATTR(1, 0);
|
||||
|
||||
QString *qobject_to_json(const QObject *obj);
|
||||
QString *qobject_to_json_pretty(const QObject *obj);
|
||||
|
||||
#endif /* QJSON_H */
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user