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:
Daniel P. Berrange 2009-09-11 14:06:15 +01:00
parent 47e7a258db
commit a2a30038cf
21 changed files with 462 additions and 99 deletions

View File

@ -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,

View File

@ -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,

View File

@ -669,6 +669,8 @@ functions_noexcept = {
'virStorageVolGetkey': True,
'virNodeDeviceGetName': True,
'virNodeDeviceGetParent': True,
'virSecretGetUsageType': True,
'virSecretGetUsageID': True,
}
reference_keepers = {

View File

@ -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);
}

View File

@ -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;

View File

@ -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,

View File

@ -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;

View File

@ -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,
},

View File

@ -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)
{

View File

@ -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 ();

View File

@ -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
};

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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:

View File

@ -300,9 +300,12 @@ LIBVIRT_0.7.1 {
virConnectListSecrets;
virSecretLookupByUUID;
virSecretLookupByUUIDString;
virSecretLookupByUsage;
virSecretDefineXML;
virSecretGetUUID;
virSecretGetUUIDString;
virSecretGetUsageType;
virSecretGetUsageID;
virSecretGetXMLDesc;
virSecretSetValue;
virSecretGetValue;

View File

@ -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,

View File

@ -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:

View File

@ -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;

View File

@ -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,

View File

@ -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);