Add a new 'virsh domblkthreshold' command to use the new API.
The main use is an obvious mapping to the new API:
virsh domblkthreshold $dom $disk 10000000 # 10M bytes
or
virsh domblkthreshold $dom $disk 101000 --proportion # 10.1%
but I also wanted to be lazy at computing parts per million,
so I allow:
virsh domblkthreshold $dom $disk --percentage 10.1% # as before
* tools/virsh.pod (domblkthreshold): Document it.
* tools/virsh-domain-monitor.c (cmdDomblkthreshold): New function.
(domMonitoringCmds): Register it.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
tools/virsh-domain-monitor.c | 108 +++++++++++++++++++++++++++++++++++++++++++
tools/virsh.pod | 25 ++++++++++
2 files changed, 133 insertions(+)
diff --git a/tools/virsh-domain-monitor.c b/tools/virsh-domain-monitor.c
index 1d4dc25..5a0287f 100644
--- a/tools/virsh-domain-monitor.c
+++ b/tools/virsh-domain-monitor.c
@@ -571,6 +571,108 @@ cmdDomblklist(vshControl *ctl, const vshCmd *cmd)
}
/*
+ * "domblkthreshold" command
+ */
+static const vshCmdInfo info_domblkthreshold[] = {
+ {.name = "help",
+ .data = N_("set domain block device write thresholds")
+ },
+ {.name = "desc",
+ .data = N_("Set a threshold to get a one-shot event if block "
+ "allocation exceeds that size")
+ },
+ {.name = NULL}
+};
+
+static const vshCmdOptDef opts_domblkthreshold[] = {
+ {.name = "domain",
+ .type = VSH_OT_DATA,
+ .flags = VSH_OFLAG_REQ,
+ .help = N_("domain name, id or uuid"),
+ },
+ {.name = "device",
+ .type = VSH_OT_DATA,
+ .flags = VSH_OFLAG_REQ,
+ .help = N_("block device"),
+ },
+ {.name = "threshold",
+ .type = VSH_OT_INT,
+ .help = N_("new threshold, or 0 to disable"),
+ },
+ {.name = "proportion",
+ .type = VSH_OT_BOOL,
+ .help = N_("threshold is in parts-per-million instead of bytes"),
+ },
+ {.name = "percentage",
+ .type = VSH_OT_STRING, /* floating point doesn't have an option type */
+ .flags = VSH_OFLAG_REQ_OPT,
+ .help = N_("determine threshold from a percentage"),
+ },
+ {.name = NULL}
+};
+
+static bool
+cmdDomblkthreshold(vshControl *ctl, const vshCmd *cmd)
+{
+ virDomainPtr dom;
+ bool ret = false;
+ const char *device = NULL;
+ unsigned long long threshold;
+ bool proportion = vshCommandOptBool(cmd, "proportion");
+ unsigned int flags = 0;
+ const char *percentage = NULL;
+
+ VSH_EXCLUSIVE_OPTIONS("threshold", "percentage");
+ VSH_EXCLUSIVE_OPTIONS("proportion", "percentage");
+
+ if (vshCommandOptStringReq(ctl, cmd, "percentage", &percentage) <
0)
+ return false;
+ if (percentage) {
+ char *end;
+ double raw;
+
+ if (virStrToDouble(percentage, &end, &raw) < 0 ||
+ end[*end == '%'] || raw < 0.0 || raw > 100.0) {
+ vshError(ctl, _("unable to parse '%s' as percentage"),
percentage);
+ return false;
+ }
+ threshold = raw * 10000;
+ proportion = true;
+ } else if (!vshCommandOptBool(cmd, "threshold")) {
+ vshError(ctl, "%s",
+ _("either --threshold or --percentage is required"));
+ return false;
+ } else if (vshCommandOptULongLong(ctl, cmd, "threshold", &threshold)
< 0) {
+ return false;
+ }
+
+ if (proportion)
+ flags |= VIR_DOMAIN_BLOCK_SET_WRITE_THRESHOLD_PROPORTION;
+
+ if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ return false;
+
+ if (vshCommandOptStringReq(ctl, cmd, "device", &device) < 0)
+ goto cleanup;
+
+ if (virDomainBlockSetWriteThreshold(dom, device, threshold, flags) < 0)
+ goto cleanup;
+
+ if (proportion)
+ vshPrint(ctl, _("threshold of %s set to %llu.%04llu%%\n"),
+ device, threshold / 10000, threshold % 10000);
+ else
+ vshPrint(ctl, _("threshold of %s set to %llu bytes\n"),
+ device, threshold);
+
+ ret = true;
+
+ cleanup:
+ virDomainFree(dom);
+ return ret;
+}
+
+/*
* "domiflist" command
*/
static const vshCmdInfo info_domiflist[] = {
@@ -2358,6 +2460,12 @@ const vshCmdDef domMonitoringCmds[] = {
.info = info_domblkstat,
.flags = 0
},
+ {.name = "domblkthreshold",
+ .handler = cmdDomblkthreshold,
+ .opts = opts_domblkthreshold,
+ .info = info_domblkthreshold,
+ .flags = 0
+ },
{.name = "domcontrol",
.handler = cmdDomControl,
.opts = opts_domcontrol,
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 600ea42..1b67a72 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -843,6 +843,31 @@ that require a block device name (such as I<domblkinfo> or
I<snapshot-create> for disk snapshots) will accept either target
or unique source names printed by this command.
+=item B<domblkthreshold> I<domain> I<block-device> {
I<threshold>
+[I<--proportion>] | I<--percentage> I<value> }
+
+Set the write threshold for a block device of a domain. A
+I<block-device> corresponds to a unique target name (<target
+dev='name'/>) or source file (<source file='name'/>) for one of
the
+disk devices attached to I<domain> (see also B<domblklist> for listing
+these names). Some hypervisors also allow "vda[1]" to set a threshold
+on the first backing file of the target "vda", useful when doing a
+block commit.
+
+By default, I<threshold> is the byte offset within the host that will
+trigger an event; but if I<--proportion> is used, the threshold is
+instead a parts-per-million relative to the disk size (800000 maps to
+an 80% threshold). It is also possible to use I<--percentage=80.00>
+as shorthand for I<--proportion --threshold=800000>.
+
+Setting a write threshold causes an event to be delivered if the
+allocation of I<block-device> passes that point, allowing a user to
+resize the underlying storage before the guest would be forcefully
+paused due to an ENOSPC scenario. The B<event> command can be used to
+listen for such events. If the hypervisor does not support event
+notification, then B<domblkinfo> must instead be polled to track
+allocation over time. The current threshold is listed in B<domstats>.
+
=item B<domstats> [I<--raw>] [I<--enforce>] [I<--backing>]
[I<--state>]
[I<--cpu-total>] [I<--balloon>] [I<--vcpu>] [I<--interface>]
[I<--block>]
[[I<--list-active>] [I<--list-inactive>] [I<--list-persistent>]
--
2.4.3