On Wed, Feb 19, 2025 at 22:27:11 +0530, Harikumar Rajkumar wrote:
> From: Chun Feng Wu <danielw...@163.com>
> 
> Defined new public APIs:
> * virDomainSetThrottleGroup to add or update throttlegroup within specific 
> domain,
>   it will be referenced by throttlefilter later in disk to do limits
> * virDomainGetThrottleGroup to get throttlegroup info, old-style is discarded
>   (APIs to query first for the number of parameters and then give it a
>   reasonably-sized pointer), instead, the new approach is adopted that
>   API returns allocated array of fields and number of fileds that are in it.
> * virDomainDelThrottleGroup to delete throttlegroup, it fails if this 
> throttlegroup
>   is still referenced by some throttlefilter
> 
> Signed-off-by: Chun Feng Wu <danielw...@163.com>
> 
> * Reimplement getter API to fetch data from XML.
> * Apply suggested coding style changes.
> * Update of code documentation comments.
> * Update the version to 11.1.0.

I'll update all including this to 11.2.0

> 
> Signed-off-by: Harikumar Rajkumar <harirajkumar...@gmail.com>
> ---
>  include/libvirt/libvirt-domain.h    |  14 ++++
>  src/driver-hypervisor.h             |  14 ++++
>  src/libvirt-domain.c                | 122 ++++++++++++++++++++++++++++
>  src/libvirt_private.syms            |   8 ++
>  src/libvirt_public.syms             |   6 ++
>  src/qemu/qemu_monitor.c             |  13 ---
>  src/qemu/qemu_monitor.h             |   5 --
>  src/remote/remote_daemon_dispatch.c | 105 ++++++++++++++++++++++++
>  src/remote/remote_driver.c          |   3 +
>  src/remote/remote_protocol.x        |  50 +++++++++++-
>  src/remote_protocol-structs         |  28 +++++++
>  11 files changed, 349 insertions(+), 19 deletions(-)

[...]

> diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
> index 072cc32255..326bbd9abb 100644
> --- a/src/libvirt-domain.c
> +++ b/src/libvirt-domain.c
> @@ -14162,3 +14162,125 @@ virDomainGraphicsReload(virDomainPtr domain,
>      virDispatchError(domain->conn);
>      return -1;
>  }
> +
> +
> +/**
> + * virDomainSetThrottleGroup:
> + * @dom: pointer to domain object
> + * @group: throttle group name
> + * @params: Pointer to blkio parameter objects
> + * @nparams: Number of blkio parameters (this value can be the same or
> + *           less than the number of parameters supported)
> + * @flags: bitwise-OR of virDomainModificationImpact
> + *
> + * Add throttlegroup or change all of the throttlegroup options
> + * within specific domain
> + *
> + * The @group parameter is the name for new or existing throttlegroup,
> + * it cannot be NULL, detailed throttlegroup info is included in @params,
> + * it either creates new throttlegroup with @params or updates existing
> + * throttlegroup with @params, throttlegroup can be referenced by throttle
> + * filter in attached disk to do limits, the difference from iotune is that
> + * multiple throttlegroups can be referenced within attached disk
> + *
> + * Returns -1 in case of error, 0 in case of success.
> + *
> + * Since: 11.1.0


^^^

> + */
> +int
> +virDomainSetThrottleGroup(virDomainPtr dom,
> +                          const char *group,
> +                          virTypedParameterPtr params,
> +                          int nparams,
> +                          unsigned int flags)
> +{
> +    virConnectPtr conn;
> +
> +    VIR_DOMAIN_DEBUG(dom, "params=%p, group='%s', nparams=%d, flags=0x%x",
> +                     params, group, nparams, flags);
> +    VIR_TYPED_PARAMS_DEBUG(params, nparams);
> +
> +    virResetLastError();
> +
> +    virCheckDomainReturn(dom, -1);
> +    conn = dom->conn;
> +
> +    virCheckReadOnlyGoto(conn->flags, error);
> +    virCheckNonNullArgGoto(group, error);
> +    virCheckPositiveArgGoto(nparams, error);
> +    virCheckNonNullArgGoto(params, error);
> +
> +    if (virTypedParameterValidateSet(dom->conn, params, nparams) < 0)
> +        goto error;
> +
> +    if (conn->driver->domainSetThrottleGroup) {
> +        int ret;
> +        ret = conn->driver->domainSetThrottleGroup(dom, group, params, 
> nparams, flags);
> +        if (ret < 0)
> +            goto error;
> +        return ret;
> +    }
> +
> +    virReportUnsupportedError();
> +
> + error:
> +    virDispatchError(dom->conn);
> +    return -1;
> +}
> +
> +
> +/**
> + * virDomainDelThrottleGroup:
> + * @dom: pointer to domain object
> + * @group: throttle group name
> + * @flags: bitwise-OR of virDomainModificationImpact
> + *
> + * Delete an throttlegroup from the domain. @group cannot be NULL,
> + * and the @group to be deleted must not have a throttlefilter associated 
> with
> + * it and can be any of the current valid group.
> + *
> + * @flags may include VIR_DOMAIN_AFFECT_LIVE or VIR_DOMAIN_AFFECT_CONFIG.
> + * Both flags may be set.
> + * If VIR_DOMAIN_AFFECT_LIVE is set, the change affects a running domain
> + * and may fail if domain is not alive.
> + * If VIR_DOMAIN_AFFECT_CONFIG is set, the change affects persistent state,
> + * and will fail for transient domains. If neither flag is specified (that 
> is,
> + * @flags is VIR_DOMAIN_AFFECT_CURRENT), then an inactive domain modifies
> + * persistent setup, while an active domain is hypervisor-dependent on 
> whether
> + * just live or both live and persistent state is changed.
> + *
> + * Returns -1 in case of error, 0 in case of success.
> + *
> + * Since: 11.1.0


^^^

> + */
> +int
> +virDomainDelThrottleGroup(virDomainPtr dom,
> +                          const char *group,
> +                          unsigned int flags)
> +{


[...]

> diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
> index 7a3492d9d7..7448bcb1f0 100644
> --- a/src/libvirt_public.syms
> +++ b/src/libvirt_public.syms
> @@ -948,4 +948,10 @@ LIBVIRT_10.2.0 {
>          virDomainGraphicsReload;
>  } LIBVIRT_10.1.0;
>  
> +LIBVIRT_11.1.0 {

^^^

> +    global:
> +        virDomainSetThrottleGroup;
> +        virDomainDelThrottleGroup;
> +} LIBVIRT_10.2.0;
> +
>  # .... define new API here using predicted next version number ....
> diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
> index 015f8f11cc..89669ccb15 100644
> --- a/src/qemu/qemu_monitor.c
> +++ b/src/qemu/qemu_monitor.c
> @@ -3058,19 +3058,6 @@ qemuMonitorUpdateThrottleGroup(qemuMonitor *mon,
>  }
>  
>  
> -int
> -qemuMonitorGetThrottleGroup(qemuMonitor *mon,
> -                            const char *groupname,
> -                            virDomainBlockIoTuneInfo *reply)
> -{
> -    VIR_DEBUG("throttle-group=%s, reply=%p", groupname, reply);
> -
> -    QEMU_CHECK_MONITOR(mon);
> -
> -    return qemuMonitorJSONGetThrottleGroup(mon, groupname, reply);
> -}
> -
> -
>  int
>  qemuMonitorVMStatusToPausedReason(const char *status)
>  {

This definitely doesn't belong to this patch.


> diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
> index 7b58d988d8..c6332630bd 100644
> --- a/src/qemu/qemu_monitor.h
> +++ b/src/qemu/qemu_monitor.h
> @@ -1083,11 +1083,6 @@ qemuMonitorUpdateThrottleGroup(qemuMonitor *mon,
>                                 const char *qomid,
>                                 virDomainBlockIoTuneInfo *info);
>  
> -int
> -qemuMonitorGetThrottleGroup(qemuMonitor *mon,
> -                            const char *groupname,
> -                            virDomainBlockIoTuneInfo *reply);
> -
>  int qemuMonitorSystemWakeup(qemuMonitor *mon);

Same here.

>  
>  int qemuMonitorGetVersion(qemuMonitor *mon,
> diff --git a/src/remote/remote_daemon_dispatch.c 
> b/src/remote/remote_daemon_dispatch.c
> index e812f5c3e9..2781e70396 100644
> --- a/src/remote/remote_daemon_dispatch.c
> +++ b/src/remote/remote_daemon_dispatch.c
> @@ -3618,6 +3618,111 @@ remoteDispatchDomainGetBlockIoTune(virNetServer 
> *server G_GNUC_UNUSED,
>      return rv;
>  }
>  
> +#define PARSE_THROTTLER_GROUP(val) \
> +    if (virXPathULongLong("string(./" #val ")", \
> +                          ctxt, &throttleGroup->val) == -2) { \
> +       goto cleanup; \
> +    } \
> +    if ((virTypedParamsAddULLong(&params, &nparams, &maxparams, \
> +                                 #val, throttleGroup->val) < 0)) { \
> +       goto cleanup; \
> +    }
> +
> +static int
> +remoteDispatchDomainGetThrottleGroup(virNetServer *server G_GNUC_UNUSED,
> +                                     virNetServerClient *client,
> +                                     virNetMessage *hdr G_GNUC_UNUSED,
> +                                     struct virNetMessageError *rerr,
> +                                     remote_domain_get_throttle_group_args 
> *args,
> +                                     remote_domain_get_throttle_group_ret 
> *ret)

The getter doesn't exist so this doesn't make sense either.

> +{
> +    virDomainPtr dom = NULL;
> +    int rv = -1;
> +    g_autofree char *doc = NULL;
> +    g_autoptr(xmlDoc) xml = NULL;
> +    g_autoptr(xmlXPathContext) ctxt = NULL;
> +    g_autofree xmlNodePtr *node = NULL;
> +    int n = 0;
> +    int maxparams = 0;
> +    size_t i;
> +
> +    virTypedParameterPtr params = NULL;
> +    int nparams = 0;
> +    virConnectPtr conn = remoteGetHypervisorConn(client);
> +
> +    if (!conn)
> +        goto cleanup;
> +
> +    if (!(dom = get_nonnull_domain(conn, args->dom)))
> +        goto cleanup;
> +    virCheckNonNullArgGoto(*args->group, cleanup);
> +
> +    doc = virDomainGetXMLDesc(dom, args->flags);
> +
> +    if (!(xml = virXMLParseStringCtxt(doc, _("(domain_definition)"), 
> &ctxt))) {
> +        return false;
> +    }
> +
> +    if ((n = virXPathNodeSet("/domain/throttlegroups/throttlegroup", ctxt, 
> &node)) < 0)
> +        goto cleanup;
> +
> +    if (n == 0)
> +        return 0;
> +
> +    for (i = 0; i < n; i++) {
> +        g_autoptr(virDomainThrottleGroupDef) throttleGroup = 
> g_new0(virDomainThrottleGroupDef, 1);
> +
> +        VIR_XPATH_NODE_AUTORESTORE(ctxt)
> +        ctxt->node = node[i];
> +
> +        if (STREQ(*args->group, virXPathString("string(./group_name)", 
> ctxt)) == 0) {
> +            continue;
> +        }
> +
> +        PARSE_THROTTLER_GROUP(total_bytes_sec);
> +        PARSE_THROTTLER_GROUP(read_bytes_sec);
> +        PARSE_THROTTLER_GROUP(write_bytes_sec);
> +        PARSE_THROTTLER_GROUP(total_iops_sec);
> +        PARSE_THROTTLER_GROUP(read_iops_sec);
> +        PARSE_THROTTLER_GROUP(write_iops_sec);
> +
> +        PARSE_THROTTLER_GROUP(total_bytes_sec_max);
> +        PARSE_THROTTLER_GROUP(read_bytes_sec_max);
> +        PARSE_THROTTLER_GROUP(write_bytes_sec_max);
> +        PARSE_THROTTLER_GROUP(total_iops_sec_max);
> +        PARSE_THROTTLER_GROUP(read_iops_sec_max);
> +        PARSE_THROTTLER_GROUP(write_iops_sec_max);
> +
> +        PARSE_THROTTLER_GROUP(size_iops_sec);
> +
> +        PARSE_THROTTLER_GROUP(total_bytes_sec_max_length);
> +        PARSE_THROTTLER_GROUP(read_bytes_sec_max_length);
> +        PARSE_THROTTLER_GROUP(write_bytes_sec_max_length);
> +        PARSE_THROTTLER_GROUP(total_iops_sec_max_length);
> +        PARSE_THROTTLER_GROUP(read_iops_sec_max_length);
> +        PARSE_THROTTLER_GROUP(write_iops_sec_max_length);
> +    }
> +
> +    /* Serialize the ThrottleGroup parameters. */
> +    if (virTypedParamsSerialize(params, nparams,
> +                                REMOTE_DOMAIN_THROTTLE_GROUP_PARAMETERS_MAX,
> +                                (struct _virTypedParameterRemote **) 
> &ret->params.params_val,
> +                                &ret->params.params_len,
> +                                args->flags) < 0)
> +        goto cleanup;
> +
> +    rv = 0;
> +
> + cleanup:
> +    if (rv < 0)
> +        virNetMessageSaveError(rerr);
> +    virTypedParamsFree(params, nparams);
> +    virObjectUnref(dom);
> +    return rv;
> +}
> +#undef PARSE_THROTTLEGROUP
> +
> +
>  /*-------------------------------------------------------------*/
>  
>  static int
> diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
> index 307f9ca945..a76212a22b 100644
> --- a/src/remote/remote_driver.c
> +++ b/src/remote/remote_driver.c
> @@ -2582,6 +2582,7 @@ static int remoteDomainGetBlockIoTune(virDomainPtr 
> domain,
>      return 0;
>  }
>  
> +
>  static int remoteDomainGetCPUStats(virDomainPtr domain,

Spurious newline.

>                                     virTypedParameterPtr params,
>                                     unsigned int nparams,
> @@ -7835,6 +7836,8 @@ static virHypervisorDriver hypervisor_driver = {
>      .domainSetLaunchSecurityState = remoteDomainSetLaunchSecurityState, /* 
> 8.0.0 */
>      .domainFDAssociate = remoteDomainFDAssociate, /* 9.0.0 */
>      .domainGraphicsReload = remoteDomainGraphicsReload, /* 10.2.0 */
> +    .domainSetThrottleGroup = remoteDomainSetThrottleGroup, /* 11.1.0 */
> +    .domainDelThrottleGroup = remoteDomainDelThrottleGroup, /* 11.1.0 */
>  };
>  
>  static virNetworkDriver network_driver = {
> diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
> index 41c045ff78..1d3e8a7a8c 100644
> --- a/src/remote/remote_protocol.x
> +++ b/src/remote/remote_protocol.x
> @@ -113,6 +113,9 @@ const REMOTE_DOMAIN_MEMORY_PARAMETERS_MAX = 16;
>  /* Upper limit on list of blockio tuning parameters. */
>  const REMOTE_DOMAIN_BLOCK_IO_TUNE_PARAMETERS_MAX = 32;
>  
> +/* Upper limit on list of throttle group parameters. */
> +const REMOTE_DOMAIN_THROTTLE_GROUP_PARAMETERS_MAX = 32;

We should be able to reuse the former.


> +
>  /* Upper limit on list of numa parameters. */
>  const REMOTE_DOMAIN_NUMA_PARAMETERS_MAX = 16;
>  
> @@ -1475,6 +1478,29 @@ struct remote_domain_get_block_io_tune_ret {
>      int nparams;
>  };
>  
> +struct remote_domain_set_throttle_group_args {
> +    remote_nonnull_domain dom;
> +    remote_nonnull_string group;
> +    remote_typed_param params<REMOTE_DOMAIN_THROTTLE_GROUP_PARAMETERS_MAX>;
> +    unsigned int flags;
> +};
> +
> +struct remote_domain_get_throttle_group_args {
> +    remote_nonnull_domain dom;
> +    remote_string group;
> +    unsigned int flags;
> +};
> +
> +struct remote_domain_get_throttle_group_ret {
> +    remote_typed_param params<REMOTE_DOMAIN_THROTTLE_GROUP_PARAMETERS_MAX>;
> +};

Getter doesn't exist yet you declare RPC for it.


> +
> +struct remote_domain_del_throttle_group_args {
> +    remote_nonnull_domain dom;
> +    remote_string group;
> +    unsigned int flags;
> +};
> +
>  struct remote_domain_get_cpu_stats_args {
>      remote_nonnull_domain dom;
>      unsigned int nparams;
> @@ -7048,5 +7074,27 @@ enum remote_procedure {
>       * @generate: both
>       * @acl: domain:write
>       */
> -    REMOTE_PROC_DOMAIN_GRAPHICS_RELOAD = 448
> +    REMOTE_PROC_DOMAIN_GRAPHICS_RELOAD = 448,
> +
> +    /**
> +     * @generate: both
> +     * @acl: domain:write
> +     * @acl: domain:save:!VIR_DOMAIN_AFFECT_CONFIG|VIR_DOMAIN_AFFECT_LIVE
> +     * @acl: domain:save:VIR_DOMAIN_AFFECT_CONFIG
> +     */
> +    REMOTE_PROC_DOMAIN_SET_THROTTLE_GROUP = 449,
> +
> +    /**
> +     * @generate: none
> +     * @acl: domain:read
> +     */
> +    REMOTE_PROC_DOMAIN_GET_THROTTLE_GROUP = 450,

... and here too.

> +
> +    /**
> +     * @generate: both
> +     * @acl: domain:write
> +     * @acl: domain:save:!VIR_DOMAIN_AFFECT_CONFIG|VIR_DOMAIN_AFFECT_LIVE
> +     * @acl: domain:save:VIR_DOMAIN_AFFECT_CONFIG
> +     */
> +    REMOTE_PROC_DOMAIN_DEL_THROTTLE_GROUP = 451
>  };

Reply via email to