[libvirt] [PATCH v6 5/9] backup: Document new XML for checkpoints

Eric Blake eblake at redhat.com
Tue Mar 26 06:13:49 UTC 2019


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 at redhat.com>
---
 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




More information about the libvir-list mailing list