[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH 09/10] vcpubandwidth: Implement virsh support



Introduce new command vcpu-bandwidth to change and query bandwidth for each vcpu.

Usage:
1. query bandwidth for all vcpus:
   # virsh vcpu-bandwidth <domain>

2. query bandwidth for a vcpu:
   # virsh vcpu-bandwidth <domain> <vcpuid>

3. change bandwidth for a vcpu:
   # virsh vcpu-bandwidth <domain> <vcpuid> <period> <quota>
   You can omit period or quota.

The option --live, --config, and --current is the same as the other commands.

---
 tools/virsh.c   |  142 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 tools/virsh.pod |   16 ++++++
 2 files changed, 157 insertions(+), 1 deletions(-)

diff --git a/tools/virsh.c b/tools/virsh.c
index d15d206..b5a49dd 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -3049,7 +3049,7 @@ cmdVcpuPin(vshControl *ctl, const vshCmd *cmd)
             flags |= VIR_DOMAIN_AFFECT_LIVE;
         /* neither option is specified */
         if (!live && !config)
-            flags = -1;
+            flags = VIR_DOMAIN_AFFECT_CURRENT;
     }
 
     if (!vshConnectionUsability(ctl, ctl->conn))
@@ -3239,6 +3239,144 @@ parse_error:
 }
 
 /*
+ * "vcpu-bandwidth" command
+ */
+static const vshCmdInfo info_vcpu_bandwidth[] = {
+    {"help", N_("control or query domain vcpu bandwidth")},
+    {"desc", N_("Change or query the bandwidth of virtual CPUs in the guest domain.")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_vcpu_bandwidth[] = {
+    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
+    {"vcpu", VSH_OT_INT, 0, N_("vcpu number")},
+    {"period", VSH_OT_INT, VSH_OFLAG_EMPTY_OK, N_("bandwidth period in usecs")},
+    {"quota", VSH_OT_INT, VSH_OFLAG_EMPTY_OK,
+     N_("cpu bandwidth (in usecs) that this vcpu will be allowed to consume over period")},
+    {"config", VSH_OT_BOOL, 0, N_("affect next boot")},
+    {"live", VSH_OT_BOOL, 0, N_("affect running domain")},
+    {"current", VSH_OT_BOOL, 0, N_("affect current domain")},
+    {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdVcpuBandwidth(vshControl *ctl, const vshCmd *cmd)
+{
+    virDomainPtr dom;
+    int vcpu = -1;
+    int max_vcpus, nvcpus = 0;
+    unsigned long long period = 0;
+    long long quota = 0;
+    int period_found, quota_found;
+    virDomainVcpuBWDefPtr vcpubw_list = NULL;
+    virDomainVcpuBWDefPtr vcpubw = NULL;
+    bool ret = false;
+    bool config = vshCommandOptBool(cmd, "config");
+    bool live = vshCommandOptBool(cmd, "live");
+    bool current = vshCommandOptBool(cmd, "current");
+    bool query = false; /* Query mode if no period and no quota */
+    int flags = 0;
+    int rc;
+    int i;
+
+    if (current) {
+        if (live || config) {
+            vshError(ctl, "%s", _("--current must be specified exclusively"));
+            return false;
+        }
+        flags = VIR_DOMAIN_AFFECT_CURRENT;
+    } else {
+        if (config)
+            flags |= VIR_DOMAIN_AFFECT_CONFIG;
+        if (live)
+            flags |= VIR_DOMAIN_AFFECT_LIVE;
+        /* neither option is specified */
+        if (!live && !config)
+            flags = VIR_DOMAIN_AFFECT_CURRENT;
+    }
+
+    if (!vshConnectionUsability(ctl, ctl->conn))
+        return false;
+
+    if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+        return false;
+
+    if ((period_found = vshCommandOptULongLong(cmd, "period", &period)) < 0) {
+        vshError(ctl, "%s", _("Invalid value of period"));
+        goto cleanup;
+    }
+
+    if ((quota_found = vshCommandOptLongLong(cmd, "quota", &quota)) < 0) {
+        vshError(ctl, "%s", _("Invalid value of quota"));
+        goto cleanup;
+    }
+
+    query = quota_found == 0 && period_found == 0;
+
+    /* In query mode, "vcpu" is optional */
+    if (vshCommandOptInt(cmd, "vcpu", &vcpu) < !query) {
+        vshError(ctl, "%s", _("Invalid or missing VCPU number."));
+        goto cleanup;
+    }
+
+    max_vcpus = virDomainGetVcpusFlags(dom, flags | VIR_DOMAIN_VCPU_MAXIMUM);
+    if (max_vcpus < 0)
+        goto cleanup;
+
+    /* In query mode, we need to know current setting. In change mode, if user
+     * does not specify period or quota, we need to know its origin setting.
+     */
+    if (quota_found == 0 || period_found == 0) {
+        nvcpus = max_vcpus;
+        vcpubw_list = vshMalloc(ctl, nvcpus * sizeof(*vcpubw_list));
+        rc = virDomainGetVcpuBW(dom, vcpubw_list, &nvcpus, flags);
+        if (rc < 0)
+            goto cleanup;
+    }
+
+    /* Query mode: show CPU bandwidth information then exit.*/
+    if (query) {
+        vshPrint(ctl, "%s %s %s\n", _("vcpu:"), _("period"), _("quota"));
+        vshPrint(ctl, "----------------------------------\n");
+        for (i = 0; i < nvcpus; i++) {
+            if (vcpu != -1 && i != vcpu)
+                continue;
+            vshPrint(ctl, "%4d: ", i);
+            vshPrint(ctl, "%6llu ", vcpubw_list[i].period);
+            vshPrint(ctl, "%5lld\n", vcpubw_list[i].quota);
+        }
+        goto cleanup;
+    }
+
+    if (vcpu >= max_vcpus) {
+        vshError(ctl, _("Virtual CPU %d doesn't exist."), vcpu);
+        goto cleanup;
+    }
+
+    vcpubw = vshMalloc(ctl, sizeof(*vcpubw));
+    vcpubw[0].vcpuid = vcpu;
+    if (period_found)
+        vcpubw[0].period = period;
+    else
+        vcpubw[0].period = vcpubw_list[vcpu].period;
+    if (quota_found)
+        vcpubw[0].quota = quota;
+    else
+        vcpubw[0].quota = vcpubw_list[vcpu].quota;
+    rc = virDomainSetVcpuBW(dom, vcpubw, 1, flags);
+    if (rc < 0)
+        goto cleanup;
+
+    ret = true;
+
+cleanup:
+    VIR_FREE(vcpubw_list);
+    VIR_FREE(vcpubw);
+    virDomainFree(dom);
+    return ret;
+}
+
+/*
  * "setvcpus" command
  */
 static const vshCmdInfo info_setvcpus[] = {
@@ -11675,6 +11813,8 @@ static const vshCmdDef domManagementCmds[] = {
     {"vcpucount", cmdVcpucount, opts_vcpucount, info_vcpucount, 0},
     {"vcpuinfo", cmdVcpuinfo, opts_vcpuinfo, info_vcpuinfo, 0},
     {"vcpupin", cmdVcpuPin, opts_vcpupin, info_vcpupin, 0},
+    {"vcpu-bandwidth", cmdVcpuBandwidth, opts_vcpu_bandwidth,
+     info_vcpu_bandwidth, 0},
     {"version", cmdVersion, opts_version, info_version, 0},
     {"vncdisplay", cmdVNCDisplay, opts_vncdisplay, info_vncdisplay, 0},
     {NULL, NULL, NULL, NULL, 0}
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 736b919..686d8ba 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -849,6 +849,22 @@ If no flag is specified, behavior is different depending on hypervisor.
 B<Note>: The expression is sequentially evaluated, so "0-15,^8" is
 identical to "9-14,0-7,15" but not identical to "^8,0-15".
 
+=item B<vcpu-bandwidth> I<domain-id> optional I<vcpu> I<period> I<quota>
+I<--live> I<--config> I<--current>
+
+Change or query the bandwidth of domain vcpus. To change a single I<vcpu>,
+specify I<period> or I<quota>; otherwise, you can query one I<vcpu> or omit
+I<vcpu> to list all at once.
+
+I<period> is bandwidth period in usecs, and I<quota> is cpu bandwidth (in usecs)
+that this vcpu will be allowed to consume over period.
+If I<--live> is specified, affect a running guest.
+If I<--config> is specified, affect the next boot of a persistent guest.
+If I<--current> is specified, affect the current guest state.
+Both I<--live> and I<--config> flags may be given if I<period> or I<quota> is
+present, but I<--current> is exclusive.
+If no flag is specified, it is identical to I<--current>.
+
 =item B<vncdisplay> I<domain-id>
 
 Output the IP address and port number for the VNC display. If the information
-- 
1.7.1


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]