From: Chun Feng Wu <danielwuwy@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 <danielwuwy@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.
Signed-off-by: Harikumar Rajkumar <harirajkumar230@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/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index f5420bca6e..a34dafc705 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -6612,4 +6612,18 @@ virDomainGraphicsReload(virDomainPtr domain,
unsigned int type,
unsigned int flags);
+
+int
+virDomainSetThrottleGroup(virDomainPtr dom,
+ const char *group,
+ virTypedParameterPtr params,
+ int nparams,
+ unsigned int flags);
+
+int
+virDomainDelThrottleGroup(virDomainPtr dom,
+ const char *group,
+ unsigned int flags);
+
+
#endif /* LIBVIRT_DOMAIN_H */
diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h
index 4ce8da078d..124b1a12e3 100644
--- a/src/driver-hypervisor.h
+++ b/src/driver-hypervisor.h
@@ -1453,6 +1453,18 @@ typedef int
unsigned int type,
unsigned int flags);
+typedef int
+(*virDrvDomainSetThrottleGroup)(virDomainPtr dom,
+ const char *groupname,
+ virTypedParameterPtr params,
+ int nparams,
+ unsigned int flags);
+
+typedef int
+(*virDrvDomainDelThrottleGroup)(virDomainPtr dom,
+ const char *groupname,
+ unsigned int flags);
+
typedef struct _virHypervisorDriver virHypervisorDriver;
/**
@@ -1726,4 +1738,6 @@ struct _virHypervisorDriver {
virDrvDomainStartDirtyRateCalc domainStartDirtyRateCalc;
virDrvDomainFDAssociate domainFDAssociate;
virDrvDomainGraphicsReload domainGraphicsReload;
+ virDrvDomainSetThrottleGroup domainSetThrottleGroup;
+ virDrvDomainDelThrottleGroup domainDelThrottleGroup;
};
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)
+{
+ virConnectPtr conn;
+
+ VIR_DOMAIN_DEBUG(dom, "group='%s', flags=0x%x",
+ group, flags);
+
+ virResetLastError();
+
+ virCheckDomainReturn(dom, -1);
+ virCheckNonNullArgGoto(group, error);
+
+ conn = dom->conn;
+
+ if (conn->driver->domainDelThrottleGroup) {
+ int ret;
+ ret = conn->driver->domainDelThrottleGroup(dom, group, flags);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virReportUnsupportedError();
+
+ error:
+ virDispatchError(dom->conn);
+ return -1;
+}
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 30a9f806f0..df7481c144 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -680,6 +680,14 @@ virDomainTaintMessageTypeFromString;
virDomainTaintMessageTypeToString;
virDomainTaintTypeFromString;
virDomainTaintTypeToString;
+virDomainThrottleFilterDefClear;
+virDomainThrottleFilterFind;
+virDomainThrottleGroupAdd;
+virDomainThrottleGroupByName;
+virDomainThrottleGroupDefCopy;
+virDomainThrottleGroupDefFree;
+virDomainThrottleGroupDel;
+virDomainThrottleGroupUpdate;
virDomainTimerModeTypeFromString;
virDomainTimerModeTypeToString;
virDomainTimerNameTypeFromString;
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)
{
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);
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(¶ms, &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)
+{
+ 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,
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;
+
/* 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>;
+};
+
+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,
+
+ /**
+ * @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
};
diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
index 4d3dc2d249..a94e29f9c9 100644
--- a/src/remote_protocol-structs
+++ b/src/remote_protocol-structs
@@ -1050,6 +1050,31 @@ struct remote_domain_get_block_io_tune_ret {
} params;
int nparams;
};
+struct remote_domain_set_throttle_group_args {
+ remote_nonnull_domain dom;
+ remote_nonnull_string group;
+ struct {
+ u_int params_len;
+ remote_typed_param * params_val;
+ } params;
+ u_int flags;
+};
+struct remote_domain_get_throttle_group_args {
+ remote_nonnull_domain dom;
+ remote_string group;
+ u_int flags;
+};
+struct remote_domain_get_throttle_group_ret {
+ struct {
+ u_int params_len;
+ remote_typed_param * params_val;
+ } params;
+};
+struct remote_domain_del_throttle_group_args {
+ remote_nonnull_domain dom;
+ remote_string group;
+ u_int flags;
+};
struct remote_domain_get_cpu_stats_args {
remote_nonnull_domain dom;
u_int nparams;
@@ -3755,4 +3780,7 @@ enum remote_procedure {
REMOTE_PROC_NETWORK_EVENT_CALLBACK_METADATA_CHANGE = 446,
REMOTE_PROC_NODE_DEVICE_UPDATE = 447,
REMOTE_PROC_DOMAIN_GRAPHICS_RELOAD = 448,
+ REMOTE_PROC_DOMAIN_SET_THROTTLE_GROUP = 449,
+ REMOTE_PROC_DOMAIN_GET_THROTTLE_GROUP = 450,
+ REMOTE_PROC_DOMAIN_DEL_THROTTLE_GROUP = 451,
};
--
2.39.5 (Apple Git-154)
On Wed, Feb 19, 2025 at 22:27:11 +0530, Harikumar Rajkumar wrote: > From: Chun Feng Wu <danielwuwy@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 <danielwuwy@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. > > Signed-off-by: Harikumar Rajkumar <harirajkumar230@gmail.com> > --- [...] > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms > index 30a9f806f0..df7481c144 100644 > --- a/src/libvirt_private.syms > +++ b/src/libvirt_private.syms > @@ -680,6 +680,14 @@ virDomainTaintMessageTypeFromString; > virDomainTaintMessageTypeToString; > virDomainTaintTypeFromString; > virDomainTaintTypeToString; > +virDomainThrottleFilterDefClear; > +virDomainThrottleFilterFind; > +virDomainThrottleGroupAdd; > +virDomainThrottleGroupByName; > +virDomainThrottleGroupDefCopy; > +virDomainThrottleGroupDefFree; > +virDomainThrottleGroupDel; > +virDomainThrottleGroupUpdate; > virDomainTimerModeTypeFromString; > virDomainTimerModeTypeToString; > virDomainTimerNameTypeFromString; This also doesn't belong into this patch.
On Wed, Feb 19, 2025 at 22:27:11 +0530, Harikumar Rajkumar wrote:
> From: Chun Feng Wu <danielwuwy@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 <danielwuwy@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 <harirajkumar230@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(¶ms, &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
> };
© 2016 - 2025 Red Hat, Inc.