aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel P. Berrange <berrange@redhat.com>2009-09-11 14:06:15 +0100
committerDaniel P. Berrange <berrange@redhat.com>2009-09-14 17:49:33 +0100
commita2a30038cfd6157622d8013a6023e3e8afd337d4 (patch)
treedfcab597b712b08ba584f1acb851aeb004068d00
parentFix UUID handling in secrets/storage encryption APIs (diff)
downloadlibvirt-a2a30038cfd6157622d8013a6023e3e8afd337d4.tar.gz
libvirt-a2a30038cfd6157622d8013a6023e3e8afd337d4.tar.bz2
libvirt-a2a30038cfd6157622d8013a6023e3e8afd337d4.zip
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
-rw-r--r--include/libvirt/libvirt.h11
-rw-r--r--include/libvirt/libvirt.h.in11
-rwxr-xr-xpython/generator.py2
-rw-r--r--qemud/remote.c24
-rw-r--r--qemud/remote_dispatch_args.h1
-rw-r--r--qemud/remote_dispatch_prototypes.h7
-rw-r--r--qemud/remote_dispatch_ret.h1
-rw-r--r--qemud/remote_dispatch_table.h5
-rw-r--r--qemud/remote_protocol.c24
-rw-r--r--qemud/remote_protocol.h18
-rw-r--r--qemud/remote_protocol.x14
-rw-r--r--src/datatypes.c14
-rw-r--r--src/datatypes.h6
-rw-r--r--src/driver.h5
-rw-r--r--src/libvirt.c106
-rw-r--r--src/libvirt_public.syms3
-rw-r--r--src/remote_internal.c33
-rw-r--r--src/secret_conf.c7
-rw-r--r--src/secret_conf.h6
-rw-r--r--src/secret_driver.c231
-rw-r--r--src/virsh.c28
21 files changed, 460 insertions, 97 deletions
diff --git a/include/libvirt/libvirt.h b/include/libvirt/libvirt.h
index eadf420d5..552760028 100644
--- a/include/libvirt/libvirt.h
+++ b/include/libvirt/libvirt.h
@@ -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,
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index 1391af819..6028d5fa9 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -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,
diff --git a/python/generator.py b/python/generator.py
index c25ff551c..ad9c54423 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -669,6 +669,8 @@ functions_noexcept = {
'virStorageVolGetkey': True,
'virNodeDeviceGetName': True,
'virNodeDeviceGetParent': True,
+ 'virSecretGetUsageType': True,
+ 'virSecretGetUsageID': True,
}
reference_keepers = {
diff --git a/qemud/remote.c b/qemud/remote.c
index a9fcc58d4..17426cd08 100644
--- a/qemud/remote.c
+++ b/qemud/remote.c
@@ -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);
}
diff --git a/qemud/remote_dispatch_args.h b/qemud/remote_dispatch_args.h
index 9f3796324..95f668ad0 100644
--- a/qemud/remote_dispatch_args.h
+++ b/qemud/remote_dispatch_args.h
@@ -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;
diff --git a/qemud/remote_dispatch_prototypes.h b/qemud/remote_dispatch_prototypes.h
index 7773cd924..060554201 100644
--- a/qemud/remote_dispatch_prototypes.h
+++ b/qemud/remote_dispatch_prototypes.h
@@ -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,
diff --git a/qemud/remote_dispatch_ret.h b/qemud/remote_dispatch_ret.h
index 15d33861e..6ced13a2e 100644
--- a/qemud/remote_dispatch_ret.h
+++ b/qemud/remote_dispatch_ret.h
@@ -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;
diff --git a/qemud/remote_dispatch_table.h b/qemud/remote_dispatch_table.h
index 07e36bb27..6b5df8065 100644
--- a/qemud/remote_dispatch_table.h
+++ b/qemud/remote_dispatch_table.h
@@ -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,
+},
diff --git a/qemud/remote_protocol.c b/qemud/remote_protocol.c
index b6666a119..1d2d24214 100644
--- a/qemud/remote_protocol.c
+++ b/qemud/remote_protocol.c
@@ -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;
}
@@ -2674,6 +2678,26 @@ xdr_remote_secret_undefine_args (XDR *xdrs, remote_secret_undefine_args *objp)
}
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)
{
diff --git a/qemud/remote_protocol.h b/qemud/remote_protocol.h
index 4b73ee160..ceaf82c90 100644
--- a/qemud/remote_protocol.h
+++ b/qemud/remote_protocol.h
@@ -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 ();
diff --git a/qemud/remote_protocol.x b/qemud/remote_protocol.x
index 5712d984a..29abdb7df 100644
--- a/qemud/remote_protocol.x
+++ b/qemud/remote_protocol.x
@@ -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
};
diff --git a/src/datatypes.c b/src/datatypes.c
index b0067f636..d7cf2ee51 100644
--- a/src/datatypes.c
+++ b/src/datatypes.c
@@ -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);
diff --git a/src/datatypes.h b/src/datatypes.h
index 531930880..a33c365a6 100644
--- a/src/datatypes.h
+++ b/src/datatypes.h
@@ -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
diff --git a/src/driver.h b/src/driver.h
index 9f197d9cc..d4f972f3e 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -822,6 +822,10 @@ 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,
unsigned int flags);
@@ -867,6 +871,7 @@ struct _virSecretDriver {
virDrvSecretNumOfSecrets numOfSecrets;
virDrvSecretListSecrets listSecrets;
virDrvSecretLookupByUUID lookupByUUID;
+ virDrvSecretLookupByUsage lookupByUsage;
virDrvSecretDefineXML defineXML;
virDrvSecretGetXMLDesc getXMLDesc;
virDrvSecretSetValue setValue;
diff --git a/src/libvirt.c b/src/libvirt.c
index 4cb04cf5c..4a1168831 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -8915,6 +8915,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
* @xml: XML describing the secret.
@@ -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:
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index c34bbae9c..cf5be38e1 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -300,9 +300,12 @@ LIBVIRT_0.7.1 {
virConnectListSecrets;
virSecretLookupByUUID;
virSecretLookupByUUIDString;
+ virSecretLookupByUsage;
virSecretDefineXML;
virSecretGetUUID;
virSecretGetUUIDString;
+ virSecretGetUsageType;
+ virSecretGetUsageID;
virSecretGetXMLDesc;
virSecretSetValue;
virSecretGetValue;
diff --git a/src/remote_internal.c b/src/remote_internal.c
index e7f01863e..dd7b31e8a 100644
--- a/src/remote_internal.c
+++ b/src/remote_internal.c
@@ -6502,6 +6502,34 @@ done:
}
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)
{
virSecretPtr rv = NULL;
@@ -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,
diff --git a/src/secret_conf.c b/src/secret_conf.c
index 51ac13d45..21215b29b 100644
--- a/src/secret_conf.c
+++ b/src/secret_conf.c
@@ -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:
diff --git a/src/secret_conf.h b/src/secret_conf.h
index 556f5a4f1..1ecf419f3 100644
--- a/src/secret_conf.h
+++ b/src/secret_conf.h
@@ -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;
diff --git a/src/secret_driver.c b/src/secret_driver.c
index a581fce72..20a3fa865 100644
--- a/src/secret_driver.c
+++ b/src/secret_driver.c
@@ -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);
- return NULL;
-}
+ if (s->def->usage_type != usageType)
+ continue;
-static virSecretEntryPtr
-secretFindOrCreate(virConnectPtr conn, virSecretDriverStatePtr driver,
- const unsigned char *uuid, bool *created_new)
-{
- virSecretEntryPtr *pptr, secret;
+ switch (usageType) {
+ case VIR_SECRET_USAGE_TYPE_NONE:
+ /* never match this */
+ break;
- pptr = secretFind(driver, uuid);
- if (pptr != NULL) {
- if (created_new != NULL)
- *created_new = false;
- return *pptr;
+ case VIR_SECRET_USAGE_TYPE_VOLUME:
+ if (STREQ(s->def->usage.volume, usageID))
+ return s;
+ break;
+ }
}
-
- secret = secretCreate(conn, driver, uuid);
- if (secret != NULL && created_new != NULL)
- *created_new = true;
- return secret;
+ return NULL;
}
- /* 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,
diff --git a/src/virsh.c b/src/virsh.c
index 74147dab4..4825f1c91 100644
--- a/src/virsh.c
+++ b/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);