[PATCH RFC v3 16/16] virsh: Add option "throttle-groups" to "attach_disk"

wucf@linux.ibm.com posted 16 patches 3 months ago
There is a newer version of this series
[PATCH RFC v3 16/16] virsh: Add option "throttle-groups" to "attach_disk"
Posted by wucf@linux.ibm.com 3 months ago
From: Chun Feng Wu <wucf@linux.ibm.com>

* Update "attach_disk" to support new option: throttle-groups to
  form filter chain in QEMU for specific disk

Signed-off-by: Chun Feng Wu <wucf@linux.ibm.com>
---
 tools/virsh-completer-domain.c | 64 ++++++++++++++++++++++++++++++++++
 tools/virsh-completer-domain.h |  5 +++
 tools/virsh-domain.c           | 25 ++++++++++++-
 3 files changed, 93 insertions(+), 1 deletion(-)

diff --git a/tools/virsh-completer-domain.c b/tools/virsh-completer-domain.c
index 61362224a3..000cf65c99 100644
--- a/tools/virsh-completer-domain.c
+++ b/tools/virsh-completer-domain.c
@@ -248,6 +248,70 @@ virshDomainMigrateDisksCompleter(vshControl *ctl,
 }
 
 
+static 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;
+    int ngroups;
+    size_t i;
+    g_auto(GStrv) tmp = NULL;
+
+    virCheckFlags(0, NULL);
+
+    if (!priv->conn || virConnectIsAlive(priv->conn) <= 0)
+        return NULL;
+
+    if (virshDomainGetXML(ctl, cmd, 0, &xmldoc, &ctxt) < 0)
+        return NULL;
+
+    ngroups = virXPathNodeSet("./throttlegroups/throttlegroup", ctxt, &groups);
+    if (ngroups < 0)
+        return NULL;
+
+    tmp = g_new0(char *, ngroups + 1);
+
+    for (i = 0; i < ngroups; i++) {
+        ctxt->node = groups[i];
+        if (!(tmp[i] = virXPathString("string(./group_name)", ctxt)))
+            return NULL;
+    }
+
+    return g_steal_pointer(&tmp);
+}
+
+
+static char **
+virshDomainThrottleGroupListCompleter(vshControl *ctl,
+                                      const vshCmd *cmd,
+                                      const char *argname)
+{
+    const char *curval = NULL;
+    g_auto(GStrv) groups = virshDomainThrottleGroupCompleter(ctl, cmd, 0);
+
+    if (vshCommandOptStringQuiet(ctl, cmd, argname, &curval) < 0)
+        return NULL;
+
+    if (!groups)
+        return NULL;
+
+    return virshCommaStringListComplete(curval, (const char **) groups);
+}
+
+
+char **
+virshDomainThrottleGroupsCompleter(vshControl *ctl,
+                                   const vshCmd *cmd,
+                                   unsigned int completeflags G_GNUC_UNUSED)
+{
+    return virshDomainThrottleGroupListCompleter(ctl, cmd, "throttle-groups");
+}
+
+
 char **
 virshDomainUndefineStorageDisksCompleter(vshControl *ctl,
                                  const vshCmd *cmd,
diff --git a/tools/virsh-completer-domain.h b/tools/virsh-completer-domain.h
index 27cf963912..95ec3e28df 100644
--- a/tools/virsh-completer-domain.h
+++ b/tools/virsh-completer-domain.h
@@ -41,6 +41,11 @@ virshDomainDiskTargetCompleter(vshControl *ctl,
                                const vshCmd *cmd,
                                unsigned int flags);
 
+char **
+virshDomainThrottleGroupsCompleter(vshControl *ctl,
+                                   const vshCmd *cmd,
+                                   unsigned int completeflags);
+
 char **
 virshDomainInterfaceStateCompleter(vshControl *ctl,
                                    const vshCmd *cmd,
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index f84a65451a..ec2330c8dd 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -522,6 +522,11 @@ static const vshCmdOptDef opts_attach_disk[] = {
      .type = VSH_OT_STRING,
      .help = N_("host socket for source of disk device")
     },
+    {.name = "throttle-groups",
+     .type = VSH_OT_STRING,
+     .completer = virshDomainThrottleGroupsCompleter,
+     .help = N_("comma separated list of throttle groups to be applied")
+    },
     VIRSH_COMMON_OPT_DOMAIN_PERSISTENT,
     VIRSH_COMMON_OPT_DOMAIN_CONFIG,
     VIRSH_COMMON_OPT_DOMAIN_LIVE,
@@ -611,6 +616,8 @@ cmdAttachDisk(vshControl *ctl, const vshCmd *cmd)
     const char *host_name = NULL;
     const char *host_transport = NULL;
     const char *host_socket = NULL;
+    const char *throttle_groups_str = NULL;
+    g_autofree char **throttle_groups = NULL;
     int ret;
     unsigned int flags = VIR_DOMAIN_AFFECT_CURRENT;
     const char *stype = NULL;
@@ -622,6 +629,7 @@ cmdAttachDisk(vshControl *ctl, const vshCmd *cmd)
     g_auto(virBuffer) sourceAttrBuf = VIR_BUFFER_INITIALIZER;
     g_auto(virBuffer) sourceChildBuf = VIR_BUFFER_INIT_CHILD(&diskChildBuf);
     g_auto(virBuffer) hostAttrBuf = VIR_BUFFER_INITIALIZER;
+    g_auto(virBuffer) throttleChildBuf = VIR_BUFFER_INITIALIZER;
     g_autofree char *xml = NULL;
     struct stat st;
     bool current = vshCommandOptBool(cmd, "current");
@@ -665,9 +673,14 @@ cmdAttachDisk(vshControl *ctl, const vshCmd *cmd)
         vshCommandOptString(ctl, cmd, "source-protocol", &source_protocol) < 0 ||
         vshCommandOptString(ctl, cmd, "source-host-name", &host_name) < 0 ||
         vshCommandOptString(ctl, cmd, "source-host-transport", &host_transport) < 0 ||
-        vshCommandOptString(ctl, cmd, "source-host-socket", &host_socket) < 0)
+        vshCommandOptString(ctl, cmd, "source-host-socket", &host_socket) < 0 ||
+        vshCommandOptString(ctl, cmd, "throttle-groups", &throttle_groups_str) < 0)
         return false;
 
+    if (throttle_groups_str) {
+        throttle_groups = g_strsplit(throttle_groups_str, ",", 0);
+    }
+
     if (stype &&
         (type = virshAttachDiskSourceTypeFromString(stype)) < 0) {
         vshError(ctl, _("Unknown source type: '%1$s'"), stype);
@@ -714,6 +727,16 @@ cmdAttachDisk(vshControl *ctl, const vshCmd *cmd)
 
     virXMLFormatElement(&diskChildBuf, "driver", &driverAttrBuf, NULL);
 
+    if (throttle_groups) {
+        char **iter;
+        for (iter = throttle_groups; *iter != NULL; iter++) {
+            g_auto(virBuffer) throttleAttrBuf = VIR_BUFFER_INITIALIZER;
+            virBufferAsprintf(&throttleAttrBuf, " group='%s'", *iter);
+            virXMLFormatElement(&throttleChildBuf, "throttlefilter", &throttleAttrBuf, NULL);
+        }
+        virXMLFormatElement(&diskChildBuf, "throttlefilters", NULL, &throttleChildBuf);
+    }
+
     switch ((enum virshAttachDiskSourceType) type) {
     case VIRSH_ATTACH_DISK_SOURCE_TYPE_FILE:
         virBufferEscapeString(&sourceAttrBuf, " file='%s'", source);
-- 
2.34.1
Re: [PATCH RFC v3 16/16] virsh: Add option "throttle-groups" to "attach_disk"
Posted by Peter Krempa 1 month, 1 week ago
On Wed, Jun 12, 2024 at 03:02:24 -0700, wucf@linux.ibm.com wrote:
> From: Chun Feng Wu <wucf@linux.ibm.com>
> 
> * Update "attach_disk" to support new option: throttle-groups to
>   form filter chain in QEMU for specific disk
> 
> Signed-off-by: Chun Feng Wu <wucf@linux.ibm.com>
> ---
>  tools/virsh-completer-domain.c | 64 ++++++++++++++++++++++++++++++++++
>  tools/virsh-completer-domain.h |  5 +++
>  tools/virsh-domain.c           | 25 ++++++++++++-
>  3 files changed, 93 insertions(+), 1 deletion(-)

Missing corresponding manpage update.

> diff --git a/tools/virsh-completer-domain.c b/tools/virsh-completer-domain.c
> index 61362224a3..000cf65c99 100644
> --- a/tools/virsh-completer-domain.c
> +++ b/tools/virsh-completer-domain.c
> @@ -248,6 +248,70 @@ virshDomainMigrateDisksCompleter(vshControl *ctl,
>  }
>  
>  
> +static char **
> +virshDomainThrottleGroupCompleter(vshControl *ctl,
> +                                  const vshCmd *cmd,
> +                                  unsigned int flags)

Well, you see that it's possible to complete these. Add this helper
beforehand and use it approprately also when adding the helpers in
previous patch.

> +{
> +    virshControl *priv = ctl->privData;
> +    g_autoptr(xmlDoc) xmldoc = NULL;
> +    g_autoptr(xmlXPathContext) ctxt = NULL;
> +    g_autofree xmlNodePtr *groups = NULL;
> +    int ngroups;
> +    size_t i;
> +    g_auto(GStrv) tmp = NULL;
> +
> +    virCheckFlags(0, NULL);
> +
> +    if (!priv->conn || virConnectIsAlive(priv->conn) <= 0)
> +        return NULL;
> +
> +    if (virshDomainGetXML(ctl, cmd, 0, &xmldoc, &ctxt) < 0)
> +        return NULL;
> +
> +    ngroups = virXPathNodeSet("./throttlegroups/throttlegroup", ctxt, &groups);
> +    if (ngroups < 0)
> +        return NULL;
> +
> +    tmp = g_new0(char *, ngroups + 1);
> +
> +    for (i = 0; i < ngroups; i++) {
> +        ctxt->node = groups[i];
> +        if (!(tmp[i] = virXPathString("string(./group_name)", ctxt)))
> +            return NULL;

Since this also does everything that the 'throttlegrouplist' command
does, you can theoretically even reuse this there and use it to fill the
table.

> +    }
> +
> +    return g_steal_pointer(&tmp);
> +}

[...]