Define two new virsh commands: * blockpull: Initiate a blockPull for the given disk * blockjob: Retrieve progress info, modify speed, and cancel active block jobs Share print_job_progress() with the migration code. * tools/virsh.c: implement the new commands Signed-off-by: Adam Litke <agl@xxxxxxxxxx> --- tools/virsh.c | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 131 insertions(+), 4 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index a6803d8..2b590d3 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -4527,7 +4527,8 @@ out_sig: } static void -print_job_progress(unsigned long long remaining, unsigned long long total) +print_job_progress(const char *label, unsigned long long remaining, + unsigned long long total) { int progress; @@ -4547,7 +4548,7 @@ print_job_progress(unsigned long long remaining, unsigned long long total) } } - fprintf(stderr, "\rMigration: [%3d %%]", progress); + fprintf(stderr, "\r%s: [%3d %%]", label, progress); } static bool @@ -4632,7 +4633,7 @@ repoll: functionReturn = true; if (verbose) { /* print [100 %] */ - print_job_progress(0, 1); + print_job_progress("Migration", 0, 1); } } else functionReturn = false; @@ -4668,7 +4669,8 @@ repoll: ret = virDomainGetJobInfo(dom, &jobinfo); pthread_sigmask(SIG_SETMASK, &oldsigmask, NULL); if (ret == 0) - print_job_progress(jobinfo.dataRemaining, jobinfo.dataTotal); + print_job_progress("Migration", jobinfo.dataRemaining, + jobinfo.dataTotal); } } @@ -4771,6 +4773,129 @@ done: return ret; } +typedef enum { + VSH_CMD_BLOCK_JOB_ABORT = 0, + VSH_CMD_BLOCK_JOB_INFO = 1, + VSH_CMD_BLOCK_JOB_SPEED = 2, + VSH_CMD_BLOCK_JOB_PULL = 3, +} VSH_CMD_BLOCK_JOB_MODE; + +static int +blockJobImpl(vshControl *ctl, const vshCmd *cmd, + virDomainBlockJobInfoPtr info, int mode) +{ + virDomainPtr dom = NULL; + const char *name, *path; + unsigned long bandwidth = 0; + int ret = -1; + + if (!vshConnectionUsability(ctl, ctl->conn)) + goto out; + + if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) + goto out; + + if (vshCommandOptString(cmd, "path", &path) < 0) + goto out; + + if (vshCommandOptUL(cmd, "bandwidth", &bandwidth) < 0) + goto out; + + if (mode == VSH_CMD_BLOCK_JOB_ABORT) + ret = virDomainBlockJobAbort(dom, path, 0); + else if (mode == VSH_CMD_BLOCK_JOB_INFO) + ret = virDomainGetBlockJobInfo(dom, path, info, 0); + else if (mode == VSH_CMD_BLOCK_JOB_SPEED) + ret = virDomainBlockJobSetSpeed(dom, path, bandwidth, 0); + else if (mode == VSH_CMD_BLOCK_JOB_PULL) + ret = virDomainBlockPull(dom, path, bandwidth, 0); + +out: + virDomainFree(dom); + return ret; +} + +/* + * "blockpull" command + */ +static const vshCmdInfo info_block_pull[] = { + {"help", N_("Populate a disk from its backing image.")}, + {"desc", N_("Populate a disk from its backing image.")}, + {NULL, NULL} +}; + +static const vshCmdOptDef opts_block_pull[] = { + {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")}, + {"path", VSH_OT_DATA, VSH_OFLAG_REQ, N_("Fully-qualified path of disk")}, + {"bandwidth", VSH_OT_DATA, VSH_OFLAG_NONE, N_("Bandwidth limit in MB/s")}, + {NULL, 0, 0, NULL} +}; + +static bool +cmdBlockPull(vshControl *ctl, const vshCmd *cmd) +{ + if (blockJobImpl(ctl, cmd, NULL, VSH_CMD_BLOCK_JOB_PULL) != 0) + return false; + return true; +} + +/* + * "blockjobinfo" command + */ +static const vshCmdInfo info_block_job[] = { + {"help", N_("Manage active block operations.")}, + {"desc", N_("Manage active block operations.")}, + {NULL, NULL} +}; + +static const vshCmdOptDef opts_block_job[] = { + {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")}, + {"path", VSH_OT_DATA, VSH_OFLAG_REQ, N_("Fully-qualified path of disk")}, + {"abort", VSH_OT_BOOL, VSH_OFLAG_NONE, N_("Abort the active job on the speficied disk")}, + {"info", VSH_OT_BOOL, VSH_OFLAG_NONE, N_("Get active job information for the specified disk")}, + {"bandwidth", VSH_OT_DATA, VSH_OFLAG_NONE, N_("Set the Bandwidth limit in MB/s")}, + {NULL, 0, 0, NULL} +}; + +static bool +cmdBlockJob(vshControl *ctl, const vshCmd *cmd) +{ + int mode; + virDomainBlockJobInfo info; + const char *type; + int ret; + + if (vshCommandOptBool (cmd, "abort")) { + mode = VSH_CMD_BLOCK_JOB_ABORT; + } else if (vshCommandOptBool (cmd, "info")) { + mode = VSH_CMD_BLOCK_JOB_INFO; + } else if (vshCommandOptBool (cmd, "bandwidth")) { + mode = VSH_CMD_BLOCK_JOB_SPEED; + } else { + vshError(ctl, "%s", + _("One of --abort, --info, or --bandwidth is required")); + return false; + } + + ret = blockJobImpl(ctl, cmd, &info, mode); + if (ret < 0) + return false; + + if (ret == 0 || mode != VSH_CMD_BLOCK_JOB_INFO) + return true; + + if (info.type == VIR_DOMAIN_BLOCK_JOB_TYPE_PULL) + type = "Block Pull"; + else + type = "Unknown job"; + + print_job_progress(type, info.end - info.cur, info.end); + if (info.bandwidth != 0) + vshPrint(ctl, " Bandwidth limit: %lu MB/s\n", info.bandwidth); + return true; +} + + /* * "net-autostart" command */ @@ -11920,6 +12045,8 @@ static const vshCmdDef domManagementCmds[] = { info_attach_interface, 0}, {"autostart", cmdAutostart, opts_autostart, info_autostart, 0}, {"blkiotune", cmdBlkiotune, opts_blkiotune, info_blkiotune, 0}, + {"blockpull", cmdBlockPull, opts_block_pull, info_block_pull, 0}, + {"blockjob", cmdBlockJob, opts_block_job, info_block_job, 0}, #ifndef WIN32 {"console", cmdConsole, opts_console, info_console, 0}, #endif -- 1.7.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list