[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH 2/3] Show migration progress.



from: Wen Congyang <wency cn fujitsu com>

Show migration progress if `migrate --verbose'.
---
 tools/virsh.c   |   86 ++++++++++++++++++++++++++++++++++++++++++------------
 tools/virsh.pod |    4 ++-
 2 files changed, 70 insertions(+), 20 deletions(-)

diff --git a/tools/virsh.c b/tools/virsh.c
index a9d9110..356d8d5 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")},
@@ -3515,6 +3516,30 @@ 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 {
+        /* use float to avoid overflow */
+        progress = (int)(100.0 - remaining * 100.0 / total);
+        if (progress >= 100) {
+            /* migration has not completed, do not print [100 %] */
+            progress = 99;
+        }
+    }
+
+    fprintf(stderr, "\rMigration: [%3d %%]", progress);
+}
+
 static int
 cmdMigrate (vshControl *ctl, const vshCmd *cmd)
 {
@@ -3526,12 +3551,18 @@ 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;
 
     vshCtrlData data;
 
     if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
         return FALSE;
 
+    if (vshCommandOptBool (cmd, "verbose"))
+        verbose = true;
+
     if (pipe(p) < 0)
         goto cleanup;
 
@@ -3554,29 +3585,46 @@ cmdMigrate (vshControl *ctl, const vshCmd *cmd)
     pollfd.fd = p[0];
     pollfd.events = POLLIN;
     pollfd.revents = 0;
+    sigemptyset(&sigmask);
+    sigaddset(&sigmask, SIGINT);
 
+    while (1) {
 repoll:
-    ret = poll(&pollfd, 1, -1);
-    if (ret > 0) {
-        if (saferead(p[0], &retchar, sizeof(retchar)) > 0) {
-            if (retchar == '0')
-                ret = TRUE;
-            else
-                ret = FALSE;
-        } else
-            ret = FALSE;
-    } else if (ret < 0) {
-        if (errno == EINTR) {
-            if (intCaught) {
-                virDomainAbortJob(dom);
-                ret = FALSE;
-                intCaught = 0;
+        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
-                goto repoll;
+                ret = FALSE;
+            break;
+        }
+
+        if (ret < 0) {
+            if (errno == EINTR) {
+                if (intCaught) {
+                    virDomainAbortJob(dom);
+                    ret = FALSE;
+                    intCaught = 0;
+                } else
+                    goto repoll;
+            }
+            break;
+        }
+
+        if (verbose) {
+            pthread_sigmask(SIG_BLOCK, &sigmask, &oldsigmask);
+            ret = virDomainGetJobInfo(dom, &jobinfo);
+            pthread_sigmask(SIG_SETMASK, &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.3.1


-- 
Thanks,
Hu Tao


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]