[libvirt] [PATCH 09/10] list: Use virConnectListAllStoragePools in virsh

Osier Yang jyang at redhat.com
Tue Sep 4 15:16:32 UTC 2012


tools/virsh-pool.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-pool.c |  631 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 tools/virsh.pod    |   24 ++-
 2 files changed, 652 insertions(+), 3 deletions(-)

diff --git a/tools/virsh-pool.c b/tools/virsh-pool.c
index fd239d2..0b328cc 100644
--- a/tools/virsh-pool.c
+++ b/tools/virsh-pool.c
@@ -36,6 +36,7 @@
 #include "memory.h"
 #include "util.h"
 #include "xml.h"
+#include "conf/storage_conf.h"
 
 virStoragePoolPtr
 vshCommandOptPoolBy(vshControl *ctl, const vshCmd *cmd, const char *optname,
@@ -551,6 +552,232 @@ 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 vshStrcasecmp(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.10.0 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) {
+        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_STORAGE_POOLS_ACTIVE |
+                                         VIR_CONNECT_LIST_STORAGE_POOLS_INACTIVE);
+        vshResetLibvirtError();
+        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) */
+    vshResetLibvirtError();
+
+    /* There is no way to get the pool type */
+    if (MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_POOL_TYPE)) {
+        vshError(ctl, "%s", _("Filtering using --type is not supported "
+                              "by this libvirt"));
+        goto cleanup;
+    }
+
+    /* 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;
+        }
+
+        /* 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
  */
@@ -563,6 +790,11 @@ 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")},
+    {"type", VSH_OT_STRING, 0, N_("only list pool of specified type(s) (if supported)")},
     {"details", VSH_OT_BOOL, 0, N_("display extended details for pools")},
     {NULL, 0, 0, NULL}
 };
@@ -571,7 +803,403 @@ static bool
 cmdPoolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
 {
     virStoragePoolInfo info;
-    char **poolNames = NULL;
+    int i, ret;
+    bool functionReturn = false;
+    size_t stringLength = 0, nameStrLength = 0;
+    size_t autostartStrLength = 0, persistStrLength = 0;
+    size_t stateStrLength = 0, capStrLength = 0;
+    size_t allocStrLength = 0, availStrLength = 0;
+    struct poolInfoText {
+        char *state;
+        char *autostart;
+        char *persistent;
+        char *capacity;
+        char *allocation;
+        char *available;
+    };
+    struct poolInfoText *poolInfoTexts = NULL;
+    unsigned int flags = VIR_CONNECT_LIST_STORAGE_POOLS_ACTIVE;
+    vshStoragePoolListPtr list = NULL;
+    const char *type = NULL;
+    bool details = vshCommandOptBool(cmd, "details");
+    bool inactive, all;
+
+    inactive = vshCommandOptBool(cmd, "inactive");
+    all = vshCommandOptBool(cmd, "all");
+
+    if (inactive)
+        flags = VIR_CONNECT_LIST_STORAGE_POOLS_INACTIVE;
+
+    if (all)
+        flags = VIR_CONNECT_LIST_STORAGE_POOLS_ACTIVE |
+                VIR_CONNECT_LIST_STORAGE_POOLS_INACTIVE;
+
+    if (vshCommandOptBool(cmd, "autostart"))
+        flags |= VIR_CONNECT_LIST_STORAGE_POOLS_AUTOSTART;
+
+    if (vshCommandOptBool(cmd, "no-autostart"))
+        flags |= VIR_CONNECT_LIST_STORAGE_POOLS_NO_AUTOSTART;
+
+    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;
+    }
+
+    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);
+    }
+
+    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 < list->npools; i++) {
+        int autostart = 0, persistent = 0;
+
+        /* Retrieve the autostart status of the pool */
+        if (virStoragePoolGetAutostart(list->pools[i], &autostart) < 0)
+            poolInfoTexts[i].autostart = vshStrdup(ctl, _("no autostart"));
+        else
+            poolInfoTexts[i].autostart = vshStrdup(ctl, autostart ?
+                                                    _("yes") : _("no"));
+
+        /* Retrieve the persistence status of the pool */
+        if (details) {
+            persistent = virStoragePoolIsPersistent(list->pools[i]);
+            vshDebug(ctl, VSH_ERR_DEBUG, "Persistent flag value: %d\n",
+                     persistent);
+            if (persistent < 0)
+                poolInfoTexts[i].persistent = vshStrdup(ctl, _("unknown"));
+            else
+                poolInfoTexts[i].persistent = vshStrdup(ctl, persistent ?
+                                                         _("yes") : _("no"));
+
+            /* Keep the length of persistent string if longest so far */
+            stringLength = strlen(poolInfoTexts[i].persistent);
+            if (stringLength > persistStrLength)
+                persistStrLength = stringLength;
+        }
+
+        /* Collect further extended information about the pool */
+        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"));
+            if (details) {
+                poolInfoTexts[i].capacity = vshStrdup(ctl, _("unknown"));
+                poolInfoTexts[i].allocation = vshStrdup(ctl, _("unknown"));
+                poolInfoTexts[i].available = vshStrdup(ctl, _("unknown"));
+            }
+        } else {
+            /* Decide which state string to display */
+            if (details) {
+                /* --details option was specified, we're using detailed state
+                 * strings */
+                switch (info.state) {
+                case VIR_STORAGE_POOL_INACTIVE:
+                    poolInfoTexts[i].state = vshStrdup(ctl, _("inactive"));
+                    break;
+                case VIR_STORAGE_POOL_BUILDING:
+                    poolInfoTexts[i].state = vshStrdup(ctl, _("building"));
+                    break;
+                case VIR_STORAGE_POOL_RUNNING:
+                    poolInfoTexts[i].state = vshStrdup(ctl, _("running"));
+                    break;
+                case VIR_STORAGE_POOL_DEGRADED:
+                    poolInfoTexts[i].state = vshStrdup(ctl, _("degraded"));
+                    break;
+                case VIR_STORAGE_POOL_INACCESSIBLE:
+                    poolInfoTexts[i].state = vshStrdup(ctl, _("inaccessible"));
+                    break;
+                }
+
+                /* Create the pool size related strings */
+                if (info.state == VIR_STORAGE_POOL_RUNNING ||
+                    info.state == VIR_STORAGE_POOL_DEGRADED) {
+                    double val;
+                    const char *unit;
+
+                    /* Create the capacity output string */
+                    val = vshPrettyCapacity(info.capacity, &unit);
+                    ret = virAsprintf(&poolInfoTexts[i].capacity,
+                                      "%.2lf %s", val, unit);
+                    if (ret < 0)
+                        /* An error occurred creating the string, return */
+                        goto asprintf_failure;
+
+                    /* Create the allocation output string */
+                    val = vshPrettyCapacity(info.allocation, &unit);
+                    ret = virAsprintf(&poolInfoTexts[i].allocation,
+                                      "%.2lf %s", val, unit);
+                    if (ret < 0)
+                        /* An error occurred creating the string, return */
+                        goto asprintf_failure;
+
+                    /* Create the available space output string */
+                    val = vshPrettyCapacity(info.available, &unit);
+                    ret = virAsprintf(&poolInfoTexts[i].available,
+                                      "%.2lf %s", val, unit);
+                    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, _("-"));
+                    poolInfoTexts[i].allocation = vshStrdup(ctl, _("-"));
+                    poolInfoTexts[i].available = vshStrdup(ctl, _("-"));
+                }
+
+                /* Keep the length of capacity string if longest so far */
+                stringLength = strlen(poolInfoTexts[i].capacity);
+                if (stringLength > capStrLength)
+                    capStrLength = stringLength;
+
+                /* Keep the length of allocation string if longest so far */
+                stringLength = strlen(poolInfoTexts[i].allocation);
+                if (stringLength > allocStrLength)
+                    allocStrLength = stringLength;
+
+                /* Keep the length of available string if longest so far */
+                stringLength = strlen(poolInfoTexts[i].available);
+                if (stringLength > availStrLength)
+                    availStrLength = stringLength;
+            } else {
+                /* --details option was not specified, only active/inactive
+                 * 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(virStoragePoolGetName(list->pools[i]));
+        if (stringLength > nameStrLength)
+            nameStrLength = stringLength;
+
+        /* Keep the length of state string if longest so far */
+        stringLength = strlen(poolInfoTexts[i].state);
+        if (stringLength > stateStrLength)
+            stateStrLength = stringLength;
+
+        /* Keep the length of autostart string if longest so far */
+        stringLength = strlen(poolInfoTexts[i].autostart);
+        if (stringLength > autostartStrLength)
+            autostartStrLength = stringLength;
+    }
+
+    /* If the --details option wasn't selected, we output the pool
+     * info using the fixed string format from previous versions to
+     * maintain backward compatibility.
+     */
+
+    /* Output basic info then return if --details option not selected */
+    if (!details) {
+        /* Output old style header */
+        vshPrintExtra(ctl, "%-20s %-10s %-10s\n", _("Name"), _("State"),
+                      _("Autostart"));
+        vshPrintExtra(ctl, "-----------------------------------------\n");
+
+        /* Output old style pool info */
+        for (i = 0; i < list->npools; i++) {
+            const char *name = virStoragePoolGetName(list->pools[i]);
+            vshPrint(ctl, "%-20s %-10s %-10s\n",
+                 name,
+                 poolInfoTexts[i].state,
+                 poolInfoTexts[i].autostart);
+        }
+
+        /* Cleanup and return */
+        functionReturn = true;
+        goto cleanup;
+    }
+
+    /* We only get here if the --details option was selected. */
+
+    /* Use the length of name header string if it's longest */
+    stringLength = strlen(_("Name"));
+    if (stringLength > nameStrLength)
+        nameStrLength = stringLength;
+
+    /* Use the length of state header string if it's longest */
+    stringLength = strlen(_("State"));
+    if (stringLength > stateStrLength)
+        stateStrLength = stringLength;
+
+    /* Use the length of autostart header string if it's longest */
+    stringLength = strlen(_("Autostart"));
+    if (stringLength > autostartStrLength)
+        autostartStrLength = stringLength;
+
+    /* Use the length of persistent header string if it's longest */
+    stringLength = strlen(_("Persistent"));
+    if (stringLength > persistStrLength)
+        persistStrLength = stringLength;
+
+    /* Use the length of capacity header string if it's longest */
+    stringLength = strlen(_("Capacity"));
+    if (stringLength > capStrLength)
+        capStrLength = stringLength;
+
+    /* Use the length of allocation header string if it's longest */
+    stringLength = strlen(_("Allocation"));
+    if (stringLength > allocStrLength)
+        allocStrLength = stringLength;
+
+    /* Use the length of available header string if it's longest */
+    stringLength = strlen(_("Available"));
+    if (stringLength > availStrLength)
+        availStrLength = stringLength;
+
+    /* Display the string lengths for debugging. */
+    vshDebug(ctl, VSH_ERR_DEBUG, "Longest name string = %lu chars\n",
+             (unsigned long) nameStrLength);
+    vshDebug(ctl, VSH_ERR_DEBUG, "Longest state string = %lu chars\n",
+             (unsigned long) stateStrLength);
+    vshDebug(ctl, VSH_ERR_DEBUG, "Longest autostart string = %lu chars\n",
+             (unsigned long) autostartStrLength);
+    vshDebug(ctl, VSH_ERR_DEBUG, "Longest persistent string = %lu chars\n",
+             (unsigned long) persistStrLength);
+    vshDebug(ctl, VSH_ERR_DEBUG, "Longest capacity string = %lu chars\n",
+             (unsigned long) capStrLength);
+    vshDebug(ctl, VSH_ERR_DEBUG, "Longest allocation string = %lu chars\n",
+             (unsigned long) allocStrLength);
+    vshDebug(ctl, VSH_ERR_DEBUG, "Longest available string = %lu chars\n",
+             (unsigned long) availStrLength);
+
+    /* Create the output template.  Each column is sized according to
+     * the longest string.
+     */
+    char *outputStr;
+    ret = virAsprintf(&outputStr,
+              "%%-%lus  %%-%lus  %%-%lus  %%-%lus  %%%lus  %%%lus  %%%lus\n",
+              (unsigned long) nameStrLength,
+              (unsigned long) stateStrLength,
+              (unsigned long) autostartStrLength,
+              (unsigned long) persistStrLength,
+              (unsigned long) capStrLength,
+              (unsigned long) allocStrLength,
+              (unsigned long) availStrLength);
+    if (ret < 0) {
+        /* An error occurred creating the string, return */
+        goto asprintf_failure;
+    }
+
+    /* Display the header */
+    vshPrint(ctl, outputStr, _("Name"), _("State"), _("Autostart"),
+             _("Persistent"), _("Capacity"), _("Allocation"), _("Available"));
+    for (i = nameStrLength + stateStrLength + autostartStrLength
+                           + persistStrLength + capStrLength
+                           + allocStrLength + availStrLength
+                           + 12; i > 0; i--)
+        vshPrintExtra(ctl, "-");
+    vshPrintExtra(ctl, "\n");
+
+    /* Display the pool info rows */
+    for (i = 0; i < list->npools; i++) {
+        vshPrint(ctl, outputStr,
+                 virStoragePoolGetName(list->pools[i]),
+                 poolInfoTexts[i].state,
+                 poolInfoTexts[i].autostart,
+                 poolInfoTexts[i].persistent,
+                 poolInfoTexts[i].capacity,
+                 poolInfoTexts[i].allocation,
+                 poolInfoTexts[i].available);
+    }
+
+    /* Cleanup and return */
+    functionReturn = true;
+    goto cleanup;
+
+asprintf_failure:
+    /* Display an appropriate error message then cleanup and return */
+    switch (errno) {
+    case ENOMEM:
+        /* Couldn't allocate memory */
+        vshError(ctl, "%s", _("Out of memory"));
+        break;
+    default:
+        /* Some other error */
+        vshError(ctl, _("virAsprintf failed (errno %d)"), errno);
+    }
+    functionReturn = false;
+
+cleanup:
+    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);
+
+    vshStoragePoolListFree(list);
+    return functionReturn;
+}
+
+#if 0
+static bool
+cmdPoolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
+{
+    virStoragePoolInfo info;
     int i, ret;
     bool functionReturn;
     int numActivePools = 0, numInactivePools = 0, numAllPools = 0;
@@ -956,6 +1584,7 @@ cleanup:
     /* Return the desired value */
     return functionReturn;
 }
+#endif
 
 /*
  * "find-storage-pool-sources-as" command
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 98ed4b0..9aeb47e 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -2185,13 +2185,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