[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH 05/13] blockjob: add virDomainBlockCopy



This new API provides additional flexibility over what can be
crammed on top of virDomainBlockRebase, at the expense that it
cannot be backported without bumping the .so version.

* include/libvirt/libvirt.h.in (virDomainBlockCopy): New API.
* src/libvirt.c (virDomainBlockCopy): Implement it.
* src/libvirt_public.syms (LIBVIRT_0.9.12): Export it.
* src/driver.h (virDrvDomainBlockCopy): New driver callback.
* docs/apibuild.py (CParser.parseSignature): Add exception.
---
 docs/apibuild.py             |    1 +
 include/libvirt/libvirt.h.in |   18 ++++++-
 src/driver.h                 |    6 ++
 src/libvirt.c                |  120 +++++++++++++++++++++++++++++++++++++++++-
 src/libvirt_public.syms      |    5 ++
 5 files changed, 147 insertions(+), 3 deletions(-)

diff --git a/docs/apibuild.py b/docs/apibuild.py
index 1ac0281..bf06f3b 100755
--- a/docs/apibuild.py
+++ b/docs/apibuild.py
@@ -1650,6 +1650,7 @@ class CParser:
         "virDomainBlockJobSetSpeed"      : (False, ("bandwidth")),
         "virDomainBlockPull"             : (False, ("bandwidth")),
         "virDomainBlockRebase"           : (False, ("bandwidth")),
+        "virDomainBlockCopy"             : (False, ("bandwidth")),
         "virDomainMigrateGetMaxSpeed"    : (False, ("bandwidth")) }

     def checkLongLegacyFunction(self, name, return_type, signature):
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index 9901a82..9e55307 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -1937,7 +1937,7 @@ int virDomainUpdateDeviceFlags(virDomainPtr domain,
  * VIR_DOMAIN_BLOCK_JOB_TYPE_PULL: Block Pull (virDomainBlockPull, or
  * virDomainBlockRebase without flags), job ends on completion
  * VIR_DOMAIN_BLOCK_JOB_TYPE_COPY: Block Copy (virDomainBlockRebase with
- * flags), job exists as long as mirroring is active
+ * flags, or virDomainBlockCopy), job exists as long as mirroring is active
  */
 typedef enum {
     VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN = 0,
@@ -2006,6 +2006,22 @@ int           virDomainBlockRebase(virDomainPtr dom, const char *disk,
                                    const char *base, unsigned long bandwidth,
                                    unsigned int flags);

+/**
+ * virDomainBlockCopyFlags:
+ *
+ * Flags available for virDomainBlockCopy().
+ */
+typedef enum {
+    VIR_DOMAIN_BLOCK_COPY_SHALLOW   = 1 << 0, /* Limit copy to top of source
+                                                 backing chain */
+    VIR_DOMAIN_BLOCK_COPY_REUSE_EXT = 1 << 1, /* Reuse existing external
+                                                 file for a copy */
+} virDomainBlockCopyFlags;
+
+int virDomainBlockCopy(virDomainPtr dom, const char *disk, const char *base,
+                       const char *dest, const char *format,
+                       unsigned long bandwidth, unsigned int flags);
+

 /* Block I/O throttling support */

diff --git a/src/driver.h b/src/driver.h
index 03d249b..37eecbc 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -788,6 +788,11 @@ typedef int
     (*virDrvDomainBlockRebase)(virDomainPtr dom, const char *path,
                                const char *base, unsigned long bandwidth,
                                unsigned int flags);
+typedef int
+    (*virDrvDomainBlockCopy)(virDomainPtr dom, const char *path,
+                             const char *base, const char *dest,
+                             const char *format, unsigned long bandwidth,
+                             unsigned int flags);

 typedef int
     (*virDrvSetKeepAlive)(virConnectPtr conn,
@@ -1005,6 +1010,7 @@ struct _virDriver {
     virDrvDomainBlockJobSetSpeed domainBlockJobSetSpeed;
     virDrvDomainBlockPull domainBlockPull;
     virDrvDomainBlockRebase domainBlockRebase;
+    virDrvDomainBlockCopy domainBlockCopy;
     virDrvSetKeepAlive setKeepAlive;
     virDrvConnectIsAlive isAlive;
     virDrvNodeSuspendForDuration nodeSuspendForDuration;
diff --git a/src/libvirt.c b/src/libvirt.c
index 9212c08..a433c30 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -18253,7 +18253,10 @@ error:
  * return an error if bandwidth is not 0.
  *
  * When @base is NULL and @flags is 0, this is identical to
- * virDomainBlockPull().
+ * virDomainBlockPull().  Conversely, when @flags includes
+ * VIR_DOMAIN_BLOCK_REBASE_COPY, this is shorthand for
+ * virDomainBlockCopy(dom, disk, NULL, base, NULL, bandwidth,
+ * flags & ~VIR_DOMAIN_BLOCK_REBASE_COPY).
  *
  * Returns 0 if the operation has started, -1 on failure.
  */
@@ -18263,7 +18266,7 @@ int virDomainBlockRebase(virDomainPtr dom, const char *disk,
 {
     virConnectPtr conn;

-    VIR_DOMAIN_DEBUG(dom, "disk=%s, base=%s bandwidth=%lu, flags=%x",
+    VIR_DOMAIN_DEBUG(dom, "disk=%s, base=%s, bandwidth=%lu, flags=%x",
                      disk, NULLSTR(base), bandwidth, flags);

     virResetLastError();
@@ -18320,6 +18323,119 @@ error:


 /**
+ * virDomainBlockCopy:
+ * @dom: pointer to domain object
+ * @disk: path to the block device, or device shorthand
+ * @base: path to backing file to keep, or NULL for no backing file
+ * @dest: path to the copy destination
+ * @format: format of the destination
+ * @bandwidth: (optional) specify copy bandwidth limit in Mbps
+ * @flags: bitwise-OR of virDomainBlockCopyFlags
+ *
+ * Copy a portion of a backing chain to a new file @dest, where the copy
+ * will have @base as its backing file; or, if @base is NULL, then the
+ * copy will default to being flat, but if @flags includes
+ * VIR_DOMAIN_BLOCK_COPY_SHALLOW, then the copy will have the same backing
+ * fils as the source.  The destination file will have the format given by
+ * @format; if this is NULL, then the format will be the same as the
+ * top level of the source chain.  By default, if @dest exists as a
+ * non-empty regular file, the copy is rejected to avoid losing content
+ * of that file.  However, if @flags additionally includes
+ * VIR_DOMAIN_BLOCK_COPY_REUSE_EXT, then the destination file must
+ * already exist and contain content identical to the source file (this
+ * allows a management app to pre-create files with relative backing
+ * file names, rather than the default of creating with absolute backing
+ * file names).  A copy job has two parts; in the first phase, the
+ * @bandwidth parameter affects how fast the source is pulled into the
+ * destination, and the job can only be canceled by reverting to the
+ * source file; progress in this phase can be tracked via the
+ * virDomainBlockJobInfo() command, with a job type of
+ * VIR_DOMAIN_BLOCK_JOB_TYPE_COPY.  An asynchronous event is sent when
+ * this phase ends, at which point the job remains alive to indicate
+ * that both source and destination files contain mirrored contents, and
+ * the user must call virDomainBlockJobAbort() to end the mirroring while
+ * choosing whether to revert to source or pivot to the destination.
+ * Some hypervisors will restrict certain actions, such as virDomainSave()
+ * or virDomainDetachDevice(), while a copy job is active; they may
+ * also restrict a copy job to transient domains.
+ *
+ * The @disk parameter is either an unambiguous source name of the
+ * block device (the <source file='...'/> sub-element, such as
+ * "/path/to/image"), or the device target shorthand (the
+ * <target dev='...'/> sub-element, such as "xvda").  Valid names
+ * can be found by calling virDomainGetXMLDesc() and inspecting
+ * elements within //domain/devices/disk.
+ *
+ * The maximum bandwidth (in Mbps) that will be used to do the copy can be
+ * specified with the bandwidth parameter.  If set to 0, libvirt will choose a
+ * suitable default.  Some hypervisors do not support this feature and will
+ * return an error if bandwidth is not 0.
+ *
+ * When @base and @format are NULL, this is equivalent to calling
+ * virDomainBlockRebase() with the VIR_DOMAIN_BLOCK_REBASE_COPY flag.
+ *
+ * Returns 0 if the operation has started, -1 on failure.
+ */
+int virDomainBlockCopy(virDomainPtr dom, const char *disk,
+                       const char *base, const char *dest,
+                       const char *format, unsigned long bandwidth,
+                       unsigned int flags)
+{
+    virConnectPtr conn;
+
+    VIR_DOMAIN_DEBUG(dom, "disk=%s, base=%s, dest=%s, format=%s, "
+                     "bandwidth=%lu, flags=%x", disk, NULLSTR(base),
+                     dest, NULLSTR(format), bandwidth, flags);
+
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_DOMAIN (dom)) {
+        virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        virDispatchError(NULL);
+        return -1;
+    }
+    conn = dom->conn;
+
+    if (dom->conn->flags & VIR_CONNECT_RO) {
+        virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        goto error;
+    }
+
+    if (!disk) {
+        virLibDomainError(VIR_ERR_INVALID_ARG,
+                          _("disk is NULL"));
+        goto error;
+    }
+    if (!dest) {
+        virLibDomainError(VIR_ERR_INVALID_ARG,
+                          _("dest is NULL"));
+        goto error;
+    }
+
+    if ((flags & VIR_DOMAIN_BLOCK_COPY_SHALLOW) && base) {
+        virLibDomainError(VIR_ERR_INVALID_ARG,
+                          _("base not permitted when doing shallow copy"));
+        goto error;
+    }
+
+    if (conn->driver->domainBlockCopy) {
+        int ret;
+        ret = conn->driver->domainBlockCopy(dom, disk, base, dest, format,
+                                            bandwidth, flags);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibDomainError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    virDispatchError(dom->conn);
+    return -1;
+}
+
+
+/**
  * virDomainOpenGraphics:
  * @dom: pointer to domain object
  * @idx: index of graphics config to open
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 46c13fb..d152ab9 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -534,4 +534,9 @@ LIBVIRT_0.9.11 {
         virDomainPMWakeup;
 } LIBVIRT_0.9.10;

+LIBVIRT_0.9.12 {
+    global:
+        virDomainBlockCopy;
+} LIBVIRT_0.9.11;
+
 # .... define new API here using predicted next version number ....
-- 
1.7.7.6


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]