[PATCH 14/14] virsh-completer: Provide completer for '--top' and '--base' for blockjobs

Peter Krempa pkrempa at redhat.com
Thu Sep 16 17:10:45 UTC 2021


Complete with the indexed targets (e.g. vda[3]) based on existing
indexes.

Signed-off-by: Peter Krempa <pkrempa at redhat.com>
---
 tools/virsh-completer-domain.c | 100 +++++++++++++++++++++++++++++++++
 tools/virsh-completer-domain.h |   5 ++
 tools/virsh-domain.c           |   3 +
 3 files changed, 108 insertions(+)

diff --git a/tools/virsh-completer-domain.c b/tools/virsh-completer-domain.c
index 34985f6281..93e992e9b1 100644
--- a/tools/virsh-completer-domain.c
+++ b/tools/virsh-completer-domain.c
@@ -32,6 +32,7 @@
 #include "virperf.h"
 #include "virbitmap.h"
 #include "virkeycode.h"
+#include "virglibutil.h"
 #include "virkeynametable_linux.h"
 #include "virkeynametable_osx.h"
 #include "virkeynametable_win32.h"
@@ -256,6 +257,105 @@ virshDomainUndefineStorageDisksCompleter(vshControl *ctl,
 }


+static GSList *
+virshDomainBlockjobBaseTopCompleteDisk(const char *target,
+                                       xmlXPathContext *ctxt)
+{
+    g_autofree xmlNodePtr *indexlist = NULL;
+    int nindexlist = 0;
+    size_t i;
+    GSList *ret = NULL;
+
+    if ((nindexlist = virXPathNodeSet("./source|./backingStore",
+                                      ctxt, &indexlist)) < 0)
+        return NULL;
+
+    ret = g_slist_prepend(ret, g_strdup(target));
+
+    for (i = 0; i < nindexlist; i++) {
+        g_autofree char *idx = virXMLPropString(indexlist[i], "index");
+
+        if (!idx)
+            continue;
+
+        ret = g_slist_prepend(ret, g_strdup_printf("%s[%s]", target, idx));
+    }
+
+    return ret;
+}
+
+
+char **
+virshDomainBlockjobBaseTopCompleter(vshControl *ctl,
+                                    const vshCmd *cmd,
+                                    unsigned int flags)
+{
+    virshControl *priv = ctl->privData;
+    g_autoptr(xmlDoc) xmldoc = NULL;
+    g_autoptr(xmlXPathContext) ctxt = NULL;
+    g_autofree xmlNodePtr *disks = NULL;
+    int ndisks;
+    size_t i;
+    const char *path = NULL;
+    g_autoptr(virGSListString) list = NULL;
+    GSList *n;
+    GStrv ret = NULL;
+    size_t nelems;
+
+    virCheckFlags(0, NULL);
+
+    if (!priv->conn || virConnectIsAlive(priv->conn) <= 0)
+        return NULL;
+
+    if (virshDomainGetXML(ctl, cmd, 0, &xmldoc, &ctxt) < 0)
+        return NULL;
+
+    ignore_value(vshCommandOptStringQuiet(ctl, cmd, "path", &path));
+
+    if ((ndisks = virXPathNodeSet("./devices/disk", ctxt, &disks)) <= 0)
+        return NULL;
+
+    for (i = 0; i < ndisks; i++) {
+        g_autofree char *disktarget = NULL;
+
+        ctxt->node = disks[i];
+        disktarget = virXPathString("string(./target/@dev)", ctxt);
+
+        if (STREQ_NULLABLE(path, disktarget))
+            break;
+    }
+
+    if (i == ndisks)
+        path = NULL;
+
+    for (i = 0; i < ndisks; i++) {
+        g_autofree char *disktarget = NULL;
+        GSList *tmplist;
+
+        ctxt->node = disks[i];
+
+        if (!(disktarget = virXPathString("string(./target/@dev)", ctxt)))
+            return NULL;
+
+        if (path && STRNEQ(path, disktarget))
+            continue;
+
+        /* note that ctxt->node moved */
+        if ((tmplist = virshDomainBlockjobBaseTopCompleteDisk(disktarget, ctxt)))
+            list = g_slist_concat(tmplist, list);
+    }
+
+    list = g_slist_reverse(list);
+    nelems = g_slist_length(list);
+    ret = g_new0(char *, nelems + 1);
+    i = 0;
+
+    for (n = list; n; n = n->next)
+        ret[i++] = g_strdup(n->data);
+
+    return ret;
+}
+
 char **
 virshDomainEventNameCompleter(vshControl *ctl G_GNUC_UNUSED,
                               const vshCmd *cmd G_GNUC_UNUSED,
diff --git a/tools/virsh-completer-domain.h b/tools/virsh-completer-domain.h
index 1ed3f94094..ec7909888e 100644
--- a/tools/virsh-completer-domain.h
+++ b/tools/virsh-completer-domain.h
@@ -176,3 +176,8 @@ char **
 virshDomainUndefineStorageDisksCompleter(vshControl *ctl,
                                  const vshCmd *cmd,
                                  unsigned int completeflags);
+
+char **
+virshDomainBlockjobBaseTopCompleter(vshControl *ctl,
+                                    const vshCmd *cmd,
+                                    unsigned int flags);
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index d2e604f5dd..1d8af2d274 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -1991,6 +1991,7 @@ static const vshCmdOptDef opts_blockcommit[] = {
     },
     {.name = "base",
      .type = VSH_OT_STRING,
+     .completer = virshDomainBlockjobBaseTopCompleter,
      .help = N_("path of base file to commit into (default bottom of chain)")
     },
     {.name = "shallow",
@@ -1999,6 +2000,7 @@ static const vshCmdOptDef opts_blockcommit[] = {
     },
     {.name = "top",
      .type = VSH_OT_STRING,
+     .completer = virshDomainBlockjobBaseTopCompleter,
      .help = N_("path of top file to commit from (default top of chain)")
     },
     {.name = "active",
@@ -2772,6 +2774,7 @@ static const vshCmdOptDef opts_blockpull[] = {
     },
     {.name = "base",
      .type = VSH_OT_STRING,
+     .completer = virshDomainBlockjobBaseTopCompleter,
      .help = N_("path of backing file in chain for a partial pull")
     },
     {.name = "wait",
-- 
2.31.1




More information about the libvir-list mailing list