* [Qemu-devel] [PATCH v1 00/20] QEMU Monitor Protocol
@ 2009-11-27 0:58 Luiz Capitulino
2009-11-27 0:58 ` [Qemu-devel] [PATCH 01/20] monitor: Introduce MONITOR_USE_CONTROL flag Luiz Capitulino
` (20 more replies)
0 siblings, 21 replies; 23+ messages in thread
From: Luiz Capitulino @ 2009-11-27 0:58 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori, avi, armbru
Hi,
This series has a number of improvements over v0 and is a serious
candidate for inclusion.
Something I'd like to make clear is that QMP is still unstable:
some commands output are being fixed and most of the error handling
has not been done yet.
It might look scary to have an unstable protocol merged, on the other
hand several issues will only come to light with real people testing
QMP (yeah, I'm not real ;) ).
I have two solutions for this problem, both assumes QMP is merged:
1. We merge it ASAP and rush to fix its issues until the release
date
2. We add a compile time switch (eg. --enable-protocol) and disable
QMP by default
Now, regarding this series, the biggest visible change is that we now
support 'query-' commands.
For example, instead of:
{ "execute": "info", "arguments": { "item": "version" } }
Clients should do:
{ "execute": "query-version" }
A summarized changelog follows.
changelog
---------
v0 -> v1
- query- commands support
- Better error classes
- Using the stream parser
- Improved patch split
- Several smalls changes and fixes
^ permalink raw reply [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 01/20] monitor: Introduce MONITOR_USE_CONTROL flag
2009-11-27 0:58 [Qemu-devel] [PATCH v1 00/20] QEMU Monitor Protocol Luiz Capitulino
@ 2009-11-27 0:58 ` Luiz Capitulino
2009-11-27 0:58 ` [Qemu-devel] [PATCH 02/20] monitor: Command-line flag to enable control mode Luiz Capitulino
` (19 subsequent siblings)
20 siblings, 0 replies; 23+ messages in thread
From: Luiz Capitulino @ 2009-11-27 0:58 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori, avi, armbru
This flag will be set when Monitor enters "control mode", in
which the output will be defined by the QEMU Monitor Protocol.
This also introduces a macro to check if the flag is set.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
monitor.c | 6 ++++++
monitor.h | 1 +
2 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/monitor.c b/monitor.c
index fcbe9d4..5907252 100644
--- a/monitor.c
+++ b/monitor.c
@@ -119,6 +119,12 @@ Monitor *cur_mon = NULL;
static void monitor_command_cb(Monitor *mon, const char *cmdline,
void *opaque);
+/* Return true if in control mode, false otherwise */
+static inline int monitor_ctrl_mode(const Monitor *mon)
+{
+ return (mon->flags & MONITOR_USE_CONTROL);
+}
+
static void monitor_read_command(Monitor *mon, int show_prompt)
{
readline_start(mon->rs, "(qemu) ", 0, monitor_command_cb, NULL);
diff --git a/monitor.h b/monitor.h
index c7d2d0b..6cb1d4b 100644
--- a/monitor.h
+++ b/monitor.h
@@ -11,6 +11,7 @@ extern Monitor *cur_mon;
/* flags for monitor_init */
#define MONITOR_IS_DEFAULT 0x01
#define MONITOR_USE_READLINE 0x02
+#define MONITOR_USE_CONTROL 0x04
void monitor_init(CharDriverState *chr, int flags);
--
1.6.6.rc0.50.gaf06e
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 02/20] monitor: Command-line flag to enable control mode
2009-11-27 0:58 [Qemu-devel] [PATCH v1 00/20] QEMU Monitor Protocol Luiz Capitulino
2009-11-27 0:58 ` [Qemu-devel] [PATCH 01/20] monitor: Introduce MONITOR_USE_CONTROL flag Luiz Capitulino
@ 2009-11-27 0:58 ` Luiz Capitulino
2009-11-27 0:58 ` [Qemu-devel] [PATCH 03/20] monitor: Introduce monitor_call_handler() Luiz Capitulino
` (18 subsequent siblings)
20 siblings, 0 replies; 23+ messages in thread
From: Luiz Capitulino @ 2009-11-27 0:58 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori, avi, armbru
This commit adds a flag called 'control' to the '-monitor'
command-line option. This flag enables control mode.
The syntax is:
qemu [...] -monitor control,<device>
Where <device> is a chardev (excluding 'vc', for obvious reasons).
For example:
$ qemu [...] -monitor control,tcp:localhost:4444,server
Will run QEMU in control mode, waiting for a client TCP connection
on localhost port 4444.
NOTE: I've tried using QemuOpts for this, but turns out that it
will try to parse the device part, which should be untouched.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
monitor.c | 18 ++++++++++++++++++
monitor.h | 1 +
qemu-options.hx | 5 +++--
vl.c | 11 +++++++----
4 files changed, 29 insertions(+), 6 deletions(-)
diff --git a/monitor.c b/monitor.c
index 5907252..4d18699 100644
--- a/monitor.c
+++ b/monitor.c
@@ -3620,6 +3620,24 @@ static void monitor_event(void *opaque, int event)
* End:
*/
+const char *monitor_cmdline_parse(const char *cmdline, int *flags)
+{
+ const char *dev;
+
+ if (strstart(cmdline, "control,", &dev)) {
+ if (strstart(dev, "vc", NULL)) {
+ fprintf(stderr, "qemu: control mode is for low-level interaction ");
+ fprintf(stderr, "cannot be used with device 'vc'\n");
+ exit(1);
+ }
+ *flags &= ~MONITOR_USE_READLINE;
+ *flags |= MONITOR_USE_CONTROL;
+ return dev;
+ }
+
+ return cmdline;
+}
+
void monitor_init(CharDriverState *chr, int flags)
{
static int is_first_init = 1;
diff --git a/monitor.h b/monitor.h
index 6cb1d4b..556507c 100644
--- a/monitor.h
+++ b/monitor.h
@@ -13,6 +13,7 @@ extern Monitor *cur_mon;
#define MONITOR_USE_READLINE 0x02
#define MONITOR_USE_CONTROL 0x04
+const char *monitor_cmdline_parse(const char *cmdline, int *flags);
void monitor_init(CharDriverState *chr, int flags);
int monitor_suspend(Monitor *mon);
diff --git a/qemu-options.hx b/qemu-options.hx
index b65fd74..1b5781a 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1577,13 +1577,14 @@ Use @code{-parallel none} to disable all parallel ports.
ETEXI
DEF("monitor", HAS_ARG, QEMU_OPTION_monitor, \
- "-monitor dev redirect the monitor to char device 'dev'\n")
+ "-monitor [control,]dev redirect the monitor to char device 'dev'\n")
STEXI
-@item -monitor @var{dev}
+@item -monitor [@var{control},]@var{dev}
Redirect the monitor to host device @var{dev} (same devices as the
serial port).
The default device is @code{vc} in graphical mode and @code{stdio} in
non graphical mode.
+The option @var{control} enables the QEMU Monitor Protocol.
ETEXI
DEF("pidfile", HAS_ARG, QEMU_OPTION_pidfile, \
diff --git a/vl.c b/vl.c
index e7d0754..dd9b74b 100644
--- a/vl.c
+++ b/vl.c
@@ -4639,6 +4639,7 @@ int main(int argc, char **argv, char **envp)
const char *r, *optarg;
CharDriverState *monitor_hds[MAX_MONITOR_DEVICES];
const char *monitor_devices[MAX_MONITOR_DEVICES];
+ int monitor_flags[MAX_MONITOR_DEVICES];
int monitor_device_index;
const char *serial_devices[MAX_SERIAL_PORTS];
int serial_device_index;
@@ -4726,8 +4727,10 @@ int main(int argc, char **argv, char **envp)
virtio_console_index = 0;
monitor_devices[0] = "vc:80Cx24C";
+ monitor_flags[0] = MONITOR_IS_DEFAULT | MONITOR_USE_READLINE;
for (i = 1; i < MAX_MONITOR_DEVICES; i++) {
monitor_devices[i] = NULL;
+ monitor_flags[i] = MONITOR_USE_READLINE;
}
monitor_device_index = 0;
@@ -5148,7 +5151,9 @@ int main(int argc, char **argv, char **envp)
fprintf(stderr, "qemu: too many monitor devices\n");
exit(1);
}
- monitor_devices[monitor_device_index] = optarg;
+ monitor_devices[monitor_device_index] =
+ monitor_cmdline_parse(optarg,
+ &monitor_flags[monitor_device_index]);
monitor_device_index++;
break;
case QEMU_OPTION_chardev:
@@ -5842,9 +5847,7 @@ int main(int argc, char **argv, char **envp)
for (i = 0; i < MAX_MONITOR_DEVICES; i++) {
if (monitor_devices[i] && monitor_hds[i]) {
- monitor_init(monitor_hds[i],
- MONITOR_USE_READLINE |
- ((i == 0) ? MONITOR_IS_DEFAULT : 0));
+ monitor_init(monitor_hds[i], monitor_flags[i]);
}
}
--
1.6.6.rc0.50.gaf06e
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 03/20] monitor: Introduce monitor_call_handler()
2009-11-27 0:58 [Qemu-devel] [PATCH v1 00/20] QEMU Monitor Protocol Luiz Capitulino
2009-11-27 0:58 ` [Qemu-devel] [PATCH 01/20] monitor: Introduce MONITOR_USE_CONTROL flag Luiz Capitulino
2009-11-27 0:58 ` [Qemu-devel] [PATCH 02/20] monitor: Command-line flag to enable control mode Luiz Capitulino
@ 2009-11-27 0:58 ` Luiz Capitulino
2009-11-27 0:58 ` [Qemu-devel] [PATCH 04/20] monitor: Introduce monitor_find_command() Luiz Capitulino
` (17 subsequent siblings)
20 siblings, 0 replies; 23+ messages in thread
From: Luiz Capitulino @ 2009-11-27 0:58 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori, avi, armbru
This commit moves the code which calls Monitor handlers to
its own function, as it will be used by QMP code as well.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
monitor.c | 20 +++++++++++++-------
1 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/monitor.c b/monitor.c
index 4d18699..e0cc941 100644
--- a/monitor.c
+++ b/monitor.c
@@ -3272,6 +3272,18 @@ static void monitor_print_error(Monitor *mon)
mon->error = NULL;
}
+static void monitor_call_handler(Monitor *mon, const mon_cmd_t *cmd,
+ const QDict *params)
+{
+ QObject *data = NULL;
+
+ cmd->mhandler.cmd_new(mon, params, &data);
+ if (data)
+ cmd->user_print(mon, data);
+
+ qobject_decref(data);
+}
+
static void monitor_handle_command(Monitor *mon, const char *cmdline)
{
QDict *qdict;
@@ -3286,13 +3298,7 @@ static void monitor_handle_command(Monitor *mon, const char *cmdline)
qemu_errors_to_mon(mon);
if (monitor_handler_ported(cmd)) {
- QObject *data = NULL;
-
- cmd->mhandler.cmd_new(mon, qdict, &data);
- if (data)
- cmd->user_print(mon, data);
-
- qobject_decref(data);
+ monitor_call_handler(mon, cmd, qdict);
} else {
cmd->mhandler.cmd(mon, qdict);
}
--
1.6.6.rc0.50.gaf06e
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 04/20] monitor: Introduce monitor_find_command()
2009-11-27 0:58 [Qemu-devel] [PATCH v1 00/20] QEMU Monitor Protocol Luiz Capitulino
` (2 preceding siblings ...)
2009-11-27 0:58 ` [Qemu-devel] [PATCH 03/20] monitor: Introduce monitor_call_handler() Luiz Capitulino
@ 2009-11-27 0:58 ` Luiz Capitulino
2009-11-27 0:58 ` [Qemu-devel] [PATCH 05/20] monitor: Rename monitor_handle_command() Luiz Capitulino
` (16 subsequent siblings)
20 siblings, 0 replies; 23+ messages in thread
From: Luiz Capitulino @ 2009-11-27 0:58 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori, avi, armbru
This commit moves the loop which searches for the command
entry corresponding to a command name to its own function.
It will be used by QMP code as well.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
monitor.c | 22 +++++++++++++++-------
1 files changed, 15 insertions(+), 7 deletions(-)
diff --git a/monitor.c b/monitor.c
index e0cc941..6c2c1f1 100644
--- a/monitor.c
+++ b/monitor.c
@@ -3017,6 +3017,19 @@ 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)
+{
+ const mon_cmd_t *cmd;
+
+ for (cmd = mon_cmds; cmd->name != NULL; cmd++) {
+ if (compare_cmd(cmdname, cmd->name)) {
+ return cmd;
+ }
+ }
+
+ return NULL;
+}
+
static const mon_cmd_t *monitor_parse_command(Monitor *mon,
const char *cmdline,
QDict *qdict)
@@ -3037,13 +3050,8 @@ static const mon_cmd_t *monitor_parse_command(Monitor *mon,
if (!p)
return NULL;
- /* find the command */
- for(cmd = mon_cmds; cmd->name != NULL; cmd++) {
- if (compare_cmd(cmdname, cmd->name))
- break;
- }
-
- if (cmd->name == NULL) {
+ cmd = monitor_find_command(cmdname);
+ if (!cmd) {
monitor_printf(mon, "unknown command: '%s'\n", cmdname);
return NULL;
}
--
1.6.6.rc0.50.gaf06e
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 05/20] monitor: Rename monitor_handle_command()
2009-11-27 0:58 [Qemu-devel] [PATCH v1 00/20] QEMU Monitor Protocol Luiz Capitulino
` (3 preceding siblings ...)
2009-11-27 0:58 ` [Qemu-devel] [PATCH 04/20] monitor: Introduce monitor_find_command() Luiz Capitulino
@ 2009-11-27 0:58 ` Luiz Capitulino
2009-11-27 0:58 ` [Qemu-devel] [PATCH 06/20] monitor: Introduce 'info commands' Luiz Capitulino
` (15 subsequent siblings)
20 siblings, 0 replies; 23+ messages in thread
From: Luiz Capitulino @ 2009-11-27 0:58 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori, avi, armbru
As this series will add a new kind of Monitor command, it's better
to rename monitor_handle_command() to what it really is:
handle_user_command().
This will avoid confusion.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
monitor.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/monitor.c b/monitor.c
index 6c2c1f1..4c402e4 100644
--- a/monitor.c
+++ b/monitor.c
@@ -3292,7 +3292,7 @@ static void monitor_call_handler(Monitor *mon, const mon_cmd_t *cmd,
qobject_decref(data);
}
-static void monitor_handle_command(Monitor *mon, const char *cmdline)
+static void handle_user_command(Monitor *mon, const char *cmdline)
{
QDict *qdict;
const mon_cmd_t *cmd;
@@ -3556,7 +3556,7 @@ static void monitor_read(void *opaque, const uint8_t *buf, int size)
if (size == 0 || buf[size - 1] != 0)
monitor_printf(cur_mon, "corrupted command\n");
else
- monitor_handle_command(cur_mon, (char *)buf);
+ handle_user_command(cur_mon, (char *)buf);
}
cur_mon = old_mon;
@@ -3565,7 +3565,7 @@ static void monitor_read(void *opaque, const uint8_t *buf, int size)
static void monitor_command_cb(Monitor *mon, const char *cmdline, void *opaque)
{
monitor_suspend(mon);
- monitor_handle_command(mon, cmdline);
+ handle_user_command(mon, cmdline);
monitor_resume(mon);
}
--
1.6.6.rc0.50.gaf06e
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 06/20] monitor: Introduce 'info commands'
2009-11-27 0:58 [Qemu-devel] [PATCH v1 00/20] QEMU Monitor Protocol Luiz Capitulino
` (4 preceding siblings ...)
2009-11-27 0:58 ` [Qemu-devel] [PATCH 05/20] monitor: Rename monitor_handle_command() Luiz Capitulino
@ 2009-11-27 0:58 ` Luiz Capitulino
2009-11-27 0:58 ` [Qemu-devel] [PATCH 07/20] QError: Add errors needed by QMP Luiz Capitulino
` (14 subsequent siblings)
20 siblings, 0 replies; 23+ messages in thread
From: Luiz Capitulino @ 2009-11-27 0:58 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori, avi, armbru
List QMP available commands. Only valid in control mode, where
has to be used as 'query-commands.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
monitor.c | 37 +++++++++++++++++++++++++++++++++++++
1 files changed, 37 insertions(+), 0 deletions(-)
diff --git a/monitor.c b/monitor.c
index 4c402e4..02dea2e 100644
--- a/monitor.c
+++ b/monitor.c
@@ -363,6 +363,35 @@ static void do_info_version(Monitor *mon, QObject **ret_data)
}
/**
+ * do_info_commands(): List QMP available commands
+ *
+ * Return a QList of QStrings.
+ */
+static void do_info_commands(Monitor *mon, QObject **ret_data)
+{
+ QList *cmd_list;
+ const mon_cmd_t *cmd;
+
+ cmd_list = qlist_new();
+
+ for (cmd = mon_cmds; cmd->name != NULL; cmd++) {
+ if (monitor_handler_ported(cmd) && !compare_cmd(cmd->name, "info")) {
+ qlist_append(cmd_list, qstring_from_str(cmd->name));
+ }
+ }
+
+ for (cmd = info_cmds; cmd->name != NULL; cmd++) {
+ if (monitor_handler_ported(cmd)) {
+ char buf[128];
+ snprintf(buf, sizeof(buf), "query-%s", cmd->name);
+ qlist_append(cmd_list, qstring_from_str(buf));
+ }
+ }
+
+ *ret_data = QOBJECT(cmd_list);
+}
+
+/**
* do_info_name(): Show VM name
*
* Return a QString with the current VM name.
@@ -2047,6 +2076,14 @@ static const mon_cmd_t info_cmds[] = {
.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 = "",
.params = "",
--
1.6.6.rc0.50.gaf06e
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 07/20] QError: Add errors needed by QMP
2009-11-27 0:58 [Qemu-devel] [PATCH v1 00/20] QEMU Monitor Protocol Luiz Capitulino
` (5 preceding siblings ...)
2009-11-27 0:58 ` [Qemu-devel] [PATCH 06/20] monitor: Introduce 'info commands' Luiz Capitulino
@ 2009-11-27 0:58 ` Luiz Capitulino
2009-11-27 0:58 ` [Qemu-devel] [PATCH 08/20] QMP: Initial support Luiz Capitulino
` (13 subsequent siblings)
20 siblings, 0 replies; 23+ messages in thread
From: Luiz Capitulino @ 2009-11-27 0:58 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori, avi, armbru
Only QERR_QMP_BAD_INPUT_OBJECT is QMP specific, the others can
be used in different contexts by other subsystems.
Please, note that QERR_JSON_PARSING signals any parsing error
from the json parser. We will need it until the parser gets
updated to use QError.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
qerror.c | 24 ++++++++++++++++++++++++
qerror.h | 18 ++++++++++++++++++
2 files changed, 42 insertions(+), 0 deletions(-)
diff --git a/qerror.c b/qerror.c
index d8b125e..6560996 100644
--- a/qerror.c
+++ b/qerror.c
@@ -41,6 +41,10 @@ static const QType qerror_type = {
*/
const QErrorStringTable qerror_table[] = {
{
+ .error_fmt = QERR_COMMAND_NOT_FOUND,
+ .desc = "The command %(name) has not been found",
+ },
+ {
.error_fmt = QERR_DEVICE_NOT_FOUND,
.desc = "The %(device) device has not been found",
},
@@ -49,9 +53,29 @@ const QErrorStringTable qerror_table[] = {
.desc = "The %(device) device has not been activated by the guest",
},
{
+ .error_fmt = QERR_INVALID_PARAMETER_TYPE,
+ .desc = "Invalid parameter type, expected: %(expected)",
+ },
+ {
.error_fmt = QERR_KVM_MISSING_CAP,
.desc = "Using KVM without %(capability), %(feature) unavailable",
},
+ {
+ .error_fmt = QERR_MISSING_PARAMETER,
+ .desc = "Parameter %(name) is missing",
+ },
+ {
+ .error_fmt = QERR_QMP_BAD_INPUT_OBJECT,
+ .desc = "Bad QMP input object",
+ },
+ {
+ .error_fmt = QERR_JSON_PARSING,
+ .desc = "Invalid JSON synaxt",
+ },
+ {
+ .error_fmt = QERR_UNDEFINED_ERROR,
+ .desc = "An undefined error has ocurred",
+ },
{}
};
diff --git a/qerror.h b/qerror.h
index 6c100af..5fd9931 100644
--- a/qerror.h
+++ b/qerror.h
@@ -38,13 +38,31 @@ QError *qobject_to_qerror(const QObject *obj);
/*
* QError class list
*/
+#define QERR_COMMAND_NOT_FOUND \
+ "{ 'class': 'CommandNotFound', 'data': { 'name': %s } }"
+
#define QERR_DEVICE_NOT_FOUND \
"{ 'class': 'DeviceNotFound', 'data': { 'device': %s } }"
#define QERR_DEVICE_NOT_ACTIVE \
"{ 'class': 'DeviceNotActive', 'data': { 'device': %s } }"
+#define QERR_INVALID_PARAMETER_TYPE \
+ "{ 'class': 'InvalidParameterType', 'data': { 'name': %s,'expected': %s } }"
+
#define QERR_KVM_MISSING_CAP \
"{ 'class': 'KVMMissingCap', 'data': { 'capability': %s, 'feature': %s } }"
+#define QERR_MISSING_PARAMETER \
+ "{ 'class': 'MissingParameter', 'data': { 'name': %s } }"
+
+#define QERR_QMP_BAD_INPUT_OBJECT \
+ "{ 'class': 'QMPBadInputObject', 'data': { 'expected': %s } }"
+
+#define QERR_JSON_PARSING \
+ "{ 'class': 'JSONParsing', 'data': {} }"
+
+#define QERR_UNDEFINED_ERROR \
+ "{ 'class': 'UndefinedError', 'data': {} }"
+
#endif /* QERROR_H */
--
1.6.6.rc0.50.gaf06e
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 08/20] QMP: Initial support
2009-11-27 0:58 [Qemu-devel] [PATCH v1 00/20] QEMU Monitor Protocol Luiz Capitulino
` (6 preceding siblings ...)
2009-11-27 0:58 ` [Qemu-devel] [PATCH 07/20] QError: Add errors needed by QMP Luiz Capitulino
@ 2009-11-27 0:58 ` Luiz Capitulino
2009-11-27 0:58 ` [Qemu-devel] [PATCH 09/20] QMP: Output support Luiz Capitulino
` (12 subsequent siblings)
20 siblings, 0 replies; 23+ messages in thread
From: Luiz Capitulino @ 2009-11-27 0:58 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori, avi, armbru
This commit adds initial QMP support in QEMU. It's important
to notice that most QMP code will be part of the Monitor.
Input will be read by monitor_control_read(). Currently it
does nothing but next patches will add proper input support.
The function monitor_json_emitter(), as its name implies, is
used by the Monitor to emit JSON output. In this commit it's
used by monitor_control_event() to print our greeting message.
Finally, control mode support is also added to monitor_init(),
allowing QMP to be really enabled.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
monitor.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 51 insertions(+), 2 deletions(-)
diff --git a/monitor.c b/monitor.c
index 02dea2e..c333b7a 100644
--- a/monitor.c
+++ b/monitor.c
@@ -50,6 +50,7 @@
#include "qdict.h"
#include "qstring.h"
#include "qerror.h"
+#include "qjson.h"
//#define DEBUG
//#define DEBUG_COMPLETION
@@ -255,6 +256,17 @@ static void monitor_print_qobject(Monitor *mon, const QObject *data)
monitor_puts(mon, "\n");
}
+static void monitor_json_emitter(Monitor *mon, const QObject *data)
+{
+ QString *json;
+
+ json = qobject_to_json(data);
+ assert(json != NULL);
+
+ monitor_printf(mon, "%s\n", qstring_get_str(json));
+ QDECREF(json);
+}
+
static int compare_cmd(const char *name, const char *list)
{
const char *p, *pstart;
@@ -3579,6 +3591,20 @@ static int monitor_can_read(void *opaque)
return (mon->suspend_cnt == 0) ? 128 : 0;
}
+/**
+ * monitor_control_read(): Read and handle QMP input
+ */
+static void monitor_control_read(void *opaque, const uint8_t *buf, int size)
+{
+ Monitor *old_mon = cur_mon;
+
+ cur_mon = opaque;
+
+ // TODO: read QMP input
+
+ cur_mon = old_mon;
+}
+
static void monitor_read(void *opaque, const uint8_t *buf, int size)
{
Monitor *old_mon = cur_mon;
@@ -3622,6 +3648,23 @@ void monitor_resume(Monitor *mon)
readline_show_prompt(mon->rs);
}
+/**
+ * monitor_control_event(): Print QMP gretting
+ */
+static void monitor_control_event(void *opaque, int event)
+{
+ if (event == CHR_EVENT_OPENED) {
+ QObject *data;
+ Monitor *mon = opaque;
+
+ data = qobject_from_jsonf("{ 'QMP': { 'capabilities': [] } }");
+ assert(data != NULL);
+
+ monitor_json_emitter(mon, data);
+ qobject_decref(data);
+ }
+}
+
static void monitor_event(void *opaque, int event)
{
Monitor *mon = opaque;
@@ -3708,8 +3751,14 @@ void monitor_init(CharDriverState *chr, int flags)
monitor_read_command(mon, 0);
}
- qemu_chr_add_handlers(chr, monitor_can_read, monitor_read, monitor_event,
- mon);
+ if (monitor_ctrl_mode(mon)) {
+ /* Control mode requires special handlers */
+ qemu_chr_add_handlers(chr, monitor_can_read, monitor_control_read,
+ monitor_control_event, mon);
+ } else {
+ qemu_chr_add_handlers(chr, monitor_can_read, monitor_read,
+ monitor_event, mon);
+ }
QLIST_INSERT_HEAD(&mon_list, mon, entry);
if (!cur_mon || (flags & MONITOR_IS_DEFAULT))
--
1.6.6.rc0.50.gaf06e
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 09/20] QMP: Output support
2009-11-27 0:58 [Qemu-devel] [PATCH v1 00/20] QEMU Monitor Protocol Luiz Capitulino
` (7 preceding siblings ...)
2009-11-27 0:58 ` [Qemu-devel] [PATCH 08/20] QMP: Initial support Luiz Capitulino
@ 2009-11-27 0:58 ` Luiz Capitulino
2009-11-27 0:59 ` [Qemu-devel] [PATCH 10/20] QMP: do_info() checks Luiz Capitulino
` (11 subsequent siblings)
20 siblings, 0 replies; 23+ messages in thread
From: Luiz Capitulino @ 2009-11-27 0:58 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori, avi, armbru
In the new Monitor output is always performed by only two
functions: do_info() and monitor_call_handler().
To support QMP output, we modify those functions to check if we
are in control mode. If so, we call monitor_protocol_emitter()
to emit QMP output, otherwise we do regular output.
QMP has two types of responses to issued commands: success and
error. The outputed data is always a JSON object.
Success responses have the following format:
{ "return": json-value, "id": json-value }
Error responses have the following format:
{ "error": { "class": json-string,
"desc": json-string,
"data": json-value } "id": json-value }
Please, note that the "id" key is part of the input code, and
thus is not added in this commit.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
monitor.c | 48 ++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 44 insertions(+), 4 deletions(-)
diff --git a/monitor.c b/monitor.c
index c333b7a..ffb5ed2 100644
--- a/monitor.c
+++ b/monitor.c
@@ -267,6 +267,32 @@ static void monitor_json_emitter(Monitor *mon, const QObject *data)
QDECREF(json);
}
+static void monitor_protocol_emitter(Monitor *mon, QObject *data)
+{
+ QDict *qmp;
+
+ qmp = qdict_new();
+
+ if (!monitor_has_error(mon)) {
+ /* success response */
+ if (data) {
+ qobject_incref(data);
+ qdict_put_obj(qmp, "return", data);
+ } else {
+ qdict_put(qmp, "return", qstring_from_str("OK"));
+ }
+ } else {
+ /* error response */
+ qdict_put(qmp, "error", mon->error->error);
+ QINCREF(mon->error->error);
+ QDECREF(mon->error);
+ mon->error = NULL;
+ }
+
+ monitor_json_emitter(mon, QOBJECT(qmp));
+ QDECREF(qmp);
+}
+
static int compare_cmd(const char *name, const char *list)
{
const char *p, *pstart;
@@ -354,8 +380,15 @@ static void do_info(Monitor *mon, const QDict *qdict, QObject **ret_data)
if (monitor_handler_ported(cmd)) {
cmd->mhandler.info_new(mon, ret_data);
- if (*ret_data)
- cmd->user_print(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);
+ }
} else {
cmd->mhandler.info(mon);
}
@@ -3335,8 +3368,15 @@ static void monitor_call_handler(Monitor *mon, const mon_cmd_t *cmd,
QObject *data = NULL;
cmd->mhandler.cmd_new(mon, params, &data);
- if (data)
- cmd->user_print(mon, data);
+
+ 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);
}
--
1.6.6.rc0.50.gaf06e
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 10/20] QMP: do_info() checks
2009-11-27 0:58 [Qemu-devel] [PATCH v1 00/20] QEMU Monitor Protocol Luiz Capitulino
` (8 preceding siblings ...)
2009-11-27 0:58 ` [Qemu-devel] [PATCH 09/20] QMP: Output support Luiz Capitulino
@ 2009-11-27 0:59 ` Luiz Capitulino
2009-11-27 0:59 ` [Qemu-devel] [PATCH 11/20] QMP: Input support Luiz Capitulino
` (10 subsequent siblings)
20 siblings, 0 replies; 23+ messages in thread
From: Luiz Capitulino @ 2009-11-27 0:59 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori, avi, armbru
This commit adds specific QMP checks to do_info(), so that
it behaves as expected in QMP mode.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
monitor.c | 18 +++++++++++++++---
1 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/monitor.c b/monitor.c
index ffb5ed2..de56201 100644
--- a/monitor.c
+++ b/monitor.c
@@ -367,16 +367,23 @@ static void do_info(Monitor *mon, const QDict *qdict, QObject **ret_data)
const mon_cmd_t *cmd;
const char *item = qdict_get_try_str(qdict, "item");
- if (!item)
+ if (!item) {
+ assert(monitor_ctrl_mode(mon) == 0);
goto help;
+ }
for (cmd = info_cmds; cmd->name != NULL; cmd++) {
if (compare_cmd(item, cmd->name))
break;
}
- if (cmd->name == NULL)
+ if (cmd->name == NULL) {
+ if (monitor_ctrl_mode(mon)) {
+ qemu_error_new(QERR_COMMAND_NOT_FOUND, item);
+ return;
+ }
goto help;
+ }
if (monitor_handler_ported(cmd)) {
cmd->mhandler.info_new(mon, ret_data);
@@ -390,7 +397,12 @@ static void do_info(Monitor *mon, const QDict *qdict, QObject **ret_data)
cmd->user_print(mon, *ret_data);
}
} else {
- cmd->mhandler.info(mon);
+ if (monitor_ctrl_mode(mon)) {
+ /* handler not converted yet */
+ qemu_error_new(QERR_COMMAND_NOT_FOUND, item);
+ } else {
+ cmd->mhandler.info(mon);
+ }
}
return;
--
1.6.6.rc0.50.gaf06e
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 11/20] QMP: Input support
2009-11-27 0:58 [Qemu-devel] [PATCH v1 00/20] QEMU Monitor Protocol Luiz Capitulino
` (9 preceding siblings ...)
2009-11-27 0:59 ` [Qemu-devel] [PATCH 10/20] QMP: do_info() checks Luiz Capitulino
@ 2009-11-27 0:59 ` Luiz Capitulino
2009-11-27 0:59 ` [Qemu-devel] [PATCH 12/20] QMP: Allow 'query-' commands Luiz Capitulino
` (9 subsequent siblings)
20 siblings, 0 replies; 23+ messages in thread
From: Luiz Capitulino @ 2009-11-27 0:59 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori, avi, armbru
The JSON stream parser is used to do QMP input. When there
are enough characters to be parsed it calls Monitor's
handle_qmp_command() function to handle the input.
This function's job is to check if the input is correct and
call the appropriate handler. In other words, it does for QMP
what handle_user_command() does for the user protocol.
This means that handle_qmp_command() also has to parse the
(ugly) "args_type" format to able to get the arguments names
and types expected by the handler.
The format to input commands in QMP is as follows:
{ "execute": json-string,
"id": json-value, "arguments": json-object }
Please, note that this commit also adds "id" support.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
monitor.c | 241 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 240 insertions(+), 1 deletions(-)
diff --git a/monitor.c b/monitor.c
index de56201..c172343 100644
--- a/monitor.c
+++ b/monitor.c
@@ -48,9 +48,12 @@
#include "qint.h"
#include "qlist.h"
#include "qdict.h"
+#include "qbool.h"
#include "qstring.h"
#include "qerror.h"
#include "qjson.h"
+#include "json-streamer.h"
+#include "json-parser.h"
//#define DEBUG
//#define DEBUG_COMPLETION
@@ -93,6 +96,11 @@ struct mon_fd_t {
QLIST_ENTRY(mon_fd_t) next;
};
+typedef struct MonitorControl {
+ QObject *id;
+ JSONMessageParser parser;
+} MonitorControl;
+
struct Monitor {
CharDriverState *chr;
int mux_out;
@@ -102,6 +110,7 @@ struct Monitor {
uint8_t outbuf[1024];
int outbuf_index;
ReadLineState *rs;
+ MonitorControl *mc;
CPUState *mon_cpu;
BlockDriverCompletionFunc *password_completion_cb;
void *password_opaque;
@@ -289,6 +298,11 @@ static void monitor_protocol_emitter(Monitor *mon, QObject *data)
mon->error = NULL;
}
+ if (mon->mc->id) {
+ qdict_put_obj(qmp, "id", mon->mc->id);
+ mon->mc->id = NULL;
+ }
+
monitor_json_emitter(mon, QOBJECT(qmp));
QDECREF(qmp);
}
@@ -3643,6 +3657,228 @@ static int monitor_can_read(void *opaque)
return (mon->suspend_cnt == 0) ? 128 : 0;
}
+typedef struct CmdArgs {
+ QString *name;
+ int type;
+ int flag;
+ int optional;
+} CmdArgs;
+
+static int check_opt(const CmdArgs *cmd_args, const char *name, QDict *args)
+{
+ if (!cmd_args->optional) {
+ qemu_error_new(QERR_MISSING_PARAMETER, name);
+ return -1;
+ }
+
+ if (cmd_args->type == '-') {
+ /* handlers expect a value, they need to be changed */
+ qdict_put(args, name, qint_from_int(0));
+ }
+
+ return 0;
+}
+
+static int check_arg(const CmdArgs *cmd_args, QDict *args)
+{
+ QObject *value;
+ const char *name;
+
+ name = qstring_get_str(cmd_args->name);
+
+ if (!args) {
+ return check_opt(cmd_args, name, args);
+ }
+
+ value = qdict_get(args, name);
+ if (!value) {
+ return check_opt(cmd_args, name, args);
+ }
+
+ switch (cmd_args->type) {
+ case 'F':
+ case 'B':
+ case 's':
+ if (qobject_type(value) != QTYPE_QSTRING) {
+ qemu_error_new(QERR_INVALID_PARAMETER_TYPE, name, "string");
+ return -1;
+ }
+ break;
+ case '/': {
+ int i;
+ const char *keys[] = { "count", "format", "size", NULL };
+
+ for (i = 0; keys[i]; i++) {
+ QObject *obj = qdict_get(args, keys[i]);
+ if (!obj) {
+ qemu_error_new(QERR_MISSING_PARAMETER, name);
+ return -1;
+ }
+ if (qobject_type(obj) != QTYPE_QINT) {
+ qemu_error_new(QERR_INVALID_PARAMETER_TYPE, name, "int");
+ return -1;
+ }
+ }
+ break;
+ }
+ case 'i':
+ case 'l':
+ if (qobject_type(value) != QTYPE_QINT) {
+ qemu_error_new(QERR_INVALID_PARAMETER_TYPE, name, "int");
+ return -1;
+ }
+ break;
+ case '-':
+ if (qobject_type(value) != QTYPE_QINT &&
+ qobject_type(value) != QTYPE_QBOOL) {
+ qemu_error_new(QERR_INVALID_PARAMETER_TYPE, name, "bool");
+ return -1;
+ }
+ if (qobject_type(value) == QTYPE_QBOOL) {
+ /* handlers expect a QInt, they need to be changed */
+ qdict_put(args, name,
+ qint_from_int(qbool_get_int(qobject_to_qbool(value))));
+ }
+ break;
+ default:
+ /* impossible */
+ abort();
+ }
+
+ return 0;
+}
+
+static void cmd_args_init(CmdArgs *cmd_args)
+{
+ cmd_args->name = qstring_new();
+ cmd_args->type = cmd_args->flag = cmd_args->optional = 0;
+}
+
+/*
+ * This is not trivial, we have to parse Monitor command's argument
+ * type syntax to be able to check the arguments provided by clients.
+ *
+ * In the near future we will be using an array for that and will be
+ * able to drop all this parsing...
+ */
+static int monitor_check_qmp_args(const mon_cmd_t *cmd, QDict *args)
+{
+ int err;
+ const char *p;
+ CmdArgs cmd_args;
+
+ if (cmd->args_type == '\0') {
+ return (qdict_size(args) == 0 ? 0 : -1);
+ }
+
+ err = 0;
+ cmd_args_init(&cmd_args);
+
+ for (p = cmd->args_type;; p++) {
+ if (*p == ':') {
+ cmd_args.type = *++p;
+ p++;
+ if (cmd_args.type == '-') {
+ cmd_args.flag = *p++;
+ cmd_args.optional = 1;
+ } else if (*p == '?') {
+ cmd_args.optional = 1;
+ p++;
+ }
+
+ assert(*p == ',' || *p == '\0');
+ err = check_arg(&cmd_args, args);
+
+ QDECREF(cmd_args.name);
+ cmd_args_init(&cmd_args);
+
+ if (err < 0) {
+ break;
+ }
+ } else {
+ qstring_append_chr(cmd_args.name, *p);
+ }
+
+ if (*p == '\0') {
+ break;
+ }
+ }
+
+ QDECREF(cmd_args.name);
+ return err;
+}
+
+static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
+{
+ int err;
+ QObject *obj;
+ QDict *input, *args;
+ const char *cmd_name;
+ const mon_cmd_t *cmd;
+ Monitor *mon = cur_mon;
+
+ args = NULL;
+ qemu_errors_to_mon(mon);
+
+ obj = json_parser_parse(tokens, NULL);
+ if (!obj) {
+ // FIXME: should be triggered in json_parser_parse()
+ qemu_error_new(QERR_JSON_PARSING);
+ goto err_out;
+ } else if (qobject_type(obj) != QTYPE_QDICT) {
+ qemu_error_new(QERR_QMP_BAD_INPUT_OBJECT, "object");
+ qobject_decref(obj);
+ goto err_out;
+ }
+
+ input = qobject_to_qdict(obj);
+
+ mon->mc->id = qdict_get(input, "id");
+ qobject_incref(mon->mc->id);
+
+ obj = qdict_get(input, "execute");
+ if (!obj) {
+ qemu_error_new(QERR_QMP_BAD_INPUT_OBJECT, "execute");
+ goto err_input;
+ } else if (qobject_type(obj) != QTYPE_QSTRING) {
+ qemu_error_new(QERR_QMP_BAD_INPUT_OBJECT, "string");
+ goto err_input;
+ }
+
+ cmd_name = qstring_get_str(qobject_to_qstring(obj));
+ cmd = monitor_find_command(cmd_name);
+ if (!cmd) {
+ qemu_error_new(QERR_COMMAND_NOT_FOUND, cmd_name);
+ goto err_input;
+ }
+
+ obj = qdict_get(input, "arguments");
+ if (!obj) {
+ args = qdict_new();
+ } else {
+ args = qobject_to_qdict(obj);
+ QINCREF(args);
+ }
+
+ QDECREF(input);
+
+ err = monitor_check_qmp_args(cmd, args);
+ if (err < 0) {
+ goto err_out;
+ }
+
+ monitor_call_handler(mon, cmd, args);
+ goto out;
+
+err_input:
+ QDECREF(input);
+err_out:
+ monitor_protocol_emitter(mon, NULL);
+out:
+ QDECREF(args);
+ qemu_errors_to_previous();
+}
+
/**
* monitor_control_read(): Read and handle QMP input
*/
@@ -3652,7 +3888,7 @@ static void monitor_control_read(void *opaque, const uint8_t *buf, int size)
cur_mon = opaque;
- // TODO: read QMP input
+ json_message_parser_feed(&cur_mon->mc->parser, (const char *) buf, size);
cur_mon = old_mon;
}
@@ -3709,6 +3945,8 @@ static void monitor_control_event(void *opaque, int event)
QObject *data;
Monitor *mon = opaque;
+ json_message_parser_init(&mon->mc->parser, handle_qmp_command);
+
data = qobject_from_jsonf("{ 'QMP': { 'capabilities': [] } }");
assert(data != NULL);
@@ -3804,6 +4042,7 @@ void monitor_init(CharDriverState *chr, int flags)
}
if (monitor_ctrl_mode(mon)) {
+ mon->mc = qemu_mallocz(sizeof(MonitorControl));
/* Control mode requires special handlers */
qemu_chr_add_handlers(chr, monitor_can_read, monitor_control_read,
monitor_control_event, mon);
--
1.6.6.rc0.50.gaf06e
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 12/20] QMP: Allow 'query-' commands
2009-11-27 0:58 [Qemu-devel] [PATCH v1 00/20] QEMU Monitor Protocol Luiz Capitulino
` (10 preceding siblings ...)
2009-11-27 0:59 ` [Qemu-devel] [PATCH 11/20] QMP: Input support Luiz Capitulino
@ 2009-11-27 0:59 ` Luiz Capitulino
2009-11-27 0:59 ` [Qemu-devel] [PATCH 13/20] QMP: Asynchronous events infrastructure Luiz Capitulino
` (8 subsequent siblings)
20 siblings, 0 replies; 23+ messages in thread
From: Luiz Capitulino @ 2009-11-27 0:59 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori, avi, armbru
The 'info' command makes sense for the user protocol, but for QMP
it doesn't, as its return data is not well defined. That is, it
can return anything.
To fix this Avi proposes having 'query-' commands when in protocol
mode. For example, 'info balloon' would become 'query-balloon'.
The right way of supporting this would probably be to move all
info handlers to qemu-monitor.hx, add a flags field to mon_cmd_t
to identify them and then modify do_info() to do its search based
on that flag.
Unfortunately, this would require a big change in the Monitor.
To make things simpler for now, this commit takes a different
approach: a check for commands starting with "query-" is added to
toplevel QMP code, if it's true we setup things so that do_info()
is called with the appropriate arguments.
This is a hack, but is a temporary one and guarantees that query-
commands will work from the first day.
Also note that 'info' is not allowed in protocol mode.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
monitor.c | 20 +++++++++++++++++---
1 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/monitor.c b/monitor.c
index c172343..0d4380d 100644
--- a/monitor.c
+++ b/monitor.c
@@ -3813,9 +3813,9 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
int err;
QObject *obj;
QDict *input, *args;
- const char *cmd_name;
const mon_cmd_t *cmd;
Monitor *mon = cur_mon;
+ const char *cmd_name, *info_item;
args = NULL;
qemu_errors_to_mon(mon);
@@ -3846,10 +3846,24 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
}
cmd_name = qstring_get_str(qobject_to_qstring(obj));
- cmd = monitor_find_command(cmd_name);
- if (!cmd) {
+
+ /*
+ * XXX: We need this special case until we get info handlers
+ * converted into 'query-' commands
+ */
+ if (compare_cmd(cmd_name, "info")) {
qemu_error_new(QERR_COMMAND_NOT_FOUND, cmd_name);
goto err_input;
+ } 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) {
+ qemu_error_new(QERR_COMMAND_NOT_FOUND, cmd_name);
+ goto err_input;
+ }
}
obj = qdict_get(input, "arguments");
--
1.6.6.rc0.50.gaf06e
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 13/20] QMP: Asynchronous events infrastructure
2009-11-27 0:58 [Qemu-devel] [PATCH v1 00/20] QEMU Monitor Protocol Luiz Capitulino
` (11 preceding siblings ...)
2009-11-27 0:59 ` [Qemu-devel] [PATCH 12/20] QMP: Allow 'query-' commands Luiz Capitulino
@ 2009-11-27 0:59 ` Luiz Capitulino
2009-11-27 0:59 ` [Qemu-devel] [PATCH 14/20] QMP: Introduce basic asynchronous events Luiz Capitulino
` (7 subsequent siblings)
20 siblings, 0 replies; 23+ messages in thread
From: Luiz Capitulino @ 2009-11-27 0:59 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori, avi, armbru
Asynchronous events are generated with a call to
monitor_protocol_event().
This function builds the right data-type and emit the event
right away. The emitted data is always a JSON object and its
format is as follows:
{ "event": json-string,
"timestamp": { "seconds": json-number, "microseconds": json-number },
"data": json-value }
This design is based on ideas by Amit Shah <amit.shah@redhat.com>.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
monitor.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
monitor.h | 6 ++++++
qemu-tool.c | 4 ++++
3 files changed, 60 insertions(+), 0 deletions(-)
diff --git a/monitor.c b/monitor.c
index 0d4380d..a555f12 100644
--- a/monitor.c
+++ b/monitor.c
@@ -307,6 +307,56 @@ static void monitor_protocol_emitter(Monitor *mon, QObject *data)
QDECREF(qmp);
}
+static void timestamp_put(QDict *qdict)
+{
+ int err;
+ QObject *obj;
+ struct timeval tv;
+
+ err = gettimeofday(&tv, NULL);
+ if (err < 0)
+ return;
+
+ obj = qobject_from_jsonf("{ 'seconds': %" PRId64 ", "
+ "'microseconds': %" PRId64 " }",
+ (int64_t) tv.tv_sec, (int64_t) tv.tv_usec);
+ assert(obj != NULL);
+
+ qdict_put_obj(qdict, "timestamp", obj);
+}
+
+/**
+ * monitor_protocol_event(): Generate a Monitor event
+ *
+ * Event-specific data can be emitted through the (optional) 'data' parameter.
+ */
+void monitor_protocol_event(MonitorEvent event, QObject *data)
+{
+ QDict *qmp;
+ const char *event_name;
+ Monitor *mon = cur_mon;
+
+ assert(event < EVENT_MAX);
+
+ if (!monitor_ctrl_mode(mon))
+ return;
+
+ switch (event) {
+ default:
+ abort();
+ break;
+ }
+
+ qmp = qdict_new();
+ timestamp_put(qmp);
+ qdict_put(qmp, "event", qstring_from_str(event_name));
+ if (data)
+ qdict_put_obj(qmp, "data", data);
+
+ monitor_json_emitter(mon, QOBJECT(qmp));
+ QDECREF(qmp);
+}
+
static int compare_cmd(const char *name, const char *list)
{
const char *p, *pstart;
diff --git a/monitor.h b/monitor.h
index 556507c..a1d8b7a 100644
--- a/monitor.h
+++ b/monitor.h
@@ -13,6 +13,12 @@ extern Monitor *cur_mon;
#define MONITOR_USE_READLINE 0x02
#define MONITOR_USE_CONTROL 0x04
+/* QMP events */
+typedef enum MonitorEvent {
+ EVENT_MAX,
+} MonitorEvent;
+
+void monitor_protocol_event(MonitorEvent event, QObject *data);
const char *monitor_cmdline_parse(const char *cmdline, int *flags);
void monitor_init(CharDriverState *chr, int flags);
diff --git a/qemu-tool.c b/qemu-tool.c
index b35ea8e..18b48af 100644
--- a/qemu-tool.c
+++ b/qemu-tool.c
@@ -56,6 +56,10 @@ int get_async_context_id(void)
return 0;
}
+void monitor_protocol_event(MonitorEvent event, QObject *data)
+{
+}
+
QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque)
{
QEMUBH *bh;
--
1.6.6.rc0.50.gaf06e
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 14/20] QMP: Introduce basic asynchronous events
2009-11-27 0:58 [Qemu-devel] [PATCH v1 00/20] QEMU Monitor Protocol Luiz Capitulino
` (12 preceding siblings ...)
2009-11-27 0:59 ` [Qemu-devel] [PATCH 13/20] QMP: Asynchronous events infrastructure Luiz Capitulino
@ 2009-11-27 0:59 ` Luiz Capitulino
2009-11-27 0:59 ` [Qemu-devel] [PATCH 15/20] QMP: Disable monitor print functions Luiz Capitulino
` (6 subsequent siblings)
20 siblings, 0 replies; 23+ messages in thread
From: Luiz Capitulino @ 2009-11-27 0:59 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori, avi, armbru
Debug, shutdown, reset, powerdown and stop are all basic events,
as they are very simple they can be added in the same commit.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
monitor.c | 15 +++++++++++++++
monitor.h | 5 +++++
vl.c | 11 +++++++++--
3 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/monitor.c b/monitor.c
index a555f12..89115a6 100644
--- a/monitor.c
+++ b/monitor.c
@@ -342,6 +342,21 @@ void monitor_protocol_event(MonitorEvent event, QObject *data)
return;
switch (event) {
+ case EVENT_DEBUG:
+ event_name = "DEBUG";
+ break;
+ case EVENT_SHUTDOWN:
+ event_name = "SHUTDOWN";
+ break;
+ case EVENT_RESET:
+ event_name = "RESET";
+ break;
+ case EVENT_POWERDOWN:
+ event_name = "POWERDOWN";
+ break;
+ case EVENT_STOP:
+ event_name = "STOP";
+ break;
default:
abort();
break;
diff --git a/monitor.h b/monitor.h
index a1d8b7a..851fd33 100644
--- a/monitor.h
+++ b/monitor.h
@@ -15,6 +15,11 @@ extern Monitor *cur_mon;
/* QMP events */
typedef enum MonitorEvent {
+ EVENT_DEBUG,
+ EVENT_SHUTDOWN,
+ EVENT_RESET,
+ EVENT_POWERDOWN,
+ EVENT_STOP,
EVENT_MAX,
} MonitorEvent;
diff --git a/vl.c b/vl.c
index dd9b74b..6c709d0 100644
--- a/vl.c
+++ b/vl.c
@@ -4110,9 +4110,12 @@ static void main_loop(void)
#endif
} while (vm_can_run());
- if (qemu_debug_requested())
+ if (qemu_debug_requested()) {
+ monitor_protocol_event(EVENT_DEBUG, NULL);
vm_stop(EXCP_DEBUG);
+ }
if (qemu_shutdown_requested()) {
+ monitor_protocol_event(EVENT_SHUTDOWN, NULL);
if (no_shutdown) {
vm_stop(0);
no_shutdown = 0;
@@ -4120,15 +4123,19 @@ static void main_loop(void)
break;
}
if (qemu_reset_requested()) {
+ monitor_protocol_event(EVENT_RESET, NULL);
pause_all_vcpus();
qemu_system_reset();
resume_all_vcpus();
}
if (qemu_powerdown_requested()) {
+ monitor_protocol_event(EVENT_POWERDOWN, NULL);
qemu_irq_raise(qemu_system_powerdown);
}
- if ((r = qemu_vmstop_requested()))
+ if ((r = qemu_vmstop_requested())) {
+ monitor_protocol_event(EVENT_STOP, NULL);
vm_stop(r);
+ }
}
pause_all_vcpus();
}
--
1.6.6.rc0.50.gaf06e
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 15/20] QMP: Disable monitor print functions
2009-11-27 0:58 [Qemu-devel] [PATCH v1 00/20] QEMU Monitor Protocol Luiz Capitulino
` (13 preceding siblings ...)
2009-11-27 0:59 ` [Qemu-devel] [PATCH 14/20] QMP: Introduce basic asynchronous events Luiz Capitulino
@ 2009-11-27 0:59 ` Luiz Capitulino
2009-11-27 0:59 ` [Qemu-devel] [PATCH 16/20] QMP: Introduce README file Luiz Capitulino
` (5 subsequent siblings)
20 siblings, 0 replies; 23+ messages in thread
From: Luiz Capitulino @ 2009-11-27 0:59 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori, avi, armbru
We still have handlers which will call monitor print functions
in several places. Usually to report errors.
If they do this when we are in control mode, we will be emitting
garbage to our clients.
To avoid this problem, this commit adds a way to disable those
functions. If any of them is called when in control mode, we will
emit a generic error.
Although this is far from the perfect solution, it guarantees
that only JSON is sent to Clients.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
monitor.c | 14 +++++++++++---
1 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/monitor.c b/monitor.c
index 89115a6..a056503 100644
--- a/monitor.c
+++ b/monitor.c
@@ -98,6 +98,7 @@ struct mon_fd_t {
typedef struct MonitorControl {
QObject *id;
+ int print_enabled;
JSONMessageParser parser;
} MonitorControl;
@@ -186,9 +187,13 @@ static void monitor_puts(Monitor *mon, const char *str)
void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
{
- char buf[4096];
- vsnprintf(buf, sizeof(buf), fmt, ap);
- monitor_puts(mon, buf);
+ if (mon->mc && !mon->mc->print_enabled) {
+ qemu_error_new(QERR_UNDEFINED_ERROR);
+ } else {
+ char buf[4096];
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ monitor_puts(mon, buf);
+ }
}
void monitor_printf(Monitor *mon, const char *fmt, ...)
@@ -272,7 +277,10 @@ static void monitor_json_emitter(Monitor *mon, const QObject *data)
json = qobject_to_json(data);
assert(json != NULL);
+ mon->mc->print_enabled = 1;
monitor_printf(mon, "%s\n", qstring_get_str(json));
+ mon->mc->print_enabled = 0;
+
QDECREF(json);
}
--
1.6.6.rc0.50.gaf06e
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 16/20] QMP: Introduce README file
2009-11-27 0:58 [Qemu-devel] [PATCH v1 00/20] QEMU Monitor Protocol Luiz Capitulino
` (14 preceding siblings ...)
2009-11-27 0:59 ` [Qemu-devel] [PATCH 15/20] QMP: Disable monitor print functions Luiz Capitulino
@ 2009-11-27 0:59 ` Luiz Capitulino
2009-11-27 0:59 ` [Qemu-devel] [PATCH 17/20] QMP: Introduce specification Luiz Capitulino
` (4 subsequent siblings)
20 siblings, 0 replies; 23+ messages in thread
From: Luiz Capitulino @ 2009-11-27 0:59 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori, avi, armbru
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
QMP/README | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 51 insertions(+), 0 deletions(-)
create mode 100644 QMP/README
diff --git a/QMP/README b/QMP/README
new file mode 100644
index 0000000..50c31f2
--- /dev/null
+++ b/QMP/README
@@ -0,0 +1,51 @@
+ QEMU Monitor Protocol
+ =====================
+
+Introduction
+-------------
+
+The QEMU Monitor Protocol (QMP) is a JSON[1] based protocol for QEMU.
+
+By using it applications can control QEMU in reliable and "parseable" way,
+QMP also provides asynchronous events support.
+
+For more information, please, refer to the following files:
+
+o qmp-spec.txt QEMU Monitor Protocol current draft specification
+o qmp-events.txt List of available asynchronous events
+
+There are also two simple Python scripts available:
+
+o qmp-shell A shell
+o vm-info Show some informations about the Virtal Machine
+
+[1] http://www.json.org
+
+Usage
+-----
+
+To enable QMP, QEMU has to be started in "control mode". This is done
+by passing the flag "control" to the "-monitor" command-line option.
+
+For example:
+
+$ qemu [...] -monitor control,tcp:localhost:4444,server
+
+Will start QEMU in control mode, waiting for a client TCP connection
+on localhost port 4444.
+
+To manually test it you can connect with telnet and issue commands:
+
+$ telnet localhost 4444
+Trying ::1...
+Connected to localhost.
+Escape character is '^]'.
+{"QMP": {"capabilities": []}}
+{ "execute": "query-version" }
+{"return": "0.11.50"}
+
+Contact
+-------
+
+http://www.linux-kvm.org/page/MonitorProtocol
+Luiz Fernando N. Capitulino <lcapitulino@redhat.com>
--
1.6.6.rc0.50.gaf06e
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 17/20] QMP: Introduce specification
2009-11-27 0:58 [Qemu-devel] [PATCH v1 00/20] QEMU Monitor Protocol Luiz Capitulino
` (15 preceding siblings ...)
2009-11-27 0:59 ` [Qemu-devel] [PATCH 16/20] QMP: Introduce README file Luiz Capitulino
@ 2009-11-27 0:59 ` Luiz Capitulino
2009-11-27 0:59 ` [Qemu-devel] [PATCH 18/20] QMP: Introduce qmp-events.txt Luiz Capitulino
` (3 subsequent siblings)
20 siblings, 0 replies; 23+ messages in thread
From: Luiz Capitulino @ 2009-11-27 0:59 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori, avi, armbru
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
QMP/qmp-spec.txt | 192 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 192 insertions(+), 0 deletions(-)
create mode 100644 QMP/qmp-spec.txt
diff --git a/QMP/qmp-spec.txt b/QMP/qmp-spec.txt
new file mode 100644
index 0000000..8429789
--- /dev/null
+++ b/QMP/qmp-spec.txt
@@ -0,0 +1,192 @@
+ QEMU Monitor Protocol Draft Specification - Version 0.1
+
+1. Introduction
+===============
+
+This document specifies the QEMU Monitor Protocol (QMP), a JSON-based protocol
+which is available for applications to control QEMU at the machine-level.
+
+To enable QMP support, QEMU has to be run in "control mode". This is done by
+starting QEMU with the appropriate command-line options. Please, refer to the
+QEMU manual page for more information.
+
+2. Protocol Specification
+=========================
+
+This section details the protocol format. For the purpose of this document
+"Client" is any application which is communicating with QEMU in control mode,
+and "Server" is QEMU itself.
+
+JSON data structures, when mentioned in this document, are always in the
+following format:
+
+ json-DATA-STRUCTURE-NAME
+
+Where DATA-STRUCTURE-NAME is any valid JSON data structure, as defined by
+the JSON standard:
+
+http://www.ietf.org/rfc/rfc4627.txt
+
+For convenience, json-objects mentioned in this document will have its members
+in a certain order. However, in real protocol usage json-objects members can
+be in ANY order, thus no particular order should be assumed.
+
+2.1 General Definitions
+-----------------------
+
+2.1.1 All interactions transmitted by the Server are json-objects, always
+ terminating with CRLF
+
+2.1.2 All json-objects members are mandatory when not specified otherwise
+
+2.2 Server Greeting
+-------------------
+
+Right when connected the Server will issue a greeting message, which signals
+that the connection has been successfully established and that the Server is
+waiting for commands.
+
+The format is:
+
+{ "QMP": { "capabilities": json-array } }
+
+ Where,
+
+- The "capabilities" member specify the availability of features beyond the
+ baseline specification
+
+2.3 Issuing Commands
+--------------------
+
+The format for command execution is:
+
+{ "execute": json-string, "arguments": json-object, "id": json-value }
+
+ Where,
+
+- The "execute" member identifies the command to be executed by the Server
+- The "arguments" member is used to pass any arguments required for the
+ execution of the command, it is optional when no arguments are required
+- The "id" member is a transaction identification associated with the
+ command execution, it is optional and will be part of the response if
+ provided
+
+2.4 Commands Responses
+----------------------
+
+There are two possible responses which the Server will issue as the result
+of a command execution: success or error.
+
+2.4.1 success
+-------------
+
+The success response is issued when the command execution has finished
+without errors.
+
+The format is:
+
+{ "return": json-value, "id": json-value }
+
+ Where,
+
+- The "return" member contains the command returned data, which is defined
+ in a per-command basis or "OK" if the command does not return data
+- The "id" member contains the transaction identification associated
+ with the command execution (if issued by the Client)
+
+2.4.2 error
+-----------
+
+The error response is issued when the command execution could not be
+completed because of an error condition.
+
+The format is:
+
+{ "error": { "class": json-string, "data": json-value }, "id": json-value }
+
+ Where,
+
+- The "class" member contains the error class name (eg. "ServiceUnavailable")
+- The "data" member contains specific error data and is defined in a
+ per-command basis, it will be an empty json-object if the error has no data
+- The "id" member contains the transaction identification associated with
+ the command execution (if issued by the Client)
+
+NOTE: Some errors can occur before the Server is able to read the "id" member,
+in these cases the "id" member will not be part of the error response, even
+if provided by the client.
+
+2.5 Asynchronous events
+-----------------------
+
+As a result of state changes, the Server may send messages unilaterally
+to the Client at any time. They are called 'asynchronous events'.
+
+The format is:
+
+{ "event": json-string, "data": json-value,
+ "timestamp": { "seconds": json-number, "microseconds": json-number } }
+
+ Where,
+
+- The "event" member contains the event's name
+- The "data" member contains event specific data, which is defined in a
+ per-event basis, it is optional
+- The "timestamp" member contains the exact time of when the event ocurred
+ in the Server. It is a fixed json-object with time in seconds and
+ microseconds
+
+For a listing of supported asynchronous events, please, refer to the
+qmp-events.txt file.
+
+3. QMP Examples
+===============
+
+This section provides some examples of real QMP usage, in all of them
+'C' stands for 'Client' and 'S' stands for 'Server'.
+
+3.1 Server greeting
+-------------------
+
+S: {"QMP": {"capabilities": []}}
+
+3.2 Simple 'stop' execution
+---------------------------
+
+C: { "execute": "stop" }
+S: {"return": "OK"}
+
+3.3 KVM information
+-------------------
+
+C: {"execute": "query-kvm", "id": "example"}
+S: {"return": "enabled", "id": "example"}
+
+3.4 Parsing error
+------------------
+
+C: { "execute": }
+S: {"error": {"class": "JSONParsing", "data": {}}}
+
+3.5 Powerdown event
+-------------------
+
+S: {"timestamp": {"seconds": 1258551470, "microseconds": 802384}, "event":
+"POWERDOWN"}
+
+4. Notes to Client implementors
+-------------------------------
+
+4.1 It is recommended to always start the Server in pause mode, thus the
+ Client is able to perform any setup procedure without the risk of
+ race conditions and related problems
+
+4.2 It is recommended to always check the capabilities json-array, issued
+ with the greeting message, at connection time
+
+4.3 Json-objects or json-arrays mentioned in this document are not fixed
+ and no particular size or number of members/elements should be assumed.
+ New members/elements can be added at any time.
+
+4.4 No particular order of json-objects members should be assumed, they
+ can change at any time
--
1.6.6.rc0.50.gaf06e
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 18/20] QMP: Introduce qmp-events.txt
2009-11-27 0:58 [Qemu-devel] [PATCH v1 00/20] QEMU Monitor Protocol Luiz Capitulino
` (16 preceding siblings ...)
2009-11-27 0:59 ` [Qemu-devel] [PATCH 17/20] QMP: Introduce specification Luiz Capitulino
@ 2009-11-27 0:59 ` Luiz Capitulino
2009-11-27 0:59 ` [Qemu-devel] [PATCH 19/20] QMP: Introduce qmp-shell Luiz Capitulino
` (2 subsequent siblings)
20 siblings, 0 replies; 23+ messages in thread
From: Luiz Capitulino @ 2009-11-27 0:59 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori, avi, armbru
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
QMP/qmp-events.txt | 26 ++++++++++++++++++++++++++
1 files changed, 26 insertions(+), 0 deletions(-)
create mode 100644 QMP/qmp-events.txt
diff --git a/QMP/qmp-events.txt b/QMP/qmp-events.txt
new file mode 100644
index 0000000..682a5e5
--- /dev/null
+++ b/QMP/qmp-events.txt
@@ -0,0 +1,26 @@
+ QEMU Monitor Protocol: Events
+ =============================
+
+1 SHUTDOWN
+-----------
+
+Description: Issued when the Virtual Machine is powered down.
+Data: None.
+
+2 RESET
+-------
+
+Description: Issued when the Virtual Machine is reseted.
+Data: None.
+
+3 STOP
+------
+
+Description: Issued when the Virtual Machine is stopped.
+Data: None.
+
+4 DEBUG
+-------
+
+Description: Issued when the Virtual Machine enters debug mode.
+Data: None.
--
1.6.6.rc0.50.gaf06e
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 19/20] QMP: Introduce qmp-shell
2009-11-27 0:58 [Qemu-devel] [PATCH v1 00/20] QEMU Monitor Protocol Luiz Capitulino
` (17 preceding siblings ...)
2009-11-27 0:59 ` [Qemu-devel] [PATCH 18/20] QMP: Introduce qmp-events.txt Luiz Capitulino
@ 2009-11-27 0:59 ` Luiz Capitulino
2009-11-27 0:59 ` [Qemu-devel] [PATCH 20/20] QMP: Introduce vm-info Luiz Capitulino
2009-12-01 11:38 ` [Qemu-devel] [PATCH v1 00/20] QEMU Monitor Protocol Daniel P. Berrange
20 siblings, 0 replies; 23+ messages in thread
From: Luiz Capitulino @ 2009-11-27 0:59 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori, avi, armbru
This is a very simple shell written in Python for demonstration
purposes.
Unfortunately it's a bit awkward right now, as the user has
to specify the arguments names and the printed data can be
a raw dictionary or list, like the following example:
(QEMU) pci_add pci_addr=auto type=nic
{u'slot': 5, u'bus': 0, u'domain': 0, u'function': 0}
(QEMU)
It's worth to note that the shell is broken into two files.
One is the shell itself, the other is the QMP class which
handles the communication with QEMU.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
QMP/qmp-shell | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
QMP/qmp.py | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 144 insertions(+), 0 deletions(-)
create mode 100755 QMP/qmp-shell
create mode 100644 QMP/qmp.py
diff --git a/QMP/qmp-shell b/QMP/qmp-shell
new file mode 100755
index 0000000..f89b9af
--- /dev/null
+++ b/QMP/qmp-shell
@@ -0,0 +1,72 @@
+#!/usr/bin/python
+#
+# Simple QEMU shell on top of QMP
+#
+# Copyright (C) 2009 Red Hat Inc.
+#
+# Authors:
+# Luiz Capitulino <lcapitulino@redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2. See
+# the COPYING file in the top-level directory.
+#
+# Usage:
+#
+# Start QEMU with:
+#
+# $ qemu [...] -monitor control,unix:./qmp,server
+#
+# Run the shell:
+#
+# $ qmp-shell ./qmp
+#
+# Commands have the following format:
+#
+# < command-name > [ arg-name1=arg1 ] ... [ arg-nameN=argN ]
+#
+# For example:
+#
+# (QEMU) info item=network
+
+import qmp
+import readline
+from sys import argv,exit
+
+def shell_help():
+ print 'bye exit from the shell'
+
+def main():
+ if len(argv) != 2:
+ print 'qemu-shell <unix-socket>'
+ exit(1)
+
+ qemu = qmp.QEMUMonitorProtocol(argv[1])
+ qemu.connect()
+
+ print 'Connected!'
+
+ while True:
+ try:
+ cmd = raw_input('(QEMU) ')
+ except EOFError:
+ print
+ break
+ if cmd == '':
+ continue
+ elif cmd == 'bye':
+ break
+ elif cmd == 'help':
+ shell_help()
+ else:
+ try:
+ resp = qemu.send(cmd)
+ if resp == None:
+ print 'Disconnected'
+ break
+ print resp
+ except IndexError:
+ print '-> command format: <command-name> ',
+ print '[arg-name1=arg1] ... [arg-nameN=argN]'
+
+if __name__ == '__main__':
+ main()
diff --git a/QMP/qmp.py b/QMP/qmp.py
new file mode 100644
index 0000000..d9da603
--- /dev/null
+++ b/QMP/qmp.py
@@ -0,0 +1,72 @@
+# QEMU Monitor Protocol Python class
+#
+# Copyright (C) 2009 Red Hat Inc.
+#
+# Authors:
+# Luiz Capitulino <lcapitulino@redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2. See
+# the COPYING file in the top-level directory.
+
+import socket, json
+
+class QMPError(Exception):
+ pass
+
+class QMPConnectError(QMPError):
+ pass
+
+class QEMUMonitorProtocol:
+ def connect(self):
+ self.sock.connect(self.filename)
+ data = self.__json_read()
+ if data == None:
+ raise QMPConnectError
+ if not data.has_key('QMP'):
+ raise QMPConnectError
+ return data['QMP']['capabilities']
+
+ def close(self):
+ self.sock.close()
+
+ def send_raw(self, line):
+ self.sock.send(str(line))
+ return self.__json_read()
+
+ def send(self, cmdline):
+ cmd = self.__build_cmd(cmdline)
+ self.__json_send(cmd)
+ resp = self.__json_read()
+ if resp == None:
+ return
+ elif resp.has_key('error'):
+ return resp['error']
+ else:
+ return resp['return']
+
+ def __build_cmd(self, cmdline):
+ cmdargs = cmdline.split()
+ qmpcmd = { 'execute': cmdargs[0], 'arguments': {} }
+ for arg in cmdargs[1:]:
+ opt = arg.split('=')
+ try:
+ value = int(opt[1])
+ except ValueError:
+ value = opt[1]
+ qmpcmd['arguments'][opt[0]] = value
+ return qmpcmd
+
+ def __json_send(self, cmd):
+ # XXX: We have to send any additional char, otherwise
+ # the Server won't read our input
+ self.sock.send(json.dumps(cmd) + ' ')
+
+ def __json_read(self):
+ try:
+ return json.loads(self.sock.recv(1024))
+ except ValueError:
+ return
+
+ def __init__(self, filename):
+ self.filename = filename
+ self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
--
1.6.6.rc0.50.gaf06e
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 20/20] QMP: Introduce vm-info
2009-11-27 0:58 [Qemu-devel] [PATCH v1 00/20] QEMU Monitor Protocol Luiz Capitulino
` (18 preceding siblings ...)
2009-11-27 0:59 ` [Qemu-devel] [PATCH 19/20] QMP: Introduce qmp-shell Luiz Capitulino
@ 2009-11-27 0:59 ` Luiz Capitulino
2009-12-01 11:38 ` [Qemu-devel] [PATCH v1 00/20] QEMU Monitor Protocol Daniel P. Berrange
20 siblings, 0 replies; 23+ messages in thread
From: Luiz Capitulino @ 2009-11-27 0:59 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori, avi, armbru
A Python script which uses qmp.py to print some simple VM info.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
QMP/vm-info | 32 ++++++++++++++++++++++++++++++++
1 files changed, 32 insertions(+), 0 deletions(-)
create mode 100755 QMP/vm-info
diff --git a/QMP/vm-info b/QMP/vm-info
new file mode 100755
index 0000000..b150d82
--- /dev/null
+++ b/QMP/vm-info
@@ -0,0 +1,32 @@
+#!/usr/bin/python
+#
+# Print Virtual Machine information
+#
+# Usage:
+#
+# Start QEMU with:
+#
+# $ qemu [...] -monitor control,unix:./qmp,server
+#
+# Run vm-info:
+#
+# $ vm-info ./qmp
+#
+# Luiz Capitulino <lcapitulino@redhat.com>
+
+import qmp
+from sys import argv,exit
+
+def main():
+ if len(argv) != 2:
+ print 'vm-info <unix-socket>'
+ exit(1)
+
+ qemu = qmp.QEMUMonitorProtocol(argv[1])
+ qemu.connect()
+
+ for cmd in [ 'version', 'hpet', 'kvm', 'status', 'uuid', 'balloon' ]:
+ print cmd + ': ' + str(qemu.send('query-' + cmd))
+
+if __name__ == '__main__':
+ main()
--
1.6.6.rc0.50.gaf06e
^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [Qemu-devel] [PATCH v1 00/20] QEMU Monitor Protocol
2009-11-27 0:58 [Qemu-devel] [PATCH v1 00/20] QEMU Monitor Protocol Luiz Capitulino
` (19 preceding siblings ...)
2009-11-27 0:59 ` [Qemu-devel] [PATCH 20/20] QMP: Introduce vm-info Luiz Capitulino
@ 2009-12-01 11:38 ` Daniel P. Berrange
2009-12-01 12:53 ` Luiz Capitulino
20 siblings, 1 reply; 23+ messages in thread
From: Daniel P. Berrange @ 2009-12-01 11:38 UTC (permalink / raw)
To: Luiz Capitulino; +Cc: armbru, aliguori, qemu-devel, avi
On Thu, Nov 26, 2009 at 10:58:50PM -0200, Luiz Capitulino wrote:
> Hi,
>
> This series has a number of improvements over v0 and is a serious
> candidate for inclusion.
>
> Something I'd like to make clear is that QMP is still unstable:
> some commands output are being fixed and most of the error handling
> has not been done yet.
>
> It might look scary to have an unstable protocol merged, on the other
> hand several issues will only come to light with real people testing
> QMP (yeah, I'm not real ;) ).
FYI, I have a fully functional libvirt tree that implements
support for this JSON based monitor protocol I am maintaining
http://gitorious.org/~berrange/libvirt/staging/commits/qemu-monitor-json
Aside from the odd bug here & there in QEMU, it is all working
very well. I think the new JSON protocol is a pretty good
improvement & we'd like to support is as the default mode of
operation in libvirt ASAP :-)
Daniel
--
|: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :|
|: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [Qemu-devel] [PATCH v1 00/20] QEMU Monitor Protocol
2009-12-01 11:38 ` [Qemu-devel] [PATCH v1 00/20] QEMU Monitor Protocol Daniel P. Berrange
@ 2009-12-01 12:53 ` Luiz Capitulino
0 siblings, 0 replies; 23+ messages in thread
From: Luiz Capitulino @ 2009-12-01 12:53 UTC (permalink / raw)
To: Daniel P. Berrange; +Cc: armbru, aliguori, qemu-devel, avi
On Tue, 1 Dec 2009 11:38:52 +0000
"Daniel P. Berrange" <berrange@redhat.com> wrote:
> On Thu, Nov 26, 2009 at 10:58:50PM -0200, Luiz Capitulino wrote:
> > Hi,
> >
> > This series has a number of improvements over v0 and is a serious
> > candidate for inclusion.
> >
> > Something I'd like to make clear is that QMP is still unstable:
> > some commands output are being fixed and most of the error handling
> > has not been done yet.
> >
> > It might look scary to have an unstable protocol merged, on the other
> > hand several issues will only come to light with real people testing
> > QMP (yeah, I'm not real ;) ).
>
> FYI, I have a fully functional libvirt tree that implements
> support for this JSON based monitor protocol I am maintaining
>
> http://gitorious.org/~berrange/libvirt/staging/commits/qemu-monitor-json
>
> Aside from the odd bug here & there in QEMU, it is all working
> very well. I think the new JSON protocol is a pretty good
> improvement & we'd like to support is as the default mode of
> operation in libvirt ASAP :-)
Thanks a lot Daniel.
I'm already working on the problems you've reported, I expect to
fix most of them in the next days.
^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2009-12-01 12:53 UTC | newest]
Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-11-27 0:58 [Qemu-devel] [PATCH v1 00/20] QEMU Monitor Protocol Luiz Capitulino
2009-11-27 0:58 ` [Qemu-devel] [PATCH 01/20] monitor: Introduce MONITOR_USE_CONTROL flag Luiz Capitulino
2009-11-27 0:58 ` [Qemu-devel] [PATCH 02/20] monitor: Command-line flag to enable control mode Luiz Capitulino
2009-11-27 0:58 ` [Qemu-devel] [PATCH 03/20] monitor: Introduce monitor_call_handler() Luiz Capitulino
2009-11-27 0:58 ` [Qemu-devel] [PATCH 04/20] monitor: Introduce monitor_find_command() Luiz Capitulino
2009-11-27 0:58 ` [Qemu-devel] [PATCH 05/20] monitor: Rename monitor_handle_command() Luiz Capitulino
2009-11-27 0:58 ` [Qemu-devel] [PATCH 06/20] monitor: Introduce 'info commands' Luiz Capitulino
2009-11-27 0:58 ` [Qemu-devel] [PATCH 07/20] QError: Add errors needed by QMP Luiz Capitulino
2009-11-27 0:58 ` [Qemu-devel] [PATCH 08/20] QMP: Initial support Luiz Capitulino
2009-11-27 0:58 ` [Qemu-devel] [PATCH 09/20] QMP: Output support Luiz Capitulino
2009-11-27 0:59 ` [Qemu-devel] [PATCH 10/20] QMP: do_info() checks Luiz Capitulino
2009-11-27 0:59 ` [Qemu-devel] [PATCH 11/20] QMP: Input support Luiz Capitulino
2009-11-27 0:59 ` [Qemu-devel] [PATCH 12/20] QMP: Allow 'query-' commands Luiz Capitulino
2009-11-27 0:59 ` [Qemu-devel] [PATCH 13/20] QMP: Asynchronous events infrastructure Luiz Capitulino
2009-11-27 0:59 ` [Qemu-devel] [PATCH 14/20] QMP: Introduce basic asynchronous events Luiz Capitulino
2009-11-27 0:59 ` [Qemu-devel] [PATCH 15/20] QMP: Disable monitor print functions Luiz Capitulino
2009-11-27 0:59 ` [Qemu-devel] [PATCH 16/20] QMP: Introduce README file Luiz Capitulino
2009-11-27 0:59 ` [Qemu-devel] [PATCH 17/20] QMP: Introduce specification Luiz Capitulino
2009-11-27 0:59 ` [Qemu-devel] [PATCH 18/20] QMP: Introduce qmp-events.txt Luiz Capitulino
2009-11-27 0:59 ` [Qemu-devel] [PATCH 19/20] QMP: Introduce qmp-shell Luiz Capitulino
2009-11-27 0:59 ` [Qemu-devel] [PATCH 20/20] QMP: Introduce vm-info Luiz Capitulino
2009-12-01 11:38 ` [Qemu-devel] [PATCH v1 00/20] QEMU Monitor Protocol Daniel P. Berrange
2009-12-01 12:53 ` Luiz Capitulino
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).