Add 'virsh net-event --list' and 'virsh net-event [net] --event=name
[--loop] [--timeout]'. Very similar to 'virsh event'.
* tools/virsh.pod (net-event): Document new command.
* tools/virsh-network.c (vshNetworkEventToString, vshNetEventData)
(vshEventLifecyclePrint, cmdNetworkEvent): New struct and
functions.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
tools/virsh-network.c | 171 +++++++++++++++++++++++++++++++++++++++++++++++++-
tools/virsh.pod | 15 +++++
2 files changed, 185 insertions(+), 1 deletion(-)
diff --git a/tools/virsh-network.c b/tools/virsh-network.c
index 44a676b..4377391 100644
--- a/tools/virsh-network.c
+++ b/tools/virsh-network.c
@@ -1,7 +1,7 @@
/*
* virsh-network.c: Commands to manage network
*
- * Copyright (C) 2005, 2007-2013 Red Hat, Inc.
+ * Copyright (C) 2005, 2007-2014 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -1130,6 +1130,169 @@ cmdNetworkEdit(vshControl *ctl, const vshCmd *cmd)
return ret;
}
+
+/*
+ * "net-event" command
+ */
+static const char *
+vshNetworkEventToString(int event)
+{
+ const char *ret = _("unknown");
+ switch ((virNetworkEventLifecycleType) event) {
+ case VIR_NETWORK_EVENT_DEFINED:
+ ret = _("Defined");
+ break;
+ case VIR_NETWORK_EVENT_UNDEFINED:
+ ret = _("Undefined");
+ break;
+ case VIR_NETWORK_EVENT_STARTED:
+ ret = _("Started");
+ break;
+ case VIR_NETWORK_EVENT_STOPPED:
+ ret = _("Stopped");
+ break;
+ case VIR_NETWORK_EVENT_LAST:
+ break;
+ }
+ return ret;
+}
+
+struct vshNetEventData {
+ vshControl *ctl;
+ bool loop;
+ int count;
+};
+typedef struct vshNetEventData vshNetEventData;
+
+VIR_ENUM_DECL(vshNetworkEvent)
+VIR_ENUM_IMPL(vshNetworkEvent,
+ VIR_NETWORK_EVENT_ID_LAST,
+ "lifecycle")
+
+static void
+vshEventLifecyclePrint(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virNetworkPtr net,
+ int event,
+ int detail ATTRIBUTE_UNUSED,
+ void *opaque)
+{
+ vshNetEventData *data = opaque;
+
+ if (!data->loop && data->count)
+ return;
+ vshPrint(data->ctl, _("event 'lifecycle' for network %s:
%s\n"),
+ virNetworkGetName(net), vshNetworkEventToString(event));
+ data->count++;
+ if (!data->loop)
+ vshEventDone(data->ctl);
+}
+
+static const vshCmdInfo info_network_event[] = {
+ {.name = "net-event",
+ .data = N_("Network Events")
+ },
+ {.name = "desc",
+ .data = N_("List event types, or wait for network events to occur")
+ },
+ {.name = NULL}
+};
+
+static const vshCmdOptDef opts_network_event[] = {
+ {.name = "network",
+ .type = VSH_OT_DATA,
+ .help = N_("filter by network name or uuid")
+ },
+ {.name = "event",
+ .type = VSH_OT_DATA,
+ .help = N_("which event type to wait for")
+ },
+ {.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 = "list",
+ .type = VSH_OT_BOOL,
+ .help = N_("list valid event types")
+ },
+ {.name = NULL}
+};
+
+static bool
+cmdNetworkEvent(vshControl *ctl, const vshCmd *cmd)
+{
+ virNetworkPtr net = NULL;
+ bool ret = false;
+ int eventId = -1;
+ int timeout = 0;
+ vshNetEventData data;
+ const char *eventName = NULL;
+ int event;
+
+ if (vshCommandOptBool(cmd, "list")) {
+ size_t i;
+
+ for (i = 0; i < VIR_NETWORK_EVENT_ID_LAST; i++)
+ vshPrint(ctl, "%s\n", vshNetworkEventTypeToString(i));
+ return true;
+ }
+
+ if (vshCommandOptString(cmd, "event", &eventName) < 0)
+ return false;
+ if (!eventName) {
+ vshError(ctl, "%s", _("either --list or event type is
required"));
+ return false;
+ }
+ if ((event = vshNetworkEventTypeFromString(eventName) < 0)) {
+ vshError(ctl, _("unknown event type %s"), eventName);
+ return false;
+ }
+
+ data.ctl = ctl;
+ data.loop = vshCommandOptBool(cmd, "loop");
+ data.count = 0;
+ if (vshCommandOptTimeoutToMs(ctl, cmd, &timeout) < 0)
+ return false;
+
+ if (vshCommandOptBool(cmd, "network"))
+ net = vshCommandOptNetwork(ctl, cmd, NULL);
+ if (vshEventStart(ctl, timeout) < 0)
+ goto cleanup;
+
+ if ((eventId = virConnectNetworkEventRegisterAny(ctl->conn, net, event,
+
VIR_NETWORK_EVENT_CALLBACK(vshEventLifecyclePrint),
+ &data, NULL)) < 0)
+ goto cleanup;
+ switch (vshEventWait(ctl)) {
+ case VSH_EVENT_INTERRUPT:
+ vshPrint(ctl, "%s", _("event loop interrupted\n"));
+ break;
+ case VSH_EVENT_TIMEOUT:
+ vshPrint(ctl, "%s", _("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 &&
+ virConnectNetworkEventDeregisterAny(ctl->conn, eventId) < 0)
+ ret = false;
+ if (net)
+ virNetworkFree(net);
+ return ret;
+}
+
+
const vshCmdDef networkCmds[] = {
{.name = "net-autostart",
.handler = cmdNetworkAutostart,
@@ -1167,6 +1330,12 @@ const vshCmdDef networkCmds[] = {
.info = info_network_edit,
.flags = 0
},
+ {.name = "net-event",
+ .handler = cmdNetworkEvent,
+ .opts = opts_network_event,
+ .info = info_network_event,
+ .flags = 0
+ },
{.name = "net-info",
.handler = cmdNetworkInfo,
.opts = opts_network_info,
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 0878778..7883231 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -2320,6 +2320,21 @@ except that it does some error checking.
The editor used can be supplied by the C<$VISUAL> or C<$EDITOR> environment
variables, and defaults to C<vi>.
+=item B<net-event> {[I<network>] I<event> [I<--loop>]
[I<--timeout>
+I<seconds>] | I<--list>}
+
+Wait for a class of network events to occur, and print appropriate details
+of events as they happen. The events can optionally be filtered by
+I<network>. Using I<--list> as the only argument will provide a list
+of possible I<event> values known by this client, although the connection
+might not allow registering for all these events.
+
+By default, tihs 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.
+
=item B<net-info> I<network>
Returns basic information about the I<network> object.
--
1.8.5.3