]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: Add shortcut for HMP pass through
authorJiri Denemark <jdenemar@redhat.com>
Wed, 2 Feb 2011 15:37:10 +0000 (16:37 +0100)
committerJiri Denemark <jdenemar@redhat.com>
Thu, 3 Feb 2011 21:20:30 +0000 (22:20 +0100)
Currently users who want to use virDomainQemuMonitorCommand() API or
it's virsh equivalent has to use the same protocol as libvirt uses for
communication to qemu. Since the protocol is QMP with current qemu and
HMP much more usable for humans, one ends up typing something like the
following:

    virsh qemu-monitor-command DOM \
'{"execute":"human-monitor-command","arguments":{"command-line":"info kvm"}}'

which is not a very convenient way of debugging qemu.

This patch introduces --hmp option to qemu-monitor-command, which says
that the provided command is in HMP. If libvirt uses QMP to talk with
qemu, the command will automatically be converted into QMP. So the
example above is simplified to just

    virsh qemu-monitor-command --hmp DOM "info kvm"

Also the result is converted from

    {"return":"kvm support: enabled\r\n"}

to just plain HMP:

    kvm support: enabled

If libvirt talks to qemu in HMP, --hmp flag is obviously a noop.

include/libvirt/libvirt-qemu.h
src/internal.h
src/qemu/qemu_driver.c
src/qemu/qemu_monitor.c
src/qemu/qemu_monitor.h
src/qemu/qemu_monitor_json.c
src/qemu/qemu_monitor_json.h
tools/virsh.c
tools/virsh.pod

index 9c191c7f1b0ee110c051d55f0f51735797a25851..9257c2f1eb06ef41a389d14beb51322acd2a59ff 100644 (file)
 extern "C" {
 # endif
 
+enum {
+    VIR_DOMAIN_QEMU_MONITOR_COMMAND_DEFAULT = 0,
+    VIR_DOMAIN_QEMU_MONITOR_COMMAND_HMP     = (1 << 0), /* cmd is in HMP */
+} virDomainQemuMonitorCommandFlags;
+
 int virDomainQemuMonitorCommand(virDomainPtr domain, const char *cmd,
                                 char **result, unsigned int flags);
 
index 11ba45f899c9113d47a601280625725fe8f0a9a3..e263684839b47ad73fcd2794913e320a1d33b5f9 100644 (file)
@@ -38,6 +38,7 @@
 # define N_(str) str
 
 # include "libvirt/libvirt.h"
+# include "libvirt/libvirt-qemu.h"
 # include "libvirt/virterror.h"
 
 # include "libvirt_internal.h"
index d16a4ab6a9b00805df2eff0065a360d1344764b4..b9367355a4d8ab7a3a65b7b1981c06ce592d50b1 100644 (file)
@@ -10242,8 +10242,9 @@ static int qemuDomainMonitorCommand(virDomainPtr domain, const char *cmd,
     virDomainObjPtr vm = NULL;
     int ret = -1;
     qemuDomainObjPrivatePtr priv;
+    bool hmp;
 
-    virCheckFlags(0, -1);
+    virCheckFlags(VIR_DOMAIN_QEMU_MONITOR_COMMAND_HMP, -1);
 
     qemuDriverLock(driver);
     vm = virDomainFindByUUID(&driver->domains, domain->uuid);
@@ -10269,10 +10270,12 @@ static int qemuDomainMonitorCommand(virDomainPtr domain, const char *cmd,
         priv->monitor_warned = 1;
     }
 
+    hmp = !!(flags & VIR_DOMAIN_QEMU_MONITOR_COMMAND_HMP);
+
     if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
         goto cleanup;
     qemuDomainObjEnterMonitorWithDriver(driver, vm);
-    ret = qemuMonitorArbitraryCommand(priv->mon, cmd, result);
+    ret = qemuMonitorArbitraryCommand(priv->mon, cmd, result, hmp);
     qemuDomainObjExitMonitorWithDriver(driver, vm);
     if (qemuDomainObjEndJob(vm) == 0) {
         vm = NULL;
index 0c142770d8dbd95a1dd8a9c00c7225b7e864fe62..fdb6b79924ccb14b79b3771d431f64885e19ec31 100644 (file)
@@ -2007,14 +2007,17 @@ int qemuMonitorDeleteSnapshot(qemuMonitorPtr mon, const char *name)
     return ret;
 }
 
-int qemuMonitorArbitraryCommand(qemuMonitorPtr mon, const char *cmd, char **reply)
+int qemuMonitorArbitraryCommand(qemuMonitorPtr mon,
+                                const char *cmd,
+                                char **reply,
+                                bool hmp)
 {
     int ret;
 
-    DEBUG("mon=%p, cmd=%s, reply=%p", mon, cmd, reply);
+    DEBUG("mon=%p, cmd=%s, reply=%p, hmp=%d", mon, cmd, reply, hmp);
 
     if (mon->json)
-        ret = qemuMonitorJSONArbitraryCommand(mon, cmd, reply);
+        ret = qemuMonitorJSONArbitraryCommand(mon, cmd, reply, hmp);
     else
         ret = qemuMonitorTextArbitraryCommand(mon, cmd, reply);
     return ret;
index 92c550bc187491786d65674487b3f40786d3a598..0ea1330de034447783ac4ec58f2af0946a41a946 100644 (file)
@@ -397,7 +397,10 @@ int qemuMonitorCreateSnapshot(qemuMonitorPtr mon, const char *name);
 int qemuMonitorLoadSnapshot(qemuMonitorPtr mon, const char *name);
 int qemuMonitorDeleteSnapshot(qemuMonitorPtr mon, const char *name);
 
-int qemuMonitorArbitraryCommand(qemuMonitorPtr mon, const char *cmd, char **reply);
+int qemuMonitorArbitraryCommand(qemuMonitorPtr mon,
+                                const char *cmd,
+                                char **reply,
+                                bool hmp);
 
 /**
  * When running two dd process and using <> redirection, we need a
index ca06e7e8d240820a8491124d6018066acae472d1..d5e8d375e41b4d9e13e27cf5ab2c360c317a0147 100644 (file)
@@ -2457,22 +2457,44 @@ int qemuMonitorJSONDeleteSnapshot(qemuMonitorPtr mon, const char *name)
 
 int qemuMonitorJSONArbitraryCommand(qemuMonitorPtr mon,
                                     const char *cmd_str,
-                                    char **reply_str)
+                                    char **reply_str,
+                                    bool hmp)
 {
     virJSONValuePtr cmd = NULL;
     virJSONValuePtr reply = NULL;
     int ret = -1;
 
-    cmd = virJSONValueFromString(cmd_str);
+    if (!hmp) {
+        cmd = virJSONValueFromString(cmd_str);
+    } else {
+        cmd = qemuMonitorJSONMakeCommand("human-monitor-command",
+                                         "s:command-line", cmd_str,
+                                         NULL);
+    }
+
     if (!cmd)
         return -1;
 
     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
         goto cleanup;
 
-    *reply_str = virJSONValueToString(reply);
-    if (!(*reply_str))
+    if (!hmp) {
+        if (!(*reply_str = virJSONValueToString(reply)))
+            goto cleanup;
+    } else if (qemuMonitorJSONCheckError(cmd, reply)) {
         goto cleanup;
+    } else {
+        const char *data;
+        if (!(data = virJSONValueObjectGetString(reply, "return"))) {
+            qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                            _("human monitor command was missing return data"));
+            goto cleanup;
+        }
+        if (!(*reply_str = strdup(data))) {
+            virReportOOMError();
+            goto cleanup;
+        }
+    }
 
     ret = 0;
 
index 4c47f109db32e5ce77045b9c6315fa9bdb73ec31..4ae472a720551b0bff179e9397abba3a0ed78c82 100644 (file)
@@ -209,6 +209,7 @@ int qemuMonitorJSONDeleteSnapshot(qemuMonitorPtr mon, const char *name);
 
 int qemuMonitorJSONArbitraryCommand(qemuMonitorPtr mon,
                                     const char *cmd_str,
-                                    char **reply_str);
+                                    char **reply_str,
+                                    bool hmp);
 
 #endif /* QEMU_MONITOR_JSON_H */
index 59d099e4914a1391313b439b116f8a45132fc60e..1f820e8b39b19769bfd4f8cea5ea738847c59f6f 100644 (file)
@@ -10176,6 +10176,7 @@ static const vshCmdInfo info_qemu_monitor_command[] = {
 static const vshCmdOptDef opts_qemu_monitor_command[] = {
     {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
     {"cmd", VSH_OT_DATA, VSH_OFLAG_REQ, N_("command")},
+    {"hmp", VSH_OT_BOOL, 0, N_("command is in human monitor protocol")},
     {NULL, 0, 0, NULL}
 };
 
@@ -10186,6 +10187,7 @@ cmdQemuMonitorCommand(vshControl *ctl, const vshCmd *cmd)
     int ret = FALSE;
     char *monitor_cmd;
     char *result = NULL;
+    unsigned int flags = 0;
 
     if (!vshConnectionUsability(ctl, ctl->conn))
         goto cleanup;
@@ -10200,7 +10202,10 @@ cmdQemuMonitorCommand(vshControl *ctl, const vshCmd *cmd)
         goto cleanup;
     }
 
-    if (virDomainQemuMonitorCommand(dom, monitor_cmd, &result, 0) < 0)
+    if (vshCommandOptBool(cmd, "hmp"))
+        flags |= VIR_DOMAIN_QEMU_MONITOR_COMMAND_HMP;
+
+    if (virDomainQemuMonitorCommand(dom, monitor_cmd, &result, flags) < 0)
         goto cleanup;
 
     printf("%s\n", result);
index d6a16f2d4f9e0df756b60e326883cc4c84a1e119..bfaa67ec45a8a9d05941c66210ec65af78641a12 100644 (file)
@@ -1253,10 +1253,13 @@ problems to the libvirt developers; the reports will be ignored.
 
 =over 4
 
-=item B<qemu-monitor-command> I<domain> I<command>
+=item B<qemu-monitor-command> I<domain> I<command> optional I<--hmp>
 
 Send an arbitrary monitor command I<command> to domain I<domain> through the
-qemu monitor.  The results of the command will be printed on stdout.
+qemu monitor.  The results of the command will be printed on stdout.  If
+I<--hmp> is passed, the command is considered to be a human monitor command
+and libvirt will automatically convert it into QMP if needed.  In that case
+the result will also be converted back from QMP.
 
 =back