flags |= VIR_DOMAIN_BLOCK_COMMIT_SHALLOW;
if (vshCommandOptBool(cmd, "delete"))
flags |= VIR_DOMAIN_BLOCK_COMMIT_DELETE;
+ if (vshCommandOptBool(cmd, "active") ||
+ vshCommandOptBool(cmd, "pivot") ||
+ vshCommandOptBool(cmd, "keep-overlay"))
+ flags |= VIR_DOMAIN_BLOCK_COMMIT_ACTIVE;
ret = virDomainBlockCommit(dom, path, base, top, bandwidth, flags);
break;
case VSH_CMD_BLOCK_JOB_COPY:
.type = VSH_OT_DATA,
.help = N_("path of top file to commit from (default top of chain)")
},
+ {.name = "active",
+ .type = VSH_OT_BOOL,
+ .help = N_("trigger two-stage active commit of top file")
+ },
{.name = "delete",
.type = VSH_OT_BOOL,
.help = N_("delete files that were successfully committed")
},
{.name = "wait",
.type = VSH_OT_BOOL,
- .help = N_("wait for job to complete")
+ .help = N_("wait for job to complete "
+ "(with --active, wait for job to sync)")
},
{.name = "verbose",
.type = VSH_OT_BOOL,
},
{.name = "timeout",
.type = VSH_OT_INT,
- .help = N_("with --wait, abort if copy exceeds timeout (in seconds)")
+ .help = N_("implies --wait, abort if copy exceeds timeout (in seconds)")
+ },
+ {.name = "pivot",
+ .type = VSH_OT_BOOL,
+ .help = N_("implies --active --wait, pivot when commit is synced")
+ },
+ {.name = "keep-overlay",
+ .type = VSH_OT_BOOL,
+ .help = N_("implies --active --wait, quit when commit is synced")
},
{.name = "async",
.type = VSH_OT_BOOL,
{
virDomainPtr dom = NULL;
bool ret = false;
- bool blocking = vshCommandOptBool(cmd, "wait");
bool verbose = vshCommandOptBool(cmd, "verbose");
+ bool pivot = vshCommandOptBool(cmd, "pivot");
+ bool finish = vshCommandOptBool(cmd, "keep-overlay");
+ bool active = vshCommandOptBool(cmd, "active") || pivot || finish;
+ bool blocking = vshCommandOptBool(cmd, "wait");
int timeout = 0;
struct sigaction sig_action;
struct sigaction old_sig_action;
bool quit = false;
int abort_flags = 0;
+ blocking |= vshCommandOptBool(cmd, "timeout") || pivot || finish;
if (blocking) {
+ if (pivot && finish) {
+ vshError(ctl, "%s", _("cannot mix --pivot and --keep-overlay"));
+ return false;
+ }
if (vshCommandOptTimeoutToMs(ctl, cmd, &timeout) < 0)
return false;
if (vshCommandOptStringReq(ctl, cmd, "path", &path) < 0)
sigaction(SIGINT, &sig_action, &old_sig_action);
GETTIMEOFDAY(&start);
- } else if (verbose || vshCommandOptBool(cmd, "timeout") ||
- vshCommandOptBool(cmd, "async")) {
+ } else if (verbose || vshCommandOptBool(cmd, "async")) {
vshError(ctl, "%s", _("missing --wait option"));
return false;
}
if (verbose)
vshPrintJobProgress(_("Block Commit"),
info.end - info.cur, info.end);
+ if (active && info.cur == info.end)
+ break;
GETTIMEOFDAY(&curr);
if (intCaught || (timeout &&
/* printf [100 %] */
vshPrintJobProgress(_("Block Commit"), 0, 1);
}
- vshPrint(ctl, "\n%s", quit ? _("Commit aborted") : _("Commit complete"));
+ if (!quit && pivot) {
+ abort_flags |= VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT;
+ if (virDomainBlockJobAbort(dom, path, abort_flags) < 0) {
+ vshError(ctl, _("failed to pivot job for disk %s"), path);
+ goto cleanup;
+ }
+ } else if (finish && !quit &&
+ virDomainBlockJobAbort(dom, path, abort_flags) < 0) {
+ vshError(ctl, _("failed to finish job for disk %s"), path);
+ goto cleanup;
+ }
+ if (quit)
+ vshPrint(ctl, "\n%s", _("Commit aborted"));
+ else if (pivot)
+ vshPrint(ctl, "\n%s", _("Successfully pivoted"));
+ else if (!finish)
+ vshPrint(ctl, "\n%s", _("Now in synchronized phase"));
+ else
+ vshPrint(ctl, "\n%s", _("Commit complete"));
ret = true;
cleanup:
I<domif-setlink>) will accept the MAC address printed by this command.
=item B<blockcommit> I<domain> I<path> [I<bandwidth>]
-{[I<base>] | [I<--shallow>]} [I<top>] [I<--delete>]
-[I<--wait> [I<--verbose>] [I<--timeout> B<seconds>] [I<--async>]]
+[I<base>] [I<--shallow>] [I<top>] [I<--delete>]
+[I<--wait> [I<--async>] [I<--verbose>]] [I<--timeout> B<seconds>]
+[I<--active>] [{I<--pivot> | I<--keep-overlay>}]
Reduce the length of a backing image chain, by committing changes at the
top of the chain (snapshot or delta files) into backing images. By
I<--shallow> can be used instead of I<base> to specify the immediate
backing file of the resulting top image to be committed. The files
being committed are rendered invalid, possibly as soon as the operation
-starts; using the I<--delete> flag will remove these files at the successful
-completion of the commit operation.
+starts; using the I<--delete> flag will attempt to remove these invalidated
+files at the successful completion of the commit operation.
+
+When I<top> is omitted or specified as the active image, it is also
+possible to specify I<--active> to trigger a two-phase active commit. In
+the first phase, I<top> is copied into I<base> and the job can only be
+canceled, with top still containing data not yet in base. In the second
+phase, I<top> and I<base> remain identical until a call to B<blockjob>
+with the I<--abort> flag (keeping top as the active image that tracks
+changes from that point in time) or the I<--pivot> flag (making base
+the new active image and invalidating top).
By default, this command returns as soon as possible, and data for
the entire disk is committed in the background; the progress of the
operation can be checked with B<blockjob>. However, if I<--wait> is
-specified, then this command will block until the operation completes,
-or cancel the operation if the optional I<timeout> in seconds elapses
+specified, then this command will block until the operation completes
+(or for I<--active>, enters the second phase), or until the operation
+is canceled because the optional I<timeout> in seconds elapses
or SIGINT is sent (usually with C<Ctrl-C>). Using I<--verbose> along
with I<--wait> will produce periodic status updates. If job cancellation
is triggered, I<--async> will return control to the user as fast as
possible, otherwise the command may continue to block a little while
-longer until the job is done cleaning up.
+longer until the job is done cleaning up. Using I<--pivot> is shorthand
+for combining I<--active> I<--wait> with an automatic B<blockjob>
+I<--pivot>; and using I<--keep-overlay> is shorthand for combining
+I<--active> I<--wait> with an automatic B<blockjob> I<--abort>.
I<path> specifies fully-qualified path of the disk; it corresponds
to a unique target name (<target dev='name'/>) or source file (<source
If I<--abort> is specified, the active job on the specified disk will
be aborted. If I<--async> is also specified, this command will return
immediately, rather than waiting for the cancellation to complete. If
-I<--pivot> is specified, this requests that an active copy job
-be pivoted over to the new copy.
+I<--pivot> is specified, this requests that an active copy or active
+commit job be pivoted over to the new image.
If I<--info> is specified, the active job information on the specified
disk will be printed.
I<bandwidth> can be used to set bandwidth limit for the active job.