[libvirt] [PATCH 05/12] Define public API for managing identities
Corey Bryant
coreyb at linux.vnet.ibm.com
Thu Jul 5 17:52:15 UTC 2012
On 05/02/2012 07:44 AM, Daniel P. Berrange wrote:
> From: "Daniel P. Berrange" <berrange at redhat.com>
>
> ---
> include/libvirt/libvirt.h.in | 30 ++++++
> include/libvirt/virterror.h | 1 +
> src/datatypes.h | 20 ++++
> src/libvirt.c | 246 ++++++++++++++++++++++++++++++++++++++++++
> src/libvirt_public.syms | 5 +
> src/util/virterror.c | 6 ++
> 6 files changed, 308 insertions(+)
>
> diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
> index ac5df95..86a9514 100644
> --- a/include/libvirt/libvirt.h.in
> +++ b/include/libvirt/libvirt.h.in
> @@ -1088,6 +1088,36 @@ typedef virConnectAuth *virConnectAuthPtr;
>
> VIR_EXPORT_VAR virConnectAuthPtr virConnectAuthPtrDefault;
>
> +typedef struct _virIdentity virIdentity;
> +typedef virIdentity *virIdentityPtr;
> +
> +typedef enum {
> + VIR_IDENTITY_ATTR_UNIX_USER_NAME,
> + VIR_IDENTITY_ATTR_UNIX_GROUP_NAME,
> + VIR_IDENTITY_ATTR_UNIX_PROCESS_ID,
> + VIR_IDENTITY_ATTR_SASL_USER_NAME,
> + VIR_IDENTITY_ATTR_X509_DISTINGUISHED_NAME,
> + VIR_IDENTITY_ATTR_SECURITY_CONTEXT,
> +
> + VIR_IDENTITY_ATTR_LAST,
> +} virIdentityAttrType;
> +
> +
> +virIdentityPtr virIdentityNew(void);
> +int virIdentityRef(virIdentityPtr ident);
> +int virIdentitySetAttr(virIdentityPtr ident,
> + unsigned int attr,
> + const char *value);
> +
> +int virIdentityGetAttr(virIdentityPtr ident,
> + unsigned int attr,
> + const char **value);
> +
> +int virIdentityIsEqual(virIdentityPtr identA,
> + virIdentityPtr identB);
> +
> +int virIdentityFree(virIdentityPtr ident);
> +
> /**
> * VIR_UUID_BUFLEN:
> *
> diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
> index 7283207..e44390e 100644
> --- a/include/libvirt/virterror.h
> +++ b/include/libvirt/virterror.h
> @@ -251,6 +251,7 @@ typedef enum {
> VIR_ERR_MIGRATE_UNSAFE = 81, /* Migration is not safe */
> VIR_ERR_OVERFLOW = 82, /* integer overflow */
> VIR_ERR_BLOCK_COPY_ACTIVE = 83, /* action prevented by block copy job */
> + VIR_ERR_INVALID_IDENTITY = 84, /* Invalid identity pointer */
> } virErrorNumber;
>
> /**
> diff --git a/src/datatypes.h b/src/datatypes.h
> index fc284d2..b8d8db2 100644
> --- a/src/datatypes.h
> +++ b/src/datatypes.h
> @@ -38,6 +38,16 @@
>
>
> /**
> + * VIR_IDENTITY_MAGIC:
> + *
> + * magic value used to protect the API when pointers to identity structures
> + * are passed down by the users.
> + */
> +# define VIR_IDENTITY_MAGIC 0xB33FCAF3
> +# define VIR_IS_IDENTITY(obj) ((obj) && (obj)->magic==VIR_IDENTITY_MAGIC)
> +
> +
> +/**
> * VIR_DOMAIN_MAGIC:
> *
> * magic value used to protect the API when pointers to domain structures
> @@ -190,6 +200,16 @@ struct _virConnect {
> int refs; /* reference count */
> };
>
> +
> +struct _virIdentity {
> + unsigned int magic;
> + virMutex lock;
> + int refs;
> +
> + char *attrs[VIR_IDENTITY_ATTR_LAST];
> +};
> +
> +
> /**
> * _virDomain:
> *
> diff --git a/src/libvirt.c b/src/libvirt.c
> index cfd7711..a206800 100644
> --- a/src/libvirt.c
> +++ b/src/libvirt.c
> @@ -1544,6 +1544,252 @@ virConnectRef(virConnectPtr conn)
> return 0;
> }
>
> +
> +/**
> + * virIdentityNew:
> + *
> + * Creates a new empty identity object. After creating, one or
> + * more identifying attributes should be set on the identity.
> + *
> + * Returns: a new empty identity
> + */
> +virIdentityPtr virIdentityNew(void)
> +{
> + virIdentityPtr ident;
> +
> + if (VIR_ALLOC(ident) < 0) {
> + virReportOOMError();
> + return NULL;
> + }
> +
> + if (virMutexInit(&ident->lock) < 0) {
> + virReportSystemError(errno, "%s",
> + _("Unable to initialize mutex"));
> + VIR_FREE(ident);
> + return NULL;
> + }
> + ident->magic = VIR_IDENTITY_MAGIC;
> + ident->refs = 1;
> +
> + return ident;
> +}
> +
> +/**
> + * virIdentityRef:
> + * @ident: the identity to hold a reference on
> + *
> + * Increment the reference count on the identity. For each
> + * additional call to this method, there shall be a corresponding
> + * call to virIdentityFree to release the reference count, once
> + * the caller no longer needs the reference to this object.
> + *
> + * This method is typically useful for applications where multiple
> + * threads are using an identity object, and it is required that
> + * the identity remain around until all threads have finished using
> + * it. ie, each new thread using a identity would increment
> + * the reference count.
> + *
> + * Returns 0 in case of success and -1 in case of failure.
> + */
> +int virIdentityRef(virIdentityPtr ident)
> +{
> + if ((!VIR_IS_IDENTITY(ident))) {
> + virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__);
> + virDispatchError(NULL);
> + return -1;
> + }
> + virMutexLock(&ident->lock);
> + VIR_DEBUG("ident=%p refs=%d", ident, ident->refs);
> + ident->refs++;
> + virMutexUnlock(&ident->lock);
> + return 0;
> +}
> +
> +
> +/**
> + * virIdentitySetAttr:
> + * @ident: the identity to modify
> + * @attr: the attribute type to set
> + * @value: the identifying value to associate with @attr
> + *
> + * Sets an identifying attribute @attr on @ident. Each
> + * @attr type can only be set once.
> + *
> + * Returns: 0 on success, or -1 on error
> + */
> +int virIdentitySetAttr(virIdentityPtr ident,
> + unsigned int attr,
> + const char *value)
> +{
> + VIR_DEBUG("ident=%p attribute=%u value=%s", ident, attr, NULLSTR(value));
> +
> + if ((!VIR_IS_IDENTITY(ident))) {
> + virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__);
> + virDispatchError(NULL);
> + return -1;
> + }
> +
> + if (attr >= VIR_IDENTITY_ATTR_LAST) {
> + virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
> + virDispatchError(NULL);
> + return -1;
> + }
> +
> + if (!value) {
> + virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
> + virDispatchError(NULL);
> + return -1;
> + }
> +
> + virMutexLock(&ident->lock);
> +
> + if (ident->attrs[attr]) {
> + virLibConnError(VIR_ERR_OPERATION_DENIED, "%s",
> + _("Identity attribute is already set"));
> + goto error;
> + }
> +
> + if (!(ident->attrs[attr] = strdup(value))) {
> + virReportOOMError();
> + goto error;
> + }
> +
> + virMutexUnlock(&ident->lock);
> + return 0;
> +
> +error:
> + virDispatchError(NULL);
> + virMutexUnlock(&ident->lock);
> + return -1;
> +}
> +
> +
> +/**
> + * virIdentityGetAttr:
> + * @ident: the identity to query
> + * @attr: the attribute to read
> + * @value: filled with the attribute value
> + *
> + * Fills @value with a pointer to the value associated
> + * with the identifying attribute @attr in @ident. If
> + * @attr is not set, then it will simply be initialized
> + * to NULL and considered as a successful read
> + *
> + * Returns 0 on success, -1 on error
> + */
> +int virIdentityGetAttr(virIdentityPtr ident,
> + unsigned int attr,
> + const char **value)
> +{
> + VIR_DEBUG("ident=%p attribute=%d value=%p", ident, attr, value);
Do you want to use %u instead of %d here?
> +
> + if ((!VIR_IS_IDENTITY(ident))) {
> + virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__);
> + virDispatchError(NULL);
> + return -1;
> + }
> +
> + if (attr >= VIR_IDENTITY_ATTR_LAST) {
> + virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
> + virDispatchError(NULL);
> + return -1;
> + }
> +
> + virMutexLock(&ident->lock);
> + *value = ident->attrs[attr];
> + virMutexUnlock(&ident->lock);
> + return 0;
> +}
> +
> +
> +/**
> + * virIdentityIsEqual:
> + * @identA: the first identity
> + * @identB: the second identity
> + *
> + * Compares every attribute in @identA and @identB
> + * to determine if they refer to the same identity
> + *
> + * Returns 1 if they are equal, 0 if not equal or -1 on error
> + */
> +int virIdentityIsEqual(virIdentityPtr identA,
> + virIdentityPtr identB)
> +{
> + VIR_DEBUG("identA=%p identB=%p", identA, identB);
> + int ret = 0;
> + size_t i;
> +
> + if ((!VIR_IS_IDENTITY(identA))) {
> + virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__);
> + virDispatchError(NULL);
> + return -1;
> + }
> + if ((!VIR_IS_IDENTITY(identB))) {
> + virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__);
> + virDispatchError(NULL);
> + return -1;
> + }
> + virMutexLock(&identA->lock);
> + virMutexLock(&identB->lock);
> +
> + for (i = 0 ; i < VIR_IDENTITY_ATTR_LAST ; i++) {
> + if (identA->attrs[i] == NULL &&
> + identB->attrs[i] != NULL)
> + goto cleanup;
> + if (identA->attrs[i] != NULL &&
> + identB->attrs[i] == NULL)
> + goto cleanup;
> + if (STRNEQ(identA->attrs[i],
> + identB->attrs[i]))
> + goto cleanup;
> + }
> +
> + ret = 1;
> +cleanup:
> + virMutexUnlock(&identA->lock);
> + virMutexUnlock(&identB->lock);
> + return ret;
> +}
> +
> +
> +/**
> + * virIdentityFree:
> + * @ident: the identity to free
> + *
> + * Decrement the reference count on @ident. If the
> + * reference count hits zero, then the @ident object
> + * will be freed
> + *
> + * Returns number of references remaining, or -1 on error
> + */
> +int virIdentityFree(virIdentityPtr ident)
> +{
> + size_t i;
> +
> + if ((!VIR_IS_IDENTITY(ident))) {
> + virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__);
> + virDispatchError(NULL);
> + return -1;
> + }
> + virMutexLock(&ident->lock);
> + VIR_DEBUG("ident=%p refs=%d", ident, ident->refs);
> + ident->refs--;
> + if (ident->refs > 0) {
> + int ret = ident->refs;
> + virMutexUnlock(&ident->lock);
> + return ret;
> + }
> + for (i = 0 ; i < VIR_IDENTITY_ATTR_LAST ; i++)
> + VIR_FREE(ident->attrs[i]);
> +
> + virMutexUnlock(&ident->lock);
> + virMutexDestroy(&ident->lock);
> + VIR_FREE(ident);
> + return 0;
> +}
> +
> +
> +
> /*
> * Not for public use. This function is part of the internal
> * implementation of driver features in the remote case.
> diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
> index 46c13fb..35f11b8 100644
> --- a/src/libvirt_public.syms
> +++ b/src/libvirt_public.syms
> @@ -527,6 +527,11 @@ LIBVIRT_0.9.10 {
> virDomainShutdownFlags;
> virStorageVolResize;
> virStorageVolWipePattern;
> + virIdentityNew;
> + virIdentityIsEqual;
> + virIdentitySetAttr;
> + virIdentityGetAttr;
> + virIdentityFree;
Do you need to add virIdentityRef here too?
--
Regards,
Corey
> } LIBVIRT_0.9.9;
>
> LIBVIRT_0.9.11 {
> diff --git a/src/util/virterror.c b/src/util/virterror.c
> index b1a5d2b..33ef713 100644
> --- a/src/util/virterror.c
> +++ b/src/util/virterror.c
> @@ -1259,6 +1259,12 @@ virErrorMsg(virErrorNumber error, const char *info)
> else
> errmsg = _("block copy still active: %s");
> break;
> + case VIR_ERR_INVALID_IDENTITY:
> + if (info == NULL)
> + errmsg = _("invalid identity pointer in");
> + else
> + errmsg = _("invalid identity pointer in %s");
> + break;
> }
> return errmsg;
> }
>
More information about the libvir-list
mailing list