[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