[PATCH (pushed)] udevListInterfaces: Honour array length for zero-length NULL arrays (CVE-2024-8235)
by Peter Krempa
The refactor of 'udevListInterfacesByStatus()' which attempted to make
it usable as backend for 'udevNumOfInterfacesByStatus()' neglected to
consider the corner case of 'g_new0(..., 0)' returning NULL if the user
actually requests 0 elements.
As the code was modified to report the full number of interfaces in the
system when the list of names is NULL, the RPC code would be asked to
serialize a NULL-list of interface names with declared lenth of 1+
causing a crash.
To fix this corner case we make callers pass '-1' as @names_len (it's
conveniently an 'int' due to RPC type usage) if they don't wish to fetch
the actual list and convert all decisions to be done on @names_len being
non-negative instead of @names being non-NULL.
CVE-2024-8235
Fixes: bc596f275129bc11b2c4bcf737d380c9e8aeb72d
Resolves: https://issues.redhat.com/browse/RHEL-55373
Reported-by: Yanqiu Zhang <yanqzhan(a)redhat.com>
Signed-off-by: Peter Krempa <pkrempa(a)redhat.com>
Reviewed-by: Martin Kletzander <mkletzan(a)redhat.com>
---
src/interface/interface_backend_udev.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/src/interface/interface_backend_udev.c b/src/interface/interface_backend_udev.c
index e1a50389c9..48eacdcdc2 100644
--- a/src/interface/interface_backend_udev.c
+++ b/src/interface/interface_backend_udev.c
@@ -143,12 +143,13 @@ udevGetDevices(struct udev *udev, virUdevStatus status)
*
* @conn: connection object
* @names: optional pointer to array to be filled with interface names
- * @names_len: size of @names
+ * @names_len: size of @names, -1 if only number of interfaces is required (@names is then ignored)
* @status: status of interfaces to be listed
* @filter: ACL filter function
*
* Lists interfaces with status matching @status filling them into @names (if
- * non-NULL) and returns the number of such interfaces.
+ * @names_len is positive, caller is expected to pass a properly sized array)
+ * and returns the number of such interfaces.
*
* In case of an error -1 is returned and no interfaces are filled into @names.
*/
@@ -189,7 +190,7 @@ udevListInterfacesByStatus(virConnectPtr conn,
g_autoptr(virInterfaceDef) def = NULL;
/* Ensure we won't exceed the size of our array */
- if (names && count >= names_len)
+ if (names_len >= 0 && count >= names_len)
break;
path = udev_list_entry_get_name(dev_entry);
@@ -204,7 +205,8 @@ udevListInterfacesByStatus(virConnectPtr conn,
def = udevGetMinimalDefForDevice(dev);
if (filter(conn, def)) {
- if (names)
+ /* Fill the array only if caller want's it */
+ if (names_len >= 0)
names[count] = g_strdup(name);
count++;
}
@@ -224,7 +226,7 @@ udevConnectNumOfInterfaces(virConnectPtr conn)
if (virConnectNumOfInterfacesEnsureACL(conn) < 0)
return -1;
- return udevListInterfacesByStatus(conn, NULL, 0, VIR_UDEV_IFACE_ACTIVE,
+ return udevListInterfacesByStatus(conn, NULL, -1, VIR_UDEV_IFACE_ACTIVE,
virConnectNumOfInterfacesCheckACL);
}
@@ -247,7 +249,7 @@ udevConnectNumOfDefinedInterfaces(virConnectPtr conn)
if (virConnectNumOfDefinedInterfacesEnsureACL(conn) < 0)
return -1;
- return udevListInterfacesByStatus(conn, NULL, 0, VIR_UDEV_IFACE_INACTIVE,
+ return udevListInterfacesByStatus(conn, NULL, -1, VIR_UDEV_IFACE_INACTIVE,
virConnectNumOfDefinedInterfacesCheckACL);
}
--
2.46.0
2 months
[PATCH FOR-10.7.0 0/3] qemu: Expose availability of PS/2 feature in domcaps
by Andrea Bolognani
<blurb supported='no'/>
Andrea Bolognani (3):
qemu: Export a few functions
qemu: Change signature for virQEMUCapsSupportsI8042Toggle()
qemu: Expose availability of PS/2 feature in domcaps
src/conf/domain_capabilities.c | 1 +
src/conf/domain_capabilities.h | 1 +
src/conf/schemas/domaincaps.rng | 9 +++++++
src/qemu/qemu_capabilities.c | 24 +++++++++++++++----
src/qemu/qemu_capabilities.h | 3 ++-
src/qemu/qemu_domain.c | 14 +++++++----
src/qemu/qemu_domain.h | 6 +++++
src/qemu/qemu_validate.c | 2 +-
.../domaincapsdata/qemu_5.2.0-q35.x86_64.xml | 1 +
.../qemu_5.2.0-tcg-virt.riscv64.xml | 1 +
.../domaincapsdata/qemu_5.2.0-tcg.x86_64.xml | 1 +
.../qemu_5.2.0-virt.aarch64.xml | 1 +
.../qemu_5.2.0-virt.riscv64.xml | 1 +
tests/domaincapsdata/qemu_5.2.0.aarch64.xml | 1 +
tests/domaincapsdata/qemu_5.2.0.ppc64.xml | 1 +
tests/domaincapsdata/qemu_5.2.0.s390x.xml | 1 +
tests/domaincapsdata/qemu_5.2.0.x86_64.xml | 1 +
.../domaincapsdata/qemu_6.0.0-q35.x86_64.xml | 1 +
.../domaincapsdata/qemu_6.0.0-tcg.x86_64.xml | 1 +
.../qemu_6.0.0-virt.aarch64.xml | 1 +
tests/domaincapsdata/qemu_6.0.0.aarch64.xml | 1 +
tests/domaincapsdata/qemu_6.0.0.s390x.xml | 1 +
tests/domaincapsdata/qemu_6.0.0.x86_64.xml | 1 +
.../domaincapsdata/qemu_6.1.0-q35.x86_64.xml | 1 +
.../domaincapsdata/qemu_6.1.0-tcg.x86_64.xml | 1 +
tests/domaincapsdata/qemu_6.1.0.x86_64.xml | 1 +
.../domaincapsdata/qemu_6.2.0-q35.x86_64.xml | 1 +
.../domaincapsdata/qemu_6.2.0-tcg.x86_64.xml | 1 +
.../qemu_6.2.0-virt.aarch64.xml | 1 +
tests/domaincapsdata/qemu_6.2.0.aarch64.xml | 1 +
tests/domaincapsdata/qemu_6.2.0.ppc64.xml | 1 +
tests/domaincapsdata/qemu_6.2.0.x86_64.xml | 1 +
.../qemu_7.0.0-hvf.aarch64+hvf.xml | 1 +
.../domaincapsdata/qemu_7.0.0-q35.x86_64.xml | 1 +
.../domaincapsdata/qemu_7.0.0-tcg.x86_64.xml | 1 +
.../qemu_7.0.0-virt.aarch64.xml | 1 +
tests/domaincapsdata/qemu_7.0.0.aarch64.xml | 1 +
tests/domaincapsdata/qemu_7.0.0.ppc64.xml | 1 +
tests/domaincapsdata/qemu_7.0.0.x86_64.xml | 1 +
.../domaincapsdata/qemu_7.1.0-q35.x86_64.xml | 1 +
.../domaincapsdata/qemu_7.1.0-tcg.x86_64.xml | 1 +
tests/domaincapsdata/qemu_7.1.0.ppc64.xml | 1 +
tests/domaincapsdata/qemu_7.1.0.x86_64.xml | 1 +
.../qemu_7.2.0-hvf.x86_64+hvf.xml | 1 +
.../domaincapsdata/qemu_7.2.0-q35.x86_64.xml | 1 +
.../qemu_7.2.0-tcg.x86_64+hvf.xml | 1 +
.../domaincapsdata/qemu_7.2.0-tcg.x86_64.xml | 1 +
tests/domaincapsdata/qemu_7.2.0.ppc.xml | 1 +
tests/domaincapsdata/qemu_7.2.0.x86_64.xml | 1 +
.../domaincapsdata/qemu_8.0.0-q35.x86_64.xml | 1 +
.../qemu_8.0.0-tcg-virt.riscv64.xml | 1 +
.../domaincapsdata/qemu_8.0.0-tcg.x86_64.xml | 1 +
.../qemu_8.0.0-virt.riscv64.xml | 1 +
tests/domaincapsdata/qemu_8.0.0.x86_64.xml | 1 +
.../domaincapsdata/qemu_8.1.0-q35.x86_64.xml | 1 +
.../domaincapsdata/qemu_8.1.0-tcg.x86_64.xml | 1 +
tests/domaincapsdata/qemu_8.1.0.s390x.xml | 1 +
tests/domaincapsdata/qemu_8.1.0.x86_64.xml | 1 +
.../domaincapsdata/qemu_8.2.0-q35.x86_64.xml | 1 +
.../qemu_8.2.0-tcg-virt.loongarch64.xml | 1 +
.../domaincapsdata/qemu_8.2.0-tcg.x86_64.xml | 1 +
.../qemu_8.2.0-virt.aarch64.xml | 1 +
.../qemu_8.2.0-virt.loongarch64.xml | 1 +
tests/domaincapsdata/qemu_8.2.0.aarch64.xml | 1 +
tests/domaincapsdata/qemu_8.2.0.armv7l.xml | 1 +
tests/domaincapsdata/qemu_8.2.0.s390x.xml | 1 +
tests/domaincapsdata/qemu_8.2.0.x86_64.xml | 1 +
.../domaincapsdata/qemu_9.0.0-q35.x86_64.xml | 1 +
.../domaincapsdata/qemu_9.0.0-tcg.x86_64.xml | 1 +
tests/domaincapsdata/qemu_9.0.0.sparc.xml | 1 +
tests/domaincapsdata/qemu_9.0.0.x86_64.xml | 1 +
.../domaincapsdata/qemu_9.1.0-q35.x86_64.xml | 1 +
.../domaincapsdata/qemu_9.1.0-tcg.x86_64.xml | 1 +
tests/domaincapsdata/qemu_9.1.0.x86_64.xml | 1 +
74 files changed, 115 insertions(+), 11 deletions(-)
--
2.46.0
2 months
[PATCH 0/2] Enable NAT network support for ch guests
by Praveen K Paladugu
Move additional domain interface management methods to hypervisor
and enable NAT mode network support for ch guests.
Praveen K Paladugu (2):
hypervisor: Move domain interface mgmt methods
ch: Enable NAT Network mode support
src/ch/ch_interface.c | 57 ++++++--
src/hypervisor/domain_interface.c | 228 ++++++++++++++++++++++++++++++
src/hypervisor/domain_interface.h | 10 ++
src/libvirt_private.syms | 1 +
src/qemu/qemu_command.c | 9 +-
src/qemu/qemu_interface.c | 219 +---------------------------
6 files changed, 289 insertions(+), 235 deletions(-)
--
2.44.0
2 months
[PATCH v3 0/6] qemu: Introduce the ability to disable the built-in PS/2 controller
by Kamil Szczęk
A while back QEMU introduced a new machine property for disabling the
i8042 PS/2 controller (commit 4ccd5fe22feb95137d325f422016a6473541fe9f)
which up until then was a built-in device included by all PC machine
type descendants unconditionally. This new option allowed users to
disable emulation of this controller, thus removing the default PS/2
peripherals. The rationale for why somebody might want to disable
PS/2 peripherals is explained in the aforementioned commit. This series
of patches exposes this machine property via the 'ps2' feature, while
also taking care of side-effects, such as inhibiting the implicit
creation of PS/2 inputs in the domain XML.
Changelog:
v2 -> v3:
- Add missing example usage of the new feature
v1 -> v2:
- Use abstract 'generic-pc' machine type instead of concrete 'pc' for
property detection
- Introduce test cases along with monitor replies and capability
flags
- Add NEWS mention of the new feature
Kamil Szczęk (6):
qemu: Improve PS/2 controller detection
qemu_capabilities: Introduce QEMU_CAPS_MACHINE_I8042_OPT
qemucapabilitiesdata: Add data for QEMU_CAPS_MACHINE_I8042_OPT
qemu: Introduce the 'ps2' feature
qemuxmlconftest: Add test cases for the new 'ps2' feature
NEWS: Mention the new 'ps2' feature
NEWS.rst | 6 +
docs/formatdomain.rst | 6 +
src/conf/domain_conf.c | 6 +-
src/conf/domain_conf.h | 1 +
src/conf/domain_validate.c | 23 ++
src/conf/schemas/domaincommon.rng | 5 +
src/qemu/qemu_capabilities.c | 35 +++
src/qemu/qemu_capabilities.h | 9 +-
src/qemu/qemu_command.c | 5 +
src/qemu/qemu_domain.c | 29 ++-
src/qemu/qemu_domain.h | 1 +
src/qemu/qemu_validate.c | 27 +-
.../caps_5.2.0_x86_64.replies | 169 ++++++++++--
.../caps_6.0.0_x86_64.replies | 189 ++++++++++++--
.../caps_6.1.0_x86_64.replies | 203 +++++++++++++--
.../caps_6.2.0_x86_64.replies | 212 ++++++++++++++--
.../caps_7.0.0_x86_64.replies | 225 ++++++++++++++--
.../caps_7.0.0_x86_64.xml | 1 +
.../caps_7.1.0_x86_64.replies | 240 ++++++++++++++++--
.../caps_7.1.0_x86_64.xml | 1 +
.../caps_7.2.0_x86_64+hvf.replies | 240 ++++++++++++++++--
.../caps_7.2.0_x86_64+hvf.xml | 1 +
.../caps_7.2.0_x86_64.replies | 240 ++++++++++++++++--
.../caps_7.2.0_x86_64.xml | 1 +
.../caps_8.0.0_x86_64.replies | 240 ++++++++++++++++--
.../caps_8.0.0_x86_64.xml | 1 +
.../caps_8.1.0_x86_64.replies | 236 +++++++++++++++--
.../caps_8.1.0_x86_64.xml | 1 +
.../caps_8.2.0_x86_64.replies | 236 +++++++++++++++--
.../caps_8.2.0_x86_64.xml | 1 +
.../caps_9.0.0_x86_64.replies | 240 ++++++++++++++++--
.../caps_9.0.0_x86_64.xml | 1 +
.../caps_9.1.0_x86_64.replies | 240 ++++++++++++++++--
.../caps_9.1.0_x86_64.xml | 1 +
...-off-explicit-ps2-inputs.x86_64-latest.err | 1 +
.../machine-i8042-off-explicit-ps2-inputs.xml | 19 ++
...hine-i8042-off-vmport-on.x86_64-latest.err | 1 +
.../machine-i8042-off-vmport-on.xml | 18 ++
.../machine-i8042-off.x86_64-6.2.0.err | 1 +
.../machine-i8042-off.x86_64-latest.args | 33 +++
.../machine-i8042-off.x86_64-latest.xml | 32 +++
tests/qemuxmlconfdata/machine-i8042-off.xml | 17 ++
.../machine-i8042-on.x86_64-6.2.0.err | 1 +
.../machine-i8042-on.x86_64-latest.args | 33 +++
.../machine-i8042-on.x86_64-latest.xml | 34 +++
tests/qemuxmlconfdata/machine-i8042-on.xml | 17 ++
tests/qemuxmlconftest.c | 6 +
47 files changed, 3024 insertions(+), 261 deletions(-)
create mode 100644 tests/qemuxmlconfdata/machine-i8042-off-explicit-ps2-inputs.x86_64-latest.err
create mode 100644 tests/qemuxmlconfdata/machine-i8042-off-explicit-ps2-inputs.xml
create mode 100644 tests/qemuxmlconfdata/machine-i8042-off-vmport-on.x86_64-latest.err
create mode 100644 tests/qemuxmlconfdata/machine-i8042-off-vmport-on.xml
create mode 100644 tests/qemuxmlconfdata/machine-i8042-off.x86_64-6.2.0.err
create mode 100644 tests/qemuxmlconfdata/machine-i8042-off.x86_64-latest.args
create mode 100644 tests/qemuxmlconfdata/machine-i8042-off.x86_64-latest.xml
create mode 100644 tests/qemuxmlconfdata/machine-i8042-off.xml
create mode 100644 tests/qemuxmlconfdata/machine-i8042-on.x86_64-6.2.0.err
create mode 100644 tests/qemuxmlconfdata/machine-i8042-on.x86_64-latest.args
create mode 100644 tests/qemuxmlconfdata/machine-i8042-on.x86_64-latest.xml
create mode 100644 tests/qemuxmlconfdata/machine-i8042-on.xml
--
2.45.0
2 months
[PATCH 0/2] Enable Bridge network support for ch guests
by Praveen K Paladugu
Enble Bridge network mode for ch guest.
Praveen K Paladugu (2):
ch: Enable bridge network mode
NEWS: Add an entry for network support in ch driver.
NEWS.rst | 4 ++++
src/ch/ch_interface.c | 2 +-
2 files changed, 5 insertions(+), 1 deletion(-)
--
2.44.0
2 months
[PATCH 0/4] qemu: Fill in panic model automatically on aarch64
by Andrea Bolognani
Back when pvpanic-pci support was introduced 1.5 years ago (!), we
required the user to manually provide the model name. This is
incovenient and doesn't match the behavior seen on other
architectures. Make things more user friendly.
Andrea Bolognani (4):
tests: Add coverage for panic on riscv64
qemu: Refactor default panic model
qemu: Sometimes the default panic model doesn't exist
qemu: Use pvpanic by default on aarch64
src/qemu/qemu_domain.c | 36 ++++++++++++-------
src/qemu/qemu_validate.c | 6 +++-
.../aarch64-panic-no-model.aarch64-latest.err | 1 -
...ault-models.aarch64-latest.abi-update.args | 1 +
...fault-models.aarch64-latest.abi-update.xml | 3 ++
...64-virt-default-models.aarch64-latest.args | 1 +
...h64-virt-default-models.aarch64-latest.xml | 3 ++
.../aarch64-virt-default-models.xml | 2 +-
.../riscv64-panic-no-model.riscv64-latest.err | 1 +
...o-model.xml => riscv64-panic-no-model.xml} | 4 +--
tests/qemuxmlconftest.c | 2 +-
11 files changed, 42 insertions(+), 18 deletions(-)
delete mode 100644 tests/qemuxmlconfdata/aarch64-panic-no-model.aarch64-latest.err
create mode 100644 tests/qemuxmlconfdata/riscv64-panic-no-model.riscv64-latest.err
rename tests/qemuxmlconfdata/{aarch64-panic-no-model.xml => riscv64-panic-no-model.xml} (65%)
--
2.46.0
2 months
[libvirt PATCH] ch: interface: correctly update nicindexes
by Pavel Hrdina
Originally nicindexes were updated only for VIR_DOMAIN_NET_TYPE_BRIDGE
and VIR_DOMAIN_NET_TYPE_DIRECT. The mentioned commit adds support for
NAT network mode and changes the code to update nicindexes for
VIR_DOMAIN_NET_TYPE_ETHERNET and VIR_DOMAIN_NET_TYPE_NETWORK as well.
It doesn't work as intended and after the change nicindexes are updated
only for VIR_DOMAIN_NET_TYPE_ETHERNET and VIR_DOMAIN_NET_TYPE_NETWORK.
Fixes: aa642090738eb276f7bd70dea97d3a4fd03d59e3
Signed-off-by: Pavel Hrdina <phrdina(a)redhat.com>
---
src/ch/ch_interface.c | 42 ++++++++++++++++++++++++++++--------------
1 file changed, 28 insertions(+), 14 deletions(-)
diff --git a/src/ch/ch_interface.c b/src/ch/ch_interface.c
index 47b02bc322..87a95cde53 100644
--- a/src/ch/ch_interface.c
+++ b/src/ch/ch_interface.c
@@ -34,6 +34,26 @@
VIR_LOG_INIT("ch.ch_interface");
+
+static int
+virCHInterfaceUpdateNicindexes(virDomainNetDef *net,
+ int **nicindexes,
+ size_t *nnicindexes)
+{
+ int nicindex = 0;
+
+ if (!nicindexes || !nnicindexes || !net->ifname)
+ return 0;
+
+ if (virNetDevGetIndex(net->ifname, &nicindex) < 0)
+ return -1;
+
+ VIR_APPEND_ELEMENT(*nicindexes, *nnicindexes, nicindex);
+
+ return 0;
+}
+
+
/**
* virCHConnetNetworkInterfaces:
* @driver: pointer to ch driver object
@@ -78,6 +98,8 @@ virCHConnetNetworkInterfaces(virCHDriver *driver,
net->driver.virtio.queues) < 0)
return -1;
+ if (virCHInterfaceUpdateNicindexes(net, nicindexes, nnicindexes) < 0)
+ return -1;
break;
case VIR_DOMAIN_NET_TYPE_NETWORK:
if (virDomainInterfaceBridgeConnect(vm, net,
@@ -88,9 +110,15 @@ virCHConnetNetworkInterfaces(virCHDriver *driver,
false,
NULL) < 0)
return -1;
+
+ if (virCHInterfaceUpdateNicindexes(net, nicindexes, nnicindexes) < 0)
+ return -1;
break;
case VIR_DOMAIN_NET_TYPE_BRIDGE:
case VIR_DOMAIN_NET_TYPE_DIRECT:
+ if (virCHInterfaceUpdateNicindexes(net, nicindexes, nnicindexes) < 0)
+ return -1;
+ break;
case VIR_DOMAIN_NET_TYPE_USER:
case VIR_DOMAIN_NET_TYPE_SERVER:
case VIR_DOMAIN_NET_TYPE_CLIENT:
@@ -109,19 +137,5 @@ virCHConnetNetworkInterfaces(virCHDriver *driver,
return -1;
}
- if (actualType == VIR_DOMAIN_NET_TYPE_ETHERNET ||
- actualType == VIR_DOMAIN_NET_TYPE_NETWORK ||
- actualType == VIR_DOMAIN_NET_TYPE_BRIDGE ||
- actualType == VIR_DOMAIN_NET_TYPE_DIRECT) {
- if (nicindexes && nnicindexes && net->ifname) {
- int nicindex = 0;
-
- if (virNetDevGetIndex(net->ifname, &nicindex) < 0)
- return -1;
-
- VIR_APPEND_ELEMENT(*nicindexes, *nnicindexes, nicindex);
- }
- }
-
return 0;
}
--
2.46.0
2 months
[PATCH RFC v4 16/17] virsh: Add support for throttle group operations
by danielwuwy@163.com
From: Chun Feng Wu <danielwuwy(a)163.com>
Implement new throttle cmds
* Add new virsh cmds: domthrottlegroupset, domthrottlegrouplist,
domthrottlegroupinfo, domthrottlegroupdel
* Add doc for new cmds at docs/manpages/virsh.rst
* Add cmd helper "virshDomainThrottleGroupCompleter", which is used by
domthrottlegroupset, domthrottlegroupinfo, domthrottlegroupdel
Signed-off-by: Chun Feng Wu <danielwuwy(a)163.com>
---
docs/manpages/virsh.rst | 132 +++++++++++++
tools/virsh-completer-domain.c | 55 ++++++
tools/virsh-completer-domain.h | 11 ++
tools/virsh-domain.c | 349 ++++++++++++++++++++++++++++++++-
4 files changed, 546 insertions(+), 1 deletion(-)
diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst
index f02a28156d..79840f2ab8 100644
--- a/docs/manpages/virsh.rst
+++ b/docs/manpages/virsh.rst
@@ -1122,6 +1122,138 @@ given, but *--current* is exclusive. For querying only one of *--live*,
is different depending on hypervisor.
+domthrottlegroupset
+-------------------
+
+**Syntax:**
+
+::
+
+ domthrottlegroupset domain group-name [[--config] [--live] | [--current]]
+ [[total-bytes-sec] | [read-bytes-sec] [write-bytes-sec]]
+ [[total-iops-sec] | [read-iops-sec] [write-iops-sec]]
+ [[total-bytes-sec-max] | [read-bytes-sec-max] [write-bytes-sec-max]]
+ [[total-iops-sec-max] | [read-iops-sec-max] [write-iops-sec-max]]
+ [[total-bytes-sec-max-length] |
+ [read-bytes-sec-max-length] [write-bytes-sec-max-length]]
+ [[total-iops-sec-max-length] |
+ [read-iops-sec-max-length] [write-iops-sec-max-length]]
+ [size-iops-sec]
+
+Add or update a throttle group against specific *domain*.
+*group-name* specifies a unique throttle group name, which defines limit, and
+will be referenced by drives.
+*domain* (see also ``domblklist`` for listing these names).
+
+If no limit is specified, default them as all zeros, which will fail,
+Otherwise, set limits with these flags:
+*--total-bytes-sec* specifies total throughput limit as a scaled integer, the
+default being bytes per second if no suffix is specified.
+*--read-bytes-sec* specifies read throughput limit as a scaled integer, the
+default being bytes per second if no suffix is specified.
+*--write-bytes-sec* specifies write throughput limit as a scaled integer, the
+default being bytes per second if no suffix is specified.
+*--total-iops-sec* specifies total I/O operations limit per second.
+*--read-iops-sec* specifies read I/O operations limit per second.
+*--write-iops-sec* specifies write I/O operations limit per second.
+*--total-bytes-sec-max* specifies maximum total throughput limit as a scaled
+integer, the default being bytes per second if no suffix is specified
+*--read-bytes-sec-max* specifies maximum read throughput limit as a scaled
+integer, the default being bytes per second if no suffix is specified.
+*--write-bytes-sec-max* specifies maximum write throughput limit as a scaled
+integer, the default being bytes per second if no suffix is specified.
+*--total-iops-sec-max* specifies maximum total I/O operations limit per second.
+*--read-iops-sec-max* specifies maximum read I/O operations limit per second.
+*--write-iops-sec-max* specifies maximum write I/O operations limit per second.
+*--total-bytes-sec-max-length* specifies duration in seconds to allow maximum
+total throughput limit.
+*--read-bytes-sec-max-length* specifies duration in seconds to allow maximum
+read throughput limit.
+*--write-bytes-sec-max-length* specifies duration in seconds to allow maximum
+write throughput limit.
+*--total-iops-sec-max-length* specifies duration in seconds to allow maximum
+total I/O operations limit.
+*--read-iops-sec-max-length* specifies duration in seconds to allow maximum
+read I/O operations limit.
+*--write-iops-sec-max-length* specifies duration in seconds to allow maximum
+write I/O operations limit.
+*--size-iops-sec* specifies size I/O operations limit per second.
+
+Bytes and iops values are independent, but setting only one value (such
+as --read-bytes-sec) resets the other two in that category to unlimited.
+An explicit 0 also clears any limit. A non-zero value for a given total
+cannot be mixed with non-zero values for read or write.
+
+It is up to the hypervisor to determine how to handle the length values.
+For the QEMU hypervisor, if an I/O limit value or maximum value is set,
+then the default value of 1 second will be displayed. Supplying a 0 will
+reset the value back to the default.
+
+If *--live* is specified, affect a running guest.
+If *--config* is specified, affect the next start of a persistent guest.
+If *--current* is specified, it is equivalent to either *--live* or
+*--config*, depending on the current state of the guest.
+When setting the disk io parameters both *--live* and *--config* flags may be
+given, but *--current* is exclusive. If no flag is specified, behavior
+is different depending on hypervisor.
+
+
+domthrottlegroupdel
+-------------------
+
+**Syntax:**
+
+::
+
+ domthrottlegroupdel domain group-name [[--config] [--live] | [--current]]
+
+Delete a Throttlegroup from the domain using the specified *group-name*.
+If an Throttlegroup is currently referenced by a disk resource such as via the
+``attach-disk`` command, then the attempt to remove the Throttlegroup will fail.
+If the *group-name* does not exist an error will occur.
+
+If *--live* is specified, affect a running guest. If the guest is not
+running an error is returned.
+If *--config* is specified, affect the next start of a persistent guest.
+If *--current* is specified, it is equivalent to either *--live* or
+*--config*, depending on the current state of the guest.
+
+
+domthrottlegroupinfo
+--------------------
+
+**Syntax:**
+
+::
+
+ domthrottlegroupinfo domain group-name [[--config] [--live] | [--current]]
+
+Display domain Throttlegroup information including I/O limits setting.
+
+If *--live* is specified, get the Throttlegroup data from the running guest. If
+the guest is not running, an error is returned.
+If *--config* is specified, get the Throttlegroup data from the next start of
+a persistent guest.
+If *--current* is specified or *--live* and *--config* are not specified,
+then get the Throttlegroup data based on the current guest state, which can
+either be live or offline.
+
+
+domthrottlegrouplist
+--------------------
+
+**Syntax:**
+
+::
+
+ domthrottlegrouplist domain [--inactive]
+
+Print a table showing names of all throttle groups
+associated with *domain*. If *--inactive* is specified, query the
+block devices that will be used on the next boot, rather than those
+currently in use by a running domain.
+
+
blkiotune
---------
diff --git a/tools/virsh-completer-domain.c b/tools/virsh-completer-domain.c
index 61362224a3..3b0df15c13 100644
--- a/tools/virsh-completer-domain.c
+++ b/tools/virsh-completer-domain.c
@@ -248,6 +248,61 @@ virshDomainMigrateDisksCompleter(vshControl *ctl,
}
+int
+virshGetThrottleGroupNames(xmlXPathContext *ctxt,
+ xmlNodePtr **groups,
+ char ***groupNames)
+{
+ int ngroups;
+ size_t i;
+
+ ngroups = virXPathNodeSet("./throttlegroups/throttlegroup", ctxt, groups);
+ if (ngroups < 0)
+ return -1;
+
+ *groupNames = g_new0(char *, ngroups + 1);
+
+ for (i = 0; i < ngroups; i++) {
+ ctxt->node = (*groups)[i];
+ if (!((*groupNames)[i] = virXPathString("string(./group_name)", ctxt))) {
+ g_strfreev(*groupNames);
+ *groupNames = NULL;
+ return -1;
+ }
+ }
+
+ return ngroups;
+}
+
+
+char **
+virshDomainThrottleGroupCompleter(vshControl *ctl,
+ const vshCmd *cmd,
+ unsigned int flags)
+{
+ virshControl *priv = ctl->privData;
+ g_autoptr(xmlDoc) xmldoc = NULL;
+ g_autoptr(xmlXPathContext) ctxt = NULL;
+ g_autofree xmlNodePtr *groups = NULL;
+ g_auto(GStrv) groupNames = NULL;
+ int ngroups;
+
+ virCheckFlags(0, NULL);
+
+ if (!priv->conn || virConnectIsAlive(priv->conn) <= 0)
+ return NULL;
+
+ if (virshDomainGetXML(ctl, cmd, 0, &xmldoc, &ctxt) < 0)
+ return NULL;
+
+ ngroups = virshGetThrottleGroupNames(ctxt, &groups, &groupNames);
+ if (ngroups < 0)
+ return NULL;
+
+ return g_steal_pointer(&groupNames);
+}
+
+
char **
virshDomainUndefineStorageDisksCompleter(vshControl *ctl,
const vshCmd *cmd,
diff --git a/tools/virsh-completer-domain.h b/tools/virsh-completer-domain.h
index 27cf963912..680b3fc018 100644
--- a/tools/virsh-completer-domain.h
+++ b/tools/virsh-completer-domain.h
@@ -21,6 +21,7 @@
#pragma once
#include "vsh.h"
+#include <libxml/xpath.h>
char **
virshDomainNameCompleter(vshControl *ctl,
@@ -41,6 +42,16 @@ virshDomainDiskTargetCompleter(vshControl *ctl,
const vshCmd *cmd,
unsigned int flags);
+int
+virshGetThrottleGroupNames(xmlXPathContext *ctxt,
+ xmlNodePtr **groups,
+ char ***groupNames);
+
+char **
+virshDomainThrottleGroupCompleter(vshControl *ctl,
+ const vshCmd *cmd,
+ unsigned int flags);
+
char **
virshDomainInterfaceStateCompleter(vshControl *ctl,
const vshCmd *cmd,
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 7c60920788..aeb783de88 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -1375,7 +1375,7 @@ static const vshCmdOptDef opts_blkdeviotune[] = {
VIRSH_COMMON_OPT_DOMAIN_CURRENT,
{.name = NULL}
};
-#undef VSH_OPTS_IOTUNE
+
static bool
cmdBlkdeviotune(vshControl *ctl, const vshCmd *cmd)
@@ -1513,6 +1513,329 @@ cmdBlkdeviotune(vshControl *ctl, const vshCmd *cmd)
goto cleanup;
}
+
+/*
+ * "throttlegrouplist" command
+ */
+static const vshCmdInfo info_throttlegrouplist = {
+ .help = N_("list all domain throttlegroups."),
+ .desc = N_("Get the summary of throttle groups for a domain."),
+};
+
+
+static const vshCmdOptDef opts_throttlegrouplist[] = {
+ VIRSH_COMMON_OPT_DOMAIN_FULL(0),
+ {.name = "inactive",
+ .type = VSH_OT_BOOL,
+ .help = N_("get inactive rather than running configuration")
+ },
+ {.name = NULL}
+};
+
+
+static bool
+cmdThrottleGroupList(vshControl *ctl,
+ const vshCmd *cmd)
+{
+ unsigned int flags = 0;
+ size_t i;
+ g_autoptr(xmlDoc) xml = NULL;
+ g_autoptr(xmlXPathContext) ctxt = NULL;
+ g_autofree xmlNodePtr *groups = NULL;
+ g_auto(GStrv) groupNames = NULL;
+ ssize_t ngroups;
+ g_autoptr(vshTable) table = NULL;
+
+ if (vshCommandOptBool(cmd, "inactive"))
+ flags |= VIR_DOMAIN_XML_INACTIVE;
+
+ if (virshDomainGetXML(ctl, cmd, flags, &xml, &ctxt) < 0)
+ return false;
+
+ table = vshTableNew(_("Name"), NULL);
+
+ if (!table)
+ return false;
+
+ ngroups = virshGetThrottleGroupNames(ctxt, &groups, &groupNames);
+ for (i = 0; i < ngroups; i++) {
+ if (vshTableRowAppend(table, groupNames[i], NULL) < 0)
+ return false;
+ }
+
+ vshTablePrintToStdout(table, ctl);
+
+ return true;
+}
+
+
+/*
+ * "throttlegroupset" command
+ */
+static const vshCmdInfo info_throttlegroupset = {
+ .help = N_("Add or update a throttling group."),
+ .desc = N_("Add or updte a throttling group."),
+};
+
+
+static const vshCmdOptDef opts_throttlegroupset[] = {
+ VIRSH_COMMON_OPT_DOMAIN_FULL(0),
+ {.name = "group-name",
+ .type = VSH_OT_STRING,
+ .positional = true,
+ .required = true,
+ .completer = virshDomainThrottleGroupCompleter,
+ .help = N_("throttle group name")
+ },
+ VSH_OPTS_IOTUNE(),
+ VIRSH_COMMON_OPT_DOMAIN_CONFIG,
+ VIRSH_COMMON_OPT_DOMAIN_LIVE,
+ VIRSH_COMMON_OPT_DOMAIN_CURRENT,
+ {.name = NULL}
+};
+#undef VSH_OPTS_IOTUNE
+
+
+static bool
+cmdThrottleGroupSet(vshControl *ctl,
+ const vshCmd *cmd)
+{
+ g_autoptr(virshDomain) dom = NULL;
+ const char *group_name = NULL;
+ unsigned long long value;
+ int nparams = 0;
+ int maxparams = 0;
+ virTypedParameterPtr params = NULL;
+ unsigned int flags = VIR_DOMAIN_AFFECT_CURRENT;
+ int rv = 0;
+ bool current = vshCommandOptBool(cmd, "current");
+ bool config = vshCommandOptBool(cmd, "config");
+ bool live = vshCommandOptBool(cmd, "live");
+ bool ret = false;
+
+ VSH_EXCLUSIVE_OPTIONS_VAR(current, live);
+ VSH_EXCLUSIVE_OPTIONS_VAR(current, config);
+
+ if (config)
+ flags |= VIR_DOMAIN_AFFECT_CONFIG;
+ if (live)
+ flags |= VIR_DOMAIN_AFFECT_LIVE;
+
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
+ goto cleanup;
+
+
+#define VSH_SET_THROTTLE_GROUP_SCALED(PARAM, CONST) \
+ if ((rv = vshCommandOptScaledInt(ctl, cmd, #PARAM, &value, \
+ 1, ULLONG_MAX)) < 0) { \
+ goto interror; \
+ } else if (rv > 0) { \
+ if (virTypedParamsAddULLong(¶ms, &nparams, &maxparams, \
+ VIR_DOMAIN_BLOCK_IOTUNE_##CONST, \
+ value) < 0) \
+ goto save_error; \
+ }
+
+ VSH_SET_THROTTLE_GROUP_SCALED(total-bytes-sec, TOTAL_BYTES_SEC);
+ VSH_SET_THROTTLE_GROUP_SCALED(read-bytes-sec, READ_BYTES_SEC);
+ VSH_SET_THROTTLE_GROUP_SCALED(write-bytes-sec, WRITE_BYTES_SEC);
+ VSH_SET_THROTTLE_GROUP_SCALED(total-bytes-sec-max, TOTAL_BYTES_SEC_MAX);
+ VSH_SET_THROTTLE_GROUP_SCALED(read-bytes-sec-max, READ_BYTES_SEC_MAX);
+ VSH_SET_THROTTLE_GROUP_SCALED(write-bytes-sec-max, WRITE_BYTES_SEC_MAX);
+#undef VSH_SET_THROTTLE_GROUP_SCALED
+
+#define VSH_SET_THROTTLE_GROUP(PARAM, CONST) \
+ if ((rv = vshCommandOptULongLong(ctl, cmd, #PARAM, &value)) < 0) { \
+ goto interror; \
+ } else if (rv > 0) { \
+ if (virTypedParamsAddULLong(¶ms, &nparams, &maxparams, \
+ VIR_DOMAIN_BLOCK_IOTUNE_##CONST, \
+ value) < 0) \
+ goto save_error; \
+ }
+
+ VSH_SET_THROTTLE_GROUP(total-iops-sec, TOTAL_IOPS_SEC);
+ VSH_SET_THROTTLE_GROUP(read-iops-sec, READ_IOPS_SEC);
+ VSH_SET_THROTTLE_GROUP(write-iops-sec, WRITE_IOPS_SEC);
+ VSH_SET_THROTTLE_GROUP(total-iops-sec-max, TOTAL_IOPS_SEC_MAX);
+ VSH_SET_THROTTLE_GROUP(read-iops-sec-max, READ_IOPS_SEC_MAX);
+ VSH_SET_THROTTLE_GROUP(write-iops-sec-max, WRITE_IOPS_SEC_MAX);
+ VSH_SET_THROTTLE_GROUP(size-iops-sec, SIZE_IOPS_SEC);
+
+ VSH_SET_THROTTLE_GROUP(total-bytes-sec-max-length, TOTAL_BYTES_SEC_MAX_LENGTH);
+ VSH_SET_THROTTLE_GROUP(read-bytes-sec-max-length, READ_BYTES_SEC_MAX_LENGTH);
+ VSH_SET_THROTTLE_GROUP(write-bytes-sec-max-length, WRITE_BYTES_SEC_MAX_LENGTH);
+ VSH_SET_THROTTLE_GROUP(total-iops-sec-max-length, TOTAL_IOPS_SEC_MAX_LENGTH);
+ VSH_SET_THROTTLE_GROUP(read-iops-sec-max-length, READ_IOPS_SEC_MAX_LENGTH);
+ VSH_SET_THROTTLE_GROUP(write-iops-sec-max-length, WRITE_IOPS_SEC_MAX_LENGTH);
+#undef VSH_SET_THROTTLE_GROUP
+
+ if (vshCommandOptString(ctl, cmd, "group-name", &group_name) < 0) {
+ goto cleanup;
+ }
+
+ if (group_name) {
+ if (virTypedParamsAddString(¶ms, &nparams, &maxparams,
+ VIR_DOMAIN_BLOCK_IOTUNE_GROUP_NAME,
+ group_name) < 0)
+ goto save_error;
+ }
+
+ if (virDomainSetThrottleGroup(dom, group_name, params, nparams, flags) < 0)
+ goto error;
+ vshPrintExtra(ctl, "%s", _("Throttle group set successfully\n"));
+
+ ret = true;
+
+ cleanup:
+ virTypedParamsFree(params, nparams);
+ return ret;
+
+ save_error:
+ vshSaveLibvirtError();
+ error:
+ vshError(ctl, "%s", _("Unable to set throttle group"));
+ goto cleanup;
+
+ interror:
+ vshError(ctl, "%s", _("Unable to parse integer parameter"));
+ goto cleanup;
+}
+
+
+/*
+ * "throttlegroupdel" command
+ */
+static const vshCmdInfo info_throttlegroupdel = {
+ .help = N_("Delete a throttling group."),
+ .desc = N_("Delete a throttling group."),
+};
+
+
+static const vshCmdOptDef opts_throttlegroupdel[] = {
+ VIRSH_COMMON_OPT_DOMAIN_FULL(0),
+ {.name = "group-name",
+ .type = VSH_OT_STRING,
+ .positional = true,
+ .required = true,
+ .completer = virshDomainThrottleGroupCompleter,
+ .help = N_("throttle group name")
+ },
+ VIRSH_COMMON_OPT_DOMAIN_CONFIG,
+ VIRSH_COMMON_OPT_DOMAIN_LIVE,
+ VIRSH_COMMON_OPT_DOMAIN_CURRENT,
+ {.name = NULL}
+};
+
+
+static bool
+cmdThrottleGroupDel(vshControl *ctl,
+ const vshCmd *cmd)
+{
+ g_autoptr(virshDomain) dom = NULL;
+ const char *group_name = NULL;
+ bool config = vshCommandOptBool(cmd, "config");
+ bool live = vshCommandOptBool(cmd, "live");
+ bool current = vshCommandOptBool(cmd, "current");
+ unsigned int flags = VIR_DOMAIN_AFFECT_CURRENT;
+
+ VSH_EXCLUSIVE_OPTIONS_VAR(current, live);
+ VSH_EXCLUSIVE_OPTIONS_VAR(current, config);
+
+ if (config)
+ flags |= VIR_DOMAIN_AFFECT_CONFIG;
+ if (live)
+ flags |= VIR_DOMAIN_AFFECT_LIVE;
+
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
+ return false;
+
+ if (vshCommandOptString(ctl, cmd, "group-name", &group_name) < 0) {
+ return false;
+ }
+
+ if (virDomainDelThrottleGroup(dom, group_name, flags) < 0)
+ return false;
+ vshPrintExtra(ctl, "%s", _("Throttle group deleted successfully\n"));
+
+ return true;
+}
+
+
+/*
+ * "throttlegroupinfo" command
+ */
+static const vshCmdInfo info_throttlegroupinfo = {
+ .help = N_("Get a throttling group."),
+ .desc = N_("Get a throttling group."),
+};
+
+
+static const vshCmdOptDef opts_throttlegroupinfo[] = {
+ VIRSH_COMMON_OPT_DOMAIN_FULL(0),
+ {.name = "group-name",
+ .type = VSH_OT_STRING,
+ .positional = true,
+ .required = true,
+ .completer = virshDomainThrottleGroupCompleter,
+ .help = N_("throttle group name")
+ },
+ VIRSH_COMMON_OPT_DOMAIN_CONFIG,
+ VIRSH_COMMON_OPT_DOMAIN_LIVE,
+ VIRSH_COMMON_OPT_DOMAIN_CURRENT,
+ {.name = NULL}
+};
+
+
+static bool
+cmdThrottleGroupInfo(vshControl *ctl,
+ const vshCmd *cmd)
+{
+ g_autoptr(virshDomain) dom = NULL;
+ const char *group_name = NULL;
+ int nparams = 0;
+ virTypedParameterPtr params = NULL;
+ unsigned int flags = VIR_DOMAIN_AFFECT_CURRENT;
+ size_t i;
+ bool current = vshCommandOptBool(cmd, "current");
+ bool config = vshCommandOptBool(cmd, "config");
+ bool live = vshCommandOptBool(cmd, "live");
+ bool ret = false;
+
+ VSH_EXCLUSIVE_OPTIONS_VAR(current, live);
+ VSH_EXCLUSIVE_OPTIONS_VAR(current, config);
+
+ if (config)
+ flags |= VIR_DOMAIN_AFFECT_CONFIG;
+ if (live)
+ flags |= VIR_DOMAIN_AFFECT_LIVE;
+
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
+ goto cleanup;
+
+ if (vshCommandOptString(ctl, cmd, "group-name", &group_name) < 0) {
+ goto cleanup;
+ }
+
+ if (virDomainGetThrottleGroup(dom, group_name, ¶ms, &nparams, flags) != 0) {
+ vshError(ctl, "%s",
+ _("Unable to get throttle group parameters"));
+ goto cleanup;
+ }
+
+ for (i = 0; i < nparams; i++) {
+ g_autofree char *str = vshGetTypedParamValue(ctl, ¶ms[i]);
+ vshPrint(ctl, "%-15s: %s\n", params[i].field, str);
+ }
+
+ ret = true;
+
+ cleanup:
+ virTypedParamsFree(params, nparams);
+ return ret;
+}
+
+
/*
* "blkiotune" command
*/
@@ -13382,6 +13705,30 @@ const vshCmdDef domManagementCmds[] = {
.info = &info_blkdeviotune,
.flags = 0
},
+ {.name = "domthrottlegroupset",
+ .handler = cmdThrottleGroupSet,
+ .opts = opts_throttlegroupset,
+ .info = &info_throttlegroupset,
+ .flags = 0
+ },
+ {.name = "domthrottlegroupdel",
+ .handler = cmdThrottleGroupDel,
+ .opts = opts_throttlegroupdel,
+ .info = &info_throttlegroupdel,
+ .flags = 0
+ },
+ {.name = "domthrottlegroupinfo",
+ .handler = cmdThrottleGroupInfo,
+ .opts = opts_throttlegroupinfo,
+ .info = &info_throttlegroupinfo,
+ .flags = 0
+ },
+ {.name = "domthrottlegrouplist",
+ .handler = cmdThrottleGroupList,
+ .opts = opts_throttlegrouplist,
+ .info = &info_throttlegrouplist,
+ .flags = 0
+ },
{.name = "blkiotune",
.handler = cmdBlkiotune,
.opts = opts_blkiotune,
--
2.43.0
2 months
[PATCH RFC v4 15/17] virsh: Refactor iotune options for re-use
by danielwuwy@163.com
From: Chun Feng Wu <danielwuwy(a)163.com>
Define macro for iotune options, this macro is used by opts_blkdeviotune and
later throttle group opts
Signed-off-by: Chun Feng Wu <danielwuwy(a)163.com>
---
tools/virsh-domain.c | 308 ++++++++++++++++++++++---------------------
1 file changed, 156 insertions(+), 152 deletions(-)
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 50e80689a2..7c60920788 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -1197,6 +1197,160 @@ static const vshCmdInfo info_blkdeviotune = {
.desc = N_("Set or query disk I/O parameters such as block throttling."),
};
+#define VSH_OPTS_IOTUNE() \
+ {.name = "total_bytes_sec", \
+ .type = VSH_OT_ALIAS, \
+ .help = "total-bytes-sec" \
+ }, \
+ {.name = "total-bytes-sec", \
+ .type = VSH_OT_INT, \
+ .help = N_("total throughput limit, as scaled integer (default bytes)") \
+ }, \
+ {.name = "read_bytes_sec", \
+ .type = VSH_OT_ALIAS, \
+ .help = "read-bytes-sec" \
+ }, \
+ {.name = "read-bytes-sec", \
+ .type = VSH_OT_INT, \
+ .help = N_("read throughput limit, as scaled integer (default bytes)") \
+ }, \
+ {.name = "write_bytes_sec", \
+ .type = VSH_OT_ALIAS, \
+ .help = "write-bytes-sec" \
+ }, \
+ {.name = "write-bytes-sec", \
+ .type = VSH_OT_INT, \
+ .help = N_("write throughput limit, as scaled integer (default bytes)") \
+ }, \
+ {.name = "total_iops_sec", \
+ .type = VSH_OT_ALIAS, \
+ .help = "total-iops-sec" \
+ }, \
+ {.name = "total-iops-sec", \
+ .type = VSH_OT_INT, \
+ .help = N_("total I/O operations limit per second") \
+ }, \
+ {.name = "read_iops_sec", \
+ .type = VSH_OT_ALIAS, \
+ .help = "read-iops-sec" \
+ }, \
+ {.name = "read-iops-sec", \
+ .type = VSH_OT_INT, \
+ .help = N_("read I/O operations limit per second") \
+ }, \
+ {.name = "write_iops_sec", \
+ .type = VSH_OT_ALIAS, \
+ .help = "write-iops-sec" \
+ }, \
+ {.name = "write-iops-sec", \
+ .type = VSH_OT_INT, \
+ .help = N_("write I/O operations limit per second") \
+ }, \
+ {.name = "total_bytes_sec_max", \
+ .type = VSH_OT_ALIAS, \
+ .help = "total-bytes-sec-max" \
+ }, \
+ {.name = "total-bytes-sec-max", \
+ .type = VSH_OT_INT, \
+ .help = N_("total max, as scaled integer (default bytes)") \
+ }, \
+ {.name = "read_bytes_sec_max", \
+ .type = VSH_OT_ALIAS, \
+ .help = "read-bytes-sec-max" \
+ }, \
+ {.name = "read-bytes-sec-max", \
+ .type = VSH_OT_INT, \
+ .help = N_("read max, as scaled integer (default bytes)") \
+ }, \
+ {.name = "write_bytes_sec_max", \
+ .type = VSH_OT_ALIAS, \
+ .help = "write-bytes-sec-max" \
+ }, \
+ {.name = "write-bytes-sec-max", \
+ .type = VSH_OT_INT, \
+ .help = N_("write max, as scaled integer (default bytes)") \
+ }, \
+ {.name = "total_iops_sec_max", \
+ .type = VSH_OT_ALIAS, \
+ .help = "total-iops-sec-max" \
+ }, \
+ {.name = "total-iops-sec-max", \
+ .type = VSH_OT_INT, \
+ .help = N_("total I/O operations max") \
+ }, \
+ {.name = "read_iops_sec_max", \
+ .type = VSH_OT_ALIAS, \
+ .help = "read-iops-sec-max" \
+ }, \
+ {.name = "read-iops-sec-max", \
+ .type = VSH_OT_INT, \
+ .help = N_("read I/O operations max") \
+ }, \
+ {.name = "write_iops_sec_max", \
+ .type = VSH_OT_ALIAS, \
+ .help = "write-iops-sec-max" \
+ }, \
+ {.name = "write-iops-sec-max", \
+ .type = VSH_OT_INT, \
+ .help = N_("write I/O operations max") \
+ }, \
+ {.name = "size_iops_sec", \
+ .type = VSH_OT_ALIAS, \
+ .help = "size-iops-sec" \
+ }, \
+ {.name = "size-iops-sec", \
+ .type = VSH_OT_INT, \
+ .help = N_("I/O size in bytes") \
+ }, \
+ {.name = "total_bytes_sec_max_length", \
+ .type = VSH_OT_ALIAS, \
+ .help = "total-bytes-sec-max-length" \
+ }, \
+ {.name = "total-bytes-sec-max-length", \
+ .type = VSH_OT_INT, \
+ .help = N_("duration in seconds to allow total max bytes") \
+ }, \
+ {.name = "read_bytes_sec_max_length", \
+ .type = VSH_OT_ALIAS, \
+ .help = "read-bytes-sec-max-length" \
+ }, \
+ {.name = "read-bytes-sec-max-length", \
+ .type = VSH_OT_INT, \
+ .help = N_("duration in seconds to allow read max bytes") \
+ }, \
+ {.name = "write_bytes_sec_max_length", \
+ .type = VSH_OT_ALIAS, \
+ .help = "write-bytes-sec-max-length" \
+ }, \
+ {.name = "write-bytes-sec-max-length", \
+ .type = VSH_OT_INT, \
+ .help = N_("duration in seconds to allow write max bytes") \
+ }, \
+ {.name = "total_iops_sec_max_length", \
+ .type = VSH_OT_ALIAS, \
+ .help = "total-iops-sec-max-length" \
+ }, \
+ {.name = "total-iops-sec-max-length", \
+ .type = VSH_OT_INT, \
+ .help = N_("duration in seconds to allow total I/O operations max") \
+ }, \
+ {.name = "read_iops_sec_max_length", \
+ .type = VSH_OT_ALIAS, \
+ .help = "read-iops-sec-max-length" \
+ }, \
+ {.name = "read-iops-sec-max-length", \
+ .type = VSH_OT_INT, \
+ .help = N_("duration in seconds to allow read I/O operations max") \
+ }, \
+ {.name = "write_iops_sec_max_length", \
+ .type = VSH_OT_ALIAS, \
+ .help = "write-iops-sec-max-length" \
+ }, \
+ {.name = "write-iops-sec-max-length", \
+ .type = VSH_OT_INT, \
+ .help = N_("duration in seconds to allow write I/O operations max") \
+ } \
+
static const vshCmdOptDef opts_blkdeviotune[] = {
VIRSH_COMMON_OPT_DOMAIN_FULL(0),
{.name = "device",
@@ -1206,110 +1360,6 @@ static const vshCmdOptDef opts_blkdeviotune[] = {
.completer = virshDomainDiskTargetCompleter,
.help = N_("block device")
},
- {.name = "total_bytes_sec",
- .type = VSH_OT_ALIAS,
- .help = "total-bytes-sec"
- },
- {.name = "total-bytes-sec",
- .type = VSH_OT_INT,
- .help = N_("total throughput limit, as scaled integer (default bytes)")
- },
- {.name = "read_bytes_sec",
- .type = VSH_OT_ALIAS,
- .help = "read-bytes-sec"
- },
- {.name = "read-bytes-sec",
- .type = VSH_OT_INT,
- .help = N_("read throughput limit, as scaled integer (default bytes)")
- },
- {.name = "write_bytes_sec",
- .type = VSH_OT_ALIAS,
- .help = "write-bytes-sec"
- },
- {.name = "write-bytes-sec",
- .type = VSH_OT_INT,
- .help = N_("write throughput limit, as scaled integer (default bytes)")
- },
- {.name = "total_iops_sec",
- .type = VSH_OT_ALIAS,
- .help = "total-iops-sec"
- },
- {.name = "total-iops-sec",
- .type = VSH_OT_INT,
- .help = N_("total I/O operations limit per second")
- },
- {.name = "read_iops_sec",
- .type = VSH_OT_ALIAS,
- .help = "read-iops-sec"
- },
- {.name = "read-iops-sec",
- .type = VSH_OT_INT,
- .help = N_("read I/O operations limit per second")
- },
- {.name = "write_iops_sec",
- .type = VSH_OT_ALIAS,
- .help = "write-iops-sec"
- },
- {.name = "write-iops-sec",
- .type = VSH_OT_INT,
- .help = N_("write I/O operations limit per second")
- },
- {.name = "total_bytes_sec_max",
- .type = VSH_OT_ALIAS,
- .help = "total-bytes-sec-max"
- },
- {.name = "total-bytes-sec-max",
- .type = VSH_OT_INT,
- .help = N_("total max, as scaled integer (default bytes)")
- },
- {.name = "read_bytes_sec_max",
- .type = VSH_OT_ALIAS,
- .help = "read-bytes-sec-max"
- },
- {.name = "read-bytes-sec-max",
- .type = VSH_OT_INT,
- .help = N_("read max, as scaled integer (default bytes)")
- },
- {.name = "write_bytes_sec_max",
- .type = VSH_OT_ALIAS,
- .help = "write-bytes-sec-max"
- },
- {.name = "write-bytes-sec-max",
- .type = VSH_OT_INT,
- .help = N_("write max, as scaled integer (default bytes)")
- },
- {.name = "total_iops_sec_max",
- .type = VSH_OT_ALIAS,
- .help = "total-iops-sec-max"
- },
- {.name = "total-iops-sec-max",
- .type = VSH_OT_INT,
- .help = N_("total I/O operations max")
- },
- {.name = "read_iops_sec_max",
- .type = VSH_OT_ALIAS,
- .help = "read-iops-sec-max"
- },
- {.name = "read-iops-sec-max",
- .type = VSH_OT_INT,
- .help = N_("read I/O operations max")
- },
- {.name = "write_iops_sec_max",
- .type = VSH_OT_ALIAS,
- .help = "write-iops-sec-max"
- },
- {.name = "write-iops-sec-max",
- .type = VSH_OT_INT,
- .help = N_("write I/O operations max")
- },
- {.name = "size_iops_sec",
- .type = VSH_OT_ALIAS,
- .help = "size-iops-sec"
- },
- {.name = "size-iops-sec",
- .type = VSH_OT_INT,
- .help = N_("I/O size in bytes")
- },
{.name = "group_name",
.type = VSH_OT_ALIAS,
.help = "group-name"
@@ -1319,59 +1369,13 @@ static const vshCmdOptDef opts_blkdeviotune[] = {
.completer = virshCompleteEmpty,
.help = N_("group name to share I/O quota between multiple drives")
},
- {.name = "total_bytes_sec_max_length",
- .type = VSH_OT_ALIAS,
- .help = "total-bytes-sec-max-length"
- },
- {.name = "total-bytes-sec-max-length",
- .type = VSH_OT_INT,
- .help = N_("duration in seconds to allow total max bytes")
- },
- {.name = "read_bytes_sec_max_length",
- .type = VSH_OT_ALIAS,
- .help = "read-bytes-sec-max-length"
- },
- {.name = "read-bytes-sec-max-length",
- .type = VSH_OT_INT,
- .help = N_("duration in seconds to allow read max bytes")
- },
- {.name = "write_bytes_sec_max_length",
- .type = VSH_OT_ALIAS,
- .help = "write-bytes-sec-max-length"
- },
- {.name = "write-bytes-sec-max-length",
- .type = VSH_OT_INT,
- .help = N_("duration in seconds to allow write max bytes")
- },
- {.name = "total_iops_sec_max_length",
- .type = VSH_OT_ALIAS,
- .help = "total-iops-sec-max-length"
- },
- {.name = "total-iops-sec-max-length",
- .type = VSH_OT_INT,
- .help = N_("duration in seconds to allow total I/O operations max")
- },
- {.name = "read_iops_sec_max_length",
- .type = VSH_OT_ALIAS,
- .help = "read-iops-sec-max-length"
- },
- {.name = "read-iops-sec-max-length",
- .type = VSH_OT_INT,
- .help = N_("duration in seconds to allow read I/O operations max")
- },
- {.name = "write_iops_sec_max_length",
- .type = VSH_OT_ALIAS,
- .help = "write-iops-sec-max-length"
- },
- {.name = "write-iops-sec-max-length",
- .type = VSH_OT_INT,
- .help = N_("duration in seconds to allow write I/O operations max")
- },
+ VSH_OPTS_IOTUNE(),
VIRSH_COMMON_OPT_DOMAIN_CONFIG,
VIRSH_COMMON_OPT_DOMAIN_LIVE,
VIRSH_COMMON_OPT_DOMAIN_CURRENT,
{.name = NULL}
};
+#undef VSH_OPTS_IOTUNE
static bool
cmdBlkdeviotune(vshControl *ctl, const vshCmd *cmd)
--
2.43.0
2 months
[PATCH RFC v4 14/17] test_driver: Test throttle group lifecycle APIs
by danielwuwy@163.com
From: Chun Feng Wu <danielwuwy(a)163.com>
Test throttle group APIs
* Extract common methods for both "testDomainSetThrottleGroup" and "testDomainSetBlockIoTune":
testDomainValidateBlockIoTune, testDomainSetBlockIoTuneFields,
testDomainCheckBlockIoTuneMutualExclusion, testDomainCheckBlockIoTuneMax
* Test "Set": testDomainSetThrottleGroup
* Test "Get": testDomainGetThrottleGroup
* Test "Del": testDomainDelThrottleGroup
Signed-off-by: Chun Feng Wu <danielwuwy(a)163.com>
---
src/test/test_driver.c | 452 ++++++++++++++++++++++++++++++-----------
1 file changed, 330 insertions(+), 122 deletions(-)
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 7cb77f044d..d485e552d8 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -3783,25 +3783,8 @@ testDomainGetInterfaceParameters(virDomainPtr dom,
#define TEST_BLOCK_IOTUNE_MAX 1000000000000000LL
static int
-testDomainSetBlockIoTune(virDomainPtr dom,
- const char *path,
- virTypedParameterPtr params,
- int nparams,
- unsigned int flags)
+testDomainValidateBlockIoTune(virTypedParameterPtr params, int nparams)
{
- virDomainObj *vm = NULL;
- virDomainDef *def = NULL;
- virDomainBlockIoTuneInfo info = {0};
- virDomainDiskDef *conf_disk = NULL;
- virTypedParameterPtr eventParams = NULL;
- int eventNparams = 0;
- int eventMaxparams = 0;
- size_t i;
- int ret = -1;
-
- virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
- VIR_DOMAIN_AFFECT_CONFIG, -1);
-
if (virTypedParamsValidate(params, nparams,
VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC,
VIR_TYPED_PARAM_ULLONG,
@@ -3846,34 +3829,29 @@ testDomainSetBlockIoTune(virDomainPtr dom,
NULL) < 0)
return -1;
- if (!(vm = testDomObjFromDomain(dom)))
- return -1;
-
- if (!(def = virDomainObjGetOneDef(vm, flags)))
- goto cleanup;
-
- if (!(conf_disk = virDomainDiskByName(def, path, true))) {
- virReportError(VIR_ERR_INVALID_ARG,
- _("missing persistent configuration for disk '%1$s'"),
- path);
- goto cleanup;
- }
+ return 0;
+}
- info = conf_disk->blkdeviotune;
- info.group_name = g_strdup(conf_disk->blkdeviotune.group_name);
- if (virTypedParamsAddString(&eventParams, &eventNparams, &eventMaxparams,
- VIR_DOMAIN_TUNABLE_BLKDEV_DISK, path) < 0)
- goto cleanup;
+static int
+testDomainSetBlockIoTuneFields(virDomainBlockIoTuneInfo *info,
+ virTypedParameterPtr params,
+ int nparams,
+ virTypedParameterPtr *eventParams,
+ int *eventNparams,
+ int *eventMaxparams)
+{
+ size_t i;
+ int ret = -1;
-#define SET_IOTUNE_FIELD(FIELD, STR, TUNABLE_STR) \
- if (STREQ(param->field, STR)) { \
- info.FIELD = param->value.ul; \
- if (virTypedParamsAddULLong(&eventParams, &eventNparams, \
- &eventMaxparams, \
- TUNABLE_STR, \
+#define SET_IOTUNE_FIELD(FIELD, CONST) \
+ if (STREQ(param->field, VIR_DOMAIN_BLOCK_IOTUNE_##CONST)) { \
+ info->FIELD = param->value.ul; \
+ if (virTypedParamsAddULLong(eventParams, eventNparams, \
+ eventMaxparams, \
+ VIR_DOMAIN_TUNABLE_BLKDEV_##CONST, \
param->value.ul) < 0) \
- goto cleanup; \
+ goto endjob; \
continue; \
}
@@ -3884,119 +3862,99 @@ testDomainSetBlockIoTune(virDomainPtr dom,
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
_("block I/O throttle limit value must be no more than %1$llu"),
TEST_BLOCK_IOTUNE_MAX);
- goto cleanup;
+ goto endjob;
}
- SET_IOTUNE_FIELD(total_bytes_sec,
- VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC,
- VIR_DOMAIN_TUNABLE_BLKDEV_TOTAL_BYTES_SEC);
- SET_IOTUNE_FIELD(read_bytes_sec,
- VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC,
- VIR_DOMAIN_TUNABLE_BLKDEV_READ_BYTES_SEC);
- SET_IOTUNE_FIELD(write_bytes_sec,
- VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC,
- VIR_DOMAIN_TUNABLE_BLKDEV_WRITE_BYTES_SEC);
- SET_IOTUNE_FIELD(total_iops_sec,
- VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC,
- VIR_DOMAIN_TUNABLE_BLKDEV_TOTAL_IOPS_SEC);
- SET_IOTUNE_FIELD(read_iops_sec,
- VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC,
- VIR_DOMAIN_TUNABLE_BLKDEV_READ_IOPS_SEC);
- SET_IOTUNE_FIELD(write_iops_sec,
- VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC,
- VIR_DOMAIN_TUNABLE_BLKDEV_WRITE_IOPS_SEC);
-
- SET_IOTUNE_FIELD(total_bytes_sec_max,
- VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC_MAX,
- VIR_DOMAIN_TUNABLE_BLKDEV_TOTAL_BYTES_SEC_MAX);
- SET_IOTUNE_FIELD(read_bytes_sec_max,
- VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC_MAX,
- VIR_DOMAIN_TUNABLE_BLKDEV_READ_BYTES_SEC_MAX);
- SET_IOTUNE_FIELD(write_bytes_sec_max,
- VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC_MAX,
- VIR_DOMAIN_TUNABLE_BLKDEV_WRITE_BYTES_SEC_MAX);
- SET_IOTUNE_FIELD(total_iops_sec_max,
- VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC_MAX,
- VIR_DOMAIN_TUNABLE_BLKDEV_TOTAL_IOPS_SEC_MAX);
- SET_IOTUNE_FIELD(read_iops_sec_max,
- VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC_MAX,
- VIR_DOMAIN_TUNABLE_BLKDEV_READ_IOPS_SEC_MAX);
- SET_IOTUNE_FIELD(write_iops_sec_max,
- VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC_MAX,
- VIR_DOMAIN_TUNABLE_BLKDEV_WRITE_IOPS_SEC_MAX);
- SET_IOTUNE_FIELD(size_iops_sec,
- VIR_DOMAIN_BLOCK_IOTUNE_SIZE_IOPS_SEC,
- VIR_DOMAIN_TUNABLE_BLKDEV_SIZE_IOPS_SEC);
-
+ SET_IOTUNE_FIELD(total_bytes_sec, TOTAL_BYTES_SEC);
+ SET_IOTUNE_FIELD(read_bytes_sec, READ_BYTES_SEC);
+ SET_IOTUNE_FIELD(write_bytes_sec, WRITE_BYTES_SEC);
+ SET_IOTUNE_FIELD(total_iops_sec, TOTAL_IOPS_SEC);
+ SET_IOTUNE_FIELD(read_iops_sec, READ_IOPS_SEC);
+ SET_IOTUNE_FIELD(write_iops_sec, WRITE_IOPS_SEC);
+
+ SET_IOTUNE_FIELD(total_bytes_sec_max, TOTAL_BYTES_SEC_MAX);
+ SET_IOTUNE_FIELD(read_bytes_sec_max, READ_BYTES_SEC_MAX);
+ SET_IOTUNE_FIELD(write_bytes_sec_max, WRITE_BYTES_SEC_MAX);
+ SET_IOTUNE_FIELD(total_iops_sec_max, TOTAL_IOPS_SEC_MAX);
+ SET_IOTUNE_FIELD(read_iops_sec_max, READ_IOPS_SEC_MAX);
+ SET_IOTUNE_FIELD(write_iops_sec_max, WRITE_IOPS_SEC_MAX);
+ SET_IOTUNE_FIELD(size_iops_sec, SIZE_IOPS_SEC);
+
+ /* NB: Cannot use macro since this is a value.s not a value.ul */
if (STREQ(param->field, VIR_DOMAIN_BLOCK_IOTUNE_GROUP_NAME)) {
- VIR_FREE(info.group_name);
- info.group_name = g_strdup(param->value.s);
- if (virTypedParamsAddString(&eventParams,
- &eventNparams,
- &eventMaxparams,
+ VIR_FREE(info->group_name);
+ info->group_name = g_strdup(param->value.s);
+ if (virTypedParamsAddString(eventParams, eventNparams,
+ eventMaxparams,
VIR_DOMAIN_TUNABLE_BLKDEV_GROUP_NAME,
param->value.s) < 0)
- goto cleanup;
+ goto endjob;
continue;
}
- SET_IOTUNE_FIELD(total_bytes_sec_max_length,
- VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC_MAX_LENGTH,
- VIR_DOMAIN_TUNABLE_BLKDEV_TOTAL_BYTES_SEC_MAX_LENGTH);
- SET_IOTUNE_FIELD(read_bytes_sec_max_length,
- VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC_MAX_LENGTH,
- VIR_DOMAIN_TUNABLE_BLKDEV_READ_BYTES_SEC_MAX_LENGTH);
- SET_IOTUNE_FIELD(write_bytes_sec_max_length,
- VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC_MAX_LENGTH,
- VIR_DOMAIN_TUNABLE_BLKDEV_WRITE_BYTES_SEC_MAX_LENGTH);
- SET_IOTUNE_FIELD(total_iops_sec_max_length,
- VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC_MAX_LENGTH,
- VIR_DOMAIN_TUNABLE_BLKDEV_TOTAL_IOPS_SEC_MAX_LENGTH);
- SET_IOTUNE_FIELD(read_iops_sec_max_length,
- VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC_MAX_LENGTH,
- VIR_DOMAIN_TUNABLE_BLKDEV_READ_IOPS_SEC_MAX_LENGTH);
- SET_IOTUNE_FIELD(write_iops_sec_max_length,
- VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC_MAX_LENGTH,
- VIR_DOMAIN_TUNABLE_BLKDEV_WRITE_IOPS_SEC_MAX_LENGTH);
+ SET_IOTUNE_FIELD(total_bytes_sec_max_length, TOTAL_BYTES_SEC_MAX_LENGTH);
+ SET_IOTUNE_FIELD(read_bytes_sec_max_length, READ_BYTES_SEC_MAX_LENGTH);
+ SET_IOTUNE_FIELD(write_bytes_sec_max_length, WRITE_BYTES_SEC_MAX_LENGTH);
+ SET_IOTUNE_FIELD(total_iops_sec_max_length, TOTAL_IOPS_SEC_MAX_LENGTH);
+ SET_IOTUNE_FIELD(read_iops_sec_max_length, READ_IOPS_SEC_MAX_LENGTH);
+ SET_IOTUNE_FIELD(write_iops_sec_max_length, WRITE_IOPS_SEC_MAX_LENGTH);
}
+
#undef SET_IOTUNE_FIELD
- if ((info.total_bytes_sec && info.read_bytes_sec) ||
- (info.total_bytes_sec && info.write_bytes_sec)) {
+ ret = 0;
+ endjob:
+ return ret;
+}
+
+
+static int
+testDomainCheckBlockIoTuneMutualExclusion(virDomainBlockIoTuneInfo *info)
+{
+ if ((info->total_bytes_sec && info->read_bytes_sec) ||
+ (info->total_bytes_sec && info->write_bytes_sec)) {
virReportError(VIR_ERR_INVALID_ARG, "%s",
_("total and read/write of bytes_sec cannot be set at the same time"));
- goto cleanup;
+ return -1;
}
- if ((info.total_iops_sec && info.read_iops_sec) ||
- (info.total_iops_sec && info.write_iops_sec)) {
+ if ((info->total_iops_sec && info->read_iops_sec) ||
+ (info->total_iops_sec && info->write_iops_sec)) {
virReportError(VIR_ERR_INVALID_ARG, "%s",
_("total and read/write of iops_sec cannot be set at the same time"));
- goto cleanup;
+ return -1;
}
- if ((info.total_bytes_sec_max && info.read_bytes_sec_max) ||
- (info.total_bytes_sec_max && info.write_bytes_sec_max)) {
+ if ((info->total_bytes_sec_max && info->read_bytes_sec_max) ||
+ (info->total_bytes_sec_max && info->write_bytes_sec_max)) {
virReportError(VIR_ERR_INVALID_ARG, "%s",
_("total and read/write of bytes_sec_max cannot be set at the same time"));
- goto cleanup;
+ return -1;
}
- if ((info.total_iops_sec_max && info.read_iops_sec_max) ||
- (info.total_iops_sec_max && info.write_iops_sec_max)) {
+ if ((info->total_iops_sec_max && info->read_iops_sec_max) ||
+ (info->total_iops_sec_max && info->write_iops_sec_max)) {
virReportError(VIR_ERR_INVALID_ARG, "%s",
_("total and read/write of iops_sec_max cannot be set at the same time"));
- goto cleanup;
+ return -1;
}
+ return 0;
+}
+
+
+static int
+testDomainCheckBlockIoTuneMax(virDomainBlockIoTuneInfo *info)
+{
+ int ret = -1;
#define TEST_BLOCK_IOTUNE_MAX_CHECK(FIELD, FIELD_MAX) \
do { \
- if (info.FIELD > info.FIELD_MAX) { \
+ if (info->FIELD > info->FIELD_MAX) { \
virReportError(VIR_ERR_INVALID_ARG, \
_("%1$s cannot be set higher than %2$s"), \
#FIELD, #FIELD_MAX); \
- goto cleanup; \
+ goto endjob; \
} \
} while (0);
@@ -4009,6 +3967,69 @@ testDomainSetBlockIoTune(virDomainPtr dom,
#undef TEST_BLOCK_IOTUNE_MAX_CHECK
+ ret = 0;
+ endjob:
+ return ret;
+}
+
+
+static int
+testDomainSetBlockIoTune(virDomainPtr dom,
+ const char *path,
+ virTypedParameterPtr params,
+ int nparams,
+ unsigned int flags)
+{
+ virDomainObj *vm = NULL;
+ virDomainDef *def = NULL;
+ virDomainBlockIoTuneInfo info = {0};
+ virDomainDiskDef *conf_disk = NULL;
+ virTypedParameterPtr eventParams = NULL;
+ int eventNparams = 0;
+ int eventMaxparams = 0;
+ int ret = -1;
+
+ virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+ VIR_DOMAIN_AFFECT_CONFIG, -1);
+
+ if (testDomainValidateBlockIoTune(params, nparams) < 0)
+ return -1;
+
+ if (!(vm = testDomObjFromDomain(dom)))
+ return -1;
+
+ if (!(def = virDomainObjGetOneDef(vm, flags)))
+ goto cleanup;
+
+ if (!(conf_disk = virDomainDiskByName(def, path, true))) {
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("missing persistent configuration for disk '%1$s'"),
+ path);
+ goto cleanup;
+ }
+
+ info = conf_disk->blkdeviotune;
+ info.group_name = g_strdup(conf_disk->blkdeviotune.group_name);
+
+ if (virTypedParamsAddString(&eventParams, &eventNparams, &eventMaxparams,
+ VIR_DOMAIN_TUNABLE_BLKDEV_DISK, path) < 0)
+ goto cleanup;
+
+ if (testDomainSetBlockIoTuneFields(&info,
+ params,
+ nparams,
+ &eventParams,
+ &eventNparams,
+ &eventMaxparams) < 0)
+ goto cleanup;
+
+ if (testDomainCheckBlockIoTuneMutualExclusion(&info) < 0)
+ goto cleanup;
+
+
+ if (testDomainCheckBlockIoTuneMax(&info) < 0)
+ goto cleanup;
+
virDomainDiskSetBlockIOTune(conf_disk, &info);
ret = 0;
@@ -4119,6 +4140,190 @@ testDomainGetBlockIoTune(virDomainPtr dom,
virDomainObjEndAPI(&vm);
return ret;
}
+
+
+static int
+testDomainSetThrottleGroup(virDomainPtr dom,
+ const char *group,
+ virTypedParameterPtr params,
+ int nparams,
+ unsigned int flags)
+{
+ virDomainObj *vm = NULL;
+ virDomainDef *def = NULL;
+ virDomainThrottleGroupDef info = { 0 };
+ virDomainThrottleGroupDef *cur_info = NULL;
+ virTypedParameterPtr eventParams = NULL;
+ int eventNparams = 0;
+ int eventMaxparams = 0;
+ int ret = -1;
+
+ virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+ VIR_DOMAIN_AFFECT_CONFIG, -1);
+ if (testDomainValidateBlockIoTune(params, nparams) < 0)
+ return -1;
+
+ if (!(vm = testDomObjFromDomain(dom)))
+ return -1;
+
+ if (!(def = virDomainObjGetOneDef(vm, flags)))
+ goto cleanup;
+
+ if (virTypedParamsAddString(&eventParams, &eventNparams, &eventMaxparams,
+ VIR_DOMAIN_TUNABLE_BLKDEV_GROUP_NAME, group) < 0)
+ goto cleanup;
+
+ if (testDomainSetBlockIoTuneFields(&info,
+ params,
+ nparams,
+ &eventParams,
+ &eventNparams,
+ &eventMaxparams) < 0)
+ goto cleanup;
+
+ if (testDomainCheckBlockIoTuneMutualExclusion(&info) < 0)
+ goto cleanup;
+
+ if (testDomainCheckBlockIoTuneMax(&info) < 0)
+ goto cleanup;
+
+ cur_info = virDomainThrottleGroupByName(def, group);
+ if (cur_info != NULL) {
+ virDomainThrottleGroupUpdate(def, &info);
+ } else {
+ virDomainThrottleGroupAdd(def, &info);
+ }
+ ret = 0;
+
+ cleanup:
+ VIR_FREE(info.group_name);
+ virDomainObjEndAPI(&vm);
+ if (eventNparams)
+ virTypedParamsFree(eventParams, eventNparams);
+ return ret;
+}
+
+
+static int
+testDomainGetThrottleGroup(virDomainPtr dom,
+ const char *groupname,
+ virTypedParameterPtr *params,
+ int *nparams,
+ unsigned int flags)
+{
+ virDomainObj *vm = NULL;
+ virDomainDef *def = NULL;
+ virDomainThrottleGroupDef groupDef = {0};
+ virDomainThrottleGroupDef *reply = &groupDef;
+ int ret = -1;
+ int maxparams = 0;
+
+ virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+ VIR_DOMAIN_AFFECT_CONFIG |
+ VIR_TYPED_PARAM_STRING_OKAY, -1);
+
+
+ if (!(vm = testDomObjFromDomain(dom)))
+ return -1;
+
+ if (!(def = virDomainObjGetOneDef(vm, flags)))
+ goto cleanup;
+
+
+ if (!(reply = virDomainThrottleGroupByName(def, groupname))) {
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("throttle group '%1$s' was not found in the domain config"),
+ groupname);
+ goto cleanup;
+ }
+ reply->group_name = g_strdup(groupname);
+
+#define TEST_THROTTLE_GROUP_ASSIGN(name, var) \
+ if (virTypedParamsAddULLong(params, \
+ nparams, \
+ &maxparams, \
+ VIR_DOMAIN_BLOCK_IOTUNE_ ## name, \
+ reply->var) < 0) \
+ goto cleanup;
+
+ if (virTypedParamsAddString(params, nparams, &maxparams,
+ "VIR_DOMAIN_BLOCK_IOTUNE_GROUP_NAME",
+ reply->group_name) < 0)
+ goto cleanup;
+
+ TEST_THROTTLE_GROUP_ASSIGN(TOTAL_BYTES_SEC, total_bytes_sec);
+ TEST_THROTTLE_GROUP_ASSIGN(READ_BYTES_SEC, read_bytes_sec);
+ TEST_THROTTLE_GROUP_ASSIGN(WRITE_BYTES_SEC, write_bytes_sec);
+ TEST_THROTTLE_GROUP_ASSIGN(TOTAL_IOPS_SEC, total_iops_sec);
+ TEST_THROTTLE_GROUP_ASSIGN(READ_IOPS_SEC, read_iops_sec);
+ TEST_THROTTLE_GROUP_ASSIGN(WRITE_IOPS_SEC, write_iops_sec);
+
+ TEST_THROTTLE_GROUP_ASSIGN(TOTAL_BYTES_SEC_MAX, total_bytes_sec_max);
+ TEST_THROTTLE_GROUP_ASSIGN(READ_BYTES_SEC_MAX, read_bytes_sec_max);
+ TEST_THROTTLE_GROUP_ASSIGN(WRITE_BYTES_SEC_MAX, write_bytes_sec_max);
+
+ TEST_THROTTLE_GROUP_ASSIGN(TOTAL_IOPS_SEC_MAX, total_iops_sec_max);
+ TEST_THROTTLE_GROUP_ASSIGN(READ_IOPS_SEC_MAX, read_iops_sec_max);
+ TEST_THROTTLE_GROUP_ASSIGN(WRITE_IOPS_SEC_MAX, write_iops_sec_max);
+
+ TEST_THROTTLE_GROUP_ASSIGN(SIZE_IOPS_SEC, size_iops_sec);
+
+ TEST_THROTTLE_GROUP_ASSIGN(TOTAL_BYTES_SEC_MAX_LENGTH, total_bytes_sec_max_length);
+ TEST_THROTTLE_GROUP_ASSIGN(READ_BYTES_SEC_MAX_LENGTH, read_bytes_sec_max_length);
+ TEST_THROTTLE_GROUP_ASSIGN(WRITE_BYTES_SEC_MAX_LENGTH, write_bytes_sec_max_length);
+
+ TEST_THROTTLE_GROUP_ASSIGN(TOTAL_IOPS_SEC_MAX_LENGTH, total_iops_sec_max_length);
+ TEST_THROTTLE_GROUP_ASSIGN(READ_IOPS_SEC_MAX_LENGTH, read_iops_sec_max_length);
+ TEST_THROTTLE_GROUP_ASSIGN(WRITE_IOPS_SEC_MAX_LENGTH, write_iops_sec_max_length);
+#undef TEST_THROTTLE_GROUP_ASSIGN
+
+ ret = 0;
+
+ cleanup:
+ if (reply != NULL && reply->group_name != NULL) {
+ g_free(reply->group_name);
+ }
+ virDomainObjEndAPI(&vm);
+ return ret;
+}
+
+
+static int
+testDomainDelThrottleGroup(virDomainPtr dom,
+ const char *groupname,
+ unsigned int flags)
+{
+ virDomainObj *vm = NULL;
+ virDomainDef *def = NULL;
+ virDomainThrottleGroupDef groupDef = {0};
+ virDomainThrottleGroupDef *reply = &groupDef;
+ int ret = -1;
+
+ virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+ VIR_DOMAIN_AFFECT_CONFIG |
+ VIR_TYPED_PARAM_STRING_OKAY, -1);
+
+
+ if (!(vm = testDomObjFromDomain(dom)))
+ return -1;
+
+ if (!(def = virDomainObjGetOneDef(vm, flags)))
+ goto cleanup;
+
+ if (!(reply = virDomainThrottleGroupByName(def, groupname))) {
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("throttle group '%1$s' was not found in the domain config"),
+ groupname);
+ goto cleanup;
+ }
+
+ ret = 0;
+
+ cleanup:
+ virDomainObjEndAPI(&vm);
+ return ret;
+}
+
#undef TEST_SET_PARAM
@@ -10684,6 +10889,9 @@ static virHypervisorDriver testHypervisorDriver = {
.domainGetInterfaceParameters = testDomainGetInterfaceParameters, /* 5.6.0 */
.domainSetBlockIoTune = testDomainSetBlockIoTune, /* 5.7.0 */
.domainGetBlockIoTune = testDomainGetBlockIoTune, /* 5.7.0 */
+ .domainSetThrottleGroup = testDomainSetThrottleGroup, /* 10.7.0 */
+ .domainGetThrottleGroup = testDomainGetThrottleGroup, /* 10.7.0 */
+ .domainDelThrottleGroup = testDomainDelThrottleGroup, /* 10.7.0 */
.domainSetBlkioParameters = testDomainSetBlkioParameters, /* 7.7.0 */
.domainGetBlkioParameters = testDomainGetBlkioParameters, /* 7.7.0 */
.connectListDefinedDomains = testConnectListDefinedDomains, /* 0.1.11 */
--
2.43.0
2 months