[libvirt] [PATCH v4 5/5] Update the remote API
Michal Privoznik
mprivozn at redhat.com
Mon Aug 20 17:10:41 UTC 2012
On 16.08.2012 00:10, Marcelo Cerri wrote:
> This 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 | 1 +
> src/qemu/qemu_driver.c | 73 ++++++++++++++++++++++++++++++++++++++++++
> src/remote/remote_driver.c | 46 ++++++++++++++++++++++++++
> src/remote/remote_protocol.x | 17 +++++++++-
> src/remote_protocol-structs | 11 ++++++
> 10 files changed, 264 insertions(+), 1 deletions(-)
>
> diff --git a/daemon/remote.c b/daemon/remote.c
> index 851bcc1..f82af86 100644
> --- a/daemon/remote.c
> +++ b/daemon/remote.c
> @@ -1417,6 +1417,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 893d380..b3fc8a8 100644
> --- a/src/libvirt.c
> +++ b/src/libvirt.c
> @@ -9021,6 +9021,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 number of elemnets in @seclabels on 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..43f2cf2 100644
> --- a/src/libvirt_public.syms
> +++ b/src/libvirt_public.syms
> @@ -549,6 +549,7 @@ LIBVIRT_0.10.0 {
> virDomainGetHostname;
> virConnectRegisterCloseCallback;
> virConnectUnregisterCloseCallback;
> + virDomainGetSecurityLabelList;
> } LIBVIRT_0.9.13;
>
> # .... define new API here using predicted next version number ....
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index 0c88310..f95feec 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -4119,6 +4119,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)
> {
> @@ -13362,6 +13434,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 c4941c5..51f89af 100644
> --- a/src/remote/remote_driver.c
> +++ b/src/remote/remote_driver.c
> @@ -1958,6 +1958,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,
> @@ -5260,6 +5305,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*/
s/0\*/0 \*/
ACK
Michal
More information about the libvir-list
mailing list