From f182da20b09d01b3eaba3c9ed81a7ffa215fc286 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Tue, 20 May 2014 22:11:29 -0600 Subject: [PATCH] virsh: expose new active commit controls Add knobs to virsh to manage a 2-phase active commit of the top layer, similar to knobs already present on blockcopy. While this code will fail until later patches actually implement the new knobs in the qemu driver, doing it now proves that the API is usable and also makes it easier for testing the qemu changes as they are made. * tools/virsh-domain.c (cmdBlockCommit): Add --active, --pivot, and --keep-overlay options, modeled after blockcopy. (blockJobImpl): Support --active flag. * tools/virsh.pod (blockcommit): Document new flags. (blockjob): Mention 2-phase commit interaction. Signed-off-by: Eric Blake --- tools/virsh-domain.c | 56 +++++++++++++++++++++++++++++++++++++++----- tools/virsh.pod | 32 ++++++++++++++++++------- 2 files changed, 73 insertions(+), 15 deletions(-) diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index d1368627d0..0ae1538a94 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -1492,6 +1492,10 @@ blockJobImpl(vshControl *ctl, const vshCmd *cmd, 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: @@ -1592,13 +1596,18 @@ static const vshCmdOptDef opts_block_commit[] = { .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, @@ -1606,7 +1615,15 @@ static const vshCmdOptDef opts_block_commit[] = { }, {.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, @@ -1620,8 +1637,11 @@ cmdBlockCommit(vshControl *ctl, const vshCmd *cmd) { 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; @@ -1632,7 +1652,12 @@ cmdBlockCommit(vshControl *ctl, const vshCmd *cmd) 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) @@ -1650,8 +1675,7 @@ cmdBlockCommit(vshControl *ctl, const vshCmd *cmd) 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; } @@ -1683,6 +1707,8 @@ cmdBlockCommit(vshControl *ctl, const vshCmd *cmd) if (verbose) vshPrintJobProgress(_("Block Commit"), info.end - info.cur, info.end); + if (active && info.cur == info.end) + break; GETTIMEOFDAY(&curr); if (intCaught || (timeout && @@ -1709,7 +1735,25 @@ cmdBlockCommit(vshControl *ctl, const vshCmd *cmd) /* 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: diff --git a/tools/virsh.pod b/tools/virsh.pod index ceec1a0b59..b41473ead7 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -774,8 +774,9 @@ address of virtual interface (such as I or I) will accept the MAC address printed by this command. =item B I I [I] -{[I] | [I<--shallow>]} [I] [I<--delete>] -[I<--wait> [I<--verbose>] [I<--timeout> B] [I<--async>]] +[I] [I<--shallow>] [I] [I<--delete>] +[I<--wait> [I<--async>] [I<--verbose>]] [I<--timeout> B] +[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 @@ -785,19 +786,32 @@ operation is constrained to committing just that portion of the chain; I<--shallow> can be used instead of I 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 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 is copied into I and the job can only be +canceled, with top still containing data not yet in base. In the second +phase, I and I remain identical until a call to B +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. However, if I<--wait> is -specified, then this command will block until the operation completes, -or cancel the operation if the optional I 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 in seconds elapses or SIGINT is sent (usually with 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 +I<--pivot>; and using I<--keep-overlay> is shorthand for combining +I<--active> I<--wait> with an automatic B I<--abort>. I specifies fully-qualified path of the disk; it corresponds to a unique target name () or source file ( for listing these names). 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 can be used to set bandwidth limit for the active job.