2012-07-23 14:18:51 +08:00
|
|
|
/*
|
|
|
|
* virsh-secret.c: Commands to manage secret
|
|
|
|
*
|
2016-01-09 21:36:29 +08:00
|
|
|
* Copyright (C) 2005, 2007-2016 Red Hat, Inc.
|
2012-07-23 14:18:51 +08:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
2012-09-21 06:30:55 +08:00
|
|
|
* License along with this library. If not, see
|
2012-07-23 14:18:51 +08:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
* Daniel Veillard <veillard@redhat.com>
|
|
|
|
* Karel Zak <kzak@redhat.com>
|
|
|
|
* Daniel P. Berrange <berrange@redhat.com>
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2012-08-21 07:14:37 +08:00
|
|
|
#include <config.h>
|
|
|
|
#include "virsh-secret.h"
|
|
|
|
|
|
|
|
#include "internal.h"
|
|
|
|
#include "base64.h"
|
2012-12-04 20:04:07 +08:00
|
|
|
#include "virbuffer.h"
|
2012-12-13 02:06:53 +08:00
|
|
|
#include "viralloc.h"
|
2013-05-10 02:59:04 +08:00
|
|
|
#include "virfile.h"
|
2012-12-14 01:44:57 +08:00
|
|
|
#include "virutil.h"
|
2013-08-06 19:49:23 +08:00
|
|
|
#include "conf/secret_conf.h"
|
2012-08-21 07:14:37 +08:00
|
|
|
|
2012-07-23 14:18:51 +08:00
|
|
|
static virSecretPtr
|
2015-06-16 00:53:58 +08:00
|
|
|
virshCommandOptSecret(vshControl *ctl, const vshCmd *cmd, const char **name)
|
2012-07-23 14:18:51 +08:00
|
|
|
{
|
|
|
|
virSecretPtr secret = NULL;
|
|
|
|
const char *n = NULL;
|
|
|
|
const char *optname = "secret";
|
2015-06-16 00:53:58 +08:00
|
|
|
virshControlPtr priv = ctl->privData;
|
2012-07-23 14:18:51 +08:00
|
|
|
|
2013-01-22 01:28:47 +08:00
|
|
|
if (vshCommandOptStringReq(ctl, cmd, optname, &n) < 0)
|
2012-07-23 14:18:51 +08:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
vshDebug(ctl, VSH_ERR_DEBUG,
|
|
|
|
"%s: found option <%s>: %s\n", cmd->def->name, optname, n);
|
|
|
|
|
|
|
|
if (name != NULL)
|
|
|
|
*name = n;
|
|
|
|
|
2015-06-16 00:53:58 +08:00
|
|
|
secret = virSecretLookupByUUIDString(priv->conn, n);
|
2012-07-23 14:18:51 +08:00
|
|
|
|
|
|
|
if (secret == NULL)
|
|
|
|
vshError(ctl, _("failed to get secret '%s'"), n);
|
|
|
|
|
|
|
|
return secret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "secret-define" command
|
|
|
|
*/
|
|
|
|
static const vshCmdInfo info_secret_define[] = {
|
2013-02-07 23:25:10 +08:00
|
|
|
{.name = "help",
|
|
|
|
.data = N_("define or modify a secret from an XML file")
|
|
|
|
},
|
|
|
|
{.name = "desc",
|
|
|
|
.data = N_("Define or modify a secret.")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-23 14:18:51 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static const vshCmdOptDef opts_secret_define[] = {
|
2016-01-09 21:36:29 +08:00
|
|
|
VIRSH_COMMON_OPT_FILE(N_("file containing secret attributes in XML")),
|
2013-01-14 22:38:52 +08:00
|
|
|
{.name = NULL}
|
2012-07-23 14:18:51 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static bool
|
|
|
|
cmdSecretDefine(vshControl *ctl, const vshCmd *cmd)
|
|
|
|
{
|
|
|
|
const char *from = NULL;
|
|
|
|
char *buffer;
|
|
|
|
virSecretPtr res;
|
|
|
|
char uuid[VIR_UUID_STRING_BUFLEN];
|
2013-01-22 01:28:47 +08:00
|
|
|
bool ret = false;
|
2015-06-16 00:53:58 +08:00
|
|
|
virshControlPtr priv = ctl->privData;
|
2012-07-23 14:18:51 +08:00
|
|
|
|
2013-01-22 01:28:47 +08:00
|
|
|
if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0)
|
2012-07-23 14:18:51 +08:00
|
|
|
return false;
|
|
|
|
|
virsh: use common namespacing
Convert the exported items in virsh.h to use a common 'vsh' prefix.
* tools/virsh.h (VIRSH_MAX_XML_FILE): Rename...
(VSH_MAX_XML_FILE): ...and parenthesize.
(DIFF_MSEC, CTRL_CLOSE_BRACKET): Delete.
(vshUsage, vshInit, vshDeinit, vshParseArgv): Remove prototype.
(editWriteToTempFile, editFile, editReadBackFile, prettyCapacity)
(virshReportError): Rename...
(vshEditWriteToTempFile, vshEditFile, vshEditReadBackFile)
(vshPrettyCapacity, vshReportError): ...into vsh namespace.
(jobWatchTimeoutFunc): Move to virsh-domain.c.
* tools/virsh.c (vshCommandRun): Inline former DIFF_MSEC.
(main): Inline former CTRL_CLOSE_BRACKET.
(vshUsage, vshInit, vshDeinit, vshParseArgv): Make static.
(prettyCapacity, virshReportError, editWriteToTempFile, editFile):
Fix naming, and adjust usage.
(vshAskReedit, vshCommandRun, vshEventLoop, vshInit): Adjust
usage.
* tools/virsh-domain.c (cmdAttachDevice, cmdCPUCompare)
(cmdCPUBaseline, cmdCreate, cmdDefine, cmdDetachDevice)
(cmdUpdateDevice, cmdDesc, cmdUndefine, cmdStart, cmdVcpucount)
(cmdAttachDevice, cmdDomjobinfo): Likewise.
* tools/virsh-edit.c (do): Likewise.
* tools/virsh-interface.c (cmdInterfaceDefine): Likewise.
* tools/virsh-network.c (cmdNetworkCreate, cmdNetworkDefine):
Likewise.
* tools/virsh-nodedev.c (cmdNodeDeviceCreate): Likewise.
* tools/virsh-nwfilter.c (cmdNWFilterDefine): Likewise.
* tools/virsh-pool.c (cmdPoolCreate, cmdPoolDefine)
(cmdPoolDiscoverSources, cmdPoolList): Likewise.
* tools/virsh-secret.c (cmdSecretDefine): Likewise.
* tools/virsh-snapshot.c (cmdSnapshotCreate, vshSnapshotCreate)
(vshLookupSnapshot, cmdSnapshotEdit, cmdSnapshotCurrent)
(vshGetSnapshotParent): Likewise.
* tools/virsh-volume.c (cmdVolCreate, cmdVolCreateFrom)
(cmdVolInfo, cmdVolList): Likewise.
2012-08-19 12:10:17 +08:00
|
|
|
if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0)
|
2012-07-23 14:18:51 +08:00
|
|
|
return false;
|
|
|
|
|
2015-06-16 00:53:58 +08:00
|
|
|
if (!(res = virSecretDefineXML(priv->conn, buffer, 0))) {
|
2012-07-23 14:18:51 +08:00
|
|
|
vshError(ctl, _("Failed to set attributes from %s"), from);
|
2013-01-22 01:28:47 +08:00
|
|
|
goto cleanup;
|
2012-07-23 14:18:51 +08:00
|
|
|
}
|
2013-01-22 01:28:47 +08:00
|
|
|
|
2012-07-23 14:18:51 +08:00
|
|
|
if (virSecretGetUUIDString(res, &(uuid[0])) < 0) {
|
|
|
|
vshError(ctl, "%s", _("Failed to get UUID of created secret"));
|
2013-01-22 01:28:47 +08:00
|
|
|
goto cleanup;
|
2012-07-23 14:18:51 +08:00
|
|
|
}
|
2013-01-22 01:28:47 +08:00
|
|
|
|
2012-07-23 14:18:51 +08:00
|
|
|
vshPrint(ctl, _("Secret %s created\n"), uuid);
|
2013-01-22 01:28:47 +08:00
|
|
|
ret = true;
|
|
|
|
|
2014-03-25 14:53:59 +08:00
|
|
|
cleanup:
|
2013-01-22 01:28:47 +08:00
|
|
|
VIR_FREE(buffer);
|
2013-03-29 19:55:38 +08:00
|
|
|
if (res)
|
|
|
|
virSecretFree(res);
|
2013-01-22 01:28:47 +08:00
|
|
|
return ret;
|
2012-07-23 14:18:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "secret-dumpxml" command
|
|
|
|
*/
|
|
|
|
static const vshCmdInfo info_secret_dumpxml[] = {
|
2013-02-07 23:25:10 +08:00
|
|
|
{.name = "help",
|
|
|
|
.data = N_("secret attributes in XML")
|
|
|
|
},
|
|
|
|
{.name = "desc",
|
|
|
|
.data = N_("Output attributes of a secret as an XML dump to stdout.")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-23 14:18:51 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static const vshCmdOptDef opts_secret_dumpxml[] = {
|
2013-01-14 22:38:52 +08:00
|
|
|
{.name = "secret",
|
|
|
|
.type = VSH_OT_DATA,
|
|
|
|
.flags = VSH_OFLAG_REQ,
|
|
|
|
.help = N_("secret UUID")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-23 14:18:51 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static bool
|
|
|
|
cmdSecretDumpXML(vshControl *ctl, const vshCmd *cmd)
|
|
|
|
{
|
|
|
|
virSecretPtr secret;
|
|
|
|
bool ret = false;
|
|
|
|
char *xml;
|
|
|
|
|
2015-06-16 00:53:58 +08:00
|
|
|
secret = virshCommandOptSecret(ctl, cmd, NULL);
|
2012-07-23 14:18:51 +08:00
|
|
|
if (secret == NULL)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
xml = virSecretGetXMLDesc(secret, 0);
|
|
|
|
if (xml == NULL)
|
|
|
|
goto cleanup;
|
|
|
|
vshPrint(ctl, "%s", xml);
|
|
|
|
VIR_FREE(xml);
|
|
|
|
ret = true;
|
|
|
|
|
2014-03-25 14:53:59 +08:00
|
|
|
cleanup:
|
2012-07-23 14:18:51 +08:00
|
|
|
virSecretFree(secret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "secret-set-value" command
|
|
|
|
*/
|
|
|
|
static const vshCmdInfo info_secret_set_value[] = {
|
2013-02-07 23:25:10 +08:00
|
|
|
{.name = "help",
|
|
|
|
.data = N_("set a secret value")
|
|
|
|
},
|
|
|
|
{.name = "desc",
|
|
|
|
.data = N_("Set a secret value.")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-23 14:18:51 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static const vshCmdOptDef opts_secret_set_value[] = {
|
2013-01-14 22:38:52 +08:00
|
|
|
{.name = "secret",
|
|
|
|
.type = VSH_OT_DATA,
|
|
|
|
.flags = VSH_OFLAG_REQ,
|
|
|
|
.help = N_("secret UUID")
|
|
|
|
},
|
|
|
|
{.name = "base64",
|
|
|
|
.type = VSH_OT_DATA,
|
|
|
|
.flags = VSH_OFLAG_REQ,
|
|
|
|
.help = N_("base64-encoded secret value")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-23 14:18:51 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static bool
|
|
|
|
cmdSecretSetValue(vshControl *ctl, const vshCmd *cmd)
|
|
|
|
{
|
|
|
|
virSecretPtr secret;
|
|
|
|
size_t value_size;
|
|
|
|
const char *base64 = NULL;
|
|
|
|
char *value;
|
|
|
|
int res;
|
|
|
|
bool ret = false;
|
|
|
|
|
2015-06-16 00:53:58 +08:00
|
|
|
if (!(secret = virshCommandOptSecret(ctl, cmd, NULL)))
|
2012-07-23 14:18:51 +08:00
|
|
|
return false;
|
|
|
|
|
2013-01-22 01:28:47 +08:00
|
|
|
if (vshCommandOptStringReq(ctl, cmd, "base64", &base64) < 0)
|
2012-07-23 14:18:51 +08:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!base64_decode_alloc(base64, strlen(base64), &value, &value_size)) {
|
|
|
|
vshError(ctl, "%s", _("Invalid base64 data"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (value == NULL) {
|
|
|
|
vshError(ctl, "%s", _("Failed to allocate memory"));
|
2013-01-22 01:28:47 +08:00
|
|
|
goto cleanup;
|
2012-07-23 14:18:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
res = virSecretSetValue(secret, (unsigned char *)value, value_size, 0);
|
|
|
|
memset(value, 0, value_size);
|
|
|
|
VIR_FREE(value);
|
|
|
|
|
|
|
|
if (res != 0) {
|
|
|
|
vshError(ctl, "%s", _("Failed to set secret value"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
vshPrint(ctl, "%s", _("Secret value set\n"));
|
|
|
|
ret = true;
|
|
|
|
|
2014-03-25 14:53:59 +08:00
|
|
|
cleanup:
|
2012-07-23 14:18:51 +08:00
|
|
|
virSecretFree(secret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "secret-get-value" command
|
|
|
|
*/
|
|
|
|
static const vshCmdInfo info_secret_get_value[] = {
|
2013-02-07 23:25:10 +08:00
|
|
|
{.name = "help",
|
|
|
|
.data = N_("Output a secret value")
|
|
|
|
},
|
|
|
|
{.name = "desc",
|
|
|
|
.data = N_("Output a secret value to stdout.")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-23 14:18:51 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static const vshCmdOptDef opts_secret_get_value[] = {
|
2013-01-14 22:38:52 +08:00
|
|
|
{.name = "secret",
|
|
|
|
.type = VSH_OT_DATA,
|
|
|
|
.flags = VSH_OFLAG_REQ,
|
|
|
|
.help = N_("secret UUID")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-23 14:18:51 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static bool
|
|
|
|
cmdSecretGetValue(vshControl *ctl, const vshCmd *cmd)
|
|
|
|
{
|
|
|
|
virSecretPtr secret;
|
|
|
|
char *base64;
|
|
|
|
unsigned char *value;
|
|
|
|
size_t value_size;
|
|
|
|
bool ret = false;
|
|
|
|
|
2015-06-16 00:53:58 +08:00
|
|
|
secret = virshCommandOptSecret(ctl, cmd, NULL);
|
2012-07-23 14:18:51 +08:00
|
|
|
if (secret == NULL)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
value = virSecretGetValue(secret, &value_size, 0);
|
|
|
|
if (value == NULL)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
base64_encode_alloc((char *)value, value_size, &base64);
|
|
|
|
memset(value, 0, value_size);
|
|
|
|
VIR_FREE(value);
|
|
|
|
|
|
|
|
if (base64 == NULL) {
|
|
|
|
vshError(ctl, "%s", _("Failed to allocate memory"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
vshPrint(ctl, "%s", base64);
|
|
|
|
memset(base64, 0, strlen(base64));
|
|
|
|
VIR_FREE(base64);
|
|
|
|
ret = true;
|
|
|
|
|
2014-03-25 14:53:59 +08:00
|
|
|
cleanup:
|
2012-07-23 14:18:51 +08:00
|
|
|
virSecretFree(secret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "secret-undefine" command
|
|
|
|
*/
|
|
|
|
static const vshCmdInfo info_secret_undefine[] = {
|
2013-02-07 23:25:10 +08:00
|
|
|
{.name = "help",
|
|
|
|
.data = N_("undefine a secret")
|
|
|
|
},
|
|
|
|
{.name = "desc",
|
|
|
|
.data = N_("Undefine a secret.")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-23 14:18:51 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static const vshCmdOptDef opts_secret_undefine[] = {
|
2013-01-14 22:38:52 +08:00
|
|
|
{.name = "secret",
|
|
|
|
.type = VSH_OT_DATA,
|
|
|
|
.flags = VSH_OFLAG_REQ,
|
|
|
|
.help = N_("secret UUID")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-23 14:18:51 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static bool
|
|
|
|
cmdSecretUndefine(vshControl *ctl, const vshCmd *cmd)
|
|
|
|
{
|
|
|
|
virSecretPtr secret;
|
|
|
|
bool ret = false;
|
|
|
|
const char *uuid;
|
|
|
|
|
2015-06-16 00:53:58 +08:00
|
|
|
secret = virshCommandOptSecret(ctl, cmd, &uuid);
|
2012-07-23 14:18:51 +08:00
|
|
|
if (secret == NULL)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (virSecretUndefine(secret) < 0) {
|
|
|
|
vshError(ctl, _("Failed to delete secret %s"), uuid);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
vshPrint(ctl, _("Secret %s deleted\n"), uuid);
|
|
|
|
ret = true;
|
|
|
|
|
2014-03-25 14:53:59 +08:00
|
|
|
cleanup:
|
2012-07-23 14:18:51 +08:00
|
|
|
virSecretFree(secret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-09-14 16:38:52 +08:00
|
|
|
static int
|
2015-06-16 00:53:58 +08:00
|
|
|
virshSecretSorter(const void *a, const void *b)
|
2012-09-14 16:38:52 +08:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2015-06-16 00:53:58 +08:00
|
|
|
struct virshSecretList {
|
2012-09-14 16:38:52 +08:00
|
|
|
virSecretPtr *secrets;
|
|
|
|
size_t nsecrets;
|
|
|
|
};
|
2015-06-16 00:53:58 +08:00
|
|
|
typedef struct virshSecretList *virshSecretListPtr;
|
2012-09-14 16:38:52 +08:00
|
|
|
|
|
|
|
static void
|
2015-06-16 00:53:58 +08:00
|
|
|
virshSecretListFree(virshSecretListPtr list)
|
2012-09-14 16:38:52 +08:00
|
|
|
{
|
Convert 'int i' to 'size_t i' in tools/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 22:09:33 +08:00
|
|
|
size_t i;
|
2012-09-14 16:38:52 +08:00
|
|
|
|
2013-08-27 19:27:50 +08:00
|
|
|
if (list && list->secrets) {
|
2012-09-14 16:38:52 +08:00
|
|
|
for (i = 0; i < list->nsecrets; i++) {
|
|
|
|
if (list->secrets[i])
|
|
|
|
virSecretFree(list->secrets[i]);
|
|
|
|
}
|
|
|
|
VIR_FREE(list->secrets);
|
|
|
|
}
|
|
|
|
VIR_FREE(list);
|
|
|
|
}
|
|
|
|
|
2015-06-16 00:53:58 +08:00
|
|
|
static virshSecretListPtr
|
|
|
|
virshSecretListCollect(vshControl *ctl,
|
|
|
|
unsigned int flags)
|
2012-09-14 16:38:52 +08:00
|
|
|
{
|
2015-06-16 00:53:58 +08:00
|
|
|
virshSecretListPtr list = vshMalloc(ctl, sizeof(*list));
|
Convert 'int i' to 'size_t i' in tools/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 22:09:33 +08:00
|
|
|
size_t i;
|
2012-09-14 16:38:52 +08:00
|
|
|
int ret;
|
|
|
|
virSecretPtr secret;
|
|
|
|
bool success = false;
|
|
|
|
size_t deleted = 0;
|
|
|
|
int nsecrets = 0;
|
|
|
|
char **uuids = NULL;
|
2015-06-16 00:53:58 +08:00
|
|
|
virshControlPtr priv = ctl->privData;
|
2012-09-14 16:38:52 +08:00
|
|
|
|
|
|
|
/* try the list with flags support (0.10.2 and later) */
|
2015-06-16 00:53:58 +08:00
|
|
|
if ((ret = virConnectListAllSecrets(priv->conn,
|
2012-09-14 16:38:52 +08:00
|
|
|
&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;
|
|
|
|
|
|
|
|
|
2014-03-25 14:53:59 +08:00
|
|
|
fallback:
|
2012-09-14 16:38:52 +08:00
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
|
2015-06-16 00:53:58 +08:00
|
|
|
nsecrets = virConnectNumOfSecrets(priv->conn);
|
2012-09-14 16:38:52 +08:00
|
|
|
if (nsecrets < 0) {
|
|
|
|
vshError(ctl, "%s", _("Failed to count secrets"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nsecrets == 0)
|
|
|
|
return list;
|
|
|
|
|
|
|
|
uuids = vshMalloc(ctl, sizeof(char *) * nsecrets);
|
|
|
|
|
2015-06-16 00:53:58 +08:00
|
|
|
nsecrets = virConnectListSecrets(priv->conn, uuids, nsecrets);
|
2012-09-14 16:38:52 +08:00
|
|
|
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 */
|
2013-05-21 15:44:53 +08:00
|
|
|
for (i = 0; i < nsecrets; i++) {
|
2015-06-16 00:53:58 +08:00
|
|
|
if (!(secret = virSecretLookupByUUIDString(priv->conn, uuids[i])))
|
2012-09-14 16:38:52 +08:00
|
|
|
continue;
|
|
|
|
list->secrets[list->nsecrets++] = secret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* truncate secrets that weren't found */
|
|
|
|
deleted = nsecrets - list->nsecrets;
|
|
|
|
|
2014-03-25 14:53:59 +08:00
|
|
|
finished:
|
2012-09-14 16:38:52 +08:00
|
|
|
/* sort the list */
|
|
|
|
if (list->secrets && list->nsecrets)
|
|
|
|
qsort(list->secrets, list->nsecrets,
|
2015-06-16 00:53:58 +08:00
|
|
|
sizeof(*list->secrets), virshSecretSorter);
|
2012-09-14 16:38:52 +08:00
|
|
|
|
|
|
|
/* truncate the list for not found secret objects */
|
|
|
|
if (deleted)
|
|
|
|
VIR_SHRINK_N(list->secrets, list->nsecrets, deleted);
|
|
|
|
|
|
|
|
success = true;
|
|
|
|
|
2014-03-25 14:53:59 +08:00
|
|
|
cleanup:
|
Convert 'int i' to 'size_t i' in tools/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 22:09:33 +08:00
|
|
|
if (nsecrets > 0) {
|
|
|
|
for (i = 0; i < nsecrets; i++)
|
|
|
|
VIR_FREE(uuids[i]);
|
|
|
|
VIR_FREE(uuids);
|
|
|
|
}
|
2012-09-14 16:38:52 +08:00
|
|
|
|
|
|
|
if (!success) {
|
2015-06-16 00:53:58 +08:00
|
|
|
virshSecretListFree(list);
|
2012-09-14 16:38:52 +08:00
|
|
|
list = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
2012-07-23 14:18:51 +08:00
|
|
|
/*
|
|
|
|
* "secret-list" command
|
|
|
|
*/
|
|
|
|
static const vshCmdInfo info_secret_list[] = {
|
2013-02-07 23:25:10 +08:00
|
|
|
{.name = "help",
|
|
|
|
.data = N_("list secrets")
|
|
|
|
},
|
|
|
|
{.name = "desc",
|
|
|
|
.data = N_("Returns a list of secrets")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-23 14:18:51 +08:00
|
|
|
};
|
|
|
|
|
2012-09-14 16:38:52 +08:00
|
|
|
static const vshCmdOptDef opts_secret_list[] = {
|
2013-01-14 22:38:52 +08:00
|
|
|
{.name = "ephemeral",
|
|
|
|
.type = VSH_OT_BOOL,
|
|
|
|
.help = N_("list ephemeral secrets")
|
|
|
|
},
|
|
|
|
{.name = "no-ephemeral",
|
|
|
|
.type = VSH_OT_BOOL,
|
|
|
|
.help = N_("list non-ephemeral secrets")
|
|
|
|
},
|
|
|
|
{.name = "private",
|
|
|
|
.type = VSH_OT_BOOL,
|
|
|
|
.help = N_("list private secrets")
|
|
|
|
},
|
|
|
|
{.name = "no-private",
|
|
|
|
.type = VSH_OT_BOOL,
|
|
|
|
.help = N_("list non-private secrets")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-09-14 16:38:52 +08:00
|
|
|
};
|
|
|
|
|
2012-07-23 14:18:51 +08:00
|
|
|
static bool
|
|
|
|
cmdSecretList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
|
|
|
|
{
|
Convert 'int i' to 'size_t i' in tools/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 22:09:33 +08:00
|
|
|
size_t i;
|
2015-06-16 00:53:58 +08:00
|
|
|
virshSecretListPtr list = NULL;
|
2012-09-14 16:38:52 +08:00
|
|
|
bool ret = false;
|
|
|
|
unsigned int flags = 0;
|
2012-07-23 14:18:51 +08:00
|
|
|
|
2012-09-14 16:38:52 +08:00
|
|
|
if (vshCommandOptBool(cmd, "ephemeral"))
|
|
|
|
flags |= VIR_CONNECT_LIST_SECRETS_EPHEMERAL;
|
2012-07-23 14:18:51 +08:00
|
|
|
|
2012-09-14 16:38:52 +08:00
|
|
|
if (vshCommandOptBool(cmd, "no-ephemeral"))
|
|
|
|
flags |= VIR_CONNECT_LIST_SECRETS_NO_EPHEMERAL;
|
|
|
|
|
|
|
|
if (vshCommandOptBool(cmd, "private"))
|
|
|
|
flags |= VIR_CONNECT_LIST_SECRETS_PRIVATE;
|
2012-07-23 14:18:51 +08:00
|
|
|
|
2012-09-14 16:38:52 +08:00
|
|
|
if (vshCommandOptBool(cmd, "no-private"))
|
|
|
|
flags |= VIR_CONNECT_LIST_SECRETS_NO_PRIVATE;
|
|
|
|
|
2015-06-16 00:53:58 +08:00
|
|
|
if (!(list = virshSecretListCollect(ctl, flags)))
|
2012-09-14 16:38:52 +08:00
|
|
|
return false;
|
2012-07-23 14:18:51 +08:00
|
|
|
|
2013-11-13 00:42:43 +08:00
|
|
|
vshPrintExtra(ctl, " %-36s %s\n", _("UUID"), _("Usage"));
|
|
|
|
vshPrintExtra(ctl, "----------------------------------------"
|
|
|
|
"----------------------------------------\n");
|
2012-07-23 14:18:51 +08:00
|
|
|
|
2012-09-14 16:38:52 +08:00
|
|
|
for (i = 0; i < list->nsecrets; i++) {
|
|
|
|
virSecretPtr sec = list->secrets[i];
|
2013-08-06 19:49:23 +08:00
|
|
|
int usageType = virSecretGetUsageType(sec);
|
2014-05-15 03:48:15 +08:00
|
|
|
const char *usageStr = virSecretUsageTypeToString(usageType);
|
2012-09-14 16:38:52 +08:00
|
|
|
char uuid[VIR_UUID_STRING_BUFLEN];
|
2013-08-06 19:49:23 +08:00
|
|
|
|
2014-04-29 10:10:18 +08:00
|
|
|
if (virSecretGetUUIDString(sec, uuid) < 0) {
|
2012-09-14 16:38:52 +08:00
|
|
|
vshError(ctl, "%s", _("Failed to get uuid of secret"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2012-07-23 14:18:51 +08:00
|
|
|
if (usageType) {
|
2013-11-13 00:42:43 +08:00
|
|
|
vshPrint(ctl, " %-36s %s %s\n",
|
2013-08-06 19:49:23 +08:00
|
|
|
uuid, usageStr,
|
2012-07-23 14:18:51 +08:00
|
|
|
virSecretGetUsageID(sec));
|
|
|
|
} else {
|
2013-11-13 00:42:43 +08:00
|
|
|
vshPrint(ctl, " %-36s %s\n",
|
2012-09-14 16:38:52 +08:00
|
|
|
uuid, _("Unused"));
|
2012-07-23 14:18:51 +08:00
|
|
|
}
|
|
|
|
}
|
2012-09-14 16:38:52 +08:00
|
|
|
|
|
|
|
ret = true;
|
|
|
|
|
2014-03-25 14:53:59 +08:00
|
|
|
cleanup:
|
2015-06-16 00:53:58 +08:00
|
|
|
virshSecretListFree(list);
|
2012-09-14 16:38:52 +08:00
|
|
|
return ret;
|
2012-07-23 14:18:51 +08:00
|
|
|
}
|
2012-07-23 15:19:04 +08:00
|
|
|
|
2012-08-21 07:14:37 +08:00
|
|
|
const vshCmdDef secretCmds[] = {
|
2013-02-07 23:25:10 +08:00
|
|
|
{.name = "secret-define",
|
|
|
|
.handler = cmdSecretDefine,
|
|
|
|
.opts = opts_secret_define,
|
|
|
|
.info = info_secret_define,
|
|
|
|
.flags = 0
|
|
|
|
},
|
|
|
|
{.name = "secret-dumpxml",
|
|
|
|
.handler = cmdSecretDumpXML,
|
|
|
|
.opts = opts_secret_dumpxml,
|
|
|
|
.info = info_secret_dumpxml,
|
|
|
|
.flags = 0
|
|
|
|
},
|
|
|
|
{.name = "secret-get-value",
|
|
|
|
.handler = cmdSecretGetValue,
|
|
|
|
.opts = opts_secret_get_value,
|
|
|
|
.info = info_secret_get_value,
|
|
|
|
.flags = 0
|
|
|
|
},
|
|
|
|
{.name = "secret-list",
|
|
|
|
.handler = cmdSecretList,
|
|
|
|
.opts = opts_secret_list,
|
|
|
|
.info = info_secret_list,
|
|
|
|
.flags = 0
|
|
|
|
},
|
|
|
|
{.name = "secret-set-value",
|
|
|
|
.handler = cmdSecretSetValue,
|
|
|
|
.opts = opts_secret_set_value,
|
|
|
|
.info = info_secret_set_value,
|
|
|
|
.flags = 0
|
|
|
|
},
|
|
|
|
{.name = "secret-undefine",
|
|
|
|
.handler = cmdSecretUndefine,
|
|
|
|
.opts = opts_secret_undefine,
|
|
|
|
.info = info_secret_undefine,
|
|
|
|
.flags = 0
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-23 15:19:04 +08:00
|
|
|
};
|