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@xxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list