mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-20 07:59:00 +00:00
qemu: virsh wrapper for qemu events
Any new API deserves a good virsh wrapper :) qemu-monitor-event [<domain>] [<event>] [--pretty] [--loop] [--timeout <number>] Very similar to the previous work on 'virsh event'. For an example session: $ virsh -c qemu:///system qemu-monitor-event --event SHUTDOWN& $ virsh -c qemu:///system start f18-live Domain f18-live started $ virsh -c qemu:///system destroy f18-live Domain f18-live destroyed event SHUTDOWN at 1391212552.026544 for domain f18-live: (null) events received: 1 [1]+ Done virsh -c qemu:///system qemu-monitor-event --event SHUTDOWN $ * tools/virsh-domain.c (cmdQemuMonitorEvent): New command. * tools/virsh.pod (qemu-monitor-event): Document it. Signed-off-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
parent
2629520342
commit
88996de1c3
@ -7915,6 +7915,135 @@ cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* "qemu-monitor-event" command
|
||||
*/
|
||||
|
||||
struct vshQemuEventData {
|
||||
vshControl *ctl;
|
||||
bool loop;
|
||||
bool pretty;
|
||||
int count;
|
||||
};
|
||||
typedef struct vshQemuEventData vshQemuEventData;
|
||||
|
||||
static void
|
||||
vshEventPrint(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom,
|
||||
const char *event, long long seconds, unsigned int micros,
|
||||
const char *details, void *opaque)
|
||||
{
|
||||
vshQemuEventData *data = opaque;
|
||||
virJSONValuePtr pretty = NULL;
|
||||
char *str = NULL;
|
||||
|
||||
if (!data->loop && data->count)
|
||||
return;
|
||||
if (data->pretty && details) {
|
||||
pretty = virJSONValueFromString(details);
|
||||
if (pretty && (str = virJSONValueToString(pretty, true)))
|
||||
details = str;
|
||||
}
|
||||
vshPrint(data->ctl, "event %s at %lld.%06u for domain %s: %s\n",
|
||||
event, seconds, micros, virDomainGetName(dom), NULLSTR(details));
|
||||
data->count++;
|
||||
if (!data->loop)
|
||||
vshEventDone(data->ctl);
|
||||
|
||||
VIR_FREE(str);
|
||||
}
|
||||
|
||||
static const vshCmdInfo info_qemu_monitor_event[] = {
|
||||
{.name = "help",
|
||||
.data = N_("QEMU Monitor Events")
|
||||
},
|
||||
{.name = "desc",
|
||||
.data = N_("Listen for QEMU Monitor Events")
|
||||
},
|
||||
{.name = NULL}
|
||||
};
|
||||
|
||||
static const vshCmdOptDef opts_qemu_monitor_event[] = {
|
||||
{.name = "domain",
|
||||
.type = VSH_OT_DATA,
|
||||
.help = N_("filter by domain name, id or uuid")
|
||||
},
|
||||
{.name = "event",
|
||||
.type = VSH_OT_DATA,
|
||||
.help = N_("filter by event name")
|
||||
},
|
||||
{.name = "pretty",
|
||||
.type = VSH_OT_BOOL,
|
||||
.help = N_("pretty-print any JSON output")
|
||||
},
|
||||
{.name = "loop",
|
||||
.type = VSH_OT_BOOL,
|
||||
.help = N_("loop until timeout or interrupt, rather than one-shot")
|
||||
},
|
||||
{.name = "timeout",
|
||||
.type = VSH_OT_INT,
|
||||
.help = N_("timeout seconds")
|
||||
},
|
||||
{.name = NULL}
|
||||
};
|
||||
|
||||
static bool
|
||||
cmdQemuMonitorEvent(vshControl *ctl, const vshCmd *cmd)
|
||||
{
|
||||
virDomainPtr dom = NULL;
|
||||
bool ret = false;
|
||||
unsigned int flags = 0;
|
||||
int eventId = -1;
|
||||
int timeout = 0;
|
||||
const char *event = NULL;
|
||||
vshQemuEventData data;
|
||||
|
||||
data.ctl = ctl;
|
||||
data.loop = vshCommandOptBool(cmd, "loop");
|
||||
data.pretty = vshCommandOptBool(cmd, "pretty");
|
||||
data.count = 0;
|
||||
if (vshCommandOptTimeoutToMs(ctl, cmd, &timeout) < 0)
|
||||
return false;
|
||||
if (vshCommandOptString(cmd, "event", &event) < 0)
|
||||
return false;
|
||||
|
||||
if (vshCommandOptBool(cmd, "domain"))
|
||||
dom = vshCommandOptDomain(ctl, cmd, NULL);
|
||||
if (vshEventStart(ctl, timeout) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if ((eventId = virConnectDomainQemuMonitorEventRegister(ctl->conn, dom,
|
||||
event,
|
||||
vshEventPrint,
|
||||
&data, NULL,
|
||||
flags)) < 0)
|
||||
goto cleanup;
|
||||
switch (vshEventWait(ctl)) {
|
||||
case VSH_EVENT_INTERRUPT:
|
||||
vshPrint(ctl, _("event loop interrupted\n"));
|
||||
break;
|
||||
case VSH_EVENT_TIMEOUT:
|
||||
vshPrint(ctl, _("event loop timed out\n"));
|
||||
break;
|
||||
case VSH_EVENT_DONE:
|
||||
break;
|
||||
default:
|
||||
goto cleanup;
|
||||
}
|
||||
vshPrint(ctl, _("events received: %d\n"), data.count);
|
||||
if (data.count)
|
||||
ret = true;
|
||||
|
||||
cleanup:
|
||||
vshEventCleanup(ctl);
|
||||
if (eventId >= 0 &&
|
||||
virConnectDomainQemuMonitorEventDeregister(ctl->conn, eventId) < 0)
|
||||
ret = false;
|
||||
if (dom)
|
||||
virDomainFree(dom);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* "qemu-attach" command
|
||||
*/
|
||||
@ -11550,6 +11679,12 @@ const vshCmdDef domManagementCmds[] = {
|
||||
.info = info_qemu_monitor_command,
|
||||
.flags = 0
|
||||
},
|
||||
{.name = "qemu-monitor-event",
|
||||
.handler = cmdQemuMonitorEvent,
|
||||
.opts = opts_qemu_monitor_event,
|
||||
.info = info_qemu_monitor_event,
|
||||
.flags = 0
|
||||
},
|
||||
{.name = "qemu-agent-command",
|
||||
.handler = cmdQemuAgentCommand,
|
||||
.opts = opts_qemu_agent_command,
|
||||
|
@ -3326,12 +3326,15 @@ variables, and defaults to C<vi>.
|
||||
|
||||
=back
|
||||
|
||||
=head1 QEMU-SPECIFIC COMMANDS
|
||||
=head1 HYPERVISOR-SPECIFIC COMMANDS
|
||||
|
||||
NOTE: Use of the following commands is B<strongly> discouraged. They
|
||||
can cause libvirt to become confused and do the wrong thing on subsequent
|
||||
operations. Once you have used this command, please do not report
|
||||
problems to the libvirt developers; the reports will be ignored.
|
||||
operations. Once you have used these commands, please do not report
|
||||
problems to the libvirt developers; the reports will be ignored. If
|
||||
you find that these commands are the only way to accomplish something,
|
||||
then it is better to request that the feature be added as a first-class
|
||||
citizen in the regular libvirt library.
|
||||
|
||||
=over 4
|
||||
|
||||
@ -3370,7 +3373,8 @@ and the monitor uses QMP, then the output will be pretty-printed. If more
|
||||
than one argument is provided for I<command>, they are concatenated with a
|
||||
space in between before passing the single command to the monitor.
|
||||
|
||||
=item B<qemu-agent-command> I<domain> [I<--timeout> I<seconds> | I<--async> | I<--block>] I<command>...
|
||||
=item B<qemu-agent-command> I<domain> [I<--timeout> I<seconds> | I<--async> |
|
||||
I<--block>] I<command>...
|
||||
|
||||
Send an arbitrary guest agent command I<command> to domain I<domain> through
|
||||
qemu agent.
|
||||
@ -3380,6 +3384,21 @@ When I<--aysnc> is given, the command waits for timeout whether success or
|
||||
failed. And when I<--block> is given, the command waits forever with blocking
|
||||
timeout.
|
||||
|
||||
=item B<qemu-monitor-event> [I<domain>] [I<--event> I<event-name>] [I<--loop>]
|
||||
[I<--timeout> I<seconds>] [I<--pretty>]
|
||||
|
||||
Wait for arbitrary QEMU monitor events to occur, and print out the
|
||||
details of events as they happen. The events can optionally be filtered
|
||||
by I<domain> or I<event-name>. The 'query-events' QMP command can be
|
||||
used via I<qemu-monitor-command> to learn what events are supported.
|
||||
|
||||
By default, this command is one-shot, and returns success once an event
|
||||
occurs; you can send SIGINT (usually via C<Ctrl-C>) to quit immediately.
|
||||
If I<--timeout> is specified, the command gives up waiting for events
|
||||
after I<seconds> have elapsed. With I<--loop>, the command prints all
|
||||
events until a timeout or interrupt key. If I<--pretty> is specified,
|
||||
any JSON event details are pretty-printed for better legibility.
|
||||
|
||||
=item B<lxc-enter-namespace> I<domain> -- /path/to/binary [arg1, [arg2, ...]]
|
||||
|
||||
Enter the namespace of I<domain> and execute the command C</path/to/binary>
|
||||
|
Loading…
x
Reference in New Issue
Block a user