提交 88996de1 编写于 作者: E Eric Blake

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: NEric Blake <eblake@redhat.com>
上级 26295203
...@@ -7915,6 +7915,135 @@ cleanup: ...@@ -7915,6 +7915,135 @@ cleanup:
return ret; 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 * "qemu-attach" command
*/ */
...@@ -11550,6 +11679,12 @@ const vshCmdDef domManagementCmds[] = { ...@@ -11550,6 +11679,12 @@ const vshCmdDef domManagementCmds[] = {
.info = info_qemu_monitor_command, .info = info_qemu_monitor_command,
.flags = 0 .flags = 0
}, },
{.name = "qemu-monitor-event",
.handler = cmdQemuMonitorEvent,
.opts = opts_qemu_monitor_event,
.info = info_qemu_monitor_event,
.flags = 0
},
{.name = "qemu-agent-command", {.name = "qemu-agent-command",
.handler = cmdQemuAgentCommand, .handler = cmdQemuAgentCommand,
.opts = opts_qemu_agent_command, .opts = opts_qemu_agent_command,
......
...@@ -3326,12 +3326,15 @@ variables, and defaults to C<vi>. ...@@ -3326,12 +3326,15 @@ variables, and defaults to C<vi>.
=back =back
=head1 QEMU-SPECIFIC COMMANDS =head1 HYPERVISOR-SPECIFIC COMMANDS
NOTE: Use of the following commands is B<strongly> discouraged. They NOTE: Use of the following commands is B<strongly> discouraged. They
can cause libvirt to become confused and do the wrong thing on subsequent can cause libvirt to become confused and do the wrong thing on subsequent
operations. Once you have used this command, please do not report operations. Once you have used these commands, please do not report
problems to the libvirt developers; the reports will be ignored. 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 =over 4
...@@ -3370,7 +3373,8 @@ and the monitor uses QMP, then the output will be pretty-printed. If more ...@@ -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 than one argument is provided for I<command>, they are concatenated with a
space in between before passing the single command to the monitor. 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 Send an arbitrary guest agent command I<command> to domain I<domain> through
qemu agent. qemu agent.
...@@ -3380,6 +3384,21 @@ When I<--aysnc> is given, the command waits for timeout whether success or ...@@ -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 failed. And when I<--block> is given, the command waits forever with blocking
timeout. 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, ...]] =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> Enter the namespace of I<domain> and execute the command C</path/to/binary>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册