qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Dr. David Alan Gilbert (git)" <dgilbert@redhat.com>
To: qemu-devel@nongnu.org
Cc: amit.shah@redhat.com, liang.z.li@intel.com, quintela@redhat.com
Subject: [Qemu-devel] [RFC 1/1] Execute arbitrary QMP commands from command line
Date: Thu, 29 Jan 2015 15:06:37 +0000	[thread overview]
Message-ID: <1422543997-22808-2-git-send-email-dgilbert@redhat.com> (raw)
In-Reply-To: <1422543997-22808-1-git-send-email-dgilbert@redhat.com>

From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>

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 <dgilbert@redhat.com>
---
 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
+@item -qmp-command @var{command}
+@findex --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	other threads:[~2015-01-29 15:06 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-01-29 15:06 [Qemu-devel] [RFC 0/1] Incoming migration vs early monitor commands Dr. David Alan Gilbert (git)
2015-01-29 15:06 ` Dr. David Alan Gilbert (git) [this message]
2015-01-29 15:15   ` [Qemu-devel] [RFC 1/1] Execute arbitrary QMP commands from command line Daniel P. Berrange
2015-01-29 15:21     ` Eric Blake
2015-01-29 15:54       ` Dr. David Alan Gilbert
2015-01-29 16:01         ` Eric Blake
2015-01-29 16:28           ` Dr. David Alan Gilbert
2015-01-29 17:45             ` Eric Blake
2015-01-29 20:21               ` Dr. David Alan Gilbert
2015-01-29 20:48                 ` Eric Blake
2015-01-30  9:38                   ` Dr. David Alan Gilbert
2015-01-30  9:50                     ` Paolo Bonzini
2015-01-30  9:56                       ` Dr. David Alan Gilbert
2015-02-03 10:12                       ` Amit Shah
2015-02-03 11:02                         ` Paolo Bonzini
2015-01-30  9:50                     ` Daniel P. Berrange
2015-01-30  8:34                 ` Markus Armbruster
2015-01-30  9:20                   ` Dr. David Alan Gilbert
2015-01-30  9:43                     ` Markus Armbruster
2015-01-30  8:35       ` Markus Armbruster
2015-01-29 15:22     ` Dr. David Alan Gilbert
2015-01-29 15:31       ` Daniel P. Berrange
2015-01-29 15:46         ` Dr. David Alan Gilbert
2015-01-29 15:50           ` Eric Blake
2015-01-29 15:56             ` Dr. David Alan Gilbert
2015-01-29 15:58           ` Daniel P. Berrange
2015-01-30  9:52       ` Paolo Bonzini
2015-01-30 10:02         ` Dr. David Alan Gilbert
2015-01-30 10:27           ` Paolo Bonzini
2015-01-29 15:25 ` [Qemu-devel] [RFC 0/1] Incoming migration vs early monitor commands Eric Blake
2015-01-29 23:08 ` Paolo Bonzini
2015-01-30  9:42   ` Dr. David Alan Gilbert

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1422543997-22808-2-git-send-email-dgilbert@redhat.com \
    --to=dgilbert@redhat.com \
    --cc=amit.shah@redhat.com \
    --cc=liang.z.li@intel.com \
    --cc=qemu-devel@nongnu.org \
    --cc=quintela@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).