list: Use virConnectListAllSecrets in virsh

This introduces four new options for secret-list, to filter the
returned secrets by whether it's ephemeral or not, and/or by
whether it's private or not.

* tools/virsh-secret.c: (New helper vshSecretSorter,
  vshSecretListFree, and vshCollectSecretList; Use the new
  API for secret-list; error out if flags are specified,
  because there is no way to filter the results when using
  old APIs (no APIs to get the properties (ephemeral, private)
  of a secret yet).

* tools/virsh.pod: Document the 4 new options.
This commit is contained in:
Osier Yang 2012-09-14 16:38:52 +08:00
parent 473ee27e6a
commit d15d092cda
2 changed files with 183 additions and 32 deletions

View File

@ -290,6 +290,141 @@ 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 vshStrcasecmp(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.10.2 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)
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.10.1 and older) */
vshResetLibvirtError();
if (flags) {
vshError(ctl, "%s", _("Filtering is not supported by this libvirt"));
goto cleanup;
}
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
*/
@ -299,59 +434,71 @@ static const vshCmdInfo info_secret_list[] = {
{NULL, NULL}
};
static const vshCmdOptDef opts_secret_list[] = {
{"ephemeral", VSH_OT_BOOL, 0, N_("list ephemeral secrets")},
{"no-ephemeral", VSH_OT_BOOL, 0, N_("list non-ephemeral secrets")},
{"private", VSH_OT_BOOL, 0, N_("list private secrets")},
{"no-private", VSH_OT_BOOL, 0, N_("list non-private secrets")},
{NULL, 0, 0, NULL}
};
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;
unsigned int flags = 0;
maxuuids = virConnectNumOfSecrets(ctl->conn);
if (maxuuids < 0) {
vshError(ctl, "%s", _("Failed to list secrets"));
if (vshCommandOptBool(cmd, "ephemeral"))
flags |= VIR_CONNECT_LIST_SECRETS_EPHEMERAL;
if (vshCommandOptBool(cmd, "no-ephemeral"))
flags |= VIR_CONNECT_LIST_SECRETS_NO_EPHEMERAL;
if (vshCommandOptBool(cmd, "private"))
flags |= VIR_CONNECT_LIST_SECRETS_PRIVATE;
if (vshCommandOptBool(cmd, "no-private"))
flags |= VIR_CONNECT_LIST_SECRETS_NO_PRIVATE;
if (!(list = vshSecretListCollect(ctl, flags)))
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);
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;
}
const vshCmdDef secretCmds[] = {
@ -361,7 +508,7 @@ const vshCmdDef secretCmds[] = {
info_secret_dumpxml, 0},
{"secret-get-value", cmdSecretGetValue, opts_secret_get_value,
info_secret_get_value, 0},
{"secret-list", cmdSecretList, NULL, info_secret_list, 0},
{"secret-list", cmdSecretList, opts_secret_list, info_secret_list, 0},
{"secret-set-value", cmdSecretSetValue, opts_secret_set_value,
info_secret_set_value, 0},
{"secret-undefine", cmdSecretUndefine, opts_secret_undefine,

View File

@ -2469,9 +2469,13 @@ encoded using Base64.
Delete a I<secret> (specified by its UUID), including the associated value, if
any.
=item B<secret-list>
=item B<secret-list> [I<--ephemeral>] [I<--no-ephemeral>]
[I<--private>] [I<--no-private>]
Output a list of UUIDs of known secrets to stdout.
Returns the list of secrets. You may also want to filter the returned secrets
by I<--ephemeral> to list the ephemeral ones, I<--no-ephemeral> to list the
non-ephemeral ones, I<--private> to list the private ones, and
I<--no-private> to list the non-private ones.
=back