[libvirt] [PATCHv2 05/15] blockjob: add 'blockcopy' to virsh

Eric Blake eblake at redhat.com
Fri Apr 6 04:36:51 UTC 2012


Rather than further overloading 'blockpull', I decided to create a
new virsh command to expose the new flags of virDomainBlockRebase.

Someday, I'd also like to make blockpull and blockcopy have a
synchronous mode, which blocks until the event happens or Ctrl-C
is pressed, as well as a --verbose flag to print status updates
before the job finishes - but not today.

* tools/virsh.c (VSH_CMD_BLOCK_JOB_COPY): New mode.
(blockJobImpl): Support new flags.
(cmdBlockCopy): New command.
(cmdBlockJob): Support new job info, new abort flag.
* tools/virsh.pod (blockcopy, blockjob): Document the new command
and flags.
---
 tools/virsh.c   |   81 +++++++++++++++++++++++++++++++++++++++++++++++-------
 tools/virsh.pod |   37 +++++++++++++++++++++++--
 2 files changed, 104 insertions(+), 14 deletions(-)

diff --git a/tools/virsh.c b/tools/virsh.c
index 7180b83..99f3d22 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -7515,16 +7515,18 @@ typedef enum {
     VSH_CMD_BLOCK_JOB_INFO = 1,
     VSH_CMD_BLOCK_JOB_SPEED = 2,
     VSH_CMD_BLOCK_JOB_PULL = 3,
-} VSH_CMD_BLOCK_JOB_MODE;
+    VSH_CMD_BLOCK_JOB_COPY = 4,
+} vshCmdBlockJobMode;

 static int
 blockJobImpl(vshControl *ctl, const vshCmd *cmd,
-              virDomainBlockJobInfoPtr info, int mode)
+             virDomainBlockJobInfoPtr info, int mode)
 {
     virDomainPtr dom = NULL;
     const char *name, *path;
     unsigned long bandwidth = 0;
     int ret = -1;
+    const char *base = NULL;
     unsigned int flags = 0;

     if (!vshConnectionUsability(ctl, ctl->conn))
@@ -7541,22 +7543,39 @@ blockJobImpl(vshControl *ctl, const vshCmd *cmd,
         goto cleanup;
     }

-    if (mode == VSH_CMD_BLOCK_JOB_ABORT) {
+    switch ((vshCmdBlockJobMode) mode) {
+    case  VSH_CMD_BLOCK_JOB_ABORT:
         if (vshCommandOptBool(cmd, "async"))
             flags |= VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC;
+        if (vshCommandOptBool(cmd, "pivot"))
+            flags |= VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT;
         ret = virDomainBlockJobAbort(dom, path, flags);
-    } else if (mode == VSH_CMD_BLOCK_JOB_INFO) {
+        break;
+    case VSH_CMD_BLOCK_JOB_INFO:
         ret = virDomainGetBlockJobInfo(dom, path, info, 0);
-    } else if (mode == VSH_CMD_BLOCK_JOB_SPEED) {
+        break;
+    case VSH_CMD_BLOCK_JOB_SPEED:
         ret = virDomainBlockJobSetSpeed(dom, path, bandwidth, 0);
-    } else if (mode == VSH_CMD_BLOCK_JOB_PULL) {
-        const char *base = NULL;
+        break;
+    case VSH_CMD_BLOCK_JOB_PULL:
         if (vshCommandOptString(cmd, "base", &base) < 0)
             goto cleanup;
         if (base)
             ret = virDomainBlockRebase(dom, path, base, bandwidth, 0);
         else
             ret = virDomainBlockPull(dom, path, bandwidth, 0);
+        break;
+    case VSH_CMD_BLOCK_JOB_COPY:
+        flags |= VIR_DOMAIN_BLOCK_REBASE_COPY;
+        if (vshCommandOptBool(cmd, "shallow"))
+            flags |= VIR_DOMAIN_BLOCK_REBASE_SHALLOW;
+        if (vshCommandOptBool(cmd, "reuse-external"))
+            flags |= VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT;
+        if (vshCommandOptBool(cmd, "raw"))
+            flags |= VIR_DOMAIN_BLOCK_REBASE_COPY_RAW;
+        if (vshCommandOptString(cmd, "dest", &base) < 0)
+            goto cleanup;
+        ret = virDomainBlockRebase(dom, path, base, bandwidth, flags);
     }

 cleanup:
@@ -7566,6 +7585,34 @@ cleanup:
 }

 /*
+ * "blockcopy" command
+ */
+static const vshCmdInfo info_block_copy[] = {
+    {"help", N_("Start a block copy operation.")},
+    {"desc", N_("Populate a disk from its backing image.")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_block_copy[] = {
+    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
+    {"path", VSH_OT_DATA, VSH_OFLAG_REQ, N_("Fully-qualified path of disk")},
+    {"dest", VSH_OT_DATA, VSH_OFLAG_REQ, N_("path of the copy to create")},
+    {"bandwidth", VSH_OT_DATA, VSH_OFLAG_NONE, N_("Bandwidth limit in MB/s")},
+    {"shallow", VSH_OT_BOOL, 0, N_("make the copy share a backing chain")},
+    {"reuse-external", VSH_OT_BOOL, 0, N_("reuse existing destination")},
+    {"raw", VSH_OT_BOOL, 0, N_("use raw destination file")},
+    {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdBlockCopy(vshControl *ctl, const vshCmd *cmd)
+{
+    if (blockJobImpl(ctl, cmd, NULL, VSH_CMD_BLOCK_JOB_COPY) != 0)
+        return false;
+    return true;
+}
+
+/*
  * "blockpull" command
  */
 static const vshCmdInfo info_block_pull[] = {
@@ -7607,6 +7654,8 @@ static const vshCmdOptDef opts_block_job[] = {
      N_("Abort the active job on the specified disk")},
     {"async", VSH_OT_BOOL, VSH_OFLAG_NONE,
      N_("don't wait for --abort to complete")},
+    {"pivot", VSH_OT_BOOL, VSH_OFLAG_NONE,
+     N_("conclude and pivot a copy job")},
     {"info", VSH_OT_BOOL, VSH_OFLAG_NONE,
      N_("Get active job information for the specified disk")},
     {"bandwidth", VSH_OT_DATA, VSH_OFLAG_NONE,
@@ -7621,7 +7670,9 @@ cmdBlockJob(vshControl *ctl, const vshCmd *cmd)
     virDomainBlockJobInfo info;
     const char *type;
     int ret;
-    bool abortMode = vshCommandOptBool(cmd, "abort");
+    bool abortMode = (vshCommandOptBool(cmd, "abort") ||
+                      vshCommandOptBool(cmd, "async") ||
+                      vshCommandOptBool(cmd, "pivot"));
     bool infoMode = vshCommandOptBool(cmd, "info");
     bool bandwidth = vshCommandOptBool(cmd, "bandwidth");

@@ -7645,10 +7696,17 @@ cmdBlockJob(vshControl *ctl, const vshCmd *cmd)
     if (ret == 0 || mode != VSH_CMD_BLOCK_JOB_INFO)
         return true;

-    if (info.type == VIR_DOMAIN_BLOCK_JOB_TYPE_PULL)
+    switch (info.type) {
+    case VIR_DOMAIN_BLOCK_JOB_TYPE_PULL:
         type = _("Block Pull");
-    else
+        break;
+    case VIR_DOMAIN_BLOCK_JOB_TYPE_COPY:
+        type = _("Block Copy");
+        break;
+    default:
         type = _("Unknown job");
+        break;
+    }

     print_job_progress(type, info.end - info.cur, info.end);
     if (info.bandwidth != 0)
@@ -17127,8 +17185,9 @@ static const vshCmdDef domManagementCmds[] = {
     {"autostart", cmdAutostart, opts_autostart, info_autostart, 0},
     {"blkdeviotune", cmdBlkdeviotune, opts_blkdeviotune, info_blkdeviotune, 0},
     {"blkiotune", cmdBlkiotune, opts_blkiotune, info_blkiotune, 0},
-    {"blockpull", cmdBlockPull, opts_block_pull, info_block_pull, 0},
+    {"blockcopy", cmdBlockCopy, opts_block_copy, info_block_copy, 0},
     {"blockjob", cmdBlockJob, opts_block_job, info_block_job, 0},
+    {"blockpull", cmdBlockPull, opts_block_pull, info_block_pull, 0},
     {"blockresize", cmdBlockResize, opts_block_resize, info_block_resize, 0},
     {"change-media", cmdChangeMedia, opts_change_media, info_change_media, 0},
 #ifndef WIN32
diff --git a/tools/virsh.pod b/tools/virsh.pod
index aac72d1..50a495d 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -638,6 +638,34 @@ currently in use by a running domain. Other contexts that require a MAC
 address of virtual interface (such as I<detach-interface> or
 I<domif-setlink>) will accept the MAC address printed by this command.

+=item B<blockcopy> I<domain> I<path> I<dest> [I<bandwidth>] [I<--shallow>]
+[I<--reuse-external>] [I<--raw>]
+
+Copy a disk backing image chain to I<dest>. By default, this command
+flattens the entire chain; but if I<--shallow> is specified, the copy
+shares the backing chain.
+
+If I<--reuse-external> is specified, then I<dest> must exist and have
+contents identical to the resulting backing file (that is, it must
+start with contents matching the backing file I<disk> if I<--shallow>
+is used, otherwise it must start empty); this option is typically used
+to set up a relative backing file name in the destination.
+
+The format of the destination is determined by the first match in the
+following list: if I<--raw> is specified, it will be raw; if
+I<--reuse-external> is specified, the existing destination is probed
+for a format; and in all other cases, the destination format will
+match the source format.
+
+The copy runs in the background; initially, the job must copy all data
+from the source, and during this phase, the job can only be canceled to
+revert back to the source disk.  After this phase completes, both the
+source and the destination remain mirrored until a call to B<blockjob>
+with the I<--abort> and I<--pivot> flags pivots over to the copy.
+
+I<path> specifies fully-qualified path of the disk.
+I<bandwidth> specifies copying bandwidth limit in Mbps.
+
 =item B<blockpull> I<domain> I<path> [I<bandwidth>] [I<base>]

 Populate a disk from its backing image chain. By default, this command
@@ -686,16 +714,19 @@ Both I<--live> and I<--current> flags may be given, but I<--current> is
 exclusive. If no flag is specified, behavior is different depending
 on hypervisor.

-=item B<blockjob> I<domain> I<path> { I<--abort> [I<--async>] |
+=item B<blockjob> I<domain> I<path> { [I<--abort>] [I<--async>] [I<--pivot] |
 [I<--info>] | I<bandwidth> }

-Manage active block operations.  If no mode is chosen, I<--info> is assumed.
+Manage active block operations.  If no mode is chosen, I<--info> is assumed,
+except that I<--async> and I<--pivot> imply I<--abort>.

 I<path> specifies fully-qualified path of the disk.

 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 cancelation to complete.
+immediately, rather than waiting for the cancelation to complete.  If
+I<--pivot> is specified, this requests that an active copy job
+be pivoted over to the new copy.
 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.
-- 
1.7.7.6




More information about the libvir-list mailing list