mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 21:55:25 +00:00
Add usage type/id as a public API property of virSecret
* include/libvirt/libvirt.h, include/libvirt/libvirt.h.in: Add virSecretGetUsageType, virSecretGetUsageID and virLookupSecretByUsage * python/generator.py: Mark virSecretGetUsageType, virSecretGetUsageID as not throwing exceptions * qemud/remote.c: Implement dispatch for virLookupSecretByUsage * qemud/remote_protocol.x: Add usage type & ID as attributes of remote_nonnull_secret. Add RPC calls for new public APIs * qemud/remote_dispatch_args.h, qemud/remote_dispatch_prototypes.h, qemud/remote_dispatch_ret.h, qemud/remote_dispatch_table.h, qemud/remote_protocol.c, qemud/remote_protocol.h: Re-generate * src/datatypes.c, src/datatypes.h: Add usageType and usageID as properties of virSecretPtr * src/driver.h: Add virLookupSecretByUsage driver entry point * src/libvirt.c: Implement virSecretGetUsageType, virSecretGetUsageID and virLookupSecretByUsage * src/libvirt_public.syms: Export virSecretGetUsageType, virSecretGetUsageID and virLookupSecretByUsage * src/remote_internal.c: Implement virLookupSecretByUsage entry * src/secret_conf.c, src/secret_conf.h: Remove the virSecretUsageType enum, now in public API. Make volume path mandatory when parsing XML * src/secret_driver.c: Enforce usage uniqueness when defining secrets. Implement virSecretLookupByUsage api method * src/virsh.c: Include usage for secret-list command
This commit is contained in:
parent
47e7a258db
commit
a2a30038cf
@ -1462,6 +1462,12 @@ void virEventRegisterImpl(virEventAddHandleFunc addHandle,
|
||||
typedef struct _virSecret virSecret;
|
||||
typedef virSecret *virSecretPtr;
|
||||
|
||||
typedef enum {
|
||||
VIR_SECRET_USAGE_TYPE_NONE = 0,
|
||||
VIR_SECRET_USAGE_TYPE_VOLUME = 1,
|
||||
/* Expect more owner types later... */
|
||||
} virSecretUsageType;
|
||||
|
||||
virConnectPtr virSecretGetConnect (virSecretPtr secret);
|
||||
int virConnectNumOfSecrets (virConnectPtr conn);
|
||||
int virConnectListSecrets (virConnectPtr conn,
|
||||
@ -1471,6 +1477,9 @@ virSecretPtr virSecretLookupByUUID(virConnectPtr conn,
|
||||
const unsigned char *uuid);
|
||||
virSecretPtr virSecretLookupByUUIDString(virConnectPtr conn,
|
||||
const char *uuid);
|
||||
virSecretPtr virSecretLookupByUsage(virConnectPtr conn,
|
||||
int usageType,
|
||||
const char *usageID);
|
||||
virSecretPtr virSecretDefineXML (virConnectPtr conn,
|
||||
const char *xml,
|
||||
unsigned int flags);
|
||||
@ -1478,6 +1487,8 @@ int virSecretGetUUID (virSecretPtr secret,
|
||||
unsigned char *buf);
|
||||
int virSecretGetUUIDString (virSecretPtr secret,
|
||||
char *buf);
|
||||
int virSecretGetUsageType (virSecretPtr secret);
|
||||
const char * virSecretGetUsageID (virSecretPtr secret);
|
||||
char * virSecretGetXMLDesc (virSecretPtr secret,
|
||||
unsigned int flags);
|
||||
int virSecretSetValue (virSecretPtr secret,
|
||||
|
@ -1462,6 +1462,12 @@ void virEventRegisterImpl(virEventAddHandleFunc addHandle,
|
||||
typedef struct _virSecret virSecret;
|
||||
typedef virSecret *virSecretPtr;
|
||||
|
||||
typedef enum {
|
||||
VIR_SECRET_USAGE_TYPE_NONE = 0,
|
||||
VIR_SECRET_USAGE_TYPE_VOLUME = 1,
|
||||
/* Expect more owner types later... */
|
||||
} virSecretUsageType;
|
||||
|
||||
virConnectPtr virSecretGetConnect (virSecretPtr secret);
|
||||
int virConnectNumOfSecrets (virConnectPtr conn);
|
||||
int virConnectListSecrets (virConnectPtr conn,
|
||||
@ -1471,6 +1477,9 @@ virSecretPtr virSecretLookupByUUID(virConnectPtr conn,
|
||||
const unsigned char *uuid);
|
||||
virSecretPtr virSecretLookupByUUIDString(virConnectPtr conn,
|
||||
const char *uuid);
|
||||
virSecretPtr virSecretLookupByUsage(virConnectPtr conn,
|
||||
int usageType,
|
||||
const char *usageID);
|
||||
virSecretPtr virSecretDefineXML (virConnectPtr conn,
|
||||
const char *xml,
|
||||
unsigned int flags);
|
||||
@ -1478,6 +1487,8 @@ int virSecretGetUUID (virSecretPtr secret,
|
||||
unsigned char *buf);
|
||||
int virSecretGetUUIDString (virSecretPtr secret,
|
||||
char *buf);
|
||||
int virSecretGetUsageType (virSecretPtr secret);
|
||||
const char * virSecretGetUsageID (virSecretPtr secret);
|
||||
char * virSecretGetXMLDesc (virSecretPtr secret,
|
||||
unsigned int flags);
|
||||
int virSecretSetValue (virSecretPtr secret,
|
||||
|
@ -669,6 +669,8 @@ functions_noexcept = {
|
||||
'virStorageVolGetkey': True,
|
||||
'virNodeDeviceGetName': True,
|
||||
'virNodeDeviceGetParent': True,
|
||||
'virSecretGetUsageType': True,
|
||||
'virSecretGetUsageID': True,
|
||||
}
|
||||
|
||||
reference_keepers = {
|
||||
|
@ -4778,6 +4778,26 @@ remoteDispatchSecretUndefine (struct qemud_server *server ATTRIBUTE_UNUSED,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
remoteDispatchSecretLookupByUsage (struct qemud_server *server ATTRIBUTE_UNUSED,
|
||||
struct qemud_client *client ATTRIBUTE_UNUSED,
|
||||
virConnectPtr conn, remote_error *err,
|
||||
remote_secret_lookup_by_usage_args *args,
|
||||
remote_secret_lookup_by_usage_ret *ret)
|
||||
{
|
||||
virSecretPtr secret;
|
||||
|
||||
secret = virSecretLookupByUsage (conn, args->usageType, args->usageID);
|
||||
if (secret == NULL) {
|
||||
remoteDispatchConnError (err, conn);
|
||||
return -1;
|
||||
}
|
||||
|
||||
make_nonnull_secret (&ret->secret, secret);
|
||||
virSecretFree (secret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*----- Helpers. -----*/
|
||||
|
||||
@ -4828,7 +4848,7 @@ get_nonnull_storage_vol (virConnectPtr conn, remote_nonnull_storage_vol vol)
|
||||
static virSecretPtr
|
||||
get_nonnull_secret (virConnectPtr conn, remote_nonnull_secret secret)
|
||||
{
|
||||
return virGetSecret (conn, BAD_CAST secret.uuid);
|
||||
return virGetSecret (conn, BAD_CAST secret.uuid, secret.usageType, secret.usageID);
|
||||
}
|
||||
|
||||
/* Make remote_nonnull_domain and remote_nonnull_network. */
|
||||
@ -4880,4 +4900,6 @@ static void
|
||||
make_nonnull_secret (remote_nonnull_secret *secret_dst, virSecretPtr secret_src)
|
||||
{
|
||||
memcpy (secret_dst->uuid, secret_src->uuid, VIR_UUID_BUFLEN);
|
||||
secret_dst->usageType = secret_src->usageType;
|
||||
secret_dst->usageID = strdup (secret_src->usageID);
|
||||
}
|
||||
|
@ -124,3 +124,4 @@
|
||||
remote_secret_set_value_args val_remote_secret_set_value_args;
|
||||
remote_secret_get_value_args val_remote_secret_get_value_args;
|
||||
remote_secret_undefine_args val_remote_secret_undefine_args;
|
||||
remote_secret_lookup_by_usage_args val_remote_secret_lookup_by_usage_args;
|
||||
|
@ -807,6 +807,13 @@ static int remoteDispatchSecretGetXmlDesc(
|
||||
remote_error *err,
|
||||
remote_secret_get_xml_desc_args *args,
|
||||
remote_secret_get_xml_desc_ret *ret);
|
||||
static int remoteDispatchSecretLookupByUsage(
|
||||
struct qemud_server *server,
|
||||
struct qemud_client *client,
|
||||
virConnectPtr conn,
|
||||
remote_error *err,
|
||||
remote_secret_lookup_by_usage_args *args,
|
||||
remote_secret_lookup_by_usage_ret *ret);
|
||||
static int remoteDispatchSecretLookupByUuid(
|
||||
struct qemud_server *server,
|
||||
struct qemud_client *client,
|
||||
|
@ -105,3 +105,4 @@
|
||||
remote_secret_define_xml_ret val_remote_secret_define_xml_ret;
|
||||
remote_secret_get_xml_desc_ret val_remote_secret_get_xml_desc_ret;
|
||||
remote_secret_get_value_ret val_remote_secret_get_value_ret;
|
||||
remote_secret_lookup_by_usage_ret val_remote_secret_lookup_by_usage_ret;
|
||||
|
@ -737,3 +737,8 @@
|
||||
.args_filter = (xdrproc_t) xdr_remote_secret_undefine_args,
|
||||
.ret_filter = (xdrproc_t) xdr_void,
|
||||
},
|
||||
{ /* SecretLookupByUsage => 147 */
|
||||
.fn = (dispatch_fn) remoteDispatchSecretLookupByUsage,
|
||||
.args_filter = (xdrproc_t) xdr_remote_secret_lookup_by_usage_args,
|
||||
.ret_filter = (xdrproc_t) xdr_remote_secret_lookup_by_usage_ret,
|
||||
},
|
||||
|
@ -109,6 +109,10 @@ xdr_remote_nonnull_secret (XDR *xdrs, remote_nonnull_secret *objp)
|
||||
|
||||
if (!xdr_remote_uuid (xdrs, objp->uuid))
|
||||
return FALSE;
|
||||
if (!xdr_int (xdrs, &objp->usageType))
|
||||
return FALSE;
|
||||
if (!xdr_remote_nonnull_string (xdrs, &objp->usageID))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -2673,6 +2677,26 @@ xdr_remote_secret_undefine_args (XDR *xdrs, remote_secret_undefine_args *objp)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool_t
|
||||
xdr_remote_secret_lookup_by_usage_args (XDR *xdrs, remote_secret_lookup_by_usage_args *objp)
|
||||
{
|
||||
|
||||
if (!xdr_int (xdrs, &objp->usageType))
|
||||
return FALSE;
|
||||
if (!xdr_remote_nonnull_string (xdrs, &objp->usageID))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool_t
|
||||
xdr_remote_secret_lookup_by_usage_ret (XDR *xdrs, remote_secret_lookup_by_usage_ret *objp)
|
||||
{
|
||||
|
||||
if (!xdr_remote_nonnull_secret (xdrs, &objp->secret))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool_t
|
||||
xdr_remote_procedure (XDR *xdrs, remote_procedure *objp)
|
||||
{
|
||||
|
@ -87,6 +87,8 @@ typedef struct remote_nonnull_node_device remote_nonnull_node_device;
|
||||
|
||||
struct remote_nonnull_secret {
|
||||
remote_uuid uuid;
|
||||
int usageType;
|
||||
remote_nonnull_string usageID;
|
||||
};
|
||||
typedef struct remote_nonnull_secret remote_nonnull_secret;
|
||||
|
||||
@ -1513,6 +1515,17 @@ struct remote_secret_undefine_args {
|
||||
remote_nonnull_secret secret;
|
||||
};
|
||||
typedef struct remote_secret_undefine_args remote_secret_undefine_args;
|
||||
|
||||
struct remote_secret_lookup_by_usage_args {
|
||||
int usageType;
|
||||
remote_nonnull_string usageID;
|
||||
};
|
||||
typedef struct remote_secret_lookup_by_usage_args remote_secret_lookup_by_usage_args;
|
||||
|
||||
struct remote_secret_lookup_by_usage_ret {
|
||||
remote_nonnull_secret secret;
|
||||
};
|
||||
typedef struct remote_secret_lookup_by_usage_ret remote_secret_lookup_by_usage_ret;
|
||||
#define REMOTE_PROGRAM 0x20008086
|
||||
#define REMOTE_PROTOCOL_VERSION 1
|
||||
|
||||
@ -1663,6 +1676,7 @@ enum remote_procedure {
|
||||
REMOTE_PROC_SECRET_SET_VALUE = 144,
|
||||
REMOTE_PROC_SECRET_GET_VALUE = 145,
|
||||
REMOTE_PROC_SECRET_UNDEFINE = 146,
|
||||
REMOTE_PROC_SECRET_LOOKUP_BY_USAGE = 147,
|
||||
};
|
||||
typedef enum remote_procedure remote_procedure;
|
||||
|
||||
@ -1939,6 +1953,8 @@ extern bool_t xdr_remote_secret_set_value_args (XDR *, remote_secret_set_value_
|
||||
extern bool_t xdr_remote_secret_get_value_args (XDR *, remote_secret_get_value_args*);
|
||||
extern bool_t xdr_remote_secret_get_value_ret (XDR *, remote_secret_get_value_ret*);
|
||||
extern bool_t xdr_remote_secret_undefine_args (XDR *, remote_secret_undefine_args*);
|
||||
extern bool_t xdr_remote_secret_lookup_by_usage_args (XDR *, remote_secret_lookup_by_usage_args*);
|
||||
extern bool_t xdr_remote_secret_lookup_by_usage_ret (XDR *, remote_secret_lookup_by_usage_ret*);
|
||||
extern bool_t xdr_remote_procedure (XDR *, remote_procedure*);
|
||||
extern bool_t xdr_remote_message_type (XDR *, remote_message_type*);
|
||||
extern bool_t xdr_remote_message_status (XDR *, remote_message_status*);
|
||||
@ -2191,6 +2207,8 @@ extern bool_t xdr_remote_secret_set_value_args ();
|
||||
extern bool_t xdr_remote_secret_get_value_args ();
|
||||
extern bool_t xdr_remote_secret_get_value_ret ();
|
||||
extern bool_t xdr_remote_secret_undefine_args ();
|
||||
extern bool_t xdr_remote_secret_lookup_by_usage_args ();
|
||||
extern bool_t xdr_remote_secret_lookup_by_usage_ret ();
|
||||
extern bool_t xdr_remote_procedure ();
|
||||
extern bool_t xdr_remote_message_type ();
|
||||
extern bool_t xdr_remote_message_status ();
|
||||
|
@ -189,6 +189,8 @@ struct remote_nonnull_node_device {
|
||||
/* A secret which may not be null. */
|
||||
struct remote_nonnull_secret {
|
||||
remote_uuid uuid;
|
||||
int usageType;
|
||||
remote_nonnull_string usageID;
|
||||
};
|
||||
|
||||
/* A domain or network which may be NULL. */
|
||||
@ -1338,6 +1340,15 @@ struct remote_secret_undefine_args {
|
||||
remote_nonnull_secret secret;
|
||||
};
|
||||
|
||||
struct remote_secret_lookup_by_usage_args {
|
||||
int usageType;
|
||||
remote_nonnull_string usageID;
|
||||
};
|
||||
|
||||
struct remote_secret_lookup_by_usage_ret {
|
||||
remote_nonnull_secret secret;
|
||||
};
|
||||
|
||||
/*----- Protocol. -----*/
|
||||
|
||||
/* Define the program number, protocol version and procedure numbers here. */
|
||||
@ -1505,7 +1516,8 @@ enum remote_procedure {
|
||||
REMOTE_PROC_SECRET_GET_XML_DESC = 143,
|
||||
REMOTE_PROC_SECRET_SET_VALUE = 144,
|
||||
REMOTE_PROC_SECRET_GET_VALUE = 145,
|
||||
REMOTE_PROC_SECRET_UNDEFINE = 146
|
||||
REMOTE_PROC_SECRET_UNDEFINE = 146,
|
||||
REMOTE_PROC_SECRET_LOOKUP_BY_USAGE = 147
|
||||
};
|
||||
|
||||
|
||||
|
@ -1170,12 +1170,13 @@ virUnrefNodeDevice(virNodeDevicePtr dev) {
|
||||
* Returns a pointer to the secret, or NULL in case of failure
|
||||
*/
|
||||
virSecretPtr
|
||||
virGetSecret(virConnectPtr conn, const unsigned char *uuid)
|
||||
virGetSecret(virConnectPtr conn, const unsigned char *uuid,
|
||||
int usageType, const char *usageID)
|
||||
{
|
||||
virSecretPtr ret = NULL;
|
||||
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
||||
|
||||
if (!VIR_IS_CONNECT(conn) || uuid == NULL) {
|
||||
if (!VIR_IS_CONNECT(conn) || uuid == NULL || usageID == NULL) {
|
||||
virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
@ -1193,7 +1194,12 @@ virGetSecret(virConnectPtr conn, const unsigned char *uuid)
|
||||
ret->magic = VIR_SECRET_MAGIC;
|
||||
ret->conn = conn;
|
||||
memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN);
|
||||
|
||||
ret->usageType = usageType;
|
||||
if (!(ret->usageID = strdup(usageID))) {
|
||||
virMutexUnlock(&conn->lock);
|
||||
virReportOOMError(conn);
|
||||
goto error;
|
||||
}
|
||||
if (virHashAddEntry(conn->secrets, uuidstr, ret) < 0) {
|
||||
virMutexUnlock(&conn->lock);
|
||||
virLibConnError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||
@ -1208,6 +1214,7 @@ virGetSecret(virConnectPtr conn, const unsigned char *uuid)
|
||||
|
||||
error:
|
||||
if (ret != NULL) {
|
||||
VIR_FREE(ret->usageID);
|
||||
VIR_FREE(ret->uuid);
|
||||
VIR_FREE(ret);
|
||||
}
|
||||
@ -1239,6 +1246,7 @@ virReleaseSecret(virSecretPtr secret) {
|
||||
conn = NULL;
|
||||
}
|
||||
|
||||
VIR_FREE(secret->usageID);
|
||||
secret->magic = -1;
|
||||
VIR_FREE(secret);
|
||||
|
||||
|
@ -256,6 +256,8 @@ struct _virSecret {
|
||||
int refs; /* reference count */
|
||||
virConnectPtr conn; /* pointer back to the connection */
|
||||
unsigned char uuid[VIR_UUID_BUFLEN]; /* the domain unique identifier */
|
||||
int usageType; /* the type of usage */
|
||||
char *usageID; /* the usage's unique identifier */
|
||||
};
|
||||
|
||||
|
||||
@ -296,7 +298,9 @@ virNodeDevicePtr virGetNodeDevice(virConnectPtr conn,
|
||||
int virUnrefNodeDevice(virNodeDevicePtr dev);
|
||||
|
||||
virSecretPtr virGetSecret(virConnectPtr conn,
|
||||
const unsigned char *uuid);
|
||||
const unsigned char *uuid,
|
||||
int usageType,
|
||||
const char *usageID);
|
||||
int virUnrefSecret(virSecretPtr secret);
|
||||
|
||||
#endif
|
||||
|
@ -821,6 +821,10 @@ verify((VIR_SECRET_GET_VALUE_INTERNAL_CALL &
|
||||
typedef virSecretPtr
|
||||
(*virDrvSecretLookupByUUID) (virConnectPtr conn,
|
||||
const unsigned char *uuid);
|
||||
typedef virSecretPtr
|
||||
(*virDrvSecretLookupByUsage) (virConnectPtr conn,
|
||||
int usageType,
|
||||
const char *usageID);
|
||||
typedef virSecretPtr
|
||||
(*virDrvSecretDefineXML) (virConnectPtr conn,
|
||||
const char *xml,
|
||||
@ -867,6 +871,7 @@ struct _virSecretDriver {
|
||||
virDrvSecretNumOfSecrets numOfSecrets;
|
||||
virDrvSecretListSecrets listSecrets;
|
||||
virDrvSecretLookupByUUID lookupByUUID;
|
||||
virDrvSecretLookupByUsage lookupByUsage;
|
||||
virDrvSecretDefineXML defineXML;
|
||||
virDrvSecretGetXMLDesc getXMLDesc;
|
||||
virDrvSecretSetValue setValue;
|
||||
|
106
src/libvirt.c
106
src/libvirt.c
@ -8914,6 +8914,55 @@ error:
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* virSecretLookupByUsage:
|
||||
* @conn: pointer to the hypervisor connection
|
||||
* @usageType: the type of secret usage
|
||||
* @usageID: identifier of the object using the secret
|
||||
*
|
||||
* Try to lookup a secret on the given hypervisor based on its usage
|
||||
* The usageID is unique within the set of secrets sharing the
|
||||
* same usageType value.
|
||||
*
|
||||
* Returns a new secret object or NULL in case of failure. If the
|
||||
* secret cannot be found, then VIR_ERR_NO_SECRET error is raised.
|
||||
*/
|
||||
virSecretPtr
|
||||
virSecretLookupByUsage(virConnectPtr conn,
|
||||
int usageType,
|
||||
const char *usageID)
|
||||
{
|
||||
DEBUG("conn=%p, usageType=%d usageID=%s", conn, usageType, NULLSTR(usageID));
|
||||
|
||||
virResetLastError();
|
||||
|
||||
if (!VIR_IS_CONNECT(conn)) {
|
||||
virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
|
||||
return (NULL);
|
||||
}
|
||||
if (usageID == NULL) {
|
||||
virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (conn->secretDriver &&
|
||||
conn->secretDriver->lookupByUsage) {
|
||||
virSecretPtr ret;
|
||||
ret = conn->secretDriver->lookupByUsage (conn, usageType, usageID);
|
||||
if (!ret)
|
||||
goto error;
|
||||
return ret;
|
||||
}
|
||||
|
||||
virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
|
||||
|
||||
error:
|
||||
/* Copy to connection error object for back compatability */
|
||||
virSetConnError(conn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* virSecretDefineXML:
|
||||
* @conn: virConnect connection
|
||||
@ -9038,6 +9087,63 @@ error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* virSecretGetUsageType:
|
||||
* @secret: a secret object
|
||||
*
|
||||
* Get the type of object which uses this secret. The returned
|
||||
* value is one of the constants defined in the virSecretUsageType
|
||||
* enumeration. More values may be added to this enumeration in
|
||||
* the future, so callers should expect to see usage types they
|
||||
* do not explicitly know about.
|
||||
*
|
||||
* Returns a positive integer identifying the type of object,
|
||||
* or -1 upon error.
|
||||
*/
|
||||
int
|
||||
virSecretGetUsageType(virSecretPtr secret)
|
||||
{
|
||||
DEBUG("secret=%p", secret);
|
||||
|
||||
virResetLastError();
|
||||
|
||||
if (!VIR_IS_SECRET(secret)) {
|
||||
virLibSecretError(NULL, VIR_ERR_INVALID_SECRET, __FUNCTION__);
|
||||
return (-1);
|
||||
}
|
||||
return (secret->usageType);
|
||||
}
|
||||
|
||||
/**
|
||||
* virSecretGetUsageID:
|
||||
* @secret: a secret object
|
||||
*
|
||||
* Get the unique identifier of the object with which this
|
||||
* secret is to be used. The format of the identifier is
|
||||
* dependant on the usage type of the secret. For a secret
|
||||
* with a usage type of VIR_SECRET_USAGE_TYPE_VOLUME the
|
||||
* identifier will be a fully qualfied path name. The
|
||||
* identifiers are intended to be unique within the set of
|
||||
* all secrets sharing the same usage type. ie, there shall
|
||||
* only ever be one secret for each volume path.
|
||||
*
|
||||
* Returns a string identifying the object using the secret,
|
||||
* or NULL upon error
|
||||
*/
|
||||
const char *
|
||||
virSecretGetUsageID(virSecretPtr secret)
|
||||
{
|
||||
DEBUG("secret=%p", secret);
|
||||
|
||||
virResetLastError();
|
||||
|
||||
if (!VIR_IS_SECRET(secret)) {
|
||||
virLibSecretError(NULL, VIR_ERR_INVALID_SECRET, __FUNCTION__);
|
||||
return (NULL);
|
||||
}
|
||||
return (secret->usageID);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* virSecretGetXMLDesc:
|
||||
|
@ -300,9 +300,12 @@ LIBVIRT_0.7.1 {
|
||||
virConnectListSecrets;
|
||||
virSecretLookupByUUID;
|
||||
virSecretLookupByUUIDString;
|
||||
virSecretLookupByUsage;
|
||||
virSecretDefineXML;
|
||||
virSecretGetUUID;
|
||||
virSecretGetUUIDString;
|
||||
virSecretGetUsageType;
|
||||
virSecretGetUsageID;
|
||||
virSecretGetXMLDesc;
|
||||
virSecretSetValue;
|
||||
virSecretGetValue;
|
||||
|
@ -6501,6 +6501,34 @@ done:
|
||||
return rv;
|
||||
}
|
||||
|
||||
static virSecretPtr
|
||||
remoteSecretLookupByUsage (virConnectPtr conn, int usageType, const char *usageID)
|
||||
{
|
||||
virSecretPtr rv = NULL;
|
||||
remote_secret_lookup_by_usage_args args;
|
||||
remote_secret_lookup_by_usage_ret ret;
|
||||
struct private_data *priv = conn->secretPrivateData;
|
||||
|
||||
remoteDriverLock (priv);
|
||||
|
||||
args.usageType = usageType;
|
||||
args.usageID = (char *)usageID;
|
||||
|
||||
memset (&ret, 0, sizeof (ret));
|
||||
if (call (conn, priv, 0, REMOTE_PROC_SECRET_LOOKUP_BY_USAGE,
|
||||
(xdrproc_t) xdr_remote_secret_lookup_by_usage_args, (char *) &args,
|
||||
(xdrproc_t) xdr_remote_secret_lookup_by_usage_ret, (char *) &ret) == -1)
|
||||
goto done;
|
||||
|
||||
rv = get_nonnull_secret (conn, ret.secret);
|
||||
xdr_free ((xdrproc_t) xdr_remote_secret_lookup_by_usage_ret,
|
||||
(char *) &ret);
|
||||
|
||||
done:
|
||||
remoteDriverUnlock (priv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static virSecretPtr
|
||||
remoteSecretDefineXML (virConnectPtr conn, const char *xml, unsigned int flags)
|
||||
{
|
||||
@ -7733,7 +7761,7 @@ get_nonnull_node_device (virConnectPtr conn, remote_nonnull_node_device dev)
|
||||
static virSecretPtr
|
||||
get_nonnull_secret (virConnectPtr conn, remote_nonnull_secret secret)
|
||||
{
|
||||
return virGetSecret(conn, BAD_CAST secret.uuid);
|
||||
return virGetSecret(conn, BAD_CAST secret.uuid, secret.usageType, secret.usageID);
|
||||
}
|
||||
|
||||
/* Make remote_nonnull_domain and remote_nonnull_network. */
|
||||
@ -7779,6 +7807,8 @@ static void
|
||||
make_nonnull_secret (remote_nonnull_secret *secret_dst, virSecretPtr secret_src)
|
||||
{
|
||||
memcpy (secret_dst->uuid, secret_src->uuid, VIR_UUID_BUFLEN);
|
||||
secret_dst->usageType = secret_src->usageType;
|
||||
secret_dst->usageID = secret_src->usageID;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
@ -7941,6 +7971,7 @@ static virSecretDriver secret_driver = {
|
||||
.numOfSecrets = remoteSecretNumOfSecrets,
|
||||
.listSecrets = remoteSecretListSecrets,
|
||||
.lookupByUUID = remoteSecretLookupByUUID,
|
||||
.lookupByUsage = remoteSecretLookupByUsage,
|
||||
.defineXML = remoteSecretDefineXML,
|
||||
.getXMLDesc = remoteSecretGetXMLDesc,
|
||||
.setValue = remoteSecretSetValue,
|
||||
|
@ -35,7 +35,7 @@
|
||||
|
||||
#define VIR_FROM_THIS VIR_FROM_SECRET
|
||||
|
||||
VIR_ENUM_IMPL(virSecretUsageType, VIR_SECRET_USAGE_TYPE_LAST, "none", "volume")
|
||||
VIR_ENUM_IMPL(virSecretUsageType, VIR_SECRET_USAGE_TYPE_VOLUME + 1, "none", "volume")
|
||||
|
||||
void
|
||||
virSecretDefFree(virSecretDefPtr def)
|
||||
@ -88,6 +88,11 @@ virSecretDefParseUsage(virConnectPtr conn, xmlXPathContextPtr ctxt,
|
||||
case VIR_SECRET_USAGE_TYPE_VOLUME:
|
||||
def->usage.volume = virXPathString(conn, "string(./usage/volume)",
|
||||
ctxt);
|
||||
if (!def->usage.volume) {
|
||||
virSecretReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("volume usage specified, but volume path is missing"));
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -30,12 +30,6 @@
|
||||
virReportErrorHelper(conn, VIR_FROM_SECRET, code, __FILE__, \
|
||||
__FUNCTION__, __LINE__, fmt)
|
||||
|
||||
enum virSecretUsageType {
|
||||
VIR_SECRET_USAGE_TYPE_NONE = 0, /* default when zero-initialized */
|
||||
VIR_SECRET_USAGE_TYPE_VOLUME,
|
||||
|
||||
VIR_SECRET_USAGE_TYPE_LAST
|
||||
};
|
||||
VIR_ENUM_DECL(virSecretUsageType)
|
||||
|
||||
typedef struct _virSecretDef virSecretDef;
|
||||
|
@ -110,57 +110,45 @@ secretFree(virSecretEntryPtr secret)
|
||||
VIR_FREE(secret);
|
||||
}
|
||||
|
||||
static virSecretEntryPtr *
|
||||
secretFind(virSecretDriverStatePtr driver, const unsigned char *uuid)
|
||||
static virSecretEntryPtr
|
||||
secretFindByUUID(virSecretDriverStatePtr driver, const unsigned char *uuid)
|
||||
{
|
||||
virSecretEntryPtr *pptr, s;
|
||||
|
||||
for (pptr = &driver->secrets; *pptr != NULL; pptr = &s->next) {
|
||||
s = *pptr;
|
||||
if (memcmp(s->def->uuid, uuid, VIR_UUID_BUFLEN) == 0)
|
||||
return pptr;
|
||||
return s;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static virSecretEntryPtr
|
||||
secretCreate(virConnectPtr conn, virSecretDriverStatePtr driver,
|
||||
const unsigned char *uuid)
|
||||
secretFindByUsage(virSecretDriverStatePtr driver, int usageType, const char *usageID)
|
||||
{
|
||||
virSecretEntryPtr secret = NULL;
|
||||
virSecretEntryPtr *pptr, s;
|
||||
|
||||
if (VIR_ALLOC(secret) < 0 || VIR_ALLOC(secret->def))
|
||||
goto no_memory;
|
||||
memcpy(secret->def->uuid, uuid, VIR_UUID_BUFLEN);
|
||||
listInsert(&driver->secrets, secret);
|
||||
return secret;
|
||||
for (pptr = &driver->secrets; *pptr != NULL; pptr = &s->next) {
|
||||
s = *pptr;
|
||||
|
||||
no_memory:
|
||||
virReportOOMError(conn);
|
||||
secretFree(secret);
|
||||
if (s->def->usage_type != usageType)
|
||||
continue;
|
||||
|
||||
switch (usageType) {
|
||||
case VIR_SECRET_USAGE_TYPE_NONE:
|
||||
/* never match this */
|
||||
break;
|
||||
|
||||
case VIR_SECRET_USAGE_TYPE_VOLUME:
|
||||
if (STREQ(s->def->usage.volume, usageID))
|
||||
return s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static virSecretEntryPtr
|
||||
secretFindOrCreate(virConnectPtr conn, virSecretDriverStatePtr driver,
|
||||
const unsigned char *uuid, bool *created_new)
|
||||
{
|
||||
virSecretEntryPtr *pptr, secret;
|
||||
|
||||
pptr = secretFind(driver, uuid);
|
||||
if (pptr != NULL) {
|
||||
if (created_new != NULL)
|
||||
*created_new = false;
|
||||
return *pptr;
|
||||
}
|
||||
|
||||
secret = secretCreate(conn, driver, uuid);
|
||||
if (secret != NULL && created_new != NULL)
|
||||
*created_new = true;
|
||||
return secret;
|
||||
}
|
||||
|
||||
/* Permament secret storage */
|
||||
/* Permament secret storage */
|
||||
|
||||
/* Secrets are stored in virSecretDriverStatePtr->directory. Each secret
|
||||
has virSecretDef stored as XML in "$basename.xml". If a value of the
|
||||
@ -609,17 +597,33 @@ cleanup:
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static const char *
|
||||
secretUsageIDForDef(virSecretDefPtr def)
|
||||
{
|
||||
switch (def->usage_type) {
|
||||
case VIR_SECRET_USAGE_TYPE_NONE:
|
||||
return "";
|
||||
|
||||
case VIR_SECRET_USAGE_TYPE_VOLUME:
|
||||
return def->usage.volume;
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static virSecretPtr
|
||||
secretLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
|
||||
{
|
||||
virSecretDriverStatePtr driver = conn->secretPrivateData;
|
||||
virSecretPtr ret = NULL;
|
||||
virSecretEntryPtr *pptr;
|
||||
virSecretEntryPtr secret;
|
||||
|
||||
secretDriverLock(driver);
|
||||
|
||||
pptr = secretFind(driver, uuid);
|
||||
if (pptr == NULL) {
|
||||
secret = secretFindByUUID(driver, uuid);
|
||||
if (secret == NULL) {
|
||||
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
||||
virUUIDFormat(uuid, uuidstr);
|
||||
virSecretReportError(conn, VIR_ERR_NO_SECRET,
|
||||
@ -627,7 +631,37 @@ secretLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = virGetSecret(conn, (*pptr)->def->uuid);
|
||||
ret = virGetSecret(conn,
|
||||
secret->def->uuid,
|
||||
secret->def->usage_type,
|
||||
secretUsageIDForDef(secret->def));
|
||||
|
||||
cleanup:
|
||||
secretDriverUnlock(driver);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static virSecretPtr
|
||||
secretLookupByUsage(virConnectPtr conn, int usageType, const char *usageID)
|
||||
{
|
||||
virSecretDriverStatePtr driver = conn->secretPrivateData;
|
||||
virSecretPtr ret = NULL;
|
||||
virSecretEntryPtr secret;
|
||||
|
||||
secretDriverLock(driver);
|
||||
|
||||
secret = secretFindByUsage(driver, usageType, usageID);
|
||||
if (secret == NULL) {
|
||||
virSecretReportError(conn, VIR_ERR_NO_SECRET,
|
||||
_("no secret with matching usage '%s'"), usageID);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = virGetSecret(conn,
|
||||
secret->def->uuid,
|
||||
secret->def->usage_type,
|
||||
secretUsageIDForDef(secret->def));
|
||||
|
||||
cleanup:
|
||||
secretDriverUnlock(driver);
|
||||
@ -642,8 +676,8 @@ secretDefineXML(virConnectPtr conn, const char *xml,
|
||||
virSecretDriverStatePtr driver = conn->secretPrivateData;
|
||||
virSecretPtr ret = NULL;
|
||||
virSecretEntryPtr secret;
|
||||
virSecretDefPtr backup, new_attrs;
|
||||
bool secret_is_new;
|
||||
virSecretDefPtr backup = NULL;
|
||||
virSecretDefPtr new_attrs;
|
||||
|
||||
new_attrs = virSecretDefParseString(conn, xml);
|
||||
if (new_attrs == NULL)
|
||||
@ -651,28 +685,58 @@ secretDefineXML(virConnectPtr conn, const char *xml,
|
||||
|
||||
secretDriverLock(driver);
|
||||
|
||||
secret = secretFindOrCreate(conn, driver, new_attrs->uuid,
|
||||
&secret_is_new);
|
||||
if (secret == NULL)
|
||||
goto cleanup;
|
||||
secret = secretFindByUUID(driver, new_attrs->uuid);
|
||||
if (secret == NULL) {
|
||||
/* No existing secret with same UUID, try look for matching usage instead */
|
||||
const char *usageID = secretUsageIDForDef(new_attrs);
|
||||
secret = secretFindByUsage(driver, new_attrs->usage_type, usageID);
|
||||
if (secret) {
|
||||
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
||||
virUUIDFormat(secret->def->uuid, uuidstr);
|
||||
virSecretReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||
_("a secret with UUID %s already defined for use with %s"),
|
||||
uuidstr, usageID);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Save old values of the attributes */
|
||||
backup = secret->def;
|
||||
/* No existing secret at all, create one */
|
||||
if (VIR_ALLOC(secret) < 0) {
|
||||
virReportOOMError(conn);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (backup->private && !new_attrs->private) {
|
||||
virSecretReportError(conn, VIR_ERR_OPERATION_DENIED, "%s",
|
||||
virErrorMsg(VIR_ERR_OPERATION_DENIED, NULL));
|
||||
goto cleanup;
|
||||
listInsert(&driver->secrets, secret);
|
||||
secret->def = new_attrs;
|
||||
} else {
|
||||
const char *newUsageID = secretUsageIDForDef(new_attrs);
|
||||
const char *oldUsageID = secretUsageIDForDef(secret->def);
|
||||
if (STRNEQ(oldUsageID, newUsageID)) {
|
||||
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
||||
virUUIDFormat(secret->def->uuid, uuidstr);
|
||||
virSecretReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||
_("a secret with UUID %s is already defined for use with %s"),
|
||||
uuidstr, oldUsageID);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (secret->def->private && !new_attrs->private) {
|
||||
virSecretReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("cannot change private flag on existing secret"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Got an existing secret matches attrs, so reuse that */
|
||||
backup = secret->def;
|
||||
secret->def = new_attrs;
|
||||
}
|
||||
|
||||
secret->def = new_attrs;
|
||||
if (!new_attrs->ephemeral) {
|
||||
if (backup->ephemeral) {
|
||||
if (backup && backup->ephemeral) {
|
||||
if (secretSaveValue(conn, driver, secret) < 0)
|
||||
goto restore_backup;
|
||||
}
|
||||
if (secretSaveDef(conn, driver, secret) < 0) {
|
||||
if (backup->ephemeral) {
|
||||
if (backup && backup->ephemeral) {
|
||||
char *filename;
|
||||
|
||||
/* Undo the secretSaveValue() above; ignore errors */
|
||||
@ -683,7 +747,7 @@ secretDefineXML(virConnectPtr conn, const char *xml,
|
||||
}
|
||||
goto restore_backup;
|
||||
}
|
||||
} else if (!backup->ephemeral) {
|
||||
} else if (backup && !backup->ephemeral) {
|
||||
if (secretDeleteSaved(conn, driver, secret) < 0)
|
||||
goto restore_backup;
|
||||
}
|
||||
@ -691,13 +755,17 @@ secretDefineXML(virConnectPtr conn, const char *xml,
|
||||
new_attrs = NULL;
|
||||
virSecretDefFree(backup);
|
||||
|
||||
ret = virGetSecret(conn, secret->def->uuid);
|
||||
ret = virGetSecret(conn,
|
||||
secret->def->uuid,
|
||||
secret->def->usage_type,
|
||||
secretUsageIDForDef(secret->def));
|
||||
goto cleanup;
|
||||
|
||||
restore_backup:
|
||||
/* Error - restore previous state and free new attributes */
|
||||
secret->def = backup;
|
||||
if (secret_is_new) {
|
||||
if (backup) {
|
||||
/* Error - restore previous state and free new attributes */
|
||||
secret->def = backup;
|
||||
} else {
|
||||
/* "secret" was added to the head of the list above */
|
||||
if (listUnlink(&driverState->secrets) != secret)
|
||||
virSecretReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
@ -718,12 +786,12 @@ secretGetXMLDesc(virSecretPtr obj, unsigned int flags ATTRIBUTE_UNUSED)
|
||||
{
|
||||
virSecretDriverStatePtr driver = obj->conn->secretPrivateData;
|
||||
char *ret = NULL;
|
||||
virSecretEntryPtr *pptr;
|
||||
virSecretEntryPtr secret;
|
||||
|
||||
secretDriverLock(driver);
|
||||
|
||||
pptr = secretFind(driver, obj->uuid);
|
||||
if (pptr == NULL) {
|
||||
secret = secretFindByUUID(driver, obj->uuid);
|
||||
if (secret == NULL) {
|
||||
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
||||
virUUIDFormat(obj->uuid, uuidstr);
|
||||
virSecretReportError(obj->conn, VIR_ERR_NO_SECRET,
|
||||
@ -731,7 +799,7 @@ secretGetXMLDesc(virSecretPtr obj, unsigned int flags ATTRIBUTE_UNUSED)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = virSecretDefFormat(obj->conn, (*pptr)->def);
|
||||
ret = virSecretDefFormat(obj->conn, secret->def);
|
||||
|
||||
cleanup:
|
||||
secretDriverUnlock(driver);
|
||||
@ -747,7 +815,7 @@ secretSetValue(virSecretPtr obj, const unsigned char *value,
|
||||
int ret = -1;
|
||||
unsigned char *old_value, *new_value;
|
||||
size_t old_value_size;
|
||||
virSecretEntryPtr secret, *pptr;
|
||||
virSecretEntryPtr secret;
|
||||
|
||||
if (VIR_ALLOC_N(new_value, value_size) < 0) {
|
||||
virReportOOMError(obj->conn);
|
||||
@ -756,15 +824,14 @@ secretSetValue(virSecretPtr obj, const unsigned char *value,
|
||||
|
||||
secretDriverLock(driver);
|
||||
|
||||
pptr = secretFind(driver, obj->uuid);
|
||||
if (pptr == NULL) {
|
||||
secret = secretFindByUUID(driver, obj->uuid);
|
||||
if (secret == NULL) {
|
||||
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
||||
virUUIDFormat(obj->uuid, uuidstr);
|
||||
virSecretReportError(obj->conn, VIR_ERR_NO_SECRET,
|
||||
_("no secret with matching uuid '%s'"), uuidstr);
|
||||
goto cleanup;
|
||||
}
|
||||
secret = *pptr;
|
||||
|
||||
old_value = secret->value;
|
||||
old_value_size = secret->value_size;
|
||||
@ -805,19 +872,19 @@ secretGetValue(virSecretPtr obj, size_t *value_size, unsigned int flags)
|
||||
{
|
||||
virSecretDriverStatePtr driver = obj->conn->secretPrivateData;
|
||||
unsigned char *ret = NULL;
|
||||
virSecretEntryPtr *pptr, secret;
|
||||
virSecretEntryPtr secret;
|
||||
|
||||
secretDriverLock(driver);
|
||||
|
||||
pptr = secretFind(driver, obj->uuid);
|
||||
if (pptr == NULL) {
|
||||
secret = secretFindByUUID(driver, obj->uuid);
|
||||
if (secret == NULL) {
|
||||
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
||||
virUUIDFormat(obj->uuid, uuidstr);
|
||||
virSecretReportError(obj->conn, VIR_ERR_NO_SECRET,
|
||||
_("no secret with matching uuid '%s'"), uuidstr);
|
||||
goto cleanup;
|
||||
}
|
||||
secret = *pptr;
|
||||
|
||||
if (secret->value == NULL) {
|
||||
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
||||
virUUIDFormat(obj->uuid, uuidstr);
|
||||
@ -851,12 +918,12 @@ secretUndefine(virSecretPtr obj)
|
||||
{
|
||||
virSecretDriverStatePtr driver = obj->conn->secretPrivateData;
|
||||
int ret = -1;
|
||||
virSecretEntryPtr *pptr, secret;
|
||||
virSecretEntryPtr secret;
|
||||
|
||||
secretDriverLock(driver);
|
||||
|
||||
pptr = secretFind(driver, obj->uuid);
|
||||
if (pptr == NULL) {
|
||||
secret = secretFindByUUID(driver, obj->uuid);
|
||||
if (secret == NULL) {
|
||||
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
||||
virUUIDFormat(obj->uuid, uuidstr);
|
||||
virSecretReportError(obj->conn, VIR_ERR_NO_SECRET,
|
||||
@ -864,19 +931,22 @@ secretUndefine(virSecretPtr obj)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
secret = listUnlink(pptr);
|
||||
if (!secret->def->ephemeral) {
|
||||
if (secretDeleteSaved(obj->conn, driver, secret) < 0)
|
||||
goto restore_backup;
|
||||
if (!secret->def->ephemeral &&
|
||||
secretDeleteSaved(obj->conn, driver, secret) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (driver->secrets == secret) {
|
||||
driver->secrets = secret->next;
|
||||
} else {
|
||||
virSecretEntryPtr tmp = driver->secrets;
|
||||
while (tmp && tmp->next != secret)
|
||||
tmp = tmp->next;
|
||||
if (tmp)
|
||||
tmp->next = secret->next;
|
||||
}
|
||||
secretFree(secret);
|
||||
|
||||
ret = 0;
|
||||
goto cleanup;
|
||||
|
||||
restore_backup:
|
||||
/* This may change the order of secrets in the list. We don't care. */
|
||||
listInsert(&driver->secrets, secret);
|
||||
|
||||
cleanup:
|
||||
secretDriverUnlock(driver);
|
||||
@ -995,6 +1065,7 @@ static virSecretDriver secretDriver = {
|
||||
.numOfSecrets = secretNumOfSecrets,
|
||||
.listSecrets = secretListSecrets,
|
||||
.lookupByUUID = secretLookupByUUID,
|
||||
.lookupByUsage = secretLookupByUsage,
|
||||
.defineXML = secretDefineXML,
|
||||
.getXMLDesc = secretGetXMLDesc,
|
||||
.setValue = secretSetValue,
|
||||
|
28
src/virsh.c
28
src/virsh.c
@ -5527,11 +5527,33 @@ cmdSecretList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
|
||||
|
||||
qsort(uuids, maxuuids, sizeof(char *), namesorter);
|
||||
|
||||
vshPrintExtra(ctl, "%s\n", _("UUID"));
|
||||
vshPrintExtra(ctl, "-----------------------------------------\n");
|
||||
vshPrintExtra(ctl, "%-36s %s\n", _("UUID"), _("Usage"));
|
||||
vshPrintExtra(ctl, "-----------------------------------------------------------\n");
|
||||
|
||||
for (i = 0; i < maxuuids; i++) {
|
||||
vshPrint(ctl, "%-36s\n", uuids[i]);
|
||||
virSecretPtr sec = virSecretLookupByUUIDString(ctl->conn, uuids[i]);
|
||||
const char *usageType = NULL;
|
||||
|
||||
if (!sec) {
|
||||
free(uuids[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (virSecretGetUsageType(sec)) {
|
||||
case VIR_SECRET_USAGE_TYPE_VOLUME:
|
||||
usageType = _("Volume");
|
||||
break;
|
||||
}
|
||||
|
||||
if (usageType) {
|
||||
vshPrint(ctl, "%-36s %s %s\n",
|
||||
uuids[i], usageType,
|
||||
virSecretGetUsageID(sec));
|
||||
} else {
|
||||
vshPrint(ctl, "%-36s %s\n",
|
||||
uuids[i], _("Unused"));
|
||||
}
|
||||
virSecretFree(sec);
|
||||
free(uuids[i]);
|
||||
}
|
||||
free(uuids);
|
||||
|
Loading…
Reference in New Issue
Block a user