qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [RFC 1/1] Execute arbitrary QMP commands from command line


From: Dr. David Alan Gilbert (git)
Subject: [Qemu-devel] [RFC 1/1] Execute arbitrary QMP commands from command line
Date: Thu, 29 Jan 2015 15:06:37 +0000

From: "Dr. David Alan Gilbert" <address@hidden>

For an incoming migration it's potentially useful to be able to set
capabilities and parameters prior to opening the connection, while
a separate option for that would have been possible it seems better
to give access to all the existing migration capabilities, parameters
etc.  The least restrictive way of doing this is to allow arbitrary
QMP commands to be executed prior to the -incoming being processed.

As an example:

./bin/qemu-system-x86_64 -nographic -nodefaults -qmp-command '{"execute": 
"migrate-set-capabilities", 
"arguments":{"capabilities":[{"capability":"xbzrle","state":true}]}}' 
-qmp-command '{"execute": "query-migrate-capabilities"}' -incoming tcp::444

Signed-off-by: Dr. David Alan Gilbert <address@hidden>
---
 include/monitor/monitor.h |  1 +
 monitor.c                 | 41 +++++++++++++++++++++++++++++++++++++++++
 qemu-options.hx           |  9 +++++++++
 vl.c                      | 37 ++++++++++++++++++++++++++++++++++++-
 4 files changed, 87 insertions(+), 1 deletion(-)

diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
index 47606d0..3fdac1c 100644
--- a/include/monitor/monitor.h
+++ b/include/monitor/monitor.h
@@ -25,6 +25,7 @@ void monitor_init(CharDriverState *chr, int flags);
 
 int monitor_suspend(Monitor *mon);
 void monitor_resume(Monitor *mon);
+void monitor_command_line_qmp(const char *command);
 
 int monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
                                 BlockCompletionFunc *completion_cb,
diff --git a/monitor.c b/monitor.c
index 7e4f605..be9ea57 100644
--- a/monitor.c
+++ b/monitor.c
@@ -5284,6 +5284,47 @@ static void sortcmdlist(void)
     qsort((void *)info_cmds, array_num, elem_size, compare_mon_cmd);
 }
 
+/*
+ * Process a command presented on the command line.
+ */
+void monitor_command_line_qmp(const char *command)
+{
+    Monitor *old_mon = cur_mon;
+    Monitor *mon = g_malloc(sizeof(*mon));
+    QemuOpts *opts;
+    monitor_data_init(mon);
+    bool possibly_more;
+
+    /* Create a char dev into a ringbuffer to hold output */
+    opts = qemu_opts_create(qemu_find_opts("chardev"), "cmdline-mon", 1, NULL);
+    qemu_opt_set(opts, "backend", "ringbuf");
+
+    mon->chr = qemu_chr_new_from_opts(opts, NULL, NULL);
+    mon->flags = MONITOR_USE_CONTROL;
+
+    mon->mc = g_malloc0(sizeof(MonitorControl));
+
+    do_qmp_capabilities(mon, NULL, NULL);
+    cur_mon = mon;
+    json_message_parser_init(&mon->mc->parser, handle_qmp_command);
+    json_message_parser_feed(&mon->mc->parser, command, strlen(command));
+    json_message_parser_flush(&mon->mc->parser);
+    cur_mon = old_mon;
+
+    json_message_parser_destroy(&mon->mc->parser);
+
+    /* Dump the output */
+    do {
+        char *to_print = qmp_ringbuf_read("cmdline-mon", 1024, false, 0, NULL);
+        fprintf(stderr, "%s", to_print);
+        possibly_more = to_print[0] != '\0';
+        g_free(to_print);
+    } while (possibly_more);
+
+    qemu_chr_delete(mon->chr);
+    monitor_data_destroy(mon);
+    g_free(mon);
+}
 
 /*
  * Local variables:
diff --git a/qemu-options.hx b/qemu-options.hx
index 10b9568..aa84ad8 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2799,6 +2799,15 @@ STEXI
 Like -qmp but uses pretty JSON formatting.
 ETEXI
 
+DEF("qmp-command", HAS_ARG, QEMU_OPTION_qmp_command, \
+    "-qmp-command qmp   Execute individual QMP command prior to startup\n",
+    QEMU_ARCH_ALL)
+STEXI
address@hidden -qmp-command @var{command}
address@hidden --qmp-command
+Execute individual QMP command prior to startup
+ETEXI
+
 DEF("mon", HAS_ARG, QEMU_OPTION_mon, \
     "-mon [chardev=]name[,mode=readline|control][,default]\n", QEMU_ARCH_ALL)
 STEXI
diff --git a/vl.c b/vl.c
index fbf4240..62161f6 100644
--- a/vl.c
+++ b/vl.c
@@ -239,6 +239,14 @@ static struct {
     { .driver = "qxl-vga",              .flag = &default_vga       },
 };
 
+/* A list of qmp commands specified on the command line */
+struct qmp_command_queue_entry {
+    char *command;
+    QSIMPLEQ_ENTRY(qmp_command_queue_entry) next;
+};
+
+static QSIMPLEQ_HEAD(, qmp_command_queue_entry) qmp_command_queue_head;
+
 static QemuOptsList qemu_rtc_opts = {
     .name = "rtc",
     .head = QTAILQ_HEAD_INITIALIZER(qemu_rtc_opts.head),
@@ -2595,6 +2603,17 @@ static int machine_set_property(const char *name, const 
char *value,
     return 0;
 }
 
+static void handle_qmp_commands(void)
+{
+    struct qmp_command_queue_entry *entry, *tmp;
+
+    QSIMPLEQ_FOREACH_SAFE(entry, &qmp_command_queue_head, next, tmp) {
+        monitor_command_line_qmp(entry->command);
+        free(entry->command);
+        g_free(entry);
+    }
+}
+
 static int object_create(QemuOpts *opts, void *opaque)
 {
     Error *err = NULL;
@@ -2814,7 +2833,8 @@ int main(int argc, char **argv, char **envp)
 
     rtc_clock = QEMU_CLOCK_HOST;
 
-    QLIST_INIT (&vm_change_state_head);
+    QLIST_INIT(&vm_change_state_head);
+    QSIMPLEQ_INIT(&qmp_command_queue_head);
     os_setup_early_signal_handling();
 
     module_call_init(MODULE_INIT_MACHINE);
@@ -3218,6 +3238,18 @@ int main(int argc, char **argv, char **envp)
                 monitor_parse(optarg, "control", true);
                 default_monitor = 0;
                 break;
+            case QEMU_OPTION_qmp_command:
+                /*
+                 * We can't execute these commands until after the monitor
+                 * has initialised, so just stuff them on a queue for now.
+                 */
+                {
+                    struct qmp_command_queue_entry *entry;
+                    entry = g_new(struct qmp_command_queue_entry, 1);
+                    entry->command = strdup(optarg);
+                    QSIMPLEQ_INSERT_TAIL(&qmp_command_queue_head, entry, next);
+                }
+                break;
             case QEMU_OPTION_mon:
                 opts = qemu_opts_parse(qemu_find_opts("mon"), optarg, 1);
                 if (!opts) {
@@ -4328,6 +4360,9 @@ int main(int argc, char **argv, char **envp)
     rom_load_done();
 
     qemu_system_reset(VMRESET_SILENT);
+
+    handle_qmp_commands();
+
     if (loadvm) {
         if (load_vmstate(loadvm) < 0) {
             autostart = 0;
-- 
2.1.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]