[libvirt] [PATCH v2 8/8] virsh: Introduce nodedev-event command
Cole Robinson
crobinso at redhat.com
Fri Jul 29 16:18:02 UTC 2016
On 07/28/2016 08:02 AM, Jovanka Gulicoska wrote:
> Add nodedev-event support for node device lifecycle events
> ---
> tools/virsh-nodedev.c | 182 ++++++++++++++++++++++++++++++++++++++++++++++++++
> tools/virsh.pod | 18 +++++
> 2 files changed, 200 insertions(+)
>
> diff --git a/tools/virsh-nodedev.c b/tools/virsh-nodedev.c
> index a715b61..5edcf34 100644
> --- a/tools/virsh-nodedev.c
> +++ b/tools/virsh-nodedev.c
> @@ -31,6 +31,7 @@
> #include "viralloc.h"
> #include "virfile.h"
> #include "virstring.h"
> +#include "virtime.h"
> #include "conf/node_device_conf.h"
>
> /*
> @@ -739,6 +740,181 @@ cmdNodeDeviceReset(vshControl *ctl, const vshCmd *cmd)
> return ret;
> }
>
> +/*
> + * "nodedev-event" command
> + */
> +VIR_ENUM_DECL(virshNodeDeviceEvent)
> +VIR_ENUM_IMPL(virshNodeDeviceEvent,
> + VIR_NODE_DEVICE_EVENT_LAST,
> + N_("Created"),
> + N_("Deleted"))
> +
> +static const char *
> +virshNodeDeviceEventToString(int event)
> +{
> + const char *str = virshNodeDeviceEventTypeToString(event);
> + return str ? _(str) : _("unknown");
> +}
> +
> +struct virshNodeDeviceEventData {
> + vshControl *ctl;
> + bool loop;
> + bool timestamp;
> + int count;
> +};
> +typedef struct virshNodeDeviceEventData virshNodeDeviceEventData;
> +
> +VIR_ENUM_DECL(virshNodeDeviceEventId)
> +VIR_ENUM_IMPL(virshNodeDeviceEventId,
> + VIR_NODE_DEVICE_EVENT_ID_LAST,
> + "lifecycle")
> +
> +static void
> +vshEventLifecyclePrint(virConnectPtr conn ATTRIBUTE_UNUSED,
> + virNodeDevicePtr dev,
> + int event,
> + int detail ATTRIBUTE_UNUSED,
> + void *opaque)
> +{
> + virshNodeDeviceEventData *data = opaque;
> +
> + if (!data->loop && data->count)
> + return;
> +
> + if (data->timestamp) {
> + char timestamp[VIR_TIME_STRING_BUFLEN];
> +
> + if (virTimeStringNowRaw(timestamp) < 0)
> + timestamp[0] = '\0';
> +
> + vshPrint(data->ctl, _("%s: event 'lifecycle' for node device %s: %s\n"),
> + timestamp,
> + virNodeDeviceGetName(dev), virshNodeDeviceEventToString(event));
> + } else {
> + vshPrint(data->ctl, _("event 'lifecycle' for node device %s: %s\n"),
> + virNodeDeviceGetName(dev), virshNodeDeviceEventToString(event));
> + }
> +
> + data->count++;
> + if (!data->loop)
> + vshEventDone(data->ctl);
> +}
> +
> +static const vshCmdInfo info_node_device_event[] = {
> + {.name = "help",
> + .data = N_("Node Device Events")
> + },
> + {.name = "desc",
> + .data = N_("List event types, or wait for node device events to occur")
> + },
> + {.name = NULL}
> +};
> +
> +static const vshCmdOptDef opts_node_device_event[] = {
> + {.name = "node device",
> + .type = VSH_OT_STRING,
> + .help = N_("filter by node device name")
> + },
> + {.name = "event",
> + .type = VSH_OT_STRING,
> + .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 = "timestamp",
> + .type = VSH_OT_BOOL,
> + .help = N_("show timestamp for each printed event")
> + },
> + {.name = NULL}
> +};
> +
> +static bool
> +cmdNodeDeviceEvent(vshControl *ctl, const vshCmd *cmd)
> +{
> + virNodeDevicePtr dev = NULL;
> + bool ret = false;
> + int eventId = -1;
> + int timeout = 0;
> + virshNodeDeviceEventData data;
> + const char *eventName = NULL;
> + const char *device_value = NULL;
> + int event;
> + virshControlPtr priv = ctl->privData;
> +
> + if (vshCommandOptBool(cmd, "list")) {
> + size_t i;
> +
> + for (i = 0; i < VIR_NODE_DEVICE_EVENT_ID_LAST; i++)
> + vshPrint(ctl, "%s\n", virshNodeDeviceEventIdTypeToString(i));
> + return true;
> + }
> +
> + if (vshCommandOptStringReq(ctl, cmd, "event", &eventName) < 0)
> + return false;
> + if (!eventName) {
> + vshError(ctl, "%s", _("either --list or event type is required"));
> + return false;
> + }
> + if ((event = virshNodeDeviceEventIdTypeFromString(eventName)) < 0) {
> + vshError(ctl, _("unknown event type %s"), eventName);
> + return false;
> + }
> +
> + data.ctl = ctl;
> + data.loop = vshCommandOptBool(cmd, "loop");
> + data.timestamp = vshCommandOptBool(cmd, "timestamp");
> + data.count = 0;
> + if (vshCommandOptTimeoutToMs(ctl, cmd, &timeout) < 0)
> + return false;
> +
> + if (vshCommandOptStringReq(ctl, cmd, "device", &device_value) < 0)
> + return false;
Actually it looks like this is problem, throwing an assert, since the 'device'
property isn't registered up above, instead it's called "node device". Plus
the property isn't mandatory. So I dropped this patch from my queue, please
fix and resend, it can be applied separately.
Thanks,
Cole
> + if (vshCommandOptBool(cmd, "node device"))
> + dev = virNodeDeviceLookupByName(priv->conn, device_value);
> + if (vshEventStart(ctl, timeout) < 0)
> + goto cleanup;
> +
> + if ((eventId = virConnectNodeDeviceEventRegisterAny(priv->conn, dev, event,
> + VIR_NODE_DEVICE_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 &&
> + virConnectNodeDeviceEventDeregisterAny(priv->conn, eventId) < 0)
> + ret = false;
> + if (dev)
> + virNodeDeviceFree(dev);
> + return ret;
> +}
> +
> +
> const vshCmdDef nodedevCmds[] = {
> {.name = "nodedev-create",
> .handler = cmdNodeDeviceCreate,
> @@ -788,5 +964,11 @@ const vshCmdDef nodedevCmds[] = {
> .info = info_node_device_reset,
> .flags = 0
> },
> + {.name = "nodedev-event",
> + .handler = cmdNodeDeviceEvent,
> + .opts = opts_node_device_event,
> + .info = info_node_device_event,
> + .flags = 0
> + },
> {.name = NULL}
> };
> diff --git a/tools/virsh.pod b/tools/virsh.pod
> index fc6a680..24f2c2b 100644
> --- a/tools/virsh.pod
> +++ b/tools/virsh.pod
> @@ -2957,6 +2957,24 @@ a node device between guest passthrough or the host. Libvirt will
> often do this action implicitly when required, but this command
> allows an explicit reset when needed.
>
> +=item B<nodedev-event> {[I<nodedev>] I<event> [I<--loop>] [I<--timeout>
> +I<seconds>] [I<--timestamp>] | I<--list>}
> +
> +Wait for a class of node device events to occur, and print appropriate
> +details of events as they happen. The events can optionally be filtered
> +by I<nodedev>. 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, 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.
> +
> +When I<--timestamp> is used, a human-readable timestamp will be printed
> +before the event.
> +
> =back
>
> =head1 VIRTUAL NETWORK COMMANDS
>
More information about the libvir-list
mailing list