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