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

Osier Yang jyang at redhat.com
Wed Sep 5 06:40:25 UTC 2012


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




More information about the libvir-list mailing list