diff --git a/include/libvirt/libvirt.h b/include/libvirt/libvirt.h index eadf420d54..552760028f 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 1391af819e..6028d5fa9e 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 c25ff551c5..ad9c54423b 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 a9fcc58d44..17426cd084 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 9f37963241..95f668ad00 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 7773cd924c..0605542015 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 15d33861ea..6ced13a2e8 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 07e36bb274..6b5df80657 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 b6666a119e..1d2d242148 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; } @@ -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) { diff --git a/qemud/remote_protocol.h b/qemud/remote_protocol.h index 4b73ee160c..ceaf82c907 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 5712d984a0..29abdb7df8 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 b0067f6361..d7cf2ee516 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 5319308805..a33c365a6a 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 9f197d9cc1..d4f972f3e9 100644 --- a/src/driver.h +++ b/src/driver.h @@ -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; diff --git a/src/libvirt.c b/src/libvirt.c index 4cb04cf5cc..4a11688312 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -8914,6 +8914,55 @@ error: } +/** + * virSecretLookupByUsage: + * @conn: pointer to the hypervisor connection + * @usageType: the type of secret usage + * @usageID: identifier of the object using the secret + * + * Try to lookup a secret on the given hypervisor based on its usage + * The usageID is unique within the set of secrets sharing the + * same usageType value. + * + * Returns a new secret object or NULL in case of failure. If the + * secret cannot be found, then VIR_ERR_NO_SECRET error is raised. + */ +virSecretPtr +virSecretLookupByUsage(virConnectPtr conn, + int usageType, + const char *usageID) +{ + DEBUG("conn=%p, usageType=%d usageID=%s", conn, usageType, NULLSTR(usageID)); + + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + return (NULL); + } + if (usageID == NULL) { + virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + if (conn->secretDriver && + conn->secretDriver->lookupByUsage) { + virSecretPtr ret; + ret = conn->secretDriver->lookupByUsage (conn, usageType, usageID); + if (!ret) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); + return NULL; +} + + /** * virSecretDefineXML: * @conn: virConnect connection @@ -9038,6 +9087,63 @@ error: return -1; } +/** + * virSecretGetUsageType: + * @secret: a secret object + * + * Get the type of object which uses this secret. The returned + * value is one of the constants defined in the virSecretUsageType + * enumeration. More values may be added to this enumeration in + * the future, so callers should expect to see usage types they + * do not explicitly know about. + * + * Returns a positive integer identifying the type of object, + * or -1 upon error. + */ +int +virSecretGetUsageType(virSecretPtr secret) +{ + DEBUG("secret=%p", secret); + + virResetLastError(); + + if (!VIR_IS_SECRET(secret)) { + virLibSecretError(NULL, VIR_ERR_INVALID_SECRET, __FUNCTION__); + return (-1); + } + return (secret->usageType); +} + +/** + * virSecretGetUsageID: + * @secret: a secret object + * + * Get the unique identifier of the object with which this + * secret is to be used. The format of the identifier is + * dependant on the usage type of the secret. For a secret + * with a usage type of VIR_SECRET_USAGE_TYPE_VOLUME the + * identifier will be a fully qualfied path name. The + * identifiers are intended to be unique within the set of + * all secrets sharing the same usage type. ie, there shall + * only ever be one secret for each volume path. + * + * Returns a string identifying the object using the secret, + * or NULL upon error + */ +const char * +virSecretGetUsageID(virSecretPtr secret) +{ + DEBUG("secret=%p", secret); + + virResetLastError(); + + if (!VIR_IS_SECRET(secret)) { + virLibSecretError(NULL, VIR_ERR_INVALID_SECRET, __FUNCTION__); + return (NULL); + } + return (secret->usageID); +} + /** * virSecretGetXMLDesc: diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index c34bbae9c6..cf5be38e16 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 e7f01863e8..dd7b31e8aa 100644 --- a/src/remote_internal.c +++ b/src/remote_internal.c @@ -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, diff --git a/src/secret_conf.c b/src/secret_conf.c index 51ac13d458..21215b29b7 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 556f5a4f1c..1ecf419f39 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 a581fce72f..20a3fa8658 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); + if (s->def->usage_type != usageType) + continue; + + switch (usageType) { + case VIR_SECRET_USAGE_TYPE_NONE: + /* never match this */ + break; + + case VIR_SECRET_USAGE_TYPE_VOLUME: + if (STREQ(s->def->usage.volume, usageID)) + return s; + break; + } + } return NULL; } -static virSecretEntryPtr -secretFindOrCreate(virConnectPtr conn, virSecretDriverStatePtr driver, - const unsigned char *uuid, bool *created_new) -{ - virSecretEntryPtr *pptr, secret; - - pptr = secretFind(driver, uuid); - if (pptr != NULL) { - if (created_new != NULL) - *created_new = false; - return *pptr; - } - - secret = secretCreate(conn, driver, uuid); - if (secret != NULL && created_new != NULL) - *created_new = true; - return secret; -} - - /* Permament secret storage */ +/* Permament secret storage */ /* Secrets are stored in virSecretDriverStatePtr->directory. Each secret has virSecretDef stored as XML in "$basename.xml". If a value of the @@ -609,17 +597,33 @@ cleanup: return -1; } + +static const char * +secretUsageIDForDef(virSecretDefPtr def) +{ + switch (def->usage_type) { + case VIR_SECRET_USAGE_TYPE_NONE: + return ""; + + case VIR_SECRET_USAGE_TYPE_VOLUME: + return def->usage.volume; + + default: + return NULL; + } +} + static virSecretPtr secretLookupByUUID(virConnectPtr conn, const unsigned char *uuid) { virSecretDriverStatePtr driver = conn->secretPrivateData; virSecretPtr ret = NULL; - virSecretEntryPtr *pptr; + virSecretEntryPtr secret; secretDriverLock(driver); - pptr = secretFind(driver, uuid); - if (pptr == NULL) { + secret = secretFindByUUID(driver, uuid); + if (secret == NULL) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(uuid, uuidstr); virSecretReportError(conn, VIR_ERR_NO_SECRET, @@ -627,7 +631,37 @@ secretLookupByUUID(virConnectPtr conn, const unsigned char *uuid) goto cleanup; } - ret = virGetSecret(conn, (*pptr)->def->uuid); + ret = virGetSecret(conn, + secret->def->uuid, + secret->def->usage_type, + secretUsageIDForDef(secret->def)); + +cleanup: + secretDriverUnlock(driver); + return ret; +} + + +static virSecretPtr +secretLookupByUsage(virConnectPtr conn, int usageType, const char *usageID) +{ + virSecretDriverStatePtr driver = conn->secretPrivateData; + virSecretPtr ret = NULL; + virSecretEntryPtr secret; + + secretDriverLock(driver); + + secret = secretFindByUsage(driver, usageType, usageID); + if (secret == NULL) { + virSecretReportError(conn, VIR_ERR_NO_SECRET, + _("no secret with matching usage '%s'"), usageID); + goto cleanup; + } + + ret = virGetSecret(conn, + secret->def->uuid, + secret->def->usage_type, + secretUsageIDForDef(secret->def)); cleanup: secretDriverUnlock(driver); @@ -642,8 +676,8 @@ secretDefineXML(virConnectPtr conn, const char *xml, virSecretDriverStatePtr driver = conn->secretPrivateData; virSecretPtr ret = NULL; virSecretEntryPtr secret; - virSecretDefPtr backup, new_attrs; - bool secret_is_new; + virSecretDefPtr backup = NULL; + virSecretDefPtr new_attrs; new_attrs = virSecretDefParseString(conn, xml); if (new_attrs == NULL) @@ -651,28 +685,58 @@ secretDefineXML(virConnectPtr conn, const char *xml, secretDriverLock(driver); - secret = secretFindOrCreate(conn, driver, new_attrs->uuid, - &secret_is_new); - if (secret == NULL) - goto cleanup; + secret = secretFindByUUID(driver, new_attrs->uuid); + if (secret == NULL) { + /* No existing secret with same UUID, try look for matching usage instead */ + const char *usageID = secretUsageIDForDef(new_attrs); + secret = secretFindByUsage(driver, new_attrs->usage_type, usageID); + if (secret) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(secret->def->uuid, uuidstr); + virSecretReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("a secret with UUID %s already defined for use with %s"), + uuidstr, usageID); + goto cleanup; + } - /* Save old values of the attributes */ - backup = secret->def; + /* No existing secret at all, create one */ + if (VIR_ALLOC(secret) < 0) { + virReportOOMError(conn); + goto cleanup; + } - if (backup->private && !new_attrs->private) { - virSecretReportError(conn, VIR_ERR_OPERATION_DENIED, "%s", - virErrorMsg(VIR_ERR_OPERATION_DENIED, NULL)); - goto cleanup; + listInsert(&driver->secrets, secret); + secret->def = new_attrs; + } else { + const char *newUsageID = secretUsageIDForDef(new_attrs); + const char *oldUsageID = secretUsageIDForDef(secret->def); + if (STRNEQ(oldUsageID, newUsageID)) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(secret->def->uuid, uuidstr); + virSecretReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("a secret with UUID %s is already defined for use with %s"), + uuidstr, oldUsageID); + goto cleanup; + } + + if (secret->def->private && !new_attrs->private) { + virSecretReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot change private flag on existing secret")); + goto cleanup; + } + + /* Got an existing secret matches attrs, so reuse that */ + backup = secret->def; + secret->def = new_attrs; } - secret->def = new_attrs; if (!new_attrs->ephemeral) { - if (backup->ephemeral) { + if (backup && backup->ephemeral) { if (secretSaveValue(conn, driver, secret) < 0) goto restore_backup; } if (secretSaveDef(conn, driver, secret) < 0) { - if (backup->ephemeral) { + if (backup && backup->ephemeral) { char *filename; /* Undo the secretSaveValue() above; ignore errors */ @@ -683,7 +747,7 @@ secretDefineXML(virConnectPtr conn, const char *xml, } goto restore_backup; } - } else if (!backup->ephemeral) { + } else if (backup && !backup->ephemeral) { if (secretDeleteSaved(conn, driver, secret) < 0) goto restore_backup; } @@ -691,13 +755,17 @@ secretDefineXML(virConnectPtr conn, const char *xml, new_attrs = NULL; virSecretDefFree(backup); - ret = virGetSecret(conn, secret->def->uuid); + ret = virGetSecret(conn, + secret->def->uuid, + secret->def->usage_type, + secretUsageIDForDef(secret->def)); goto cleanup; restore_backup: - /* Error - restore previous state and free new attributes */ - secret->def = backup; - if (secret_is_new) { + if (backup) { + /* Error - restore previous state and free new attributes */ + secret->def = backup; + } else { /* "secret" was added to the head of the list above */ if (listUnlink(&driverState->secrets) != secret) virSecretReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", @@ -718,12 +786,12 @@ secretGetXMLDesc(virSecretPtr obj, unsigned int flags ATTRIBUTE_UNUSED) { virSecretDriverStatePtr driver = obj->conn->secretPrivateData; char *ret = NULL; - virSecretEntryPtr *pptr; + virSecretEntryPtr secret; secretDriverLock(driver); - pptr = secretFind(driver, obj->uuid); - if (pptr == NULL) { + secret = secretFindByUUID(driver, obj->uuid); + if (secret == NULL) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(obj->uuid, uuidstr); virSecretReportError(obj->conn, VIR_ERR_NO_SECRET, @@ -731,7 +799,7 @@ secretGetXMLDesc(virSecretPtr obj, unsigned int flags ATTRIBUTE_UNUSED) goto cleanup; } - ret = virSecretDefFormat(obj->conn, (*pptr)->def); + ret = virSecretDefFormat(obj->conn, secret->def); cleanup: secretDriverUnlock(driver); @@ -747,7 +815,7 @@ secretSetValue(virSecretPtr obj, const unsigned char *value, int ret = -1; unsigned char *old_value, *new_value; size_t old_value_size; - virSecretEntryPtr secret, *pptr; + virSecretEntryPtr secret; if (VIR_ALLOC_N(new_value, value_size) < 0) { virReportOOMError(obj->conn); @@ -756,15 +824,14 @@ secretSetValue(virSecretPtr obj, const unsigned char *value, secretDriverLock(driver); - pptr = secretFind(driver, obj->uuid); - if (pptr == NULL) { + secret = secretFindByUUID(driver, obj->uuid); + if (secret == NULL) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(obj->uuid, uuidstr); virSecretReportError(obj->conn, VIR_ERR_NO_SECRET, _("no secret with matching uuid '%s'"), uuidstr); goto cleanup; } - secret = *pptr; old_value = secret->value; old_value_size = secret->value_size; @@ -805,19 +872,19 @@ secretGetValue(virSecretPtr obj, size_t *value_size, unsigned int flags) { virSecretDriverStatePtr driver = obj->conn->secretPrivateData; unsigned char *ret = NULL; - virSecretEntryPtr *pptr, secret; + virSecretEntryPtr secret; secretDriverLock(driver); - pptr = secretFind(driver, obj->uuid); - if (pptr == NULL) { + secret = secretFindByUUID(driver, obj->uuid); + if (secret == NULL) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(obj->uuid, uuidstr); virSecretReportError(obj->conn, VIR_ERR_NO_SECRET, _("no secret with matching uuid '%s'"), uuidstr); goto cleanup; } - secret = *pptr; + if (secret->value == NULL) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(obj->uuid, uuidstr); @@ -851,12 +918,12 @@ secretUndefine(virSecretPtr obj) { virSecretDriverStatePtr driver = obj->conn->secretPrivateData; int ret = -1; - virSecretEntryPtr *pptr, secret; + virSecretEntryPtr secret; secretDriverLock(driver); - pptr = secretFind(driver, obj->uuid); - if (pptr == NULL) { + secret = secretFindByUUID(driver, obj->uuid); + if (secret == NULL) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(obj->uuid, uuidstr); virSecretReportError(obj->conn, VIR_ERR_NO_SECRET, @@ -864,19 +931,22 @@ secretUndefine(virSecretPtr obj) goto cleanup; } - secret = listUnlink(pptr); - if (!secret->def->ephemeral) { - if (secretDeleteSaved(obj->conn, driver, secret) < 0) - goto restore_backup; + if (!secret->def->ephemeral && + secretDeleteSaved(obj->conn, driver, secret) < 0) + goto cleanup; + + if (driver->secrets == secret) { + driver->secrets = secret->next; + } else { + virSecretEntryPtr tmp = driver->secrets; + while (tmp && tmp->next != secret) + tmp = tmp->next; + if (tmp) + tmp->next = secret->next; } secretFree(secret); ret = 0; - goto cleanup; - -restore_backup: - /* This may change the order of secrets in the list. We don't care. */ - listInsert(&driver->secrets, secret); cleanup: secretDriverUnlock(driver); @@ -995,6 +1065,7 @@ static virSecretDriver secretDriver = { .numOfSecrets = secretNumOfSecrets, .listSecrets = secretListSecrets, .lookupByUUID = secretLookupByUUID, + .lookupByUsage = secretLookupByUsage, .defineXML = secretDefineXML, .getXMLDesc = secretGetXMLDesc, .setValue = secretSetValue, diff --git a/src/virsh.c b/src/virsh.c index 74147dab43..4825f1c91a 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);