[libvirt] [PATCH v3 5/5] Update the remote API

Michal Privoznik mprivozn at redhat.com
Mon Aug 6 13:29:55 UTC 2012


On 03.08.2012 16:18, Marcelo Cerri wrote:
> Thist patch updates libvirt's API to allow applications to inspect the
> full list of security labels of a domain.
> 
> Signed-off-by: Marcelo Cerri <mhcerri at linux.vnet.ibm.com>
> ---
>  daemon/remote.c              |   63 ++++++++++++++++++++++++++++++++++++
>  include/libvirt/libvirt.h.in |    2 +
>  python/generator.py          |    1 +
>  src/driver.h                 |    4 ++
>  src/libvirt.c                |   47 +++++++++++++++++++++++++++
>  src/libvirt_public.syms      |    5 +++
>  src/qemu/qemu_driver.c       |   73 ++++++++++++++++++++++++++++++++++++++++++
>  src/remote/remote_driver.c   |   46 ++++++++++++++++++++++++++
>  src/remote/remote_protocol.x |   17 +++++++++-
>  src/remote_protocol-structs  |    1 +
>  10 files changed, 258 insertions(+), 1 deletions(-)
> 
> diff --git a/daemon/remote.c b/daemon/remote.c
> index d25717c..367180a 100644
> --- a/daemon/remote.c
> +++ b/daemon/remote.c
> @@ -1420,6 +1420,69 @@ cleanup:
>  }
>  
>  static int
> +remoteDispatchDomainGetSecurityLabelList(virNetServerPtr server ATTRIBUTE_UNUSED,
> +                                         virNetServerClientPtr client ATTRIBUTE_UNUSED,
> +                                         virNetMessagePtr msg ATTRIBUTE_UNUSED,
> +                                         virNetMessageErrorPtr rerr,
> +                                         remote_domain_get_security_label_list_args *args,
> +                                         remote_domain_get_security_label_list_ret *ret)
> +{
> +    virDomainPtr dom = NULL;
> +    virSecurityLabelPtr seclabels = NULL;
> +    int i, len, rv = -1;
> +    struct daemonClientPrivate *priv =
> +        virNetServerClientGetPrivateData(client);
> +
> +    if (!priv->conn) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open"));
> +        goto cleanup;
> +    }
> +
> +    if (!(dom = get_nonnull_domain(priv->conn, args->dom)))
> +        goto cleanup;
> +
> +    if ((len = virDomainGetSecurityLabelList(dom, &seclabels)) < 0) {
> +        ret->ret = len;
> +        ret->labels.labels_len = 0;
> +        ret->labels.labels_val = NULL;
> +        goto done;
> +    }
> +
> +    if (VIR_ALLOC_N(ret->labels.labels_val, len) < 0) {
> +        virReportOOMError();
> +        goto cleanup;
> +    }
> +
> +    for (i = 0; i < len; i++) {
> +        size_t label_len = strlen(seclabels[i].label) + 1;
> +        remote_domain_get_security_label_ret *cur = &ret->labels.labels_val[i];
> +        if (VIR_ALLOC_N(cur->label.label_val, label_len) < 0) {
> +            virReportOOMError();
> +            goto cleanup;
> +        }
> +        if (virStrcpy(cur->label.label_val, seclabels[i].label, label_len) == NULL) {
> +            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                           _("failed to copy security label"));
> +            goto cleanup;
> +        }
> +        cur->label.label_len = label_len;
> +        cur->enforcing = seclabels[i].enforcing;
> +    }
> +    ret->labels.labels_len = ret->ret = len;
> +
> +done:
> +    rv = 0;
> +
> +cleanup:
> +    if (rv < 0)
> +        virNetMessageSaveError(rerr);
> +    if (dom)
> +        virDomainFree(dom);
> +    VIR_FREE(seclabels);
> +    return rv;
> +}
> +
> +static int
>  remoteDispatchNodeGetSecurityModel(virNetServerPtr server ATTRIBUTE_UNUSED,
>                                     virNetServerClientPtr client ATTRIBUTE_UNUSED,
>                                     virNetMessagePtr msg ATTRIBUTE_UNUSED,
> diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
> index d21d029..0985dd3 100644
> --- a/include/libvirt/libvirt.h.in
> +++ b/include/libvirt/libvirt.h.in
> @@ -1593,6 +1593,8 @@ int                     virDomainGetSecurityLabel (virDomainPtr domain,
>                                                     virSecurityLabelPtr seclabel);
>  char *                  virDomainGetHostname    (virDomainPtr domain,
>                                                   unsigned int flags);
> +int                     virDomainGetSecurityLabelList (virDomainPtr domain,
> +                                                       virSecurityLabelPtr* seclabels);
>  
>  typedef enum {
>      VIR_DOMAIN_METADATA_DESCRIPTION = 0, /* Operate on <description> */
> diff --git a/python/generator.py b/python/generator.py
> index 6559ece..1f87195 100755
> --- a/python/generator.py
> +++ b/python/generator.py
> @@ -448,6 +448,7 @@ skip_function = (
>      'virConnectOpenAuth', # Python C code is manually written
>      'virDefaultErrorFunc', # Python virErrorFuncHandler impl calls this from C
>      'virDomainGetSecurityLabel', # Needs investigation...
> +    'virDomainGetSecurityLabelList', # Needs investigation...
>      'virNodeGetSecurityModel', # Needs investigation...
>      'virConnectDomainEventRegister',   # overridden in virConnect.py
>      'virConnectDomainEventDeregister', # overridden in virConnect.py
> diff --git a/src/driver.h b/src/driver.h
> index aab9766..203497d 100644
> --- a/src/driver.h
> +++ b/src/driver.h
> @@ -320,6 +320,9 @@ typedef int
>          (*virDrvDomainGetSecurityLabel) (virDomainPtr domain,
>                                           virSecurityLabelPtr seclabel);
>  typedef int
> +        (*virDrvDomainGetSecurityLabelList) (virDomainPtr domain,
> +                                         virSecurityLabelPtr* seclabels);
> +typedef int
>          (*virDrvNodeGetSecurityModel)   (virConnectPtr conn,
>                                           virSecurityModelPtr secmodel);
>  typedef int
> @@ -941,6 +944,7 @@ struct _virDriver {
>      virDrvDomainGetVcpus                domainGetVcpus;
>      virDrvDomainGetMaxVcpus             domainGetMaxVcpus;
>      virDrvDomainGetSecurityLabel        domainGetSecurityLabel;
> +    virDrvDomainGetSecurityLabelList     domainGetSecurityLabelList;
>      virDrvNodeGetSecurityModel          nodeGetSecurityModel;
>      virDrvDomainGetXMLDesc              domainGetXMLDesc;
>      virDrvConnectDomainXMLFromNative    domainXMLFromNative;
> diff --git a/src/libvirt.c b/src/libvirt.c
> index 3c4bf8c..dfe49eb 100644
> --- a/src/libvirt.c
> +++ b/src/libvirt.c
> @@ -9027,6 +9027,53 @@ error:
>  }
>  
>  /**
> + * virDomainGetSecurityLabelList:
> + * @domain: a domain object
> + * @seclabels: will be auto-allocated and filled with domains' security labels.
> + * Caller must free memory on return.
> + *
> + * Extract the security labels of an active domain. The 'label' field
> + * in the @seclabels argument will be initialized to the empty
> + * string if the domain is not running under a security model.
> + *
> + * Returns 0 in case of success, -1 in case of failure
> + */
> +int
> +virDomainGetSecurityLabelList(virDomainPtr domain,
> +                              virSecurityLabelPtr* seclabels)
> +{
> +    virConnectPtr conn;
> +
> +    VIR_DOMAIN_DEBUG(domain, "seclabels=%p", seclabels);
> +
> +    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
> +        virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
> +        virDispatchError(NULL);
> +        return -1;
> +    }
> +
> +    if (seclabels == NULL) {
> +        virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__);
> +        goto error;
> +    }
> +
> +    conn = domain->conn;
> +
> +    if (conn->driver->domainGetSecurityLabelList) {
> +        int ret;
> +        ret = conn->driver->domainGetSecurityLabelList(domain, seclabels);
> +        if (ret < 0)
> +            goto error;
> +        return ret;
> +    }
> +
> +    virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
> +
> +error:
> +    virDispatchError(domain->conn);
> +    return -1;
> +}
> +/**
>   * virDomainSetMetadata:
>   * @domain: a domain object
>   * @type: type of description, from virDomainMetadataType
> diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
> index e3ba119..06ef08a 100644
> --- a/src/libvirt_public.syms
> +++ b/src/libvirt_public.syms
> @@ -551,4 +551,9 @@ LIBVIRT_0.10.0 {
>          virConnectUnregisterCloseCallback;
>  } LIBVIRT_0.9.13;
>  
> +LIBVIRT_0.10.1{
> +    global:
> +        virDomainGetSecurityLabelList;
> +} LIBVIRT_0.10.0;
> +

Since 0.10.0 is not out yet, I guess this can be squashed into 0.10.0
(okay, we've release -rc0 but that's because patch flow is lower making
our release prolonged about twice).

>  # .... define new API here using predicted next version number ....
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index ec0f02b..7d95fef 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -4089,6 +4089,78 @@ cleanup:
>      return ret;
>  }
>  
> +static int qemuDomainGetSecurityLabelList(virDomainPtr dom,
> +                                          virSecurityLabelPtr* seclabels)
> +{
> +    struct qemud_driver *driver = dom->conn->privateData;
> +    virDomainObjPtr vm;
> +    int i, ret = -1;
> +
> +    /* Protect domain data with qemu lock */
> +    qemuDriverLock(driver);
> +    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
> +
> +    if (!vm) {
> +        char uuidstr[VIR_UUID_STRING_BUFLEN];
> +        virUUIDFormat(dom->uuid, uuidstr);
> +        virReportError(VIR_ERR_NO_DOMAIN,
> +                       _("no domain with matching uuid '%s'"), uuidstr);
> +        goto cleanup;
> +    }
> +
> +    if (!virDomainVirtTypeToString(vm->def->virtType)) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR,
> +                       _("unknown virt type in domain definition '%d'"),
> +                       vm->def->virtType);
> +        goto cleanup;
> +    }
> +
> +    /*
> +     * Check the comment in qemudDomainGetSecurityLabel function.
> +     */
> +    if (!virDomainObjIsActive(vm)) {
> +        /* No seclabels */
> +        *seclabels = NULL;
> +        ret = 0;
> +    } else {
> +        int len = 0;
> +        virSecurityManagerPtr* mgrs = virSecurityManagerGetNested(
> +                                            driver->securityManager);
> +        if (!mgrs)
> +            goto cleanup;
> +
> +        /* Allocate seclabels array */
> +        for (i = 0; mgrs[i]; i++)
> +            len++;
> +
> +        if (VIR_ALLOC_N((*seclabels), len) < 0) {
> +            virReportOOMError();
> +            VIR_FREE(mgrs);
> +            goto cleanup;
> +        }
> +        memset(*seclabels, 0, sizeof(**seclabels) * len);
> +
> +        /* Fill the array */
> +        for (i = 0; i < len; i++) {
> +            if (virSecurityManagerGetProcessLabel(mgrs[i], vm->def, vm->pid,
> +                                                  &(*seclabels)[i]) < 0) {
> +                virReportError(VIR_ERR_INTERNAL_ERROR,
> +                               "%s", _("Failed to get security label"));
> +                VIR_FREE(mgrs);
> +                VIR_FREE(*seclabels);
> +                goto cleanup;
> +            }
> +        }
> +        ret = len;
> +        VIR_FREE(mgrs);
> +    }
> +
> +cleanup:
> +    if (vm)
> +        virDomainObjUnlock(vm);
> +    qemuDriverUnlock(driver);
> +    return ret;
> +}
>  static int qemudNodeGetSecurityModel(virConnectPtr conn,
>                                       virSecurityModelPtr secmodel)
>  {
> @@ -13332,6 +13404,7 @@ static virDriver qemuDriver = {
>      .domainGetVcpus = qemudDomainGetVcpus, /* 0.4.4 */
>      .domainGetMaxVcpus = qemudDomainGetMaxVcpus, /* 0.4.4 */
>      .domainGetSecurityLabel = qemudDomainGetSecurityLabel, /* 0.6.1 */
> +    .domainGetSecurityLabelList = qemuDomainGetSecurityLabelList, /* 0.10.0 */
>      .nodeGetSecurityModel = qemudNodeGetSecurityModel, /* 0.6.1 */
>      .domainGetXMLDesc = qemuDomainGetXMLDesc, /* 0.2.0 */
>      .domainXMLFromNative = qemuDomainXMLFromNative, /* 0.6.4 */
> diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
> index afd367b..6f56ee6 100644
> --- a/src/remote/remote_driver.c
> +++ b/src/remote/remote_driver.c
> @@ -1956,6 +1956,51 @@ done:
>  }
>  
>  static int
> +remoteDomainGetSecurityLabelList (virDomainPtr domain, virSecurityLabelPtr* seclabels)
> +{
> +    remote_domain_get_security_label_list_args args;
> +    remote_domain_get_security_label_list_ret ret;
> +    struct private_data *priv = domain->conn->privateData;
> +    int i, rv = -1;
> +
> +    remoteDriverLock(priv);
> +
> +    make_nonnull_domain (&args.dom, domain);
> +    memset(&ret, 0, sizeof(ret));
> +
> +    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_SECURITY_LABEL_LIST,
> +              (xdrproc_t) xdr_remote_domain_get_security_label_list_args, (char *)&args,
> +              (xdrproc_t) xdr_remote_domain_get_security_label_list_ret, (char *)&ret) == -1) {
> +        goto done;
> +    }
> +
> +    if (VIR_ALLOC_N(*seclabels, ret.labels.labels_len) < 0)
> +        goto cleanup;
> +
> +    for (i = 0; i < ret.labels.labels_len; i++) {
> +        remote_domain_get_security_label_ret *cur = &ret.labels.labels_val[i];
> +        if (cur->label.label_val != NULL) {
> +            if (strlen(cur->label.label_val) >= sizeof((*seclabels)->label)) {
> +                virReportError(VIR_ERR_RPC, _("security label exceeds maximum: %zd"),
> +                               sizeof((*seclabels)->label) - 1);
> +                VIR_FREE(*seclabels);
> +                goto cleanup;
> +            }
> +            strcpy((*seclabels)[i].label, cur->label.label_val);
> +            (*seclabels)[i].enforcing = cur->enforcing;
> +        }
> +    }
> +    rv = ret.ret;
> +
> +cleanup:
> +    xdr_free((xdrproc_t) xdr_remote_domain_get_security_label_list_ret, (char *)&ret);
> +
> +done:
> +    remoteDriverUnlock(priv);
> +    return rv;
> +}
> +
> +static int
>  remoteDomainGetState(virDomainPtr domain,
>                       int *state,
>                       int *reason,
> @@ -5258,6 +5303,7 @@ static virDriver remote_driver = {
>      .domainGetVcpus = remoteDomainGetVcpus, /* 0.3.0 */
>      .domainGetMaxVcpus = remoteDomainGetMaxVcpus, /* 0.3.0 */
>      .domainGetSecurityLabel = remoteDomainGetSecurityLabel, /* 0.6.1 */
> +    .domainGetSecurityLabelList = remoteDomainGetSecurityLabelList, /* 0.10.0*/
>      .nodeGetSecurityModel = remoteNodeGetSecurityModel, /* 0.6.1 */
>      .domainGetXMLDesc = remoteDomainGetXMLDesc, /* 0.3.0 */
>      .domainXMLFromNative = remoteDomainXMLFromNative, /* 0.6.4 */
> diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
> index 200fe75..3be15f5 100644
> --- a/src/remote/remote_protocol.x
> +++ b/src/remote/remote_protocol.x
> @@ -169,6 +169,11 @@ const REMOTE_DOMAIN_BLOCK_PEEK_BUFFER_MAX = 1048576;
>  const REMOTE_DOMAIN_MEMORY_PEEK_BUFFER_MAX = 1048576;
>  
>  /*
> + * Maximum length of a security label list.
> + */
> +const REMOTE_SECURITY_LABEL_LIST_MAX=64;
> +
> +/*
>   * Maximum length of a security model field.
>   */
>  const REMOTE_SECURITY_MODEL_MAX = VIR_SECURITY_MODEL_BUFLEN;
> @@ -1082,6 +1087,15 @@ struct remote_domain_get_security_label_ret {
>      int enforcing;
>  };
>  
> +struct remote_domain_get_security_label_list_args {
> +    remote_nonnull_domain dom;
> +};
> +
> +struct remote_domain_get_security_label_list_ret {
> +    remote_domain_get_security_label_ret labels<REMOTE_SECURITY_LABEL_LIST_MAX>;
> +    int ret;
> +};
> +
>  struct remote_node_get_security_model_ret {
>      char model<REMOTE_SECURITY_MODEL_MAX>;
>      char doi<REMOTE_SECURITY_DOI_MAX>;
> @@ -2854,7 +2868,8 @@ enum remote_procedure {
>      REMOTE_PROC_DOMAIN_LIST_ALL_SNAPSHOTS = 274, /* skipgen skipgen priority:high */
>      REMOTE_PROC_DOMAIN_SNAPSHOT_LIST_ALL_CHILDREN = 275, /* skipgen skipgen priority:high */
>      REMOTE_PROC_DOMAIN_EVENT_BALLOON_CHANGE = 276, /* autogen autogen */
> -    REMOTE_PROC_DOMAIN_GET_HOSTNAME = 277 /* autogen autogen */
> +    REMOTE_PROC_DOMAIN_GET_HOSTNAME = 277, /* autogen autogen */
> +    REMOTE_PROC_DOMAIN_GET_SECURITY_LABEL_LIST = 278 /* skipgen skipgen priority:high */
>  
>      /*
>       * Notice how the entries are grouped in sets of 10 ?
> diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
> index 8d09138..9cfd285 100644
> --- a/src/remote_protocol-structs
> +++ b/src/remote_protocol-structs
> @@ -2259,4 +2259,5 @@ enum remote_procedure {
>          REMOTE_PROC_DOMAIN_SNAPSHOT_LIST_ALL_CHILDREN = 275,
>          REMOTE_PROC_DOMAIN_EVENT_BALLOON_CHANGE = 276,
>          REMOTE_PROC_DOMAIN_GET_HOSTNAME = 277,
> +        REMOTE_PROC_DOMAIN_GET_SECURITY_LABEL_LIST = 278,
>  };
> 

ACK with this squashed in:

--- remote_protocol-structs     2012-08-06 14:47:40.813120178 +0200
+++ remote_protocol-struct-t3   2012-08-06 15:22:39.223650145 +0200
@@ -749,6 +749,16 @@
         } label;
         int                        enforcing;
 };
+struct remote_domain_get_security_label_list_args {
+        remote_nonnull_domain      dom;
+};
+struct remote_domain_get_security_label_list_ret {
+        struct {
+                u_int              labels_len;
+                remote_domain_get_security_label_ret * labels_val;
+        } labels;
+        int                        ret;
+};
 struct remote_node_get_security_model_ret {
         struct {
                 u_int              model_len;

and libvirt_public.syms updated.

Michal




More information about the libvir-list mailing list