Prepare for new checkpoint APIs by describing the XML that will represent a checkpoint. The checkpoint XML is modeled heavily after virDomainSnapshotPtr. (See the docs for more details). Add testsuite coverage for some minimal uses of the XML. Signed-off-by: Eric Blake <eblake@xxxxxxxxxx> --- docs/docs.html.in | 3 +- docs/format.html.in | 1 + docs/formatcheckpoint.html.in | 202 ++++++++++++++++++++ docs/index.html.in | 3 +- docs/schemas/domaincheckpoint.rng | 94 +++++++++ libvirt.spec.in | 1 + mingw-libvirt.spec.in | 2 + tests/Makefile.am | 2 + tests/domaincheckpointxml2xmlin/empty.xml | 1 + tests/domaincheckpointxml2xmlin/sample.xml | 7 + tests/domaincheckpointxml2xmlout/empty.xml | 10 + tests/domaincheckpointxml2xmlout/sample.xml | 16 ++ tests/virschematest.c | 2 + 13 files changed, 342 insertions(+), 2 deletions(-) create mode 100644 docs/formatcheckpoint.html.in create mode 100644 docs/schemas/domaincheckpoint.rng create mode 100644 tests/domaincheckpointxml2xmlin/empty.xml create mode 100644 tests/domaincheckpointxml2xmlin/sample.xml create mode 100644 tests/domaincheckpointxml2xmlout/empty.xml create mode 100644 tests/domaincheckpointxml2xmlout/sample.xml diff --git a/docs/docs.html.in b/docs/docs.html.in index d0ff844d0c..f6e599b77b 100644 --- a/docs/docs.html.in +++ b/docs/docs.html.in @@ -80,7 +80,8 @@ <a href="formatstoragecaps.html">storage pool capabilities</a>, <a href="formatnode.html">node devices</a>, <a href="formatsecret.html">secrets</a>, - <a href="formatsnapshot.html">snapshots</a></dd> + <a href="formatsnapshot.html">snapshots</a>, + <a href="formatcheckpoint.html">checkpoints</a></dd> <dt><a href="uri.html">URI format</a></dt> <dd>The URI formats used for connecting to libvirt</dd> diff --git a/docs/format.html.in b/docs/format.html.in index 640a9957ee..20f9ef3348 100644 --- a/docs/format.html.in +++ b/docs/format.html.in @@ -25,6 +25,7 @@ <li><a href="formatnode.html">Node devices</a></li> <li><a href="formatsecret.html">Secrets</a></li> <li><a href="formatsnapshot.html">Snapshots</a></li> + <li><a href="formatcheckpoint.html">Checkpoints</a></li> </ul> <h2>Command line validation</h2> diff --git a/docs/formatcheckpoint.html.in b/docs/formatcheckpoint.html.in new file mode 100644 index 0000000000..5c844f1f27 --- /dev/null +++ b/docs/formatcheckpoint.html.in @@ -0,0 +1,202 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html> +<html xmlns="http://www.w3.org/1999/xhtml"> + <body> + <h1>Checkpoint XML format</h1> + + <ul id="toc"></ul> + + <h2><a id="CheckpointAttributes">Checkpoint XML</a></h2> + + <p> + One method of capturing domain disk backups is via the use of + incremental backups. Right now, incremental backups are only + supported for the QEMU hypervisor when using qcow2 disks at the + active layer; if other disk formats are in use, capturing disk + backups requires different libvirt APIs. + </p> + <p> + Libvirt is able to facilitate incremental backups by tracking + disk checkpoints, which are points in time against which it is + easy to compute which portion of the disk has changed. Given a + full backup (a backup created from the creation of the disk to a + given point in time), coupled with the creation of a disk + checkpoint at that time, and an incremental backup (a backup + created from just the dirty portion of the disk between the + first checkpoint and the second backup operation), it is + possible to do an offline reconstruction of the state of the + disk at the time of the second backup without having to copy as + much data as a second full backup would require. Most disk + checkpoints are created in conjunction with a backup + via <code>virDomainBackupBegin()</code> or with a snapshot + via <code>virDomainSnapshotCreateXML2</code>; however, libvirt + also exposes enough support to create disk checkpoints + independently from a backup operation + via <code>virDomainCheckpointCreateXML()</code>. + </p> + <p> + Attributes of libvirt checkpoints are stored as child elements + of the <code>domaincheckpoint</code> element. At checkpoint + creation time, normally only + the <code>name</code>, <code>description</code>, + and <code>disks</code> elements are settable. The rest of the + fields are ignored on creation and will be filled in by libvirt + in for informational purposes + by <code>virDomainCheckpointGetXMLDesc()</code>. However, when + redefining a checkpoint, with + the <code>VIR_DOMAIN_CHECKPOINT_CREATE_REDEFINE</code> flag + of <code>virDomainCheckpointCreateXML()</code>, all of the XML + fields described here are relevant on input, even the fields + that are normally described as readonly for output. + </p> + <p> + Checkpoints are maintained in a hierarchy. A domain can have a + current checkpoint, which is the most recent checkpoint compared + to the current state of the domain (although a domain might have + checkpoints without a current checkpoint, if checkpoints have + been deleted in the meantime). Creating a checkpoint sets that + checkpoint as current and the prior current checkpoint is the + parent of the new checkpoint. In the future, reverting to a + domain snapshot may also affect the current checkpoint. + </p> + <p> + The top-level <code>domaincheckpoint</code> element may contain + the following elements: + </p> + <dl> + <dt><code>name</code></dt> + <dd>The optional name for this checkpoint. If the name is + omitted, libvirt will create a name based on the time of the + creation. + </dd> + <dt><code>description</code></dt> + <dd>An optional human-readable description of the checkpoint. + If the description is omitted when initially creating the + checkpoint, then this field will be empty. + </dd> + <dt><code>disks</code></dt> + <dd>On input, this is an optional listing of specific + instructions for disk checkpoints; it is needed when making a + checkpoint on only a subset of the disks associated with a + domain. In particular, since QEMU checkpoints require qcow2 + disks, this element may be needed on input for excluding guest + disks that are not in qcow2 format. If the entire element was + omitted on input, then all disks participate in the + checkpoint, otherwise, only the disks explicitly listed which + do not also use <code>checkpoint='no'</code> will + participate. On output, this is the checkpoint state of each + of the domain's disks. + <dl> + <dt><code>disk</code></dt> + <dd>This sub-element describes the checkpoint properties of + a specific disk with the following attributes: + <dl> + <dt><code>name</code></dt> + <dd>A mandatory attribute which must match either + the <code><target dev='name'/></code> or an + unambiguous <code><source file='name'/></code> + of one of + the <a href="formatdomain.html#elementsDisks">disk + devices</a> specified for the domain at the time of + the checkpoint.</dd> + <dt><code>checkpoint</code></dt> + <dd>An optional attribute; possible values + are <code>no</code> when the disk does not participate + in this checkpoint; or <code>bitmap</code> if the disk + will track all changes since the creation of this + checkpoint via a bitmap.</dd> + <dt><code>bitmap</code></dt> + <dd>The attribute <code>bitmap</code> is only valid + if <code>checkpoint='bitmap'</code>; it describes the + name of the tracking bitmap (defaulting to the + checkpoint name).</dd> + <dt><code>size</code></dt> + <dd>The attribute <code>size</code> is ignored on input; + on output, it is only present if + the <code>VIR_DOMAIN_CHECKPOINT_XML_SIZE</code> flag + was used to perform a dynamic query of the estimated + size in bytes of the changes made since the checkpoint + was created.</dd> + </dl> + </dd> + </dl> + </dd> + <dt><code>creationTime</code></dt> + <dd>A readonly representation of the time this checkpoint was + created. The time is specified in seconds since the Epoch, + UTC (i.e. Unix time). + </dd> + <dt><code>parent</code></dt> + <dd>An optional readonly representation of the parent of this + checkpoint. If present, this element contains exactly one + child element, <code>name</code>. + </dd> + <dt><code>domain</code></dt> + <dd>A readonly representation of the + inactive <a href="formatdomain.html">domain configuration</a> + at the time the checkpoint was created. This element may be + omitted for output brevity by supplying + the <code>VIR_DOMAIN_CHECKPOINT_XML_NO_DOMAIN</code> flag, but + the resulting XML is no longer viable for use with + the <code>VIR_DOMAIN_CHECKPOINT_CREATE_REDEFINE</code> flag + of <code>virDomainCheckpointCreateXML()</code>. The domain + will have security-sensitive information omitted unless the + flag <code>VIR_DOMAIN_SNAPSHOT_XML_SECURE</code> is provided + on a read-write connection. + </dd> + </dl> + + <h2><a id="example">Examples</a></h2> + + <p>Using this XML to create a checkpoint of just vda on a qemu + domain with two disks and a prior checkpoint:</p> + <pre> +<domaincheckpoint> + <description>Completion of updates after OS install</description> + <disks> + <disk name='vda' checkpoint='bitmap'/> + <disk name='vdb' checkpoint='no'/> + </disks> +</domaincheckpoint></pre> + + <p>will result in XML similar to this from + <code>virDomainCheckpointGetXMLDesc()</code>:</p> + <pre> +<domaincheckpoint> + <name>1525889631</name> + <description>Completion of updates after OS install</description> + <creationTime>1525889631</creationTime> + <parent> + <name>1525111885</name> + </parent> + <disks> + <disk name='vda' checkpoint='bitmap' bitmap='1525889631'/> + <disk name='vdb' checkpoint='no'/> + </disks> + <domain type='qemu'> + <name>fedora</name> + <uuid>93a5c045-6457-2c09-e56c-927cdf34e178</uuid> + <memory>1048576</memory> + ... + <devices> + <disk type='file' device='disk'> + <driver name='qemu' type='qcow2'/> + <source file='/path/to/file1'/> + <target dev='vda' bus='virtio'/> + </disk> + <disk type='file' device='disk' snapshot='external'> + <driver name='qemu' type='raw'/> + <source file='/path/to/file2'/> + <target dev='vdb' bus='virtio'/> + </disk> + ... + </devices> + </domain> +</domaincheckpoint></pre> + + <p>With that checkpoint created, the qcow2 image is now tracking + all changes that occur in the image since the checkpoint via + the persistent bitmap named <code>1525889631</code>. + </p> + </body> +</html> diff --git a/docs/index.html.in b/docs/index.html.in index f593445d06..0315915402 100644 --- a/docs/index.html.in +++ b/docs/index.html.in @@ -69,7 +69,8 @@ <a href="formatstoragecaps.html">storage pool capabilities</a>, <a href="formatnode.html">node devices</a>, <a href="formatsecret.html">secrets</a>, - <a href="formatsnapshot.html">snapshots</a></dd> + <a href="formatsnapshot.html">snapshots</a>, + <a href="formatcheckpoint.html">checkpoints</a></dd> <dt><a href="http://wiki.libvirt.org">Wiki</a></dt> <dd>Read further community contributed content</dd> </dl> diff --git a/docs/schemas/domaincheckpoint.rng b/docs/schemas/domaincheckpoint.rng new file mode 100644 index 0000000000..d8dfda9f1c --- /dev/null +++ b/docs/schemas/domaincheckpoint.rng @@ -0,0 +1,94 @@ +<?xml version="1.0"?> +<!-- A Relax NG schema for the libvirt domain checkpoint properties XML format --> +<grammar xmlns="http://relaxng.org/ns/structure/1.0"> + <start> + <ref name='domaincheckpoint'/> + </start> + + <include href='domaincommon.rng'/> + + <define name='domaincheckpoint'> + <element name='domaincheckpoint'> + <interleave> + <optional> + <element name='name'> + <text/> + </element> + </optional> + <optional> + <element name='description'> + <text/> + </element> + </optional> + <optional> + <element name='creationTime'> + <text/> + </element> + </optional> + <optional> + <element name='disks'> + <oneOrMore> + <ref name='diskcheckpoint'/> + </oneOrMore> + </element> + </optional> + <optional> + <choice> + <element name='domain'> + <element name='uuid'> + <ref name="UUID"/> + </element> + </element> + <!-- Nested grammar ensures that any of our overrides of + storagecommon/domaincommon defines do not conflict + with any domain.rng overrides. --> + <grammar> + <include href='domain.rng'/> + </grammar> + </choice> + </optional> + <optional> + <element name='parent'> + <element name='name'> + <text/> + </element> + </element> + </optional> + </interleave> + </element> + </define> + + <define name='diskcheckpoint'> + <element name='disk'> + <attribute name='name'> + <choice> + <ref name='diskTarget'/> + <ref name='absFilePath'/> + </choice> + </attribute> + <choice> + <attribute name='checkpoint'> + <value>no</value> + </attribute> + <group> + <optional> + <attribute name='checkpoint'> + <value>bitmap</value> + </attribute> + </optional> + <optional> + <attribute name='bitmap'> + <text/> + </attribute> + </optional> + <optional> + <attribute name='size'> + <ref name="unsignedLong"/> + </attribute> + </optional> + </group> + </choice> + </element> + </define> + +</grammar> diff --git a/libvirt.spec.in b/libvirt.spec.in index b7a35a0fb1..6a730befdd 100644 --- a/libvirt.spec.in +++ b/libvirt.spec.in @@ -1800,6 +1800,7 @@ exit 0 %{_datadir}/libvirt/schemas/cputypes.rng %{_datadir}/libvirt/schemas/domain.rng %{_datadir}/libvirt/schemas/domaincaps.rng +%{_datadir}/libvirt/schemas/domaincheckpoint.rng %{_datadir}/libvirt/schemas/domaincommon.rng %{_datadir}/libvirt/schemas/domainsnapshot.rng %{_datadir}/libvirt/schemas/interface.rng diff --git a/mingw-libvirt.spec.in b/mingw-libvirt.spec.in index bea822fd73..553533c88f 100644 --- a/mingw-libvirt.spec.in +++ b/mingw-libvirt.spec.in @@ -240,6 +240,7 @@ rm -rf $RPM_BUILD_ROOT%{mingw64_libexecdir}/libvirt-guests.sh %{mingw32_datadir}/libvirt/schemas/cputypes.rng %{mingw32_datadir}/libvirt/schemas/domain.rng %{mingw32_datadir}/libvirt/schemas/domaincaps.rng +%{mingw32_datadir}/libvirt/schemas/domaincheckpoint.rng %{mingw32_datadir}/libvirt/schemas/domaincommon.rng %{mingw32_datadir}/libvirt/schemas/domainsnapshot.rng %{mingw32_datadir}/libvirt/schemas/interface.rng @@ -328,6 +329,7 @@ rm -rf $RPM_BUILD_ROOT%{mingw64_libexecdir}/libvirt-guests.sh %{mingw64_datadir}/libvirt/schemas/cputypes.rng %{mingw64_datadir}/libvirt/schemas/domain.rng %{mingw64_datadir}/libvirt/schemas/domaincaps.rng +%{mingw64_datadir}/libvirt/schemas/domaincheckpoint.rng %{mingw64_datadir}/libvirt/schemas/domaincommon.rng %{mingw64_datadir}/libvirt/schemas/domainsnapshot.rng %{mingw64_datadir}/libvirt/schemas/interface.rng diff --git a/tests/Makefile.am b/tests/Makefile.am index d3cdbff8bb..c552d08e12 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -83,6 +83,8 @@ EXTRA_DIST = \ commanddata \ cputestdata \ domaincapsschemadata \ + domaincheckpointxml2xmlin \ + domaincheckpointxml2xmlout \ domainconfdata \ domainschemadata \ domainsnapshotxml2xmlin \ diff --git a/tests/domaincheckpointxml2xmlin/empty.xml b/tests/domaincheckpointxml2xmlin/empty.xml new file mode 100644 index 0000000000..dc36449142 --- /dev/null +++ b/tests/domaincheckpointxml2xmlin/empty.xml @@ -0,0 +1 @@ +<domaincheckpoint/> diff --git a/tests/domaincheckpointxml2xmlin/sample.xml b/tests/domaincheckpointxml2xmlin/sample.xml new file mode 100644 index 0000000000..70ed964e1e --- /dev/null +++ b/tests/domaincheckpointxml2xmlin/sample.xml @@ -0,0 +1,7 @@ +<domaincheckpoint> + <description>Completion of updates after OS install</description> + <disks> + <disk name='vda' checkpoint='bitmap'/> + <disk name='vdb' checkpoint='no'/> + </disks> +</domaincheckpoint> diff --git a/tests/domaincheckpointxml2xmlout/empty.xml b/tests/domaincheckpointxml2xmlout/empty.xml new file mode 100644 index 0000000000..a26c7caab0 --- /dev/null +++ b/tests/domaincheckpointxml2xmlout/empty.xml @@ -0,0 +1,10 @@ +<domaincheckpoint> + <name>1525889631</name> + <creationTime>1525889631</creationTime> + <disks> + <disk name='vda' checkpoint='bitmap' bitmap='1525889631'/> + </disks> + <domain> + <uuid>9d37b878-a7cc-9f9a-b78f-49b3abad25a8</uuid> + </domain> +</domaincheckpoint> diff --git a/tests/domaincheckpointxml2xmlout/sample.xml b/tests/domaincheckpointxml2xmlout/sample.xml new file mode 100644 index 0000000000..559b29c8c1 --- /dev/null +++ b/tests/domaincheckpointxml2xmlout/sample.xml @@ -0,0 +1,16 @@ +<domaincheckpoint> + <name>1525889631</name> + <description>Completion of updates after OS install</description> + <creationTime>1525889631</creationTime> + <parent> + <name>1525111885</name> + </parent> + <disks> + <disk name='vda' checkpoint='bitmap' bitmap='1525889631'/> + <disk name='vdb' checkpoint='no'/> + </disks> + <domain type='qemu'> + <name>fedora</name> + <uuid>93a5c045-6457-2c09-e56c-927cdf34e178</uuid> + </domain> +</domaincheckpoint> diff --git a/tests/virschematest.c b/tests/virschematest.c index 56bdcb2f88..fa99e67a57 100644 --- a/tests/virschematest.c +++ b/tests/virschematest.c @@ -222,6 +222,8 @@ mymain(void) "genericxml2xmloutdata", "xlconfigdata", "libxlxml2domconfigdata", "qemuhotplugtestdomains"); DO_TEST_DIR("domaincaps.rng", "domaincapsschemadata"); + DO_TEST_DIR("domaincheckpoint.rng", "domaincheckpointxml2xmlin", + "domaincheckpointxml2xmlout"); DO_TEST_DIR("domainsnapshot.rng", "domainsnapshotxml2xmlin", "domainsnapshotxml2xmlout"); DO_TEST_DIR("interface.rng", "interfaceschemadata"); -- 2.20.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list