backup: Introduce virDomainBackup APIs

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@redhat.com>
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
Eric Blake 2019-08-21 20:42:42 -05:00 committed by Peter Krempa
parent 252958ee16
commit 74ca70507a
5 changed files with 183 additions and 4 deletions

View File

@ -4143,8 +4143,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).
*
@ -4963,4 +4965,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 */

View File

@ -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;
};

View File

@ -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

View File

@ -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;
}

View File

@ -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 ....