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

[libvirt] [PATCH 48/49] list: Use virConnectListAllSecrets in virsh



tools/virsh.c:
  * vshSecretSorter to sort secret object by name

  * vshSecretListFree to free the secret objects list.

  * vshSecretListCollect to collect the secret objects, trying to use
    new API first, fall back to older APIs if it's not supported.
---
 tools/virsh.c |  192 +++++++++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 153 insertions(+), 39 deletions(-)

diff --git a/tools/virsh.c b/tools/virsh.c
index b5c4d97..2c92839 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -495,16 +495,6 @@ _vshStrdup(vshControl *ctl, const char *s, const char *filename, int line)
 #define realloc use_vshRealloc_instead_of_realloc
 #define strdup use_vshStrdup_instead_of_strdup
 
-static int
-vshNameSorter(const void *a, const void *b)
-{
-    const char **sa = (const char**)a;
-    const char **sb = (const char**)b;
-
-    /* User visible sort, so we want locale-specific case comparison. */
-    return strcasecmp(*sa, *sb);
-}
-
 static double
 prettyCapacity(unsigned long long val,
                const char **unit) {
@@ -13987,6 +13977,139 @@ cleanup:
     return ret;
 }
 
+static int
+vshSecretSorter(const void *a, const void *b)
+{
+    virSecretPtr *sa = (virSecretPtr *) a;
+    virSecretPtr *sb = (virSecretPtr *) b;
+    char uuid_sa[VIR_UUID_STRING_BUFLEN];
+    char uuid_sb[VIR_UUID_STRING_BUFLEN];
+
+    if (*sa && !*sb)
+        return -1;
+
+    if (!*sa)
+        return *sb != NULL;
+
+    virSecretGetUUIDString(*sa, uuid_sa);
+    virSecretGetUUIDString(*sb, uuid_sb);
+
+    return strcasecmp(uuid_sa, uuid_sb);
+}
+
+struct vshSecretList {
+    virSecretPtr *secrets;
+    size_t nsecrets;
+};
+typedef struct vshSecretList *vshSecretListPtr;
+
+static void
+vshSecretListFree(vshSecretListPtr list)
+{
+    int i;
+
+    if (list && list->nsecrets) {
+        for (i = 0; i < list->nsecrets; i++) {
+            if (list->secrets[i])
+                virSecretFree(list->secrets[i]);
+        }
+        VIR_FREE(list->secrets);
+    }
+    VIR_FREE(list);
+}
+
+static vshSecretListPtr
+vshSecretListCollect(vshControl *ctl,
+                     unsigned int flags)
+{
+    vshSecretListPtr list = vshMalloc(ctl, sizeof(*list));
+    int i;
+    int ret;
+    virSecretPtr secret;
+    bool success = false;
+    size_t deleted = 0;
+    int nsecrets = 0;
+    char **uuids = NULL;
+
+    /* try the list with flags support (0.9.14 and later) */
+    if ((ret = virConnectListAllSecrets(ctl->conn,
+                                        &list->secrets,
+                                        flags)) >= 0) {
+        list->nsecrets = ret;
+        goto finished;
+    }
+
+    /* check if the command is actually supported */
+    if (last_error && last_error->code == VIR_ERR_NO_SUPPORT) {
+        virFreeError(last_error);
+        last_error = NULL;
+        goto fallback;
+    }
+
+    /* there was an error during the call */
+    vshError(ctl, "%s", _("Failed to list node secrets"));
+    goto cleanup;
+
+
+fallback:
+    /* fall back to old method (0.9.13 and older) */
+    virResetLastError();
+
+    nsecrets = virConnectNumOfSecrets(ctl->conn);
+    if (nsecrets < 0) {
+        vshError(ctl, "%s", _("Failed to count secrets"));
+        goto cleanup;
+    }
+
+    if (nsecrets == 0)
+        return list;
+
+    uuids = vshMalloc(ctl, sizeof(char *) * nsecrets);
+
+    nsecrets = virConnectListSecrets(ctl->conn, uuids, nsecrets);
+    if (nsecrets < 0) {
+        vshError(ctl, "%s", _("Failed to list secrets"));
+        goto cleanup;
+    }
+
+    list->secrets = vshMalloc(ctl, sizeof(virSecretPtr) * (nsecrets));
+    list->nsecrets = 0;
+
+    /* get the secrets */
+    for (i = 0; i < nsecrets ; i++) {
+        if (!(secret = virSecretLookupByUUIDString(ctl->conn, uuids[i])))
+            continue;
+        list->secrets[list->nsecrets++] = secret;
+    }
+
+    /* truncate secrets that weren't found */
+    deleted = nsecrets - list->nsecrets;
+
+finished:
+    /* sort the list */
+    if (list->secrets && list->nsecrets)
+        qsort(list->secrets, list->nsecrets,
+              sizeof(*list->secrets), vshSecretSorter);
+
+    /* truncate the list for not found secret objects */
+    if (deleted)
+        VIR_SHRINK_N(list->secrets, list->nsecrets, deleted);
+
+    success = true;
+
+cleanup:
+    for (i = 0; i < nsecrets; i++)
+        VIR_FREE(uuids[i]);
+    VIR_FREE(uuids);
+
+    if (!success) {
+        vshSecretListFree(list);
+        list = NULL;
+    }
+
+    return list;
+}
+
 /*
  * "secret-list" command
  */
@@ -13999,59 +14122,50 @@ static const vshCmdInfo info_secret_list[] = {
 static bool
 cmdSecretList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
 {
-    int maxuuids = 0, i;
-    char **uuids = NULL;
+    int i;
+    vshSecretListPtr list = NULL;
+    bool ret = false;
 
     if (!vshConnectionUsability(ctl, ctl->conn))
         return false;
 
-    maxuuids = virConnectNumOfSecrets(ctl->conn);
-    if (maxuuids < 0) {
-        vshError(ctl, "%s", _("Failed to list secrets"));
-        return false;
-    }
-    uuids = vshMalloc(ctl, sizeof(*uuids) * maxuuids);
-
-    maxuuids = virConnectListSecrets(ctl->conn, uuids, maxuuids);
-    if (maxuuids < 0) {
-        vshError(ctl, "%s", _("Failed to list secrets"));
-        VIR_FREE(uuids);
+    if (!(list = vshSecretListCollect(ctl, 0)))
         return false;
-    }
-
-    qsort(uuids, maxuuids, sizeof(char *), vshNameSorter);
 
     vshPrintExtra(ctl, "%-36s %s\n", _("UUID"), _("Usage"));
     vshPrintExtra(ctl, "-----------------------------------------------------------\n");
 
-    for (i = 0; i < maxuuids; i++) {
-        virSecretPtr sec = virSecretLookupByUUIDString(ctl->conn, uuids[i]);
+    for (i = 0; i < list->nsecrets; i++) {
+        virSecretPtr sec = list->secrets[i];
         const char *usageType = NULL;
 
-        if (!sec) {
-            VIR_FREE(uuids[i]);
-            continue;
-        }
-
         switch (virSecretGetUsageType(sec)) {
         case VIR_SECRET_USAGE_TYPE_VOLUME:
             usageType = _("Volume");
             break;
         }
 
+        char uuid[VIR_UUID_STRING_BUFLEN];
+        if (virSecretGetUUIDString(list->secrets[i], uuid) < 0) {
+            vshError(ctl, "%s", _("Failed to get uuid of secret"));
+            goto cleanup;
+        }
+
         if (usageType) {
             vshPrint(ctl, "%-36s %s %s\n",
-                     uuids[i], usageType,
+                     uuid, usageType,
                      virSecretGetUsageID(sec));
         } else {
             vshPrint(ctl, "%-36s %s\n",
-                     uuids[i], _("Unused"));
+                     uuid, _("Unused"));
         }
-        virSecretFree(sec);
-        VIR_FREE(uuids[i]);
     }
-    VIR_FREE(uuids);
-    return true;
+
+    ret = true;
+
+cleanup:
+    vshSecretListFree(list);
+    return ret;
 }
 
 
-- 
1.7.7.3


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