[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

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




Please ignore this, and review v5 instead. (I forgot to cleanup
the "#if 0...#endif")

On 2012年09月04日 23:16, Osier Yang wrote:
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

Oops. I fogot to cleanup this. V5 will be posed.

Regards,
Osier


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]