[libvirt] [PATCH v2 05/25] backup: Introduce virDomainBackup APIs

Peter Krempa pkrempa at redhat.com
Tue Dec 3 17:17:27 UTC 2019


From: Eric Blake <eblake at redhat.com>

Introduce a few new public APIs related to incremental backups.  This
builds on the previous notion of a checkpoint (without an existing
checkpoint, the new API is a full backup, differing from
virDomainBlockCopy in the point of time chosen and in operation on
multiple disks at once); and also allows creation of a new checkpoint
at the same time as starting the backup (after all, an incremental
backup is only useful if it covers the state since the previous
backup).

A backup job also affects filtering a listing of domains, as well as
adding event reporting for signaling when a push model backup
completes (where the hypervisor creates the backup); note that the
pull model does not have an event (starting the backup lets a third
party access the data, and only the third party knows when it is
finished).

The full list of new APIs:
        virDomainBackupBegin;
        virDomainBackupGetXMLDesc;

Signed-off-by: Eric Blake <eblake at redhat.com>
Signed-off-by: Peter Krempa <pkrempa at redhat.com>
---
 include/libvirt/libvirt-domain.h |  19 +++-
 src/driver-hypervisor.h          |  12 +++
 src/libvirt-domain-checkpoint.c  |   7 +-
 src/libvirt-domain.c             | 143 +++++++++++++++++++++++++++++++
 src/libvirt_public.syms          |   6 ++
 5 files changed, 183 insertions(+), 4 deletions(-)

diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index b9908fe7b0..84c5492a7b 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -4129,8 +4129,10 @@ typedef void (*virConnectDomainEventMigrationIterationCallback)(virConnectPtr co
  * @nparams: size of the params array
  * @opaque: application specific data
  *
- * This callback occurs when a job (such as migration) running on the domain
- * is completed. The params array will contain statistics of the just completed
+ * This callback occurs when a job (such as migration or backup) running on
+ * the domain is completed.
+ *
+ * The params array will contain statistics of the just completed
  * job as virDomainGetJobStats would return. The callback must not free @params
  * (the array will be freed once the callback finishes).
  *
@@ -4949,4 +4951,17 @@ int virDomainAgentSetResponseTimeout(virDomainPtr domain,
                                      int timeout,
                                      unsigned int flags);

+typedef enum {
+    VIR_DOMAIN_BACKUP_BEGIN_REUSE_EXTERNAL = (1 << 0), /* reuse separately
+                                                          provided images */
+} virDomainBackupBeginFlags;
+
+int virDomainBackupBegin(virDomainPtr domain,
+                         const char *backupXML,
+                         const char *checkpointXML,
+                         unsigned int flags);
+
+char *virDomainBackupGetXMLDesc(virDomainPtr domain,
+                                unsigned int flags);
+
 #endif /* LIBVIRT_DOMAIN_H */
diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h
index 4afd8f6ec5..bce023017d 100644
--- a/src/driver-hypervisor.h
+++ b/src/driver-hypervisor.h
@@ -1377,6 +1377,16 @@ typedef int
                                        int timeout,
                                        unsigned int flags);

+typedef int
+(*virDrvDomainBackupBegin)(virDomainPtr domain,
+                           const char *backupXML,
+                           const char *checkpointXML,
+                           unsigned int flags);
+
+typedef char *
+(*virDrvDomainBackupGetXMLDesc)(virDomainPtr domain,
+                                unsigned int flags);
+
 typedef struct _virHypervisorDriver virHypervisorDriver;
 typedef virHypervisorDriver *virHypervisorDriverPtr;

@@ -1638,4 +1648,6 @@ struct _virHypervisorDriver {
     virDrvDomainCheckpointDelete domainCheckpointDelete;
     virDrvDomainGetGuestInfo domainGetGuestInfo;
     virDrvDomainAgentSetResponseTimeout domainAgentSetResponseTimeout;
+    virDrvDomainBackupBegin domainBackupBegin;
+    virDrvDomainBackupGetXMLDesc domainBackupGetXMLDesc;
 };
diff --git a/src/libvirt-domain-checkpoint.c b/src/libvirt-domain-checkpoint.c
index fa391f8a06..432c2d5a52 100644
--- a/src/libvirt-domain-checkpoint.c
+++ b/src/libvirt-domain-checkpoint.c
@@ -102,8 +102,11 @@ virDomainCheckpointGetConnect(virDomainCheckpointPtr checkpoint)
  * @flags: bitwise-OR of supported virDomainCheckpointCreateFlags
  *
  * Create a new checkpoint using @xmlDesc, with a top-level
- * <domaincheckpoint> element, on a running @domain.  Note that @xmlDesc
- * must validate against the <domaincheckpoint> XML schema.
+ * <domaincheckpoint> element, on a running @domain.  Note that
+ * @xmlDesc must validate against the <domaincheckpoint> XML schema.
+ * Typically, it is more common to create a new checkpoint as part of
+ * kicking off a backup job with virDomainBackupBegin(); however, it
+ * is also possible to start a checkpoint without a backup.
  *
  * See <a href="formatcheckpoint.html#CheckpointAttributes">Checkpoint XML</a>
  * for more details on @xmlDesc. In particular, some hypervisors may require
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
index b9345804ea..f873246ace 100644
--- a/src/libvirt-domain.c
+++ b/src/libvirt-domain.c
@@ -12541,3 +12541,146 @@ virDomainAgentSetResponseTimeout(virDomainPtr domain,
     virDispatchError(conn);
     return -1;
 }
+
+
+/**
+ * virDomainBackupBegin:
+ * @domain: a domain object
+ * @backupXML: description of the requested backup
+ * @checkpointXML: description of a checkpoint to create or NULL
+ * @flags: bitwise or of virDomainBackupBeginFlags
+ *
+ * Start a point-in-time backup job for the specified disks of a
+ * running domain.
+ *
+ * A backup job is a domain job and thus mutually exclusive with any other
+ * domain job such as migration.
+ *
+ * For now, backup jobs are also mutually exclusive with any
+ * other block job on the same device, although this restriction may
+ * be lifted in a future release. Progress of the backup job can be
+ * tracked via virDomainGetJobStats(). Completion of the job is also announced
+ * asynchronously via VIR_DOMAIN_EVENT_ID_JOB_COMPLETED event.
+ *
+ * There are two fundamental backup approaches. The first, called a
+ * push model, instructs the hypervisor to copy the state of the guest
+ * disk to the designated storage destination (which may be on the
+ * local file system or a network device). In this mode, the
+ * hypervisor writes the content of the guest disk to the destination,
+ * then emits VIR_DOMAIN_EVENT_ID_JOB_COMPLETED when the backup is
+ * either complete or failed (the backup image is invalid if the job
+ * fails or virDomainAbortJob() is used prior to the event being
+ * emitted). This kind of the job finishes automatically. Users can
+ * determine success by using virDomainGetJobStats() with
+ * VIR_DOMAIN_JOB_STATS_COMPLETED flag.
+ *
+ * The second, called a pull model, instructs the hypervisor to expose
+ * the state of the guest disk over an NBD export. A third-party
+ * client can then connect to this export and read whichever portions
+ * of the disk it desires.  In this mode libvirt has to be informed via
+ * virDomainAbortJob() when the third-party NBD client is done and the backup
+ * resources can be released.
+ *
+ * The @backupXML parameter contains details about the backup in the top-level
+ * element <domainbackup>, including which backup mode to use, whether the
+ * backup is incremental from a previous checkpoint, which disks
+ * participate in the backup, the destination for a push model backup,
+ * and the temporary storage and NBD server details for a pull model
+ * backup.
+ *
+ * virDomainBackupGetXMLDesc() can be called to learn actual
+ * values selected.  For more information, see
+ * formatcheckpoint.html#BackupAttributes.
+ *
+ * The @checkpointXML parameter is optional; if non-NULL, then libvirt
+ * behaves as if virDomainCheckpointCreateXML() were called to create
+ * a checkpoint atomically covering the same point in time as the
+ * backup.
+ *
+ * The VIR_DOMAIN_BACKUP_BEGIN_REUSE_EXTERNAL specifies that the output or
+ * temporary files described by the @backupXML document were created by the
+ * caller with correct format and size to hold the backup or temporary data.
+ *
+ * The creation of a new checkpoint allows for future incremental backups.
+ * Note that some hypervisors may require a particular disk format, such as
+ * qcow2, in order to take advantage of checkpoints, while allowing arbitrary
+ * formats if checkpoints are not involved.
+ *
+ * Returns 0 on success or -1 on failure.
+ */
+int
+virDomainBackupBegin(virDomainPtr domain,
+                     const char *backupXML,
+                     const char *checkpointXML,
+                     unsigned int flags)
+{
+    virConnectPtr conn;
+
+    VIR_DOMAIN_DEBUG(domain, "backupXML=%s, checkpointXML=%s, flags=0x%x",
+                     NULLSTR(backupXML), NULLSTR(checkpointXML), flags);
+
+    virResetLastError();
+
+    virCheckDomainReturn(domain, -1);
+    conn = domain->conn;
+
+    virCheckNonNullArgGoto(backupXML, error);
+    virCheckReadOnlyGoto(conn->flags, error);
+
+    if (conn->driver->domainBackupBegin) {
+        int ret;
+        ret = conn->driver->domainBackupBegin(domain, backupXML, checkpointXML,
+                                              flags);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virReportUnsupportedError();
+ error:
+    virDispatchError(conn);
+    return -1;
+}
+
+
+/**
+ * virDomainBackupGetXMLDesc:
+ * @domain: a domain object
+ * @flags: extra flags; not used yet, so callers should always pass 0
+ *
+ * Queries the configuration of the active backup job.
+ *
+ * In some cases, a user can start a backup job without supplying all
+ * details and rely on libvirt to fill in the rest (for example,
+ * selecting the port used for an NBD export). This API can then be
+ * used to learn what default values were chosen.
+ *
+ * Returns a NUL-terminated UTF-8 encoded XML instance or NULL in
+ * case of error.  The caller must free() the returned value.
+ */
+char *
+virDomainBackupGetXMLDesc(virDomainPtr domain,
+                          unsigned int flags)
+{
+    virConnectPtr conn;
+
+    VIR_DOMAIN_DEBUG(domain, "flags=0x%x", flags);
+
+    virResetLastError();
+
+    virCheckDomainReturn(domain, NULL);
+    conn = domain->conn;
+
+    if (conn->driver->domainBackupGetXMLDesc) {
+        char *ret;
+        ret = conn->driver->domainBackupGetXMLDesc(domain, flags);
+        if (!ret)
+            goto error;
+        return ret;
+    }
+
+    virReportUnsupportedError();
+ error:
+    virDispatchError(conn);
+    return NULL;
+}
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index c92f083758..539d2e3943 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -867,4 +867,10 @@ LIBVIRT_5.10.0 {
         virDomainAgentSetResponseTimeout;
 } LIBVIRT_5.8.0;

+LIBVIRT_6.0.0 {
+    global:
+        virDomainBackupBegin;
+        virDomainBackupGetXMLDesc;
+} LIBVIRT_5.10.0;
+
 # .... define new API here using predicted next version number ....
-- 
2.23.0




More information about the libvir-list mailing list