[libvirt] [PATCH 2/4] Add usage type/id as a public API property of virSecret

Daniel P. Berrange berrange at redhat.com
Fri Sep 11 14:19:18 UTC 2009


* 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
---
 include/libvirt/libvirt.h          |   11 ++
 include/libvirt/libvirt.h.in       |   11 ++
 python/generator.py                |    2 +
 qemud/remote.c                     |   24 ++++-
 qemud/remote_dispatch_args.h       |    1 +
 qemud/remote_dispatch_prototypes.h |    7 +
 qemud/remote_dispatch_ret.h        |    1 +
 qemud/remote_dispatch_table.h      |    5 +
 qemud/remote_protocol.c            |   24 ++++
 qemud/remote_protocol.h            |   18 +++
 qemud/remote_protocol.x            |   14 ++-
 src/datatypes.c                    |   14 ++-
 src/datatypes.h                    |    6 +-
 src/driver.h                       |    5 +
 src/libvirt.c                      |   94 +++++++++++++++
 src/libvirt_public.syms            |    3 +
 src/remote_internal.c              |   33 +++++-
 src/secret_conf.c                  |    7 +-
 src/secret_conf.h                  |    6 -
 src/secret_driver.c                |  231 +++++++++++++++++++++++-------------
 src/virsh.c                        |   28 ++++-
 21 files changed, 448 insertions(+), 97 deletions(-)

diff --git a/include/libvirt/libvirt.h b/include/libvirt/libvirt.h
index eadf420..5527600 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 1391af8..6028d5f 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 c25ff55..ad9c544 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 a9fcc58..17426cd 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 9f37963..95f668a 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 7773cd9..0605542 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 15d3386..6ced13a 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 07e36bb..6b5df80 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 b6666a1..1d2d242 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 4b73ee1..ceaf82c 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 5712d98..29abdb7 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 b0067f6..d7cf2ee 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 5319308..a33c365 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 9f197d9..d4f972f 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 7a915fa..1563ce5 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -8913,6 +8913,53 @@ 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
+ *
+ * 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.
@@ -9036,6 +9083,53 @@ error:
     return -1;
 }
 
+/**
+ * virSecretGetUsageType:
+ * @secret: a secret object
+ *
+ * Get the type of object which uses this secret
+ *
+ * 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
+ *
+ * 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 c34bbae..cf5be38 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 e7f0186..eff268f 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_UUID,
+              (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 51ac13d..21215b2 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 556f5a4..1ecf419 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 c1e0c67..a60b1ca 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 "none";
+
+    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,10 @@ 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:
     if (1) {
@@ -641,14 +648,41 @@ cleanup:
 
 
 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);
+    return ret;
+}
+
+
+static virSecretPtr
 secretDefineXML(virConnectPtr conn, const char *xml,
                 unsigned int flags ATTRIBUTE_UNUSED)
 {
     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)
@@ -656,28 +690,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 */
@@ -688,7 +752,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;
     }
@@ -696,13 +760,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",
@@ -723,12 +791,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,
@@ -736,7 +804,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);
@@ -752,7 +820,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);
@@ -761,15 +829,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;
@@ -810,19 +877,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);
@@ -856,12 +923,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,
@@ -869,19 +936,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);
@@ -1000,6 +1070,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 74147da..4825f1c 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);
-- 
1.6.2.5




More information about the libvir-list mailing list