[libvirt] [PATCH 4/5] virsh: implementing 'vol-event' command.

Julio Faracco jcfaracco at gmail.com
Sun May 27 19:25:38 UTC 2018


As we have some basics events for volumes, virsh can have the
'vol-event' command to check some events related to volumes.

Signed-off-by: Julio Faracco <jcfaracco at gmail.com>
---
 tools/virsh-completer.c |  27 ++++++
 tools/virsh-completer.h |   4 +
 tools/virsh-volume.c    | 192 ++++++++++++++++++++++++++++++++++++++++
 tools/virsh-volume.h    |   8 ++
 4 files changed, 231 insertions(+)

diff --git a/tools/virsh-completer.c b/tools/virsh-completer.c
index d3effe59ea..30cc595376 100644
--- a/tools/virsh-completer.c
+++ b/tools/virsh-completer.c
@@ -26,6 +26,7 @@
 #include "virsh-domain.h"
 #include "virsh.h"
 #include "virsh-pool.h"
+#include "virsh-volume.h"
 #include "virsh-nodedev.h"
 #include "virsh-util.h"
 #include "virsh-secret.h"
@@ -732,6 +733,32 @@ virshPoolEventNameCompleter(vshControl *ctl ATTRIBUTE_UNUSED,
 }
 
 
+char **
+virshVolEventNameCompleter(vshControl *ctl ATTRIBUTE_UNUSED,
+                           const vshCmd *cmd ATTRIBUTE_UNUSED,
+                           unsigned int flags)
+{
+    size_t i = 0;
+    char **ret = NULL;
+
+    virCheckFlags(0, NULL);
+
+    if (VIR_ALLOC_N(ret, VIR_STORAGE_VOL_EVENT_ID_LAST) < 0)
+        goto error;
+
+    for (i = 0; i < VIR_STORAGE_VOL_EVENT_ID_LAST; i++) {
+        if (VIR_STRDUP(ret[i], virshVolEventCallbacks[i].name) < 0)
+            goto error;
+    }
+
+    return ret;
+
+ error:
+    virStringListFree(ret);
+    return NULL;
+}
+
+
 char **
 virshNodedevEventNameCompleter(vshControl *ctl ATTRIBUTE_UNUSED,
                                const vshCmd *cmd ATTRIBUTE_UNUSED,
diff --git a/tools/virsh-completer.h b/tools/virsh-completer.h
index ee7eec68c5..831be73d7e 100644
--- a/tools/virsh-completer.h
+++ b/tools/virsh-completer.h
@@ -90,6 +90,10 @@ char ** virshPoolEventNameCompleter(vshControl *ctl,
                                     const vshCmd *cmd,
                                     unsigned int flags);
 
+char ** virshVolEventNameCompleter(vshControl *ctl,
+                                    const vshCmd *cmd,
+                                    unsigned int flags);
+
 char ** virshNodedevEventNameCompleter(vshControl *ctl,
                                        const vshCmd *cmd,
                                        unsigned int flags);
diff --git a/tools/virsh-volume.c b/tools/virsh-volume.c
index 9d6ebd2325..63497b7d8c 100644
--- a/tools/virsh-volume.c
+++ b/tools/virsh-volume.c
@@ -42,6 +42,7 @@
 #include "virsh-pool.h"
 #include "virxml.h"
 #include "virstring.h"
+#include "virtime.h"
 
 #define VIRSH_COMMON_OPT_POOL_FULL \
     VIRSH_COMMON_OPT_POOL(N_("pool name or uuid"), \
@@ -1772,6 +1773,191 @@ cmdVolPath(vshControl *ctl, const vshCmd *cmd)
     return true;
 }
 
+/*
+ * "vol-event" command
+ */
+VIR_ENUM_DECL(virshVolEvent)
+VIR_ENUM_IMPL(virshVolEvent,
+              VIR_STORAGE_VOL_EVENT_LAST,
+              N_("Created"),
+              N_("Deleted"))
+
+static const char *
+virshVolEventToString(int event)
+{
+    const char *str = virshVolEventTypeToString(event);
+    return str ? _(str) : _("unknown");
+}
+
+struct virshVolEventData {
+    vshControl *ctl;
+    bool loop;
+    bool timestamp;
+    int count;
+    virshVolEventCallback *cb;
+};
+typedef struct virshVolEventData virshVolEventData;
+
+
+static void
+vshEventLifecyclePrint(virConnectPtr conn ATTRIBUTE_UNUSED,
+                       virStorageVolPtr vol,
+                       int event,
+                       int detail ATTRIBUTE_UNUSED,
+                       void *opaque)
+{
+    virshVolEventData *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 storage vol %s: %s\n"),
+                 timestamp,
+                 virStorageVolGetName(vol),
+                 virshVolEventToString(event));
+    } else {
+        vshPrint(data->ctl, _("event 'lifecycle' for storage vol %s: %s\n"),
+                 virStorageVolGetName(vol),
+                 virshVolEventToString(event));
+    }
+
+    data->count++;
+    if (!data->loop)
+        vshEventDone(data->ctl);
+}
+
+virshVolEventCallback virshVolEventCallbacks[] = {
+    { "lifecycle",
+      VIR_STORAGE_VOL_EVENT_CALLBACK(vshEventLifecyclePrint), }
+};
+verify(VIR_STORAGE_VOL_EVENT_ID_LAST == ARRAY_CARDINALITY(virshVolEventCallbacks));
+
+
+static const vshCmdInfo info_vol_event[] = {
+    {.name = "help",
+     .data = N_("Storage Vol Events")
+    },
+    {.name = "desc",
+     .data = N_("List event types, or wait for storage vol events to occur")
+    },
+    {.name = NULL}
+};
+
+static const vshCmdOptDef opts_vol_event[] = {
+    {.name = "vol",
+     .type = VSH_OT_STRING,
+     .help = N_("filter by storage vol name or uuid")
+    },
+    {.name = "event",
+     .type = VSH_OT_STRING,
+     .completer = virshVolEventNameCompleter,
+     .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
+cmdVolEvent(vshControl *ctl, const vshCmd *cmd)
+{
+    virStorageVolPtr vol = NULL;
+    bool ret = false;
+    int eventId = -1;
+    int timeout = 0;
+    virshVolEventData data;
+    const char *eventName = NULL;
+    int event;
+    virshControlPtr priv = ctl->privData;
+
+    if (vshCommandOptBool(cmd, "list")) {
+        size_t i;
+
+        for (i = 0; i < VIR_STORAGE_VOL_EVENT_ID_LAST; i++)
+            vshPrint(ctl, "%s\n", virshVolEventCallbacks[i].name);
+        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;
+    }
+
+    for (event = 0; event < VIR_STORAGE_VOL_EVENT_ID_LAST; event++)
+        if (STREQ(eventName, virshVolEventCallbacks[event].name))
+            break;
+    if (event == VIR_STORAGE_VOL_EVENT_ID_LAST) {
+        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;
+    data.cb = &virshVolEventCallbacks[event];
+    if (vshCommandOptTimeoutToMs(ctl, cmd, &timeout) < 0)
+        return false;
+
+    if (vshCommandOptBool(cmd, "vol"))
+        vol = virshCommandOptVolBy(ctl, cmd, "vol", NULL, NULL,
+                                   VIRSH_BYUUID);
+
+    if (vshEventStart(ctl, timeout) < 0)
+        goto cleanup;
+
+    if ((eventId = virConnectStorageVolEventRegisterAny(priv->conn, vol, event,
+                                                        data.cb->cb,
+                                                        &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 &&
+        virConnectStorageVolEventDeregisterAny(priv->conn, eventId) < 0)
+        ret = false;
+    if (vol)
+        virStorageVolFree(vol);
+    return ret;
+}
+
 const vshCmdDef storageVolCmds[] = {
     {.name = "vol-clone",
      .handler = cmdVolClone,
@@ -1869,5 +2055,11 @@ const vshCmdDef storageVolCmds[] = {
      .info = info_vol_wipe,
      .flags = 0
     },
+    {.name = "vol-event",
+     .handler = cmdVolEvent,
+     .opts = opts_vol_event,
+     .info = info_vol_event,
+     .flags = 0
+    },
     {.name = NULL}
 };
diff --git a/tools/virsh-volume.h b/tools/virsh-volume.h
index 60f647776e..7869d3bfaf 100644
--- a/tools/virsh-volume.h
+++ b/tools/virsh-volume.h
@@ -38,6 +38,14 @@ virStorageVolPtr virshCommandOptVolBy(vshControl *ctl, const vshCmd *cmd,
     virshCommandOptVolBy(_ctl, _cmd, _optname, _pooloptname, _name, \
                          VIRSH_BYUUID | VIRSH_BYNAME)
 
+struct virshVolEventCallback {
+    const char *name;
+    virConnectStorageVolEventGenericCallback cb;
+};
+typedef struct virshVolEventCallback virshVolEventCallback;
+
+extern virshVolEventCallback virshVolEventCallbacks[];
+
 extern const vshCmdDef storageVolCmds[];
 
 #endif /* VIRSH_VOLUME_H */
-- 
2.17.0




More information about the libvir-list mailing list