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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list