提交 2169472a 编写于 作者: J Jiri Denemark

qemu: Add shortcut for HMP pass through

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.
上级 be23e2bd
......@@ -20,6 +20,11 @@
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);
......
......@@ -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"
......
......@@ -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;
......
......@@ -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;
......
......@@ -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
......
......@@ -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;
......
......@@ -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 */
......@@ -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);
......
......@@ -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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册