[libvirt] [PATCH 12/50] list: Use virConnectListAllStoragePools in virsh

Osier Yang jyang at redhat.com
Thu Jul 19 16:40:43 UTC 2012


tools/virsh.c:
  * vshStoragePoolSorter to sort the pool list by pool name.

  * struct vshStoragePoolList to present the pool list, pool info
    is collected by list->poolinfo if 'details' is specified by
    user.

  * vshStoragePoolListFree to free the pool list

  * vshStoragePoolListCollect to collect the pool list, new API
    virStorageListAllPools is tried first, if it's not supported,
    fall back to older APIs.

  * New options --persistent, --transient, --autostart, --no-autostart
    and --type for pool-list. --persistent or --transient is to filter
    the returned pool list by whether the pool is persistent or not.
    --autostart or --no-autostart is to filter the returned pool list
    by whether the pool is autostarting or not. --type is to filter
    the pools by pool types. E.g.

    % virsh pool-list --all --persistent --type dir,disk

tools/virsh.pod:
   * Add documentations for the new options.
---
 tools/virsh.c   |  467 +++++++++++++++++++++++++++++++++++++++++++------------
 tools/virsh.pod |   24 +++-
 2 files changed, 387 insertions(+), 104 deletions(-)

diff --git a/tools/virsh.c b/tools/virsh.c
index 2d4567d..2415053 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -10868,6 +10868,258 @@ cmdPoolDumpXML(vshControl *ctl, const vshCmd *cmd)
     return ret;
 }
 
+static int
+vshStoragePoolSorter(const void *a, const void *b)
+{
+    virStoragePoolPtr *pa = (virStoragePoolPtr *) a;
+    virStoragePoolPtr *pb = (virStoragePoolPtr *) b;
+
+    if (*pa && !*pb)
+        return -1;
+
+    if (!*pa)
+        return *pb != NULL;
+
+    return strcasecmp(virStoragePoolGetName(*pa),
+                      virStoragePoolGetName(*pb));
+}
+
+struct vshStoragePoolList {
+    virStoragePoolPtr *pools;
+    size_t npools;
+};
+typedef struct vshStoragePoolList *vshStoragePoolListPtr;
+
+static void
+vshStoragePoolListFree(vshStoragePoolListPtr list)
+{
+    int i;
+
+    if (list && list->pools) {
+        for (i = 0; i < list->npools; i++) {
+            if (list->pools[i])
+                virStoragePoolFree(list->pools[i]);
+        }
+        VIR_FREE(list->pools);
+    }
+    VIR_FREE(list);
+}
+
+static vshStoragePoolListPtr
+vshStoragePoolListCollect(vshControl *ctl,
+                          unsigned int flags)
+{
+    vshStoragePoolListPtr list = vshMalloc(ctl, sizeof(*list));
+    int i;
+    int ret;
+    char **names = NULL;
+    virStoragePoolPtr pool;
+    bool success = false;
+    size_t deleted = 0;
+    int persistent;
+    int autostart;
+    int nActivePools = 0;
+    int nInactivePools = 0;
+    int nAllPools = 0;
+
+    /* try the list with flags support (0.9.14 and later) */
+    if ((ret = virConnectListAllStoragePools(ctl->conn,
+                                             &list->pools,
+                                             flags)) >= 0) {
+        list->npools = ret;
+        goto finished;
+    }
+
+    /* check if the command is actually supported */
+    if (last_error && last_error->code == VIR_ERR_NO_SUPPORT) {
+        virFreeError(last_error);
+        last_error = NULL;
+        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_STORAGE_POOLS_ACTIVE |
+                                         VIR_CONNECT_LIST_STORAGE_POOLS_INACTIVE);
+        virFreeError(last_error);
+        last_error = NULL;
+        if ((ret = virConnectListAllStoragePools(ctl->conn, &list->pools,
+                                                 newflags)) >= 0) {
+            list->npools = ret;
+            goto filter;
+        }
+    }
+
+    /* there was an error during the first or second call */
+    vshError(ctl, "%s", _("Failed to list pools"));
+    goto cleanup;
+
+
+fallback:
+    /* fall back to old method (0.9.13 and older) */
+    virResetLastError();
+
+    /* Get the number of active pools */
+    if (!MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ACTIVE) ||
+        MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_ACTIVE)) {
+        if ((nActivePools = virConnectNumOfStoragePools(ctl->conn)) < 0) {
+            vshError(ctl, "%s", _("Failed to get the number of active pools "));
+            goto cleanup;
+        }
+    }
+
+    /* Get the number of inactive pools */
+    if (!MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ACTIVE) ||
+        MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_INACTIVE)) {
+        if ((nInactivePools = virConnectNumOfDefinedStoragePools(ctl->conn)) < 0) {
+            vshError(ctl, "%s", _("Failed to get the number of inactive pools"));
+            goto cleanup;
+        }
+    }
+
+    nAllPools = nActivePools + nInactivePools;
+
+    if (nAllPools == 0)
+        return list;
+
+    names = vshMalloc(ctl, sizeof(char *) * nAllPools);
+
+    /* Retrieve a list of active storage pool names */
+    if (!MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ACTIVE) ||
+        MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_ACTIVE)) {
+        if (virConnectListStoragePools(ctl->conn,
+                                       names, nActivePools) < 0) {
+            vshError(ctl, "%s", _("Failed to list active pools"));
+            goto cleanup;
+        }
+    }
+
+    /* Add the inactive storage pools to the end of the name list */
+    if (!MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ACTIVE) ||
+        MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_ACTIVE)) {
+        if (virConnectListDefinedStoragePools(ctl->conn,
+                                              &names[nActivePools],
+                                              nInactivePools) < 0) {
+            vshError(ctl, "%s", _("Failed to list inactive pools"));
+            goto cleanup;
+        }
+    }
+
+    list->pools = vshMalloc(ctl, sizeof(virStoragePoolPtr) * (nAllPools));
+    list->npools = 0;
+
+    /* get active pools */
+    for (i = 0; i < nActivePools; i++) {
+        if (!(pool = virStoragePoolLookupByName(ctl->conn, names[i])))
+            continue;
+        list->pools[list->npools++] = pool;
+    }
+
+    /* get inactive pools */
+    for (i = 0; i < nInactivePools; i++) {
+        if (!(pool = virStoragePoolLookupByName(ctl->conn, names[i])))
+            continue;
+        list->pools[list->npools++] = pool;
+    }
+
+    /* truncate pools that weren't found */
+    deleted = nAllPools - list->npools;
+
+filter:
+    /* filter list the list if the list was acquired by fallback means */
+    for (i = 0; i < list->npools; i++) {
+        pool = list->pools[i];
+
+        /* persistence filter */
+        if (MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_PERSISTENT)) {
+            if ((persistent = virStoragePoolIsPersistent(pool)) < 0) {
+                vshError(ctl, "%s", _("Failed to get pool persistence info"));
+                goto cleanup;
+            }
+
+            if (!((MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_PERSISTENT) && persistent) ||
+                  (MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_TRANSIENT) && !persistent)))
+                goto remove_entry;
+        }
+
+        /* autostart filter */
+        if (MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_AUTOSTART)) {
+            if (virStoragePoolGetAutostart(pool, &autostart) < 0) {
+                vshError(ctl, "%s", _("Failed to get pool autostart state"));
+                goto cleanup;
+            }
+
+            if (!((MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_AUTOSTART) && autostart) ||
+                  (MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_NO_AUTOSTART) && !autostart)))
+                goto remove_entry;
+        }
+
+        /* pool type filter */
+        if (MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_POOL_TYPE)) {
+            virStoragePoolInfo info;
+
+            if (virStoragePoolGetInfo(list->pools[i], &info) < 0) {
+                vshError(ctl, "%s", _("Failed to get pool info"));
+                goto cleanup;
+            }
+
+            if (!((MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_DIR) &&
+                   (info.type == VIR_STORAGE_POOL_DIR))            ||
+                  (MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_FS) &&
+                   (info.type == VIR_STORAGE_POOL_FS))             ||
+                  (MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_NETFS) &&
+                   (info.type == VIR_STORAGE_POOL_NETFS))          ||
+                  (MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_LOGICAL) &&
+                   (info.type == VIR_STORAGE_POOL_LOGICAL))        ||
+                  (MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_DISK) &&
+                   (info.type == VIR_STORAGE_POOL_DISK))           ||
+                  (MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_ISCSI) &&
+                   (info.type == VIR_STORAGE_POOL_ISCSI))          ||
+                  (MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_SCSI) &&
+                   (info.type == VIR_STORAGE_POOL_SCSI))           ||
+                  (MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_MPATH) &&
+                   (info.type == VIR_STORAGE_POOL_MPATH))          ||
+                  (MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_RBD) &&
+                   (info.type == VIR_STORAGE_POOL_RBD))            ||
+                  (MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_SHEEPDOG) &&
+                   (info.type == VIR_STORAGE_POOL_SHEEPDOG))))
+                 goto remove_entry;
+        }
+
+        /* the pool matched all filters, it may stay */
+        continue;
+
+remove_entry:
+        /* the pool has to be removed as it failed one of the filters */
+        virStoragePoolFree(list->pools[i]);
+        list->pools[i] = NULL;
+        deleted++;
+    }
+
+finished:
+    /* sort the list */
+    if (list->pools && list->npools)
+        qsort(list->pools, list->npools,
+              sizeof(*list->pools), vshStoragePoolSorter);
+
+    /* truncate the list if filter simulation deleted entries */
+    if (deleted)
+        VIR_SHRINK_N(list->pools, list->npools, deleted);
+
+    success = true;
+
+cleanup:
+    for (i = 0; i < nAllPools; i++)
+        VIR_FREE(names[i]);
+
+    if (!success) {
+        vshStoragePoolListFree(list);
+        list = NULL;
+    }
+
+    VIR_FREE(names);
+    return list;
+}
 
 /*
  * "pool-list" command
@@ -10881,7 +11133,12 @@ static const vshCmdInfo info_pool_list[] = {
 static const vshCmdOptDef opts_pool_list[] = {
     {"inactive", VSH_OT_BOOL, 0, N_("list inactive pools")},
     {"all", VSH_OT_BOOL, 0, N_("list inactive & active pools")},
+    {"transient", VSH_OT_BOOL, 0, N_("list transient pools")},
+    {"persistent", VSH_OT_BOOL, 0, N_("list persistent pools")},
+    {"autostart", VSH_OT_BOOL, 0, N_("list pools with autostart enabled")},
+    {"no-autostart", VSH_OT_BOOL, 0, N_("list pools with autostart disabled")},
     {"details", VSH_OT_BOOL, 0, N_("display extended details for pools")},
+    {"type", VSH_OT_STRING, 0, N_("only list pool of specified type")},
     {NULL, 0, 0, NULL}
 };
 
@@ -10889,10 +11146,8 @@ static bool
 cmdPoolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
 {
     virStoragePoolInfo info;
-    char **poolNames = NULL;
     int i, ret;
-    bool functionReturn;
-    int numActivePools = 0, numInactivePools = 0, numAllPools = 0;
+    bool functionReturn = false;
     size_t stringLength = 0, nameStrLength = 0;
     size_t autostartStrLength = 0, persistStrLength = 0;
     size_t stateStrLength = 0, capStrLength = 0;
@@ -10906,84 +11161,103 @@ cmdPoolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
         char *available;
     };
     struct poolInfoText *poolInfoTexts = NULL;
-
-    /* Determine the options passed by the user */
-    bool all = vshCommandOptBool(cmd, "all");
+    unsigned int flags = VIR_CONNECT_LIST_STORAGE_POOLS_ACTIVE;
+    vshStoragePoolListPtr list = NULL;
+    const char *type = NULL;
     bool details = vshCommandOptBool(cmd, "details");
-    bool inactive = vshCommandOptBool(cmd, "inactive");
-    bool active = !inactive || all;
-    inactive |= all;
+    bool inactive, all;
 
-    /* Check the connection to libvirtd daemon is still working */
-    if (!vshConnectionUsability(ctl, ctl->conn))
-        return false;
+    inactive = vshCommandOptBool(cmd, "inactive");
+    all = vshCommandOptBool(cmd, "all");
 
-    /* Retrieve the number of active storage pools */
-    if (active) {
-        numActivePools = virConnectNumOfStoragePools(ctl->conn);
-        if (numActivePools < 0) {
-            vshError(ctl, "%s", _("Failed to list active pools"));
-            return false;
-        }
-    }
+    if (inactive)
+        flags = VIR_CONNECT_LIST_STORAGE_POOLS_INACTIVE;
 
-    /* Retrieve the number of inactive storage pools */
-    if (inactive) {
-        numInactivePools = virConnectNumOfDefinedStoragePools(ctl->conn);
-        if (numInactivePools < 0) {
-            vshError(ctl, "%s", _("Failed to list inactive pools"));
-            return false;
-        }
-    }
+    if (all)
+        flags = VIR_CONNECT_LIST_STORAGE_POOLS_ACTIVE |
+                VIR_CONNECT_LIST_STORAGE_POOLS_INACTIVE;
 
-    /* Determine the total number of pools to list */
-    numAllPools = numActivePools + numInactivePools;
+    if (vshCommandOptBool(cmd, "autostart"))
+        flags |= VIR_CONNECT_LIST_STORAGE_POOLS_AUTOSTART;
 
-    /* Allocate memory for arrays of storage pool names and info */
-    poolNames = vshCalloc(ctl, numAllPools, sizeof(*poolNames));
-    poolInfoTexts =
-        vshCalloc(ctl, numAllPools, sizeof(*poolInfoTexts));
+    if (vshCommandOptBool(cmd, "no-autostart"))
+        flags |= VIR_CONNECT_LIST_STORAGE_POOLS_NO_AUTOSTART;
 
-    /* Retrieve a list of active storage pool names */
-    if (active) {
-        if (virConnectListStoragePools(ctl->conn,
-                                       poolNames, numActivePools) < 0) {
-            vshError(ctl, "%s", _("Failed to list active pools"));
-            VIR_FREE(poolInfoTexts);
-            VIR_FREE(poolNames);
-            return false;
-        }
+    if (vshCommandOptBool(cmd, "persistent"))
+        flags |= VIR_CONNECT_LIST_STORAGE_POOLS_PERSISTENT;
+
+    if (vshCommandOptBool(cmd, "transient"))
+        flags |= VIR_CONNECT_LIST_STORAGE_POOLS_TRANSIENT;
+
+    if (vshCommandOptString(cmd, "type", &type) < 0) {
+        vshError(ctl, "%s", _("Invalid argument for 'type'"));
+        return false;
     }
 
-    /* Add the inactive storage pools to the end of the name list */
-    if (inactive) {
-        if (virConnectListDefinedStoragePools(ctl->conn,
-                                              &poolNames[numActivePools],
-                                              numInactivePools) < 0) {
-            vshError(ctl, "%s", _("Failed to list inactive pools"));
-            VIR_FREE(poolInfoTexts);
-            VIR_FREE(poolNames);
-            return false;
+    if (type) {
+        int poolType = -1;
+        char **poolTypes = NULL;
+        int npoolTypes = 0;
+
+        npoolTypes = vshStringToArray((char *)type, &poolTypes);
+
+        for (i = 0; i < npoolTypes; i++) {
+            if ((poolType = virStoragePoolTypeFromString(poolTypes[i])) < 0) {
+                vshError(ctl, "%s", _("Invalid pool type"));
+                VIR_FREE(poolTypes);
+                return false;
+            }
+
+            switch(poolType) {
+            case VIR_STORAGE_POOL_DIR:
+                flags |= VIR_CONNECT_LIST_STORAGE_POOLS_DIR;
+                break;
+            case VIR_STORAGE_POOL_FS:
+                flags |= VIR_CONNECT_LIST_STORAGE_POOLS_FS;
+                break;
+            case VIR_STORAGE_POOL_NETFS:
+                flags |= VIR_CONNECT_LIST_STORAGE_POOLS_NETFS;
+                break;
+            case VIR_STORAGE_POOL_LOGICAL:
+                flags |= VIR_CONNECT_LIST_STORAGE_POOLS_LOGICAL;
+                break;
+            case VIR_STORAGE_POOL_DISK:
+                flags |= VIR_CONNECT_LIST_STORAGE_POOLS_DISK;
+                break;
+            case VIR_STORAGE_POOL_ISCSI:
+                flags |= VIR_CONNECT_LIST_STORAGE_POOLS_ISCSI;
+                break;
+            case VIR_STORAGE_POOL_SCSI:
+                flags |= VIR_CONNECT_LIST_STORAGE_POOLS_SCSI;
+                break;
+            case VIR_STORAGE_POOL_MPATH:
+                flags |= VIR_CONNECT_LIST_STORAGE_POOLS_MPATH;
+                break;
+            case VIR_STORAGE_POOL_RBD:
+                flags |= VIR_CONNECT_LIST_STORAGE_POOLS_RBD;
+                break;
+            default:
+                break;
+            }
         }
+        VIR_FREE(poolTypes);
     }
 
-    /* Sort the storage pool names */
-    qsort(poolNames, numAllPools, sizeof(*poolNames), vshNameSorter);
+    /* Check the connection to libvirtd daemon is still working */
+    if (!vshConnectionUsability(ctl, ctl->conn))
+        return false;
+
+    if (!(list = vshStoragePoolListCollect(ctl, flags)))
+        goto cleanup;
+
+    poolInfoTexts = vshCalloc(ctl, list->npools, sizeof(*poolInfoTexts));
 
     /* Collect the storage pool information for display */
-    for (i = 0; i < numAllPools; i++) {
+    for (i = 0; i < list->npools; i++) {
         int autostart = 0, persistent = 0;
 
-        /* Retrieve a pool object, looking it up by name */
-        virStoragePoolPtr pool = virStoragePoolLookupByName(ctl->conn,
-                                                            poolNames[i]);
-        if (!pool) {
-            VIR_FREE(poolNames[i]);
-            continue;
-        }
-
         /* Retrieve the autostart status of the pool */
-        if (virStoragePoolGetAutostart(pool, &autostart) < 0)
+        if (virStoragePoolGetAutostart(list->pools[i], &autostart) < 0)
             poolInfoTexts[i].autostart = vshStrdup(ctl, _("no autostart"));
         else
             poolInfoTexts[i].autostart = vshStrdup(ctl, autostart ?
@@ -10991,7 +11265,7 @@ cmdPoolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
 
         /* Retrieve the persistence status of the pool */
         if (details) {
-            persistent = virStoragePoolIsPersistent(pool);
+            persistent = virStoragePoolIsPersistent(list->pools[i]);
             vshDebug(ctl, VSH_ERR_DEBUG, "Persistent flag value: %d\n",
                      persistent);
             if (persistent < 0)
@@ -11007,7 +11281,7 @@ cmdPoolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
         }
 
         /* Collect further extended information about the pool */
-        if (virStoragePoolGetInfo(pool, &info) != 0) {
+        if (virStoragePoolGetInfo(list->pools[i], &info) != 0) {
             /* Something went wrong retrieving pool info, cope with it */
             vshError(ctl, "%s", _("Could not retrieve pool information"));
             poolInfoTexts[i].state = vshStrdup(ctl, _("unknown"));
@@ -11049,28 +11323,25 @@ cmdPoolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
                     val = prettyCapacity(info.capacity, &unit);
                     ret = virAsprintf(&poolInfoTexts[i].capacity,
                                       "%.2lf %s", val, unit);
-                    if (ret < 0) {
+                    if (ret < 0)
                         /* An error occurred creating the string, return */
                         goto asprintf_failure;
-                    }
 
                     /* Create the allocation output string */
                     val = prettyCapacity(info.allocation, &unit);
                     ret = virAsprintf(&poolInfoTexts[i].allocation,
                                       "%.2lf %s", val, unit);
-                    if (ret < 0) {
+                    if (ret < 0)
                         /* An error occurred creating the string, return */
                         goto asprintf_failure;
-                    }
 
                     /* Create the available space output string */
                     val = prettyCapacity(info.available, &unit);
                     ret = virAsprintf(&poolInfoTexts[i].available,
                                       "%.2lf %s", val, unit);
-                    if (ret < 0) {
+                    if (ret < 0)
                         /* An error occurred creating the string, return */
                         goto asprintf_failure;
-                    }
                 } else {
                     /* Capacity related information isn't available */
                     poolInfoTexts[i].capacity = vshStrdup(ctl, _("-"));
@@ -11094,16 +11365,16 @@ cmdPoolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
                     availStrLength = stringLength;
             } else {
                 /* --details option was not specified, only active/inactive
-                * state strings are used */
-                if (info.state == VIR_STORAGE_POOL_INACTIVE)
-                    poolInfoTexts[i].state = vshStrdup(ctl, _("inactive"));
-                else
+                 * state strings are used */
+                if (virStoragePoolIsActive(list->pools[i]))
                     poolInfoTexts[i].state = vshStrdup(ctl, _("active"));
-            }
+                else
+                    poolInfoTexts[i].state = vshStrdup(ctl, _("inactive"));
+           }
         }
 
         /* Keep the length of name string if longest so far */
-        stringLength = strlen(poolNames[i]);
+        stringLength = strlen(virStoragePoolGetName(list->pools[i]));
         if (stringLength > nameStrLength)
             nameStrLength = stringLength;
 
@@ -11116,9 +11387,6 @@ cmdPoolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
         stringLength = strlen(poolInfoTexts[i].autostart);
         if (stringLength > autostartStrLength)
             autostartStrLength = stringLength;
-
-        /* Free the pool object */
-        virStoragePoolFree(pool);
     }
 
     /* If the --details option wasn't selected, we output the pool
@@ -11134,9 +11402,10 @@ cmdPoolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
         vshPrintExtra(ctl, "-----------------------------------------\n");
 
         /* Output old style pool info */
-        for (i = 0; i < numAllPools; i++) {
+        for (i = 0; i < list->npools; i++) {
+            const char *name = virStoragePoolGetName(list->pools[i]);
             vshPrint(ctl, "%-20s %-10s %-10s\n",
-                 poolNames[i],
+                 name,
                  poolInfoTexts[i].state,
                  poolInfoTexts[i].autostart);
         }
@@ -11228,9 +11497,9 @@ cmdPoolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
     vshPrintExtra(ctl, "\n");
 
     /* Display the pool info rows */
-    for (i = 0; i < numAllPools; i++) {
+    for (i = 0; i < list->npools; i++) {
         vshPrint(ctl, outputStr,
-                 poolNames[i],
+                 virStoragePoolGetName(list->pools[i]),
                  poolInfoTexts[i].state,
                  poolInfoTexts[i].autostart,
                  poolInfoTexts[i].persistent,
@@ -11244,7 +11513,6 @@ cmdPoolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
     goto cleanup;
 
 asprintf_failure:
-
     /* Display an appropriate error message then cleanup and return */
     switch (errno) {
     case ENOMEM:
@@ -11258,24 +11526,19 @@ asprintf_failure:
     functionReturn = false;
 
 cleanup:
-
-    /* Safely free the memory allocated in this function */
-    for (i = 0; i < numAllPools; i++) {
-        /* Cleanup the memory for one pool info structure */
-        VIR_FREE(poolInfoTexts[i].state);
-        VIR_FREE(poolInfoTexts[i].autostart);
-        VIR_FREE(poolInfoTexts[i].persistent);
-        VIR_FREE(poolInfoTexts[i].capacity);
-        VIR_FREE(poolInfoTexts[i].allocation);
-        VIR_FREE(poolInfoTexts[i].available);
-        VIR_FREE(poolNames[i]);
-    }
-
-    /* Cleanup the memory for the initial arrays*/
+    if (list && list->npools) {
+        for (i = 0; i < list->npools; i++) {
+            VIR_FREE(poolInfoTexts[i].state);
+            VIR_FREE(poolInfoTexts[i].autostart);
+            VIR_FREE(poolInfoTexts[i].persistent);
+            VIR_FREE(poolInfoTexts[i].capacity);
+            VIR_FREE(poolInfoTexts[i].allocation);
+            VIR_FREE(poolInfoTexts[i].available);
+        }
+    }
     VIR_FREE(poolInfoTexts);
-    VIR_FREE(poolNames);
 
-    /* Return the desired value */
+    vshStoragePoolListFree(list);
     return functionReturn;
 }
 
diff --git a/tools/virsh.pod b/tools/virsh.pod
index f79c945..b88df9c 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -2154,13 +2154,33 @@ variables, and defaults to C<vi>.
 
 Returns basic information about the I<pool> object.
 
-=item B<pool-list> [I<--inactive> | I<--all>] [I<--details>]
+=item B<pool-list> [I<--inactive>] [I<--all>]
+                   [I<--persistent>] [I<--transient>]
+                   [I<--autostart>] [I<--no-autostart>]
+                   [[I<--details>] [<type>]
 
 List pool objects known to libvirt.  By default, only active pools
 are listed; I<--inactive> lists just the inactive pools, and I<--all>
-lists all pools. The I<--details> option instructs virsh to additionally
+lists all pools.
+
+Except the default, I<--inactive>, and I<--all>, you may want to specify more
+filtering flags. I<--persistent> is to list the persistent pools, I<--transient>
+is to list the transient pools. I<--autostart> is to list the autostarting pools,
+I<--no-autostart> is to list the pools with autostarting disabled.
+
+You may also want to list pools with specified types using I<type>, the
+pool types must be separated by comma, e.g. --type dir,disk. The valid pool
+types include 'dir', 'fs', 'netfs', 'logical', 'disk', 'iscsi', 'scsi',
+'mpath', 'rbd', and 'sheepdog'.
+
+The I<--details> option instructs virsh to additionally
 display pool persistence and capacity related information where available.
 
+NOTE: When talking to older servers, this command is forced to use a series of
+API calls with an inherent race, where a pool might not be listed or might appear
+more than once if it changed state between calls while the list was being
+collected.  Newer servers do not have this problem.
+
 =item B<pool-name> I<uuid>
 
 Convert the I<uuid> to a pool name.
-- 
1.7.7.3




More information about the libvir-list mailing list