[libvirt] [PATCH 4/5] Improve virsh autocompletion (domain completer)

Solly Ross sross at redhat.com
Sun Mar 30 02:36:12 UTC 2014


This patch introduces a custom completer for domains,
and sets it to be used for all of the "domain" arguments.

In order to facilitate this, the functions involved in
retrieve in a list of domains were moved from
virsh-domain-monitor to virsh-completer, where they
can be included by any file that needs to use them.
---
 tools/Makefile.am            |   3 +-
 tools/virsh-completer.c      | 332 +++++++++++++++++++++++++++++++++++++++++++
 tools/virsh-completer.h      |  39 +++++
 tools/virsh-domain-monitor.c | 287 ++-----------------------------------
 tools/virsh-domain.c         |  72 ++++++++++
 tools/virsh-snapshot.c       |  11 ++
 6 files changed, 468 insertions(+), 276 deletions(-)
 create mode 100644 tools/virsh-completer.c
 create mode 100644 tools/virsh-completer.h

diff --git a/tools/Makefile.am b/tools/Makefile.am
index 6847f13..e660720 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -53,7 +53,7 @@ EXTRA_DIST = \
 	virsh-network.c virsh-nodedev.c			\
 	virsh-nwfilter.c virsh-pool.c			\
 	virsh-secret.c virsh-snapshot.c			\
-	virsh-volume.c
+	virsh-volume.c virsh-completer.c
 
 
 
@@ -191,6 +191,7 @@ virsh_SOURCES =							\
 		virsh-secret.c virsh-secret.h			\
 		virsh-snapshot.c virsh-snapshot.h		\
 		virsh-volume.c virsh-volume.h			\
+		virsh-completer.c virsh-completer.h		\
 		$(NULL)
 
 virsh_LDFLAGS = \
diff --git a/tools/virsh-completer.c b/tools/virsh-completer.c
new file mode 100644
index 0000000..fedf52b
--- /dev/null
+++ b/tools/virsh-completer.c
@@ -0,0 +1,332 @@
+/*
+ * virsh-completer.h: Common custom completion utilities
+ *
+ * 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
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include "virsh-completer.h"
+
+#include "conf/domain_conf.h"
+#include "viralloc.h"
+
+
+/* Utils - Domain Listing */
+/* compare domains, pack NULLed ones at the end*/
+static int
+vshDomainSorter(const void *a, const void *b)
+{
+    virDomainPtr *da = (virDomainPtr *) a;
+    virDomainPtr *db = (virDomainPtr *) b;
+    unsigned int ida;
+    unsigned int idb;
+    unsigned int inactive = (unsigned int) -1;
+
+    if (*da && !*db)
+        return -1;
+
+    if (!*da)
+        return *db != NULL;
+
+    ida = virDomainGetID(*da);
+    idb = virDomainGetID(*db);
+
+    if (ida == inactive && idb == inactive)
+        return vshStrcasecmp(virDomainGetName(*da), virDomainGetName(*db));
+
+    if (ida != inactive && idb != inactive) {
+        if (ida > idb)
+            return 1;
+        else if (ida < idb)
+            return -1;
+    }
+
+    if (ida != inactive)
+        return -1;
+    else
+        return 1;
+}
+
+void
+vshDomainListFree(vshDomainListPtr domlist)
+{
+    size_t i;
+
+    if (domlist && domlist->domains) {
+        for (i = 0; i < domlist->ndomains; i++) {
+            if (domlist->domains[i])
+                virDomainFree(domlist->domains[i]);
+        }
+        VIR_FREE(domlist->domains);
+    }
+    VIR_FREE(domlist);
+}
+
+vshDomainListPtr
+vshDomainListCollect(vshControl *ctl, unsigned int flags)
+{
+    vshDomainListPtr list = vshMalloc(ctl, sizeof(*list));
+    size_t i;
+    int ret;
+    int *ids = NULL;
+    int nids = 0;
+    char **names = NULL;
+    int nnames = 0;
+    virDomainPtr dom;
+    bool success = false;
+    size_t deleted = 0;
+    int persistent;
+    int autostart;
+    int state;
+    int nsnap;
+    int mansave;
+
+    /* try the list with flags support (0.9.13 and later) */
+    if ((ret = virConnectListAllDomains(ctl->conn, &list->domains,
+                                        flags)) >= 0) {
+        list->ndomains = ret;
+        goto finished;
+    }
+
+    /* check if the command is actually supported */
+    if (last_error && last_error->code == VIR_ERR_NO_SUPPORT) {
+        vshResetLibvirtError();
+        goto fallback;
+    }
+
+    if (last_error && last_error->code ==  VIR_ERR_INVALID_ARG) {
+        /* try the new API again but mask non-guaranteed flags */
+        unsigned int newflags = flags & (VIR_CONNECT_LIST_DOMAINS_ACTIVE |
+                                         VIR_CONNECT_LIST_DOMAINS_INACTIVE);
+
+        vshResetLibvirtError();
+        if ((ret = virConnectListAllDomains(ctl->conn, &list->domains,
+                                            newflags)) >= 0) {
+            list->ndomains = ret;
+            goto filter;
+        }
+    }
+
+    /* there was an error during the first or second call */
+    vshError(ctl, "%s", _("Failed to list domains"));
+    goto cleanup;
+
+
+ fallback:
+    /* fall back to old method (0.9.12 and older) */
+    vshResetLibvirtError();
+
+    /* list active domains, if necessary */
+    if (!VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE) ||
+        VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_ACTIVE)) {
+        if ((nids = virConnectNumOfDomains(ctl->conn)) < 0) {
+            vshError(ctl, "%s", _("Failed to list active domains"));
+            goto cleanup;
+        }
+
+        if (nids) {
+            ids = vshMalloc(ctl, sizeof(int) * nids);
+
+            if ((nids = virConnectListDomains(ctl->conn, ids, nids)) < 0) {
+                vshError(ctl, "%s", _("Failed to list active domains"));
+                goto cleanup;
+            }
+        }
+    }
+
+    if (!VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE) ||
+        VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_INACTIVE)) {
+        if ((nnames = virConnectNumOfDefinedDomains(ctl->conn)) < 0) {
+            vshError(ctl, "%s", _("Failed to list inactive domains"));
+            goto cleanup;
+        }
+
+        if (nnames) {
+            names = vshMalloc(ctl, sizeof(char *) * nnames);
+
+            if ((nnames = virConnectListDefinedDomains(ctl->conn, names,
+                                                      nnames)) < 0) {
+                vshError(ctl, "%s", _("Failed to list inactive domains"));
+                goto cleanup;
+            }
+        }
+    }
+
+    list->domains = vshMalloc(ctl, sizeof(virDomainPtr) * (nids + nnames));
+    list->ndomains = 0;
+
+    /* get active domains */
+    for (i = 0; i < nids; i++) {
+        if (!(dom = virDomainLookupByID(ctl->conn, ids[i])))
+            continue;
+        list->domains[list->ndomains++] = dom;
+    }
+
+    /* get inactive domains */
+    for (i = 0; i < nnames; i++) {
+        if (!(dom = virDomainLookupByName(ctl->conn, names[i])))
+            continue;
+        list->domains[list->ndomains++] = dom;
+    }
+
+    /* truncate domains that weren't found */
+    deleted = (nids + nnames) - list->ndomains;
+
+ filter:
+    /* filter list the list if the list was acquired by fallback means */
+    for (i = 0; i < list->ndomains; i++) {
+        dom = list->domains[i];
+
+        /* persistence filter */
+        if (VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_PERSISTENT)) {
+            if ((persistent = virDomainIsPersistent(dom)) < 0) {
+                vshError(ctl, "%s", _("Failed to get domain persistence info"));
+                goto cleanup;
+            }
+
+            if (!((VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_PERSISTENT) && persistent) ||
+                  (VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_TRANSIENT) && !persistent)))
+                goto remove_entry;
+        }
+
+        /* domain state filter */
+        if (VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_STATE)) {
+            if (virDomainGetState(dom, &state, NULL, 0) < 0) {
+                vshError(ctl, "%s", _("Failed to get domain state"));
+                goto cleanup;
+            }
+
+            if (!((VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_RUNNING) &&
+                   state == VIR_DOMAIN_RUNNING) ||
+                  (VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_PAUSED) &&
+                   state == VIR_DOMAIN_PAUSED) ||
+                  (VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_SHUTOFF) &&
+                   state == VIR_DOMAIN_SHUTOFF) ||
+                  (VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_OTHER) &&
+                   (state != VIR_DOMAIN_RUNNING &&
+                    state != VIR_DOMAIN_PAUSED &&
+                    state != VIR_DOMAIN_SHUTOFF))))
+                goto remove_entry;
+        }
+
+        /* autostart filter */
+        if (VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_AUTOSTART)) {
+            if (virDomainGetAutostart(dom, &autostart) < 0) {
+                vshError(ctl, "%s", _("Failed to get domain autostart state"));
+                goto cleanup;
+            }
+
+            if (!((VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_AUTOSTART) && autostart) ||
+                  (VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_NO_AUTOSTART) && !autostart)))
+                goto remove_entry;
+        }
+
+        /* managed save filter */
+        if (VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_MANAGEDSAVE)) {
+            if ((mansave = virDomainHasManagedSaveImage(dom, 0)) < 0) {
+                vshError(ctl, "%s",
+                         _("Failed to check for managed save image"));
+                goto cleanup;
+            }
+
+            if (!((VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_MANAGEDSAVE) && mansave) ||
+                  (VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_NO_MANAGEDSAVE) && !mansave)))
+                goto remove_entry;
+        }
+
+        /* snapshot filter */
+        if (VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_SNAPSHOT)) {
+            if ((nsnap = virDomainSnapshotNum(dom, 0)) < 0) {
+                vshError(ctl, "%s", _("Failed to get snapshot count"));
+                goto cleanup;
+            }
+            if (!((VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_HAS_SNAPSHOT) && nsnap > 0) ||
+                  (VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_NO_SNAPSHOT) && nsnap == 0)))
+                goto remove_entry;
+        }
+
+        /* the domain matched all filters, it may stay */
+        continue;
+
+ remove_entry:
+        /* the domain has to be removed as it failed one of the filters */
+        virDomainFree(list->domains[i]);
+        list->domains[i] = NULL;
+        deleted++;
+    }
+
+ finished:
+    /* sort the list */
+    if (list->domains && list->ndomains)
+        qsort(list->domains, list->ndomains, sizeof(*list->domains),
+              vshDomainSorter);
+
+    /* truncate the list if filter simulation deleted entries */
+    if (deleted)
+        VIR_SHRINK_N(list->domains, list->ndomains, deleted);
+
+    success = true;
+
+ cleanup:
+    for (i = 0; nnames != -1 && i < nnames; i++)
+        VIR_FREE(names[i]);
+
+    if (!success) {
+        vshDomainListFree(list);
+        list = NULL;
+    }
+
+    VIR_FREE(names);
+    VIR_FREE(ids);
+    return list;
+}
+
+
+/* Common completers */
+char **
+vshCompleteDomain(unsigned int flags)
+{
+    vshControl *ctl = vshGetCompleterCtl();
+    vshDomainListPtr dom_list = NULL;
+    virDomainPtr *domains = NULL;
+    char **names = NULL;
+
+    if (!ctl)
+        return NULL;
+
+    if (flags == 0)
+        flags = VIR_CONNECT_LIST_DOMAINS_ACTIVE |
+                VIR_CONNECT_LIST_DOMAINS_INACTIVE;
+
+    dom_list = vshDomainListCollect(ctl, flags);
+
+    if (!dom_list)
+        return NULL;
+
+    domains = dom_list->domains;
+    names = vshCalloc(ctl, dom_list->ndomains+1, sizeof(char*));
+
+    for (int i = 0; i < dom_list->ndomains; i++)
+        names[i] = vshStrdup(ctl, virDomainGetName(domains[i]));
+
+    names[dom_list->ndomains] = NULL;
+
+    vshDomainListFree(dom_list);
+
+    return names;
+};
+
diff --git a/tools/virsh-completer.h b/tools/virsh-completer.h
new file mode 100644
index 0000000..828669b
--- /dev/null
+++ b/tools/virsh-completer.h
@@ -0,0 +1,39 @@
+/*
+ * virsh-completer.h: Common custom completion utilities
+ *
+ * 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
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef VIRSH_COMPLETER_H
+# define VIRSH_COMPLETER_H
+
+# include "virsh.h"
+
+struct vshDomainList {
+    virDomainPtr *domains;
+    size_t ndomains;
+};
+typedef struct vshDomainList *vshDomainListPtr;
+
+void vshDomainListFree(vshDomainListPtr domlist);
+
+vshDomainListPtr vshDomainListCollect(vshControl *ctl, unsigned int flags);
+
+char ** vshCompleteDomain(unsigned int flags);
+
+#endif /* VIRSH_COMPLETER_H */
+
diff --git a/tools/virsh-domain-monitor.c b/tools/virsh-domain-monitor.c
index 18d551a..50cb920 100644
--- a/tools/virsh-domain-monitor.c
+++ b/tools/virsh-domain-monitor.c
@@ -25,6 +25,7 @@
 
 #include <config.h>
 #include "virsh-domain-monitor.h"
+#include "virsh-completer.h"
 
 #include <libxml/parser.h>
 #include <libxml/tree.h>
@@ -268,6 +269,7 @@ static const vshCmdOptDef opts_dommemstat[] = {
     {.name = "domain",
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
+     .completer = vshCompleteDomain,
      .help = N_("domain name, id or uuid")
     },
     {.name = "period",
@@ -392,6 +394,7 @@ static const vshCmdOptDef opts_domblkinfo[] = {
     {.name = "domain",
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
+     .completer = vshCompleteDomain,
      .help = N_("domain name, id or uuid")
     },
     {.name = "device",
@@ -447,6 +450,7 @@ static const vshCmdOptDef opts_domblklist[] = {
     {.name = "domain",
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
+     .completer = vshCompleteDomain,
      .help = N_("domain name, id or uuid")
     },
     {.name = "inactive",
@@ -569,6 +573,7 @@ static const vshCmdOptDef opts_domiflist[] = {
     {.name = "domain",
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
+     .completer = vshCompleteDomain,
      .help = N_("domain name, id or uuid")
     },
     {.name = "inactive",
@@ -674,6 +679,7 @@ static const vshCmdOptDef opts_domif_getlink[] = {
     {.name = "domain",
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
+     .completer = vshCompleteDomain,
      .help = N_("domain name, id or uuid")
     },
     {.name = "interface",
@@ -789,6 +795,7 @@ static const vshCmdOptDef opts_domcontrol[] = {
     {.name = "domain",
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
+     .completer = vshCompleteDomain,
      .help = N_("domain name, id or uuid")
     },
     {.name = NULL}
@@ -842,6 +849,7 @@ static const vshCmdOptDef opts_domblkstat[] = {
     {.name = "domain",
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
+     .completer = vshCompleteDomain,
      .help = N_("domain name, id or uuid")
     },
     {.name = "device",
@@ -1032,6 +1040,7 @@ static const vshCmdOptDef opts_domifstat[] = {
     {.name = "domain",
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
+     .completer = vshCompleteDomain,
      .help = N_("domain name, id or uuid")
     },
     {.name = "interface",
@@ -1109,6 +1118,7 @@ static const vshCmdOptDef opts_domblkerror[] = {
     {.name = "domain",
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
+     .completer = vshCompleteDomain,
      .help = N_("domain name, id, or uuid")
     },
     {.name = NULL}
@@ -1174,6 +1184,7 @@ static const vshCmdOptDef opts_dominfo[] = {
     {.name = "domain",
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
+     .completer = vshCompleteDomain,
      .help = N_("domain name, id or uuid")
     },
     {.name = NULL}
@@ -1316,6 +1327,7 @@ static const vshCmdOptDef opts_domstate[] = {
     {.name = "domain",
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
+     .completer = vshCompleteDomain,
      .help = N_("domain name, id or uuid")
     },
     {.name = "reason",
@@ -1368,281 +1380,6 @@ static const vshCmdInfo info_list[] = {
     {.name = NULL}
 };
 
-/* compare domains, pack NULLed ones at the end*/
-static int
-vshDomainSorter(const void *a, const void *b)
-{
-    virDomainPtr *da = (virDomainPtr *) a;
-    virDomainPtr *db = (virDomainPtr *) b;
-    unsigned int ida;
-    unsigned int idb;
-    unsigned int inactive = (unsigned int) -1;
-
-    if (*da && !*db)
-        return -1;
-
-    if (!*da)
-        return *db != NULL;
-
-    ida = virDomainGetID(*da);
-    idb = virDomainGetID(*db);
-
-    if (ida == inactive && idb == inactive)
-        return vshStrcasecmp(virDomainGetName(*da), virDomainGetName(*db));
-
-    if (ida != inactive && idb != inactive) {
-        if (ida > idb)
-            return 1;
-        else if (ida < idb)
-            return -1;
-    }
-
-    if (ida != inactive)
-        return -1;
-    else
-        return 1;
-}
-
-struct vshDomainList {
-    virDomainPtr *domains;
-    size_t ndomains;
-};
-typedef struct vshDomainList *vshDomainListPtr;
-
-static void
-vshDomainListFree(vshDomainListPtr domlist)
-{
-    size_t i;
-
-    if (domlist && domlist->domains) {
-        for (i = 0; i < domlist->ndomains; i++) {
-            if (domlist->domains[i])
-                virDomainFree(domlist->domains[i]);
-        }
-        VIR_FREE(domlist->domains);
-    }
-    VIR_FREE(domlist);
-}
-
-static vshDomainListPtr
-vshDomainListCollect(vshControl *ctl, unsigned int flags)
-{
-    vshDomainListPtr list = vshMalloc(ctl, sizeof(*list));
-    size_t i;
-    int ret;
-    int *ids = NULL;
-    int nids = 0;
-    char **names = NULL;
-    int nnames = 0;
-    virDomainPtr dom;
-    bool success = false;
-    size_t deleted = 0;
-    int persistent;
-    int autostart;
-    int state;
-    int nsnap;
-    int mansave;
-
-    /* try the list with flags support (0.9.13 and later) */
-    if ((ret = virConnectListAllDomains(ctl->conn, &list->domains,
-                                        flags)) >= 0) {
-        list->ndomains = ret;
-        goto finished;
-    }
-
-    /* check if the command is actually supported */
-    if (last_error && last_error->code == VIR_ERR_NO_SUPPORT) {
-        vshResetLibvirtError();
-        goto fallback;
-    }
-
-    if (last_error && last_error->code ==  VIR_ERR_INVALID_ARG) {
-        /* try the new API again but mask non-guaranteed flags */
-        unsigned int newflags = flags & (VIR_CONNECT_LIST_DOMAINS_ACTIVE |
-                                         VIR_CONNECT_LIST_DOMAINS_INACTIVE);
-
-        vshResetLibvirtError();
-        if ((ret = virConnectListAllDomains(ctl->conn, &list->domains,
-                                            newflags)) >= 0) {
-            list->ndomains = ret;
-            goto filter;
-        }
-    }
-
-    /* there was an error during the first or second call */
-    vshError(ctl, "%s", _("Failed to list domains"));
-    goto cleanup;
-
-
- fallback:
-    /* fall back to old method (0.9.12 and older) */
-    vshResetLibvirtError();
-
-    /* list active domains, if necessary */
-    if (!VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE) ||
-        VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_ACTIVE)) {
-        if ((nids = virConnectNumOfDomains(ctl->conn)) < 0) {
-            vshError(ctl, "%s", _("Failed to list active domains"));
-            goto cleanup;
-        }
-
-        if (nids) {
-            ids = vshMalloc(ctl, sizeof(int) * nids);
-
-            if ((nids = virConnectListDomains(ctl->conn, ids, nids)) < 0) {
-                vshError(ctl, "%s", _("Failed to list active domains"));
-                goto cleanup;
-            }
-        }
-    }
-
-    if (!VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE) ||
-        VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_INACTIVE)) {
-        if ((nnames = virConnectNumOfDefinedDomains(ctl->conn)) < 0) {
-            vshError(ctl, "%s", _("Failed to list inactive domains"));
-            goto cleanup;
-        }
-
-        if (nnames) {
-            names = vshMalloc(ctl, sizeof(char *) * nnames);
-
-            if ((nnames = virConnectListDefinedDomains(ctl->conn, names,
-                                                      nnames)) < 0) {
-                vshError(ctl, "%s", _("Failed to list inactive domains"));
-                goto cleanup;
-            }
-        }
-    }
-
-    list->domains = vshMalloc(ctl, sizeof(virDomainPtr) * (nids + nnames));
-    list->ndomains = 0;
-
-    /* get active domains */
-    for (i = 0; i < nids; i++) {
-        if (!(dom = virDomainLookupByID(ctl->conn, ids[i])))
-            continue;
-        list->domains[list->ndomains++] = dom;
-    }
-
-    /* get inactive domains */
-    for (i = 0; i < nnames; i++) {
-        if (!(dom = virDomainLookupByName(ctl->conn, names[i])))
-            continue;
-        list->domains[list->ndomains++] = dom;
-    }
-
-    /* truncate domains that weren't found */
-    deleted = (nids + nnames) - list->ndomains;
-
- filter:
-    /* filter list the list if the list was acquired by fallback means */
-    for (i = 0; i < list->ndomains; i++) {
-        dom = list->domains[i];
-
-        /* persistence filter */
-        if (VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_PERSISTENT)) {
-            if ((persistent = virDomainIsPersistent(dom)) < 0) {
-                vshError(ctl, "%s", _("Failed to get domain persistence info"));
-                goto cleanup;
-            }
-
-            if (!((VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_PERSISTENT) && persistent) ||
-                  (VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_TRANSIENT) && !persistent)))
-                goto remove_entry;
-        }
-
-        /* domain state filter */
-        if (VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_STATE)) {
-            if (virDomainGetState(dom, &state, NULL, 0) < 0) {
-                vshError(ctl, "%s", _("Failed to get domain state"));
-                goto cleanup;
-            }
-
-            if (!((VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_RUNNING) &&
-                   state == VIR_DOMAIN_RUNNING) ||
-                  (VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_PAUSED) &&
-                   state == VIR_DOMAIN_PAUSED) ||
-                  (VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_SHUTOFF) &&
-                   state == VIR_DOMAIN_SHUTOFF) ||
-                  (VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_OTHER) &&
-                   (state != VIR_DOMAIN_RUNNING &&
-                    state != VIR_DOMAIN_PAUSED &&
-                    state != VIR_DOMAIN_SHUTOFF))))
-                goto remove_entry;
-        }
-
-        /* autostart filter */
-        if (VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_AUTOSTART)) {
-            if (virDomainGetAutostart(dom, &autostart) < 0) {
-                vshError(ctl, "%s", _("Failed to get domain autostart state"));
-                goto cleanup;
-            }
-
-            if (!((VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_AUTOSTART) && autostart) ||
-                  (VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_NO_AUTOSTART) && !autostart)))
-                goto remove_entry;
-        }
-
-        /* managed save filter */
-        if (VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_MANAGEDSAVE)) {
-            if ((mansave = virDomainHasManagedSaveImage(dom, 0)) < 0) {
-                vshError(ctl, "%s",
-                         _("Failed to check for managed save image"));
-                goto cleanup;
-            }
-
-            if (!((VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_MANAGEDSAVE) && mansave) ||
-                  (VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_NO_MANAGEDSAVE) && !mansave)))
-                goto remove_entry;
-        }
-
-        /* snapshot filter */
-        if (VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_SNAPSHOT)) {
-            if ((nsnap = virDomainSnapshotNum(dom, 0)) < 0) {
-                vshError(ctl, "%s", _("Failed to get snapshot count"));
-                goto cleanup;
-            }
-            if (!((VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_HAS_SNAPSHOT) && nsnap > 0) ||
-                  (VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_NO_SNAPSHOT) && nsnap == 0)))
-                goto remove_entry;
-        }
-
-        /* the domain matched all filters, it may stay */
-        continue;
-
- remove_entry:
-        /* the domain has to be removed as it failed one of the filters */
-        virDomainFree(list->domains[i]);
-        list->domains[i] = NULL;
-        deleted++;
-    }
-
- finished:
-    /* sort the list */
-    if (list->domains && list->ndomains)
-        qsort(list->domains, list->ndomains, sizeof(*list->domains),
-              vshDomainSorter);
-
-    /* truncate the list if filter simulation deleted entries */
-    if (deleted)
-        VIR_SHRINK_N(list->domains, list->ndomains, deleted);
-
-    success = true;
-
- cleanup:
-    for (i = 0; nnames != -1 && i < nnames; i++)
-        VIR_FREE(names[i]);
-
-    if (!success) {
-        vshDomainListFree(list);
-        list = NULL;
-    }
-
-    VIR_FREE(names);
-    VIR_FREE(ids);
-    return list;
-}
-
 static const vshCmdOptDef opts_list[] = {
     {.name = "inactive",
      .type = VSH_OT_BOOL,
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index d9aa4fa..ce17fa4 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -25,6 +25,7 @@
 
 #include <config.h>
 #include "virsh-domain.h"
+#include "virsh-completer.h"
 
 #include <fcntl.h>
 #include <poll.h>
@@ -161,6 +162,7 @@ static const vshCmdInfo info_attach_device[] = {
 
 static const vshCmdOptDef opts_attach_device[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -263,6 +265,7 @@ static const vshCmdInfo info_attach_disk[] = {
 
 static const vshCmdOptDef opts_attach_disk[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -703,6 +706,7 @@ static const vshCmdInfo info_attach_interface[] = {
 
 static const vshCmdOptDef opts_attach_interface[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -960,6 +964,7 @@ static const vshCmdInfo info_autostart[] = {
 
 static const vshCmdOptDef opts_autostart[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -1016,6 +1021,7 @@ static const vshCmdInfo info_blkdeviotune[] = {
 
 static const vshCmdOptDef opts_blkdeviotune[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -1240,6 +1246,7 @@ static const vshCmdInfo info_blkiotune[] = {
 
 static const vshCmdOptDef opts_blkiotune[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -1567,6 +1574,7 @@ static const vshCmdInfo info_block_commit[] = {
 
 static const vshCmdOptDef opts_block_commit[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -1735,6 +1743,7 @@ static const vshCmdInfo info_block_copy[] = {
 
 static const vshCmdOptDef opts_block_copy[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -1930,6 +1939,7 @@ static const vshCmdInfo info_block_job[] = {
 
 static const vshCmdOptDef opts_block_job[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -2031,6 +2041,7 @@ static const vshCmdInfo info_block_pull[] = {
 
 static const vshCmdOptDef opts_block_pull[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -2186,6 +2197,7 @@ static const vshCmdInfo info_block_resize[] = {
 
 static const vshCmdOptDef opts_block_resize[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -2256,6 +2268,7 @@ static const vshCmdInfo info_console[] = {
 
 static const vshCmdOptDef opts_console[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -2353,6 +2366,7 @@ static const vshCmdInfo info_domif_setlink[] = {
 
 static const vshCmdOptDef opts_domif_setlink[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -2540,6 +2554,7 @@ static const vshCmdInfo info_domiftune[] = {
 
 static const vshCmdOptDef opts_domiftune[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -2727,6 +2742,7 @@ static const vshCmdInfo info_suspend[] = {
 
 static const vshCmdOptDef opts_suspend[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -2773,6 +2789,7 @@ static const vshCmdInfo info_dom_pm_suspend[] = {
 
 static const vshCmdOptDef opts_dom_pm_suspend[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -2857,6 +2874,7 @@ static const vshCmdInfo info_dom_pm_wakeup[] = {
 
 static const vshCmdOptDef opts_dom_pm_wakeup[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -2906,6 +2924,7 @@ static const vshCmdInfo info_undefine[] = {
 
 static const vshCmdOptDef opts_undefine[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name or uuid")
@@ -3299,6 +3318,7 @@ static const vshCmdInfo info_start[] = {
 
 static const vshCmdOptDef opts_start[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("name of the inactive domain")
@@ -3482,6 +3502,7 @@ static const vshCmdOptDef opts_save[] = {
      .help = N_("avoid file system cache when saving")
     },
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -3951,6 +3972,7 @@ static const vshCmdOptDef opts_managedsave[] = {
      .help = N_("avoid file system cache when saving")
     },
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -4071,6 +4093,7 @@ static const vshCmdInfo info_managedsaveremove[] = {
 
 static const vshCmdOptDef opts_managedsaveremove[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -4130,6 +4153,7 @@ static const vshCmdInfo info_schedinfo[] = {
 
 static const vshCmdOptDef opts_schedinfo[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -4473,6 +4497,7 @@ static const vshCmdOptDef opts_dump[] = {
      .help = N_("reset the domain after core dump")
     },
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -4640,6 +4665,7 @@ static const vshCmdInfo info_screenshot[] = {
 
 static const vshCmdOptDef opts_screenshot[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -4788,6 +4814,7 @@ static const vshCmdInfo info_resume[] = {
 
 static const vshCmdOptDef opts_resume[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -4831,6 +4858,7 @@ static const vshCmdInfo info_shutdown[] = {
 
 static const vshCmdOptDef opts_shutdown[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -4917,6 +4945,7 @@ static const vshCmdInfo info_reboot[] = {
 
 static const vshCmdOptDef opts_reboot[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -4998,6 +5027,7 @@ static const vshCmdInfo info_reset[] = {
 
 static const vshCmdOptDef opts_reset[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -5041,6 +5071,7 @@ static const vshCmdInfo info_domjobinfo[] = {
 
 static const vshCmdOptDef opts_domjobinfo[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -5263,6 +5294,7 @@ static const vshCmdInfo info_domjobabort[] = {
 
 static const vshCmdOptDef opts_domjobabort[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -5301,6 +5333,7 @@ static const vshCmdInfo info_vcpucount[] = {
 
 static const vshCmdOptDef opts_vcpucount[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -5512,6 +5545,7 @@ static const vshCmdInfo info_vcpuinfo[] = {
 
 static const vshCmdOptDef opts_vcpuinfo[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -5621,6 +5655,7 @@ static const vshCmdInfo info_vcpupin[] = {
 
 static const vshCmdOptDef opts_vcpupin[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -5908,6 +5943,7 @@ static const vshCmdInfo info_emulatorpin[] = {
 
 static const vshCmdOptDef opts_emulatorpin[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -6027,6 +6063,7 @@ static const vshCmdInfo info_setvcpus[] = {
 
 static const vshCmdOptDef opts_setvcpus[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -6348,6 +6385,7 @@ static const vshCmdInfo info_cpu_stats[] = {
 
 static const vshCmdOptDef opts_cpu_stats[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -6682,6 +6720,7 @@ static const vshCmdInfo info_destroy[] = {
 
 static const vshCmdOptDef opts_destroy[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -6739,6 +6778,7 @@ static const vshCmdInfo info_desc[] = {
 
 static const vshCmdOptDef opts_desc[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -6911,6 +6951,7 @@ static const vshCmdInfo info_metadata[] = {
 
 static const vshCmdOptDef opts_metadata[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -7068,6 +7109,7 @@ static const vshCmdInfo info_inject_nmi[] = {
 
 static const vshCmdOptDef opts_inject_nmi[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -7106,6 +7148,7 @@ static const vshCmdInfo info_send_key[] = {
 
 static const vshCmdOptDef opts_send_key[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -7208,6 +7251,7 @@ static const vshCmdInfo info_send_process_signal[] = {
 
 static const vshCmdOptDef opts_send_process_signal[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -7323,6 +7367,7 @@ static const vshCmdInfo info_setmem[] = {
 
 static const vshCmdOptDef opts_setmem[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -7420,6 +7465,7 @@ static const vshCmdInfo info_setmaxmem[] = {
 
 static const vshCmdOptDef opts_setmaxmem[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -7522,6 +7568,7 @@ static const vshCmdInfo info_memtune[] = {
 
 static const vshCmdOptDef opts_memtune[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -7721,6 +7768,7 @@ static const vshCmdInfo info_numatune[] = {
 
 static const vshCmdOptDef opts_numatune[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -7868,6 +7916,7 @@ static const vshCmdInfo info_qemu_monitor_command[] = {
 
 static const vshCmdOptDef opts_qemu_monitor_command[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -8160,6 +8209,7 @@ static const vshCmdInfo info_qemu_agent_command[] = {
 
 static const vshCmdOptDef opts_qemu_agent_command[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -8289,6 +8339,7 @@ static const vshCmdInfo info_lxc_enter_namespace[] = {
 
 static const vshCmdOptDef opts_lxc_enter_namespace[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -8431,6 +8482,7 @@ static const vshCmdInfo info_dumpxml[] = {
 
 static const vshCmdOptDef opts_dumpxml[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -8617,6 +8669,7 @@ static const vshCmdInfo info_domname[] = {
 
 static const vshCmdOptDef opts_domname[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain id or uuid")
@@ -8653,6 +8706,7 @@ static const vshCmdInfo info_domid[] = {
 
 static const vshCmdOptDef opts_domid[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name or uuid")
@@ -8694,6 +8748,7 @@ static const vshCmdInfo info_domuuid[] = {
 
 static const vshCmdOptDef opts_domuuid[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain id or name")
@@ -8803,6 +8858,7 @@ static const vshCmdOptDef opts_migrate[] = {
      .help = N_("abort on soft errors during migration")
     },
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -9073,6 +9129,7 @@ static const vshCmdInfo info_migrate_setmaxdowntime[] = {
 
 static const vshCmdOptDef opts_migrate_setmaxdowntime[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -9127,6 +9184,7 @@ static const vshCmdInfo info_migrate_compcache[] = {
 
 static const vshCmdOptDef opts_migrate_compcache[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -9189,6 +9247,7 @@ static const vshCmdInfo info_migrate_setspeed[] = {
 
 static const vshCmdOptDef opts_migrate_setspeed[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -9241,6 +9300,7 @@ static const vshCmdInfo info_migrate_getspeed[] = {
 
 static const vshCmdOptDef opts_migrate_getspeed[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -9285,6 +9345,7 @@ static const vshCmdInfo info_domdisplay[] = {
 
 static const vshCmdOptDef opts_domdisplay[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -9472,6 +9533,7 @@ static const vshCmdInfo info_vncdisplay[] = {
 
 static const vshCmdOptDef opts_vncdisplay[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -9545,6 +9607,7 @@ static const vshCmdInfo info_ttyconsole[] = {
 
 static const vshCmdOptDef opts_ttyconsole[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -9605,6 +9668,7 @@ static const vshCmdInfo info_domhostname[] = {
 
 static const vshCmdOptDef opts_domhostname[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -9768,6 +9832,7 @@ static const vshCmdInfo info_detach_device[] = {
 
 static const vshCmdOptDef opts_detach_device[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -9869,6 +9934,7 @@ static const vshCmdInfo info_update_device[] = {
 
 static const vshCmdOptDef opts_update_device[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -9971,6 +10037,7 @@ static const vshCmdInfo info_detach_interface[] = {
 
 static const vshCmdOptDef opts_detach_interface[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -10341,6 +10408,7 @@ static const vshCmdInfo info_detach_disk[] = {
 
 static const vshCmdOptDef opts_detach_disk[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -10456,6 +10524,7 @@ static const vshCmdInfo info_edit[] = {
 
 static const vshCmdOptDef opts_edit[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -11041,6 +11110,7 @@ static const vshCmdInfo info_event[] = {
 
 static const vshCmdOptDef opts_event[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .help = N_("filter by domain name, id, or uuid")
     },
@@ -11193,6 +11263,7 @@ static const vshCmdInfo info_change_media[] = {
 
 static const vshCmdOptDef opts_change_media[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
@@ -11344,6 +11415,7 @@ static const vshCmdInfo info_domfstrim[] = {
 
 static const vshCmdOptDef opts_domfstrim[] = {
     {.name = "domain",
+     .completer = vshCompleteDomain,
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
diff --git a/tools/virsh-snapshot.c b/tools/virsh-snapshot.c
index 3ecb3de..97eb264 100644
--- a/tools/virsh-snapshot.c
+++ b/tools/virsh-snapshot.c
@@ -25,6 +25,7 @@
 
 #include <config.h>
 #include "virsh-snapshot.h"
+#include "virsh-completer.h"
 
 #include <assert.h>
 
@@ -125,6 +126,7 @@ static const vshCmdOptDef opts_snapshot_create[] = {
     {.name = "domain",
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
+     .completer = vshCompleteDomain,
      .help = N_("domain name, id or uuid")
     },
     {.name = "xmlfile",
@@ -330,6 +332,7 @@ static const vshCmdOptDef opts_snapshot_create_as[] = {
     {.name = "domain",
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
+     .completer = vshCompleteDomain,
      .help = N_("domain name, id or uuid")
     },
     {.name = "name",
@@ -526,6 +529,7 @@ static const vshCmdOptDef opts_snapshot_edit[] = {
     {.name = "domain",
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
+     .completer = vshCompleteDomain,
      .help = N_("domain name, id or uuid")
     },
     {.name = "snapshotname",
@@ -648,6 +652,7 @@ static const vshCmdOptDef opts_snapshot_current[] = {
     {.name = "domain",
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
+     .completer = vshCompleteDomain,
      .help = N_("domain name, id or uuid")
     },
     {.name = "name",
@@ -884,6 +889,7 @@ static const vshCmdOptDef opts_snapshot_info[] = {
     {.name = "domain",
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
+     .completer = vshCompleteDomain,
      .help = N_("domain name, id or uuid")
     },
     {.name = "snapshotname",
@@ -1441,6 +1447,7 @@ static const vshCmdOptDef opts_snapshot_list[] = {
     {.name = "domain",
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
+     .completer = vshCompleteDomain,
      .help = N_("domain name, id or uuid")
     },
     {.name = "parent",
@@ -1705,6 +1712,7 @@ static const vshCmdOptDef opts_snapshot_dumpxml[] = {
     {.name = "domain",
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
+     .completer = vshCompleteDomain,
      .help = N_("domain name, id or uuid")
     },
     {.name = "snapshotname",
@@ -1773,6 +1781,7 @@ static const vshCmdOptDef opts_snapshot_parent[] = {
     {.name = "domain",
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
+     .completer = vshCompleteDomain,
      .help = N_("domain name, id or uuid")
     },
     {.name = "snapshotname",
@@ -1841,6 +1850,7 @@ static const vshCmdOptDef opts_snapshot_revert[] = {
     {.name = "domain",
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
+     .completer = vshCompleteDomain,
      .help = N_("domain name, id or uuid")
     },
     {.name = "snapshotname",
@@ -1934,6 +1944,7 @@ static const vshCmdOptDef opts_snapshot_delete[] = {
     {.name = "domain",
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
+     .completer = vshCompleteDomain,
      .help = N_("domain name, id or uuid")
     },
     {.name = "snapshotname",
-- 
1.8.3.2




More information about the libvir-list mailing list