[libvirt] [PATCH 3/4] virsh: Use do_job_watch in cmdSave

Michal Privoznik mprivozn at redhat.com
Tue Dec 20 15:21:10 UTC 2011


This patch alters saving code, so we can report progress
and allow cancel via ^C.
---
 tools/virsh.c   |   86 ++++++++++++++++++++++++++++++++++++++++++++++---------
 tools/virsh.pod |    8 ++--
 2 files changed, 76 insertions(+), 18 deletions(-)

diff --git a/tools/virsh.c b/tools/virsh.c
index c2440e2..ab46b8c 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -2406,25 +2406,35 @@ static const vshCmdOptDef opts_save[] = {
      N_("filename containing updated XML for the target")},
     {"running", VSH_OT_BOOL, 0, N_("set domain to be running on restore")},
     {"paused", VSH_OT_BOOL, 0, N_("set domain to be paused on restore")},
+    {"verbose", VSH_OT_BOOL, 0, N_("display the progress of save")},
     {NULL, 0, 0, NULL}
 };
 
-static bool
-cmdSave(vshControl *ctl, const vshCmd *cmd)
+static void
+doSave(void *opaque)
 {
-    virDomainPtr dom;
+    vshCtrlData *data = opaque;
+    vshControl *ctl = data->ctl;
+    const vshCmd *cmd = data->cmd;
+    char ret = '1';
+    virDomainPtr dom = NULL;
     const char *name = NULL;
     const char *to = NULL;
-    bool ret = false;
     unsigned int flags = 0;
     const char *xmlfile = NULL;
     char *xml = NULL;
+    sigset_t sigmask, oldsigmask;
+
+    sigemptyset(&sigmask);
+    sigaddset(&sigmask, SIGINT);
+    if (pthread_sigmask(SIG_BLOCK, &sigmask, &oldsigmask) < 0)
+        goto out_sig;
 
     if (!vshConnectionUsability(ctl, ctl->conn))
-        return false;
+        goto out;
 
     if (vshCommandOptString(cmd, "file", &to) <= 0)
-        return false;
+        goto out;
 
     if (vshCommandOptBool(cmd, "bypass-cache"))
         flags |= VIR_DOMAIN_SAVE_BYPASS_CACHE;
@@ -2435,29 +2445,77 @@ cmdSave(vshControl *ctl, const vshCmd *cmd)
 
     if (vshCommandOptString(cmd, "xml", &xmlfile) < 0) {
         vshError(ctl, "%s", _("malformed xml argument"));
-        return false;
+        goto out;
     }
 
     if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
-        return false;
+        goto out;
 
     if (xmlfile &&
         virFileReadAll(xmlfile, 8192, &xml) < 0)
-        goto cleanup;
+        goto out;
 
     if (((flags || xml)
          ? virDomainSaveFlags(dom, to, xml, flags)
          : virDomainSave(dom, to)) < 0) {
         vshError(ctl, _("Failed to save domain %s to %s"), name, to);
-        goto cleanup;
+        goto out;
     }
 
-    vshPrint(ctl, _("Domain %s saved to %s\n"), name, to);
-    ret = true;
+    ret = '0';
 
-cleanup:
+out:
+    pthread_sigmask(SIG_SETMASK, &oldsigmask, NULL);
+out_sig:
+    if (dom) virDomainFree (dom);
     VIR_FREE(xml);
-    virDomainFree(dom);
+    ignore_value(safewrite(data->writefd, &ret, sizeof(ret)));
+}
+
+static bool
+cmdSave(vshControl *ctl, const vshCmd *cmd)
+{
+    bool ret = false;
+    virDomainPtr dom = NULL;
+    int p[2] = {-1. -1};
+    virThread workerThread;
+    bool verbose = false;
+    vshCtrlData data;
+    const char *to = NULL;
+    const char *name = NULL;
+
+    if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
+        return false;
+
+    if (vshCommandOptString(cmd, "file", &to) <= 0)
+        goto cleanup;
+
+    if (vshCommandOptBool (cmd, "verbose"))
+        verbose = true;
+
+    if (pipe(p) < 0)
+        goto cleanup;
+
+    data.ctl = ctl;
+    data.cmd = cmd;
+    data.writefd = p[1];
+
+    if (virThreadCreate(&workerThread,
+                        true,
+                        doSave,
+                        &data) < 0)
+        goto cleanup;
+
+    ret = do_watch_job(ctl, dom, verbose, p[0], 0, NULL, "Save");
+
+    virThreadJoin(&workerThread);
+
+    if (ret)
+        vshPrint(ctl, _("\nDomain %s saved to %s\n"), name, to);
+
+cleanup:
+    if (dom)
+        virDomainFree(dom);
     return ret;
 }
 
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 5a5fbf8..0141728 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -875,7 +875,7 @@ have also reverted all storage volumes back to the same contents as when
 the state file was created.
 
 =item B<save> I<domain-id> I<state-file> [I<--bypass-cache>] [I<--xml> B<file>]
-[{I<--running> | I<--paused>}]
+[{I<--running> | I<--paused>}] [I<--verbose>]
 
 Saves a running domain (RAM, but not disk state) to a state file so that
 it can be restored
@@ -886,9 +886,9 @@ If I<--bypass-cache> is specified, the save will avoid the file system
 cache, although this may slow down the operation.
 
 The progress may be monitored using B<domjobinfo> virsh command and canceled
-with B<domjobabort> command (sent by another virsh instance). Interrupting
-(usually with C<Ctrl-C>) the virsh process which runs B<save> command is not
-enough to actually cancel the operation.
+with B<domjobabort> command (sent by another virsh instance). Another option
+is to send SIGINT (usually with C<Ctrl-C>) to the virsh process running
+B<save> command. I<--verbose> displays the progress of save.
 
 This is roughly equivalent to doing a hibernate on a running computer,
 with all the same limitations.  Open network connections may be
-- 
1.7.3.4




More information about the libvir-list mailing list