Signed-off-by: Wen Congyang <wency@xxxxxxxxxxxxxx> --- tools/virsh.c | 78 +++++++++++++++++++++++++++++++++++++++++++----------- tools/virsh.pod | 4 ++- 2 files changed, 65 insertions(+), 17 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index aba4fd1..ee8d769 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -3413,6 +3413,7 @@ static const vshCmdOptDef opts_migrate[] = { {"suspend", VSH_OT_BOOL, 0, N_("do not restart the domain on the destination host")}, {"copy-storage-all", VSH_OT_BOOL, 0, N_("migration with non-shared storage with full disk copy")}, {"copy-storage-inc", VSH_OT_BOOL, 0, N_("migration with non-shared storage with incremental copy (same base image shared between source and destination)")}, + {"verbose", VSH_OT_BOOL, 0, N_("display the progress of migration")}, {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")}, {"desturi", VSH_OT_DATA, VSH_OFLAG_REQ, N_("connection URI of the destination host as seen from the client(normal migration) or source(p2p migration)")}, {"migrateuri", VSH_OT_DATA, 0, N_("migration URI, usually can be omitted")}, @@ -3513,6 +3514,28 @@ out_sig: ignore_value(safewrite(data->writefd, &ret, sizeof(ret))); } +static void +print_job_progress(unsigned long long remaining, unsigned long long total) +{ + int progress; + + if (total == 0) + /* migration has not been started */ + return; + + if (remaining == 0) { + /* migration has completed */ + progress = 100; + } else if (remaining * 100 / total == 0) { + /* migration has not completed, do not print [100 %] */ + progress = 99; + } else { + progress = 100 - remaining * 100 / total; + } + + fprintf(stderr, "\rMigration: [%3d %%]", progress); +} + static int cmdMigrate (vshControl *ctl, const vshCmd *cmd) { @@ -3524,6 +3547,9 @@ cmdMigrate (vshControl *ctl, const vshCmd *cmd) char retchar; struct sigaction sig_action; struct sigaction old_sig_action; + virDomainJobInfo jobinfo; + bool verbose = FALSE; + sigset_t sigmask, oldsigmask; struct { vshControl *ctl; @@ -3534,6 +3560,9 @@ cmdMigrate (vshControl *ctl, const vshCmd *cmd) if (!(dom = vshCommandOptDomain (ctl, cmd, NULL))) return FALSE; + if (vshCommandOptBool (cmd, "verbose")) + verbose = TRUE; + if (pipe(p) < 0) goto cleanup; @@ -3556,25 +3585,42 @@ cmdMigrate (vshControl *ctl, const vshCmd *cmd) pollfd.fd = p[0]; pollfd.events = POLLIN; pollfd.revents = 0; + sigemptyset(&sigmask); + sigaddset(&sigmask, SIGINT); - ret = poll(&pollfd, 1, -1); - if (ret > 0) { - if (saferead(p[0], &retchar, sizeof(retchar)) > 0) { - if (retchar == '0') - ret = TRUE; - else + while (1) { + ret = poll(&pollfd, 1, 500); + if (ret > 0) { + if (saferead(p[0], &retchar, sizeof(retchar)) > 0) { + if (retchar == '0') { + ret = TRUE; + if (verbose) { + /* print [100 %] */ + print_job_progress(0, 1); + } + } else + ret = FALSE; + } else ret = FALSE; - } else - ret = FALSE; - } else if (ret < 0) { - if (errno == EINTR && intCatched) { - virDomainAbortJob(dom); - ret = FALSE; - intCatched = FALSE; + break; + } + + if (ret < 0) { + if (errno == EINTR && intCatched) { + virDomainAbortJob(dom); + ret = FALSE; + intCatched = FALSE; + break; + } + } + + if (verbose) { + pthread_sigmask(SIG_BLOCK, &sigmask, &oldsigmask); + ret = virDomainGetJobInfo(dom, &jobinfo); + pthread_sigmask(SIG_BLOCK, &oldsigmask, NULL); + if (ret == 0) + print_job_progress(jobinfo.dataRemaining, jobinfo.dataTotal); } - } else { - /* timed out */ - ret = FALSE; } sigaction(SIGINT, &old_sig_action, NULL); diff --git a/tools/virsh.pod b/tools/virsh.pod index 1f15fef..ce7e2e7 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -489,7 +489,8 @@ type attribute for the <domain> element of XML. =item B<migrate> optional I<--live> I<--p2p> I<--direct> I<--tunnelled> I<--persistent> I<--undefinesource> I<--suspend> I<--copy-storage-all> -I<--copy-storage-inc> I<domain-id> I<desturi> I<migrateuri> I<dname> +I<--copy-storage-inc> I<--verbose> I<domain-id> I<desturi> I<migrateuri> +I<dname> Migrate domain to another host. Add I<--live> for live migration; I<--p2p> for peer-2-peer migration; I<--direct> for direct migration; or I<--tunnelled> @@ -499,6 +500,7 @@ and I<--suspend> leaves the domain paused on the destination host. I<--copy-storage-all> indicates migration with non-shared storage with full disk copy, I<--copy-storage-inc> indicates migration with non-shared storage with incremental copy (same base image shared between source and destination). +I<--verbose> displays the progress of migration. The I<desturi> is the connection URI of the destination host, and I<migrateuri> is the migration URI, which usually can be omitted. -- 1.7.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list