mirror of https://gitee.com/openkylin/libvirt.git
blockjob: add new --bytes flag to virsh blockjob
Expose the new flag just added to virDomainGetBlockJobInfo. With --raw, the presence or absence of --bytes determines which flag to use in the single API call. Without --raw, the use of --bytes forces an error if the server doesn't support it, otherwise, the code tries to silently fall back to scaling the MiB/s value. My goal is to eventually also support --bytes in bandwidth mode; but that's a bit further down the road (and needs a new API flag added in libvirt.h first). This changes the human output, but the previous patch added raw output precisely so that we can have flexibility with the human output. For this commit, I used qemu-monitor-command to force an unusual bandwidth, but the same will be possible once qemu implements virDomainBlockCopy: Before: Block Copy: [100 %] Bandwidth limit: 2 MiB/s After: Block Copy: [100 %] Bandwidth limit: 1048577 bytes/s (1.000 MiB/s) The cache avoids having to repeatedly checking whether the flag works when talking to an older server, when multiple blockjob commands are issued during a batch session and the user is manually polling for job completion. * tools/virsh.h (_vshControl): Add a cache. * tools/virsh.c (cmdConnect, vshReconnect): Initialize the cache. * tools/virsh-domain.c (opts_block_job): Add --bytes. * tools/virsh.pod (blockjob): Document this. Signed-off-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
parent
2019b7caca
commit
1105c1deff
|
@ -2048,6 +2048,10 @@ static const vshCmdOptDef opts_block_job[] = {
|
|||
.type = VSH_OT_BOOL,
|
||||
.help = N_("get active job information for the specified disk")
|
||||
},
|
||||
{.name = "bytes",
|
||||
.type = VSH_OT_BOOL,
|
||||
.help = N_("with --info, get bandwidth in bytes rather than MiB/s")
|
||||
},
|
||||
{.name = "raw",
|
||||
.type = VSH_OT_BOOL,
|
||||
.help = N_("implies --info; output details rather than human summary")
|
||||
|
@ -2080,8 +2084,9 @@ cmdBlockJob(vshControl *ctl, const vshCmd *cmd)
|
|||
{
|
||||
virDomainBlockJobInfo info;
|
||||
bool ret = false;
|
||||
int rc;
|
||||
int rc = -1;
|
||||
bool raw = vshCommandOptBool(cmd, "raw");
|
||||
bool bytes = vshCommandOptBool(cmd, "bytes");
|
||||
bool abortMode = (vshCommandOptBool(cmd, "abort") ||
|
||||
vshCommandOptBool(cmd, "async") ||
|
||||
vshCommandOptBool(cmd, "pivot"));
|
||||
|
@ -2090,12 +2095,18 @@ cmdBlockJob(vshControl *ctl, const vshCmd *cmd)
|
|||
virDomainPtr dom = NULL;
|
||||
const char *path;
|
||||
unsigned int flags = 0;
|
||||
unsigned long long speed;
|
||||
|
||||
if (abortMode + infoMode + bandwidth > 1) {
|
||||
vshError(ctl, "%s",
|
||||
_("conflict between abort, info, and bandwidth modes"));
|
||||
return false;
|
||||
}
|
||||
/* XXX also support --bytes with bandwidth mode */
|
||||
if (bytes && (abortMode || bandwidth)) {
|
||||
vshError(ctl, "%s", _("--bytes requires info mode"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (abortMode)
|
||||
return blockJobImpl(ctl, cmd, VSH_CMD_BLOCK_JOB_ABORT, NULL);
|
||||
|
@ -2110,9 +2121,47 @@ cmdBlockJob(vshControl *ctl, const vshCmd *cmd)
|
|||
if (vshCommandOptStringReq(ctl, cmd, "path", &path) < 0)
|
||||
goto cleanup;
|
||||
|
||||
/* If bytes were requested, or if raw mode is not forcing a MiB/s
|
||||
* query and cache can't prove failure, then query bytes/sec. */
|
||||
if (bytes || !(raw || ctl->blockJobNoBytes)) {
|
||||
flags |= VIR_DOMAIN_BLOCK_JOB_INFO_BANDWIDTH_BYTES;
|
||||
rc = virDomainGetBlockJobInfo(dom, path, &info, flags);
|
||||
if (rc < 0)
|
||||
if (rc < 0) {
|
||||
/* Check for particular errors, let all the rest be fatal. */
|
||||
switch (last_error->code) {
|
||||
case VIR_ERR_INVALID_ARG:
|
||||
ctl->blockJobNoBytes = true;
|
||||
/* fallthrough */
|
||||
case VIR_ERR_OVERFLOW:
|
||||
if (!bytes && !raw) {
|
||||
/* try again with MiB/s, unless forcing bytes */
|
||||
vshResetLibvirtError();
|
||||
break;
|
||||
}
|
||||
/* fallthrough */
|
||||
default:
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
speed = info.bandwidth;
|
||||
}
|
||||
/* If we don't already have a query result, query for MiB/s */
|
||||
if (rc < 0) {
|
||||
flags &= ~VIR_DOMAIN_BLOCK_JOB_INFO_BANDWIDTH_BYTES;
|
||||
if ((rc = virDomainGetBlockJobInfo(dom, path, &info, flags)) < 0)
|
||||
goto cleanup;
|
||||
speed = info.bandwidth;
|
||||
/* Scale to bytes/s unless in raw mode */
|
||||
if (!raw) {
|
||||
speed <<= 20;
|
||||
if (speed >> 20 != info.bandwidth) {
|
||||
vshError(ctl, _("overflow in converting %ld MiB/s to bytes\n"),
|
||||
info.bandwidth);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rc == 0) {
|
||||
if (!raw)
|
||||
vshPrint(ctl, _("No current block job for %s"), path);
|
||||
|
@ -2127,9 +2176,12 @@ cmdBlockJob(vshControl *ctl, const vshCmd *cmd)
|
|||
} else {
|
||||
vshPrintJobProgress(vshDomainBlockJobToString(info.type),
|
||||
info.end - info.cur, info.end);
|
||||
if (info.bandwidth != 0)
|
||||
vshPrint(ctl, _(" Bandwidth limit: %lu MiB/s"),
|
||||
info.bandwidth);
|
||||
if (speed) {
|
||||
const char *unit;
|
||||
double val = vshPrettyCapacity(speed, &unit);
|
||||
vshPrint(ctl, _(" Bandwidth limit: %llu bytes/s (%-.3lf %s/s)"),
|
||||
speed, val, unit);
|
||||
}
|
||||
vshPrint(ctl, "\n");
|
||||
}
|
||||
ret = true;
|
||||
|
|
|
@ -397,6 +397,7 @@ vshReconnect(vshControl *ctl)
|
|||
disconnected = 0;
|
||||
ctl->useGetInfo = false;
|
||||
ctl->useSnapshotOld = false;
|
||||
ctl->blockJobNoBytes = false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -454,6 +455,7 @@ cmdConnect(vshControl *ctl, const vshCmd *cmd)
|
|||
|
||||
ctl->useGetInfo = false;
|
||||
ctl->useSnapshotOld = false;
|
||||
ctl->blockJobNoBytes = false;
|
||||
ctl->readonly = ro;
|
||||
|
||||
ctl->conn = vshConnect(ctl, ctl->name, ctl->readonly);
|
||||
|
|
|
@ -238,6 +238,8 @@ struct _vshControl {
|
|||
virDomainGetState is not supported */
|
||||
bool useSnapshotOld; /* cannot use virDomainSnapshotGetParent or
|
||||
virDomainSnapshotNumChildren */
|
||||
bool blockJobNoBytes; /* true if _BANDWIDTH_BYTE blockjob flags
|
||||
are missing */
|
||||
virThread eventLoop;
|
||||
virMutex lock;
|
||||
bool eventLoopStarted;
|
||||
|
|
|
@ -1013,7 +1013,7 @@ exclusive. If no flag is specified, behavior is different depending
|
|||
on hypervisor.
|
||||
|
||||
=item B<blockjob> I<domain> I<path> { [I<--abort>] [I<--async>] [I<--pivot>] |
|
||||
[I<--info>] [I<--raw>] | [I<bandwidth>] }
|
||||
[I<--info>] [I<--raw>] [I<--bytes>] | [I<bandwidth>] }
|
||||
|
||||
Manage active block operations. There are three mutually-exclusive modes:
|
||||
I<--info>, I<bandwidth>, and I<--abort>. I<--async> and I<--pivot> imply
|
||||
|
@ -1034,7 +1034,11 @@ commit job be pivoted over to the new image.
|
|||
In I<--info> mode, the active job information on the specified
|
||||
disk will be printed. By default, the output is a single human-readable
|
||||
summary line; this format may change in future versions. Adding
|
||||
I<--raw> lists each field of the struct, in a stable format.
|
||||
I<--raw> lists each field of the struct, in a stable format. If the
|
||||
I<--bytes> flag is set, then the command errors out if the server could
|
||||
not supply bytes/s resolution; when omitting the flag, raw output is
|
||||
listed in MiB/s and human-readable output automatically selects the
|
||||
best resolution supported by the server.
|
||||
|
||||
I<bandwidth> can be used to set bandwidth limit for the active job.
|
||||
Specifying a negative value is interpreted as an unsigned long long
|
||||
|
|
Loading…
Reference in New Issue