[libvirt] [PATCH 05/12] Define public API for managing identities

Eric Blake eblake at redhat.com
Wed May 2 21:24:53 UTC 2012


On 05/02/2012 05:44 AM, Daniel P. Berrange wrote:
> From: "Daniel P. Berrange" <berrange at redhat.com>
> 

A bit sparse on the commit message; even mentioning the term
virIdentityPtr would help future crawls through 'git log' find this patch.

> +++ 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,

This last value should be guarded by VIR_ENUM_SENTINELS.

> +
> +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);

Are there any other useful operations, such as knowing how many
attributes in the identity are currently set?

>  
>  
>  /**
> + * 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

How do we pick these magic numbers, anyway? :)

>  
> +
> +struct _virIdentity {
> +    unsigned int magic;
> +    virMutex lock;
> +    int refs;
> +
> +    char *attrs[VIR_IDENTITY_ATTR_LAST];
> +};

It looks like your intent is to store everything in this identity
locally (contrast it to _virDomain, which stores only enough information
locally to pass back over RPC to the remote side and have the remote
side do a hash lookup for the rest of the domain information).  It
should be okay, though, especially since this identity does not include
a name or uuid which could be used for a hash lookup for additional
contents, anyway.

> +
> +/**
> + * 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

or NULL on error.

> +/**
> + * 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

It looks weird to start a sentence with "ie,", but I don't have an
alternative wording on the tip of my tongue.

> + * 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__);

We really should be using a better error message than __FUNCTION__,
especially since virLibConnError is already adding __FUNCTION__ into the
list of arguments.  (Throughout the patch).

> +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__);

Really?  This means I can't clear out a value by passing in NULL.
Should there be a counterpart API for clearing an attribute?

> +        virDispatchError(NULL);
> +        return -1;
> +    }
> +
> +    virMutexLock(&ident->lock);
> +
> +    if (ident->attrs[attr]) {
> +        virLibConnError(VIR_ERR_OPERATION_DENIED, "%s",
> +                        _("Identity attribute is already set"));

Then again, this makes it a write-once interface (once an identity
attribute is set, you can't change it).  Should we document that better?


> +int virIdentityIsEqual(virIdentityPtr identA,
> +                       virIdentityPtr identB)

> +
> +    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;

Use STRNEQ_NULLABLE to shorten this.


> +++ b/src/libvirt_public.syms
> @@ -527,6 +527,11 @@ LIBVIRT_0.9.10 {
>          virDomainShutdownFlags;
>          virStorageVolResize;
>          virStorageVolWipePattern;
> +        virIdentityNew;
> +        virIdentityIsEqual;
> +        virIdentitySetAttr;
> +        virIdentityGetAttr;
> +        virIdentityFree;
>  } LIBVIRT_0.9.9;

Wrong release.  This should be in the LIBVIRT_0.9.12 section.


> +++ 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");

That reads awkwardly.  That says if I call:

reportError(VIR_ERR_INVALID_IDENTITY, NULL);

my error message will be "function: invalid identity pointer in".

> +            else
> +                errmsg = _("invalid identity pointer in %s");

Then again, if I call

reportError(VIR_ERR_INVALID_IDENTITY, __FUNCTION__);

the error message will be "function: invalid identity pointer in function"

But it's copy and paste from existing practice, so it's no worse than
before.

-- 
Eric Blake   eblake at redhat.com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 620 bytes
Desc: OpenPGP digital signature
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20120502/877d6f56/attachment-0001.sig>


More information about the libvir-list mailing list