On Sat, Jul 06, 2019 at 22:56:02 -0500, Eric Blake wrote:
Introduce a bunch of new public APIs related to backup checkpoints.
Checkpoints are modeled heavily after virDomainSnapshotPtr (both
represent a point in time of the guest), although a snapshot exists
with the intent of rolling back to that state, while a checkpoint
exists to make it possible to create an incremental backup at a later
time. We may have a future hypervisor that can completely manage
checkpoints without libvirt metadata, but the first two planned
hypervisors (qemu and test) both always use libvirt for tracking
metadata relations between checkpoints, so for now, I've deferred
the counterpart of virDomainSnapshotHasMetadata for a separate
API addition at a later date if there is ever a need for it.
The following map shows the API relations to snapshots, with new APIs
on the right:
Operate on a domain object to create/redefine a child:
virDomainSnapshotCreateXML virDomainCheckpointCreateXML
Operate on a child object for lifetime management:
virDomainSnapshotDelete virDomainCheckpointDelete
virDomainSnapshotFree virDomainCheckpointFree
virDomainSnapshotRef virDomainCheckpointRef
Operate on a child object to learn more about it:
virDomainSnapshotGetXMLDesc virDomainCheckpointGetXMLDesc
virDomainSnapshotGetConnect virDomainCheckpointGetConnect
virDomainSnapshotGetDomain virDomainCheckpointGetDomain
virDomainSnapshotGetName virDomainCheckpiontGetName
virDomainSnapshotGetParent virDomainCheckpiontGetParent
virDomainSnapshotHasMetadata (deferred for later)
virDomainSnapshotIsCurrent (no counterpart, present in XML instead)
Operate on a domain object to list all children:
virDomainSnapshotNum (no counterparts, these are the old
virDomainSnapshotListNames racy interfaces)
virDomainSnapshotListAllSnapshots virDomainListAllCheckpoints
Operate on a child object to list descendents:
virDomainSnapshotNumChildren (no counterparts, these are the old
virDomainSnapshotListChildrenNames racy interfaces)
virDomainSnapshotListAllChildren virDomainCheckpointListAllChildren
Operate on a domain to locate a particular child:
virDomainSnapshotLookupByName virDomainCheckpointLookupByName
virDomainSnapshotCurrent (obtained by flag to ListAllCheckpoints)
virDomainHasCurrentSnapshot (no counterpart, old racy interface)
Operate on a snapshot to roll back to earlier state:
virDomainSnapshotRevert (no counterpart, instead checkpoints
are used in incremental backups via
XML to virDomainBackupBegin)
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
include/libvirt/libvirt-domain-checkpoint.h | 143 +++++
include/libvirt/libvirt-domain.h | 6 +
include/libvirt/libvirt.h | 5 +-
src/conf/virdomainmomentobjlist.h | 5 +-
src/driver-hypervisor.h | 38 ++
docs/Makefile.am | 3 +
docs/apibuild.py | 2 +
docs/docs.html.in | 1 +
libvirt.spec.in | 1 +
mingw-libvirt.spec.in | 2 +
po/POTFILES | 1 +
src/Makefile.am | 2 +
src/libvirt-domain-checkpoint.c | 586 ++++++++++++++++++++
src/libvirt-domain.c | 19 +-
src/libvirt_public.syms | 16 +
15 files changed, 821 insertions(+), 9 deletions(-)
create mode 100644 include/libvirt/libvirt-domain-checkpoint.h
create mode 100644 src/libvirt-domain-checkpoint.c
diff --git a/include/libvirt/libvirt-domain-checkpoint.h
b/include/libvirt/libvirt-domain-checkpoint.h
new file mode 100644
index 0000000000..b2d5c5758b
--- /dev/null
+++ b/include/libvirt/libvirt-domain-checkpoint.h
@@ -0,0 +1,143 @@
[...]
+typedef enum {
+ VIR_DOMAIN_CHECKPOINT_CREATE_REDEFINE = (1 << 0), /* Restore or alter
+ metadata */
+ VIR_DOMAIN_CHECKPOINT_CREATE_NO_METADATA = (1 << 1), /* Make checkpoint
without
+ remembering it */
[1]
+ VIR_DOMAIN_CHECKPOINT_CREATE_QUIESCE = (1 << 2), /*
use guest agent to
+ quiesce all mounted
+ file systems within
+ the domain */
+} virDomainCheckpointCreateFlags;
[...]
diff --git a/src/libvirt-domain-checkpoint.c
b/src/libvirt-domain-checkpoint.c
new file mode 100644
index 0000000000..ab82d8422b
--- /dev/null
+++ b/src/libvirt-domain-checkpoint.c
@@ -0,0 +1,586 @@
[...]
+/**
+ * virDomainCheckpointCreateXML:
+ * @domain: a domain object
+ * @xmlDesc: description of the checkpoint to create
+ * @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.
+ *
+ * See <a href=formatcheckpoint.html#CheckpointAttributes">Checkpoint
XML</a>
+ * for more details on @xmlDesc. In particular, some hypervisors may require
+ * particular disk formats, such as qcow2, in order to support this
+ * command; where @xmlDesc can be used to limit the checkpoint to a working
+ * subset of the domain's disks.
+ *
+ * If @flags includes VIR_DOMAIN_CHECKPOINT_CREATE_REDEFINE, then this
+ * is a request to reinstate checkpoint metadata that was previously
+ * captured from virDomainCheckpointGetXMLDesc() before removing that
+ * metadata, rather than creating a new checkpoint. Note that while
+ * original creation can omit a number of elements from @xmlDesc (and
+ * libvirt will supply sane defaults based on the domain state at that
+ * point in time), a redefinition must supply more elements (as the
+ * domain may have changed in the meantime, so that libvirt no longer
+ * has a way to resupply correct defaults). Not all hypervisors support
+ * this flag.
+ *
+ * If @flags includes VIR_DOMAIN_CHECKPOINT_CREATE_NO_METADATA, then
+ * the domain's disk images are modified according to @xmlDesc, but
+ * libvirt does not track any metadata (similar to immediately calling
+ * virDomainCheckpointDelete() with
[1]
+ * VIR_DOMAIN_CHECKPOINT_DELETE_METADATA_ONLY). This flag is
+ * incompatible with VIR_DOMAIN_CHECKPOINT_CREATE_REDEFINE, and is
+ * not supported by all hypervisors.
+ *
+ * If @flags includes VIR_DOMAIN_CHECKPOINT_CREATE_QUIESCE, then the
+ * libvirt will attempt to use guest agent to freeze and thaw all file
+ * systems in use within domain OS. However, if the guest agent is not
+ * present, an error is thrown. This flag is incompatible with
+ * VIR_DOMAIN_CHECKPOINT_CREATE_REDEFINE.
+ *
+ * Returns an (opaque) new virDomainCheckpointPtr on success or NULL
+ * on failure.
+ */
+virDomainCheckpointPtr
+virDomainCheckpointCreateXML(virDomainPtr domain,
+ const char *xmlDesc,
+ unsigned int flags)
+{
+ virConnectPtr conn;
+
+ VIR_DOMAIN_DEBUG(domain, "xmlDesc=%s, flags=0x%x", xmlDesc, flags);
+
+ virResetLastError();
+
+ virCheckDomainReturn(domain, NULL);
+ conn = domain->conn;
+
+ virCheckNonNullArgGoto(xmlDesc, error);
+ virCheckReadOnlyGoto(conn->flags, error);
+
+ VIR_EXCLUSIVE_FLAGS_GOTO(VIR_DOMAIN_CHECKPOINT_CREATE_REDEFINE,
+ VIR_DOMAIN_CHECKPOINT_CREATE_NO_METADATA,
+ error);
+ VIR_EXCLUSIVE_FLAGS_GOTO(VIR_DOMAIN_CHECKPOINT_CREATE_REDEFINE,
+ VIR_DOMAIN_CHECKPOINT_CREATE_QUIESCE,
+ error);
+
+ if (conn->driver->domainCheckpointCreateXML) {
+ virDomainCheckpointPtr ret;
+ ret = conn->driver->domainCheckpointCreateXML(domain, xmlDesc, flags);
+ if (!ret)
+ goto error;
+ return ret;
+ }
+
+ virReportUnsupportedError();
+ error:
+ virDispatchError(conn);
+ return NULL;
+}
[...]
ACK if and only if you remove the [1] 'NO_METADATA' checkpoint creation
flag and everything related to it.
Obviously there may be some fallout from "current".