]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Add usage type/id as a public API property of virSecret
authorDaniel P. Berrange <berrange@redhat.com>
Fri, 11 Sep 2009 13:06:15 +0000 (14:06 +0100)
committerDaniel P. Berrange <berrange@redhat.com>
Mon, 14 Sep 2009 16:49:33 +0000 (17:49 +0100)
* 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

21 files changed:
include/libvirt/libvirt.h
include/libvirt/libvirt.h.in
python/generator.py
qemud/remote.c
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
qemud/remote_protocol.x
src/datatypes.c
src/datatypes.h
src/driver.h
src/libvirt.c
src/libvirt_public.syms
src/remote_internal.c
src/secret_conf.c
src/secret_conf.h
src/secret_driver.c
src/virsh.c

index eadf420d5455506d04cb1f7054da74804623387a..552760028fc3d59aef6f89d7b8fa8202423a0277 100644 (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,
index 1391af819e22ace42ee2715a76462cd6d4b4c271..6028d5fa9e5427ee86df44533d069c6756aa7f5a 100644 (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,
index c25ff551c5a606d818e693a6e33de2a482b8e2ea..ad9c54423b3a6b2958eea57dfc33f539869c8601 100755 (executable)
@@ -669,6 +669,8 @@ functions_noexcept = {
     'virStorageVolGetkey': True,
     'virNodeDeviceGetName': True,
     'virNodeDeviceGetParent': True,
+    'virSecretGetUsageType': True,
+    'virSecretGetUsageID': True,
 }
 
 reference_keepers = {
index a9fcc58d44f82b76d228b04a01dd37e532447b49..17426cd0840981781dbda6964af1ab8b7abbf6f7 100644 (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);
 }
index 9f3796324114f3f88287312c7c03785b75959eb4..95f668ad00c226aa84595f6a86bd32410aefab5c 100644 (file)
     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;
index 7773cd924c9a21489cfac8319f594c8e31aa647e..0605542015de81de52225c8fb0db329274b0df8f 100644 (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,
index 15d33861eaaf439e9f5314a823136ec6244dc38f..6ced13a2e8e13becc5929e754506802b655468b6 100644 (file)
     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;
index 07e36bb2744c87b16c917009073d8d9388f21d7d..6b5df80657a0bf159347d10dd96049ba517e69e8 100644 (file)
     .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,
+},
index b6666a119ec2de05f93cdc158d34b14e971adfd9..1d2d242148855c411fadc54c93807be34ee9415c 100644 (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)
 {
index 4b73ee160c727e119ab5b8193421f23e8344c4e7..ceaf82c90796c2b32fced52da43f4fa9c6695e88 100644 (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 ();
index 5712d984a07bc6e93e4379f59aa3b66917e9a00f..29abdb7df8eb5aa55354587ba3c6ea6789053793 100644 (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
 };
 
 
index b0067f63616d0803e563245b1d1c4b0181cf6d29..d7cf2ee51685e27425aa8e7087e5504a0567f540 100644 (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);
 
index 53193088053268e936558e0e5d8264f9cedc8bf4..a33c365a6a502acb24cfae4d1185177c6d458688 100644 (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
index 9f197d9cc1e00d37f52230921b9a18ca4c84250e..d4f972f3e9e76d48856e1ca830dab1ce52faa860 100644 (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;
index 4cb04cf5cc547d364e7ba859ba49ef4a5438eb2a..4a11688312021f7a635f3e38f349cd1affdb39e7 100644 (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:
index c34bbae9c638a80d4701fa8bc7bd68dfd8922d3b..cf5be38e163e8872b2dd902e9825f8eece7206e8 100644 (file)
@@ -300,9 +300,12 @@ LIBVIRT_0.7.1 {
         virConnectListSecrets;
         virSecretLookupByUUID;
         virSecretLookupByUUIDString;
+        virSecretLookupByUsage;
         virSecretDefineXML;
         virSecretGetUUID;
         virSecretGetUUIDString;
+        virSecretGetUsageType;
+        virSecretGetUsageID;
         virSecretGetXMLDesc;
         virSecretSetValue;
         virSecretGetValue;
index e7f01863e89a49e2604fb5ecda764903582ca651..dd7b31e8aa32b052eb023f118b94309ce0e6f9d3 100644 (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,
index 51ac13d458a16f96948d0a7a419abcddad5fb528..21215b29b789a0885c0b1676b35a5b6a92e6fd1a 100644 (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:
index 556f5a4f1cbed92ec8238f64cef57f5239c03ec8..1ecf419f39e3c0dfa3d8b43d88742c926de76e0a 100644 (file)
     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;
index a581fce72f22e02adc61a660dda162313285189e..20a3fa8658633252551c02de75a472f9177ca058 100644 (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);
-    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;
 }
 
-\f /* 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,
index 74147dab439e3e9f843e5000b22a88ccecae59dd..4825f1c91adc81771cdcd9f2c2046976b65afdbf 100644 (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);