mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-06 11:49:29 +00:00
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.
This commit is contained in:
parent
be23e2bd65
commit
2169472ab6
@ -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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user