[libvirt] [PATCH] virsh: Enhance list command to ease creation of shell scripts

Peter Krempa pkrempa at redhat.com
Tue Feb 21 16:05:19 UTC 2012


This patch adds new options to the "virsh list" command enabling
filtering of persistent and transient domains along with the option to
print only UUIDs or names of domains instead of printing the table.

Option --name prints domain names (one per line) instead of the default
table. Similarly --uuid prints domain's UUID. The option --table is
an alias for the default behavior.

Aditionaly --persistent and/or --transient may be specified to filter
the output of domains.
---
 tools/virsh.c   |  176 ++++++++++++++++++++++++++++++++++++++++--------------
 tools/virsh.pod |   20 ++++++-
 2 files changed, 148 insertions(+), 48 deletions(-)

diff --git a/tools/virsh.c b/tools/virsh.c
index 66ba61c..10160de 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -888,6 +888,11 @@ static const vshCmdInfo info_list[] = {
 static const vshCmdOptDef opts_list[] = {
     {"inactive", VSH_OT_BOOL, 0, N_("list inactive domains")},
     {"all", VSH_OT_BOOL, 0, N_("list inactive & active domains")},
+    {"transient", VSH_OT_BOOL, 0, N_("list transient domains")},
+    {"persistent", VSH_OT_BOOL, 0, N_("list persistent domains")},
+    {"uuid", VSH_OT_BOOL, 0, N_("list uuid's only")},
+    {"name", VSH_OT_BOOL, 0, N_("list domain names only")},
+    {"table", VSH_OT_BOOL, 0, N_("list table (default)")},
     {"managed-save", VSH_OT_BOOL, 0,
      N_("mark domains with managed save state")},
     {"title", VSH_OT_BOOL, 0, N_("show short domain description")},
@@ -905,13 +910,41 @@ cmdList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
     char **names = NULL;
     int maxname = 0;
     bool managed = vshCommandOptBool(cmd, "managed-save");
-    bool desc = vshCommandOptBool(cmd, "title");
+    bool optTitle = vshCommandOptBool(cmd, "title");
+    bool optTable = vshCommandOptBool(cmd, "table");
+    bool optUUID = vshCommandOptBool(cmd, "uuid");
+    bool optName = vshCommandOptBool(cmd, "name");
+    bool optPersistent = vshCommandOptBool(cmd, "persistent");
+    bool optTransient = vshCommandOptBool(cmd, "transient");
+    bool persistUsed = true;
+    virDomainPtr dom = NULL;
     char *title;
+    char uuid[VIR_UUID_STRING_BUFLEN];
     int state;
+    int persistent;
     bool ret = false;

     inactive |= all;

+    /* process arguments */
+    if (!optPersistent && !optTransient) {
+        optPersistent = true;
+        optTransient = true;
+        persistUsed = false;
+    }
+
+    if ((optTable && optName) ||
+        (optTable && optUUID) ||
+        (optName && optUUID)) {
+        vshError(ctl, "%s",
+                 _("Only one argument from --table, --name and --uuid"
+                   "may be specified."));
+        return false;
+    }
+
+    if (!optUUID && !optName)
+        optTable = true;
+
     if (!vshConnectionUsability(ctl, ctl->conn))
         return false;

@@ -924,14 +957,15 @@ cmdList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
         if (maxid) {
             ids = vshMalloc(ctl, sizeof(int) * maxid);

-            if ((maxid = virConnectListDomains(ctl->conn, &ids[0], maxid)) < 0) {
+            if ((maxid = virConnectListDomains(ctl->conn, ids, maxid)) < 0) {
                 vshError(ctl, "%s", _("Failed to list active domains"));
                 goto cleanup;
             }

-            qsort(&ids[0], maxid, sizeof(int), idsorter);
+            qsort(ids, maxid, sizeof(int), idsorter);
         }
     }
+
     if (inactive) {
         maxname = virConnectNumOfDefinedDomains(ctl->conn);
         if (maxname < 0) {
@@ -941,7 +975,9 @@ cmdList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
         if (maxname) {
             names = vshMalloc(ctl, sizeof(char *) * maxname);

-            if ((maxname = virConnectListDefinedDomains(ctl->conn, names, maxname)) < 0) {
+            if ((maxname = virConnectListDefinedDomains(ctl->conn,
+                                                        names,
+                                                        maxname)) < 0) {
                 vshError(ctl, "%s", _("Failed to list inactive domains"));
                 goto cleanup;
             }
@@ -950,77 +986,125 @@ cmdList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
         }
     }

-    if (desc) {
-        vshPrintExtra(ctl, "%-5s %-30s %-10s %s\n", _("Id"), _("Name"), _("State"), _("Title"));
-        vshPrintExtra(ctl, "-----------------------------------------------------------\n");
-    } else {
-        vshPrintExtra(ctl, " %-5s %-30s %s\n", _("Id"), _("Name"), _("State"));
-        vshPrintExtra(ctl, "----------------------------------------------------\n");
+    /* print table header in legacy mode */
+    if (optTable) {
+        vshPrintExtra(ctl, " %-5s %-30s %-10s",
+                      _("Id"), _("Name"), _("State"));
+        if (optTitle)
+            vshPrintExtra(ctl, "%-20s", _("Title"));
+
+        vshPrintExtra(ctl, "\n"
+                      "-----------------------------------------------------------\n");
     }

     for (i = 0; i < maxid; i++) {
-         virDomainPtr dom = virDomainLookupByID(ctl->conn, ids[i]);
+         dom = virDomainLookupByID(ctl->conn, ids[i]);

         /* this kind of work with domains is not atomic operation */
         if (!dom)
             continue;

-        if (desc) {
-            if (!(title = vshGetDomainDescription(ctl, dom, true, 0)))
+        if (persistUsed) {
+            persistent = virDomainIsPersistent(dom);
+            if (persistent < 0) {
+                vshError(ctl, "%s",
+                         _("Failed to determine domain's persistent state"));
                 goto cleanup;
+            }

-            vshPrint(ctl, "%-5d %-30s %-10s %s\n",
-                     virDomainGetID(dom),
-                     virDomainGetName(dom),
-                    _(vshDomainStateToString(vshDomainState(ctl, dom, NULL))),
-                    title);
-            VIR_FREE(title);
-       } else {
-            vshPrint(ctl, " %-5d %-30s %s\n",
-                     virDomainGetID(dom),
-                     virDomainGetName(dom),
-                     _(vshDomainStateToString(vshDomainState(ctl, dom, NULL))));
+            if ((persistent && !optPersistent) ||
+                (!persistent && !optTransient)) {
+                virDomainFree(dom);
+                dom = NULL;
+                continue;
+            }
        }
+
+       if (optTable) {
+           vshPrint(ctl, " %-5d %-30s %-10s",
+                    virDomainGetID(dom),
+                    virDomainGetName(dom),
+                    _(vshDomainStateToString(vshDomainState(ctl, dom, NULL))));
+
+           if (optTitle) {
+               if (!(title = vshGetDomainDescription(ctl, dom, true, 0)))
+                   goto cleanup;
+
+               vshPrint(ctl, "%-20s", title);
+               VIR_FREE(title);
+           }
+
+           vshPrint(ctl, "\n");
+       } else if (optUUID) {
+           if (virDomainGetUUIDString(dom, uuid) < 0) {
+               vshError(ctl, "%s",
+                        _("Failed to get domain's UUID"));
+               goto cleanup;
+           }
+           vshPrint(ctl, "%s\n", uuid);
+       } else if (optName) {
+           vshPrint(ctl, "%s\n", virDomainGetName(dom));
+       }
+
        virDomainFree(dom);
+       dom = NULL;
     }
+
     for (i = 0; i < maxname; i++) {
-        virDomainPtr dom = virDomainLookupByName(ctl->conn, names[i]);
+        dom = virDomainLookupByName(ctl->conn, names[i]);

         /* this kind of work with domains is not atomic operation */
-        if (!dom) {
-            VIR_FREE(names[i]);
+        if (!dom)
             continue;
-        }

-        state = vshDomainState(ctl, dom, NULL);
-        if (managed && state == VIR_DOMAIN_SHUTOFF &&
-            virDomainHasManagedSaveImage(dom, 0) > 0)
-            state = -2;
+        if (!optPersistent) {
+            virDomainFree(dom);
+            dom = NULL;
+            continue;
+        }

-        if (desc) {
-            if (!(title = vshGetDomainDescription(ctl, dom, true, 0)))
-                goto cleanup;
+        if (optTable) {
+            state = vshDomainState(ctl, dom, NULL);
+            if (managed && state == VIR_DOMAIN_SHUTOFF &&
+                virDomainHasManagedSaveImage(dom, 0) > 0)
+                state = -2;

-            vshPrint(ctl, "%-5s %-30s %-10s %s\n",
-                     "-",
-                     names[i],
-                     state == -2 ? _("saved") : _(vshDomainStateToString(state)),
-                     title);
-            VIR_FREE(title);
-        } else {
-            vshPrint(ctl, " %-5s %-30s %s\n",
+            vshPrint(ctl, " %-5s %-30s %-10s",
                      "-",
                      names[i],
                      state == -2 ? _("saved") : _(vshDomainStateToString(state)));
-        }

-        virDomainFree(dom);
-        VIR_FREE(names[i]);
+            if (optTitle) {
+                if (!(title = vshGetDomainDescription(ctl, dom, true, 0)))
+                    goto cleanup;
+
+                vshPrint(ctl, "%-20s", title);
+                VIR_FREE(title);
+            }
+
+            vshPrint(ctl, "\n");
+       } else if (optUUID) {
+           if (virDomainGetUUIDString(dom, uuid) < 0) {
+               vshError(ctl, "%s",
+                        _("Failed to get domain's UUID"));
+               goto cleanup;
+           }
+           vshPrint(ctl, "%s\n", uuid);
+       } else if (optName) {
+           vshPrint(ctl, "%s\n", names[i]);
+       }
+
+       virDomainFree(dom);
+       dom = NULL;
     }

     ret = true;
 cleanup:
+    if (dom)
+        virDomainFree(dom);
     VIR_FREE(ids);
+    for (i = 0; i < maxname; i++)
+        VIR_FREE(names[i]);
     VIR_FREE(names);
     return ret;
 }
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 0d5a41d..aa29c00 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -280,6 +280,8 @@ The XML also show the NUMA topology information if available.
 Inject NMI to the guest.

 =item B<list> [I<--inactive> | I<--all>] [I<--managed-save>] [I<--title>]
+              [I<--name> | <I--table> | <I--uuid>] [I<--persistent>]
+              [I<--transient>]

 Prints information about existing domains.  If no options are
 specified it prints out information about running domains.
@@ -348,10 +350,24 @@ crashed.

 If I<--managed-save> is specified, then domains that have managed save
 state (only possible if they are in the B<shut off> state) will
-instead show as B<saved> in the listing.
+instead show as B<saved> in the listing. This flag is usable only with the
+default I<--table> output.
+
+If I<--name> is specified, domain names are printed instead of the table
+formated one per line. If I<--uuid> is specified domain's UUID's are printed
+instead of names. Flag I<--table> specifies that the legacy table-formated
+output should be used. This is the default. All of these are mutually
+exclusive.
+
+Flag I<--persistent> specifies that persistent domains should be printed.
+Similarly I<--transiet> enables output of transient domains. These flags
+may be combined. Default behavior is as though both were specifiedi (Although
+if any of these flags is specified, the check for the persistence state is done
+and may fail. If none of these flags is specified, the check is skipped).

 If I<--title> is specified, then the domain note is printed. The output then
-the output looks as follows.
+the output looks as follows. This flag is usable only with the default
+I<--table> output.

 B<virsh> list --title
  Id Name                 State      Title
-- 
1.7.3.4




More information about the libvir-list mailing list