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 (bare minimum,
the sample from html, and a full dumpxml, and some counter-examples
that should fail schema validation). Although use of the REDEFINE flag
will require the <domain> subelement to be present, it is easier for
most of the tests to provide counterpart output produced with the
NO_DOMAIN flag (particularly since synthesizing a valid <domain>
during testing is not trivial).
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
docs/docs.html.in | 3 +-
docs/format.html.in | 1 +
docs/formatcheckpoint.html.in | 194 ++++++++++++++++++
docs/index.html.in | 3 +-
docs/schemas/domaincheckpoint.rng | 94 +++++++++
libvirt.spec.in | 1 +
mingw-libvirt.spec.in | 2 +
tests/Makefile.am | 2 +
.../disk-default.xml | 7 +
.../disk-invalid.xml | 8 +
tests/qemudomaincheckpointxml2xmlin/empty.xml | 1 +
.../name-invalid.xml | 4 +
.../qemudomaincheckpointxml2xmlin/sample.xml | 7 +
tests/qemudomaincheckpointxml2xmlin/size.xml | 4 +
.../disk-default.xml | 11 +
.../qemudomaincheckpointxml2xmlout/empty.xml | 7 +
.../redefine.xml | 63 ++++++
.../qemudomaincheckpointxml2xmlout/sample.xml | 12 ++
tests/qemudomaincheckpointxml2xmlout/size.xml | 11 +
tests/virschematest.c | 2 +
20 files changed, 435 insertions(+), 2 deletions(-)
create mode 100644 docs/formatcheckpoint.html.in
create mode 100644 docs/schemas/domaincheckpoint.rng
create mode 100644 tests/qemudomaincheckpointxml2xmlin/disk-default.xml
create mode 100644 tests/qemudomaincheckpointxml2xmlin/disk-invalid.xml
create mode 100644 tests/qemudomaincheckpointxml2xmlin/empty.xml
create mode 100644 tests/qemudomaincheckpointxml2xmlin/name-invalid.xml
create mode 100644 tests/qemudomaincheckpointxml2xmlin/sample.xml
create mode 100644 tests/qemudomaincheckpointxml2xmlin/size.xml
create mode 100644 tests/qemudomaincheckpointxml2xmlout/disk-default.xml
create mode 100644 tests/qemudomaincheckpointxml2xmlout/empty.xml
create mode 100644 tests/qemudomaincheckpointxml2xmlout/redefine.xml
create mode 100644 tests/qemudomaincheckpointxml2xmlout/sample.xml
create mode 100644 tests/qemudomaincheckpointxml2xmlout/size.xml
diff --git a/docs/docs.html.in b/docs/docs.html.in
index 9e1ef6be41..74af38002e 100644
--- a/docs/docs.html.in
+++ b/docs/docs.html.in
@@ -81,7 +81,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 b488f7b38f..3be2237663 100644
--- a/docs/format.html.in
+++ b/docs/format.html.in
@@ -26,6 +26,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..50dd4d284c
--- /dev/null
+++ b/docs/formatcheckpoint.html.in
@@ -0,0 +1,194 @@
+<?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. Future API
+ additions will make it possible to create checkpoints in
+ conjunction with a backup
+ via <code>virDomainBackupBegin()</code> or with an external
+ snapshot via <code>virDomainSnapshotCreateXML2</code>; but for
+ now, libvirt exposes enough support to create disk checkpoints
+ independently from a backup operation
+ via <code>virDomainCheckpointCreateXML()</code> <span
class="since">since
+ 5.6.0</span>.
+ </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>
+ 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>Readonly, present if this checkpoint has a parent. The
+ parent name is given by the sub-element <code>name</code>. The
+ parent relationship allows tracking a list of related checkpoints.
+ </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_CHECKPOINT_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>
+ <parent>
+ <name>1525111885</name>
+ </parent>
+ <creationTime>1525889631</creationTime>
+ <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 2bd647f8dd..7d0ab650e3 100644
--- a/docs/index.html.in
+++ b/docs/index.html.in
@@ -58,7 +58,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..4399eca7fc
--- /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'
datatypeLibrary='http://www.w3.org/2001/XMLSchema-datatypes'>
+ <start>
+ <ref name='domaincheckpoint'/>
+ </start>
+
+ <include href='domaincommon.rng'/>
+
+ <define name='domaincheckpoint'>
+ <element name='domaincheckpoint'>
+ <interleave>
+ <optional>
+ <element name='name'>
+ <ref name='checkpointName'/>
+ </element>
+ </optional>
+ <optional>
+ <element name='description'>
+ <text/>
+ </element>
+ </optional>
+ <optional>
+ <element name='creationTime'>
+ <ref name='unsignedLong'/>
+ </element>
+ </optional>
+ <optional>
+ <element name='disks'>
+ <oneOrMore>
+ <ref name='diskcheckpoint'/>
+ </oneOrMore>
+ </element>
+ </optional>
+ <optional>
+ <!-- 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>
+ </optional>
+ <optional>
+ <element name='parent'>
+ <element name='name'>
+ <ref name='checkpointName'/>
+ </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>
+
+ <define name='checkpointName'>
+ <data type='string'>
+ <!-- Notably: no leading '.' and no embedded '/' or newline
-->
+ <param name='pattern'>[a-zA-Z0-9_\-][a-zA-Z0-9_\-.]*</param>
+ </data>
+ </define>
+
+</grammar>
diff --git a/libvirt.spec.in b/libvirt.spec.in
index b13b863928..4dee2d8ac2 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -1802,6 +1802,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 ad6d6e952e..df89d9f8b3 100644
--- a/mingw-libvirt.spec.in
+++ b/mingw-libvirt.spec.in
@@ -232,6 +232,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
@@ -321,6 +322,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 f480e68e7d..9e2e57459e 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -110,6 +110,8 @@ EXTRA_DIST = \
qemublocktestdata \
qemucapabilitiesdata \
qemucaps2xmloutdata \
+ qemudomaincheckpointxml2xmlin \
+ qemudomaincheckpointxml2xmlout \
qemudomainsnapshotxml2xmlin \
qemudomainsnapshotxml2xmlout \
qemuhotplugtestcpus \
diff --git a/tests/qemudomaincheckpointxml2xmlin/disk-default.xml
b/tests/qemudomaincheckpointxml2xmlin/disk-default.xml
new file mode 100644
index 0000000000..706a9a8fd5
--- /dev/null
+++ b/tests/qemudomaincheckpointxml2xmlin/disk-default.xml
@@ -0,0 +1,7 @@
+<domaincheckpoint>
+ <description>Completion of updates after OS install</description>
+ <disks>
+ <!-- The default checkpoint='...' is bitmap -->
+ <disk name='vda'/>
+ </disks>
+</domaincheckpoint>
diff --git a/tests/qemudomaincheckpointxml2xmlin/disk-invalid.xml
b/tests/qemudomaincheckpointxml2xmlin/disk-invalid.xml
new file mode 100644
index 0000000000..c57c8f6490
--- /dev/null
+++ b/tests/qemudomaincheckpointxml2xmlin/disk-invalid.xml
@@ -0,0 +1,8 @@
+<domaincheckpoint>
+ <name>bogus</name>
+ <disks>
+ <!-- A disk must have a name='...'; ensure that we catch this
+ thanks to our forced RNG schema validation -->
+ <disk/>
+ </disks>
+</domaincheckpoint>
diff --git a/tests/qemudomaincheckpointxml2xmlin/empty.xml
b/tests/qemudomaincheckpointxml2xmlin/empty.xml
new file mode 100644
index 0000000000..dc36449142
--- /dev/null
+++ b/tests/qemudomaincheckpointxml2xmlin/empty.xml
@@ -0,0 +1 @@
+<domaincheckpoint/>
diff --git a/tests/qemudomaincheckpointxml2xmlin/name-invalid.xml
b/tests/qemudomaincheckpointxml2xmlin/name-invalid.xml
new file mode 100644
index 0000000000..b13d7b09e9
--- /dev/null
+++ b/tests/qemudomaincheckpointxml2xmlin/name-invalid.xml
@@ -0,0 +1,4 @@
+<domaincheckpoint>
+ <!-- Our schema prevents names that can't be used as sane file names -->
+ <name>../escape</name>
+</domaincheckpoint>
diff --git a/tests/qemudomaincheckpointxml2xmlin/sample.xml
b/tests/qemudomaincheckpointxml2xmlin/sample.xml
new file mode 100644
index 0000000000..70ed964e1e
--- /dev/null
+++ b/tests/qemudomaincheckpointxml2xmlin/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/qemudomaincheckpointxml2xmlin/size.xml
b/tests/qemudomaincheckpointxml2xmlin/size.xml
new file mode 100644
index 0000000000..99ce84c7a0
--- /dev/null
+++ b/tests/qemudomaincheckpointxml2xmlin/size.xml
@@ -0,0 +1,4 @@
+<domaincheckpoint>
+ <name>c2</name>
+ <description>something fun</description>
+</domaincheckpoint>
diff --git a/tests/qemudomaincheckpointxml2xmlout/disk-default.xml
b/tests/qemudomaincheckpointxml2xmlout/disk-default.xml
new file mode 100644
index 0000000000..ea18252c17
--- /dev/null
+++ b/tests/qemudomaincheckpointxml2xmlout/disk-default.xml
@@ -0,0 +1,11 @@
+<domaincheckpoint>
+ <name>1525889631</name>
+ <description>Completion of updates after OS install</description>
+ <parent>
+ <name>1525111885</name>
+ </parent>
+ <creationTime>1525889631</creationTime>
+ <disks>
+ <disk name='vda' checkpoint='bitmap'
bitmap='1525889631'/>
+ </disks>
+</domaincheckpoint>
diff --git a/tests/qemudomaincheckpointxml2xmlout/empty.xml
b/tests/qemudomaincheckpointxml2xmlout/empty.xml
new file mode 100644
index 0000000000..6fe6124ce4
--- /dev/null
+++ b/tests/qemudomaincheckpointxml2xmlout/empty.xml
@@ -0,0 +1,7 @@
+<domaincheckpoint>
+ <name>1525889631</name>
+ <creationTime>1525889631</creationTime>
+ <disks>
+ <disk name='vda' checkpoint='bitmap'
bitmap='1525889631'/>
+ </disks>
+</domaincheckpoint>
diff --git a/tests/qemudomaincheckpointxml2xmlout/redefine.xml
b/tests/qemudomaincheckpointxml2xmlout/redefine.xml
new file mode 100644
index 0000000000..823ae1ee2d
--- /dev/null
+++ b/tests/qemudomaincheckpointxml2xmlout/redefine.xml
@@ -0,0 +1,63 @@
+<domaincheckpoint>
+ <name>c1</name>
+ <creationTime>1553647812</creationTime>
+ <disks>
+ <disk name='hda' checkpoint='no'/>
+ <disk name='hdc' checkpoint='no'/>
+ <disk name='vda' checkpoint='bitmap' bitmap='c1'/>
+ <disk name='vdb' checkpoint='bitmap' bitmap='c1'/>
+ </disks>
+ <domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219136</memory>
+ <currentMemory unit='KiB'>219136</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu-system-i686</emulator>
+ <disk type='block' device='disk'>
+ <driver name='qemu' type='raw'/>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0'
target='0' unit='0'/>
+ </disk>
+ <disk type='block' device='cdrom'>
+ <driver name='qemu' type='raw'/>
+ <source dev='/dev/HostVG/QEMUGuest2'/>
+ <target dev='hdc' bus='ide'/>
+ <readonly/>
+ <address type='drive' controller='0' bus='1'
target='0' unit='0'/>
+ </disk>
+ <disk type='file' device='disk'>
+ <driver name='qemu' type='qcow2'/>
+ <source file='/tmp/data.img'/>
+ <target dev='vda' bus='virtio'/>
+ <address type='pci' domain='0x0000' bus='0x00'
slot='0x03' function='0x0'/>
+ </disk>
+ <disk type='file' device='disk'>
+ <driver name='qemu' type='qcow2'/>
+ <source file='/tmp/logs.img'/>
+ <target dev='vdb' bus='virtio'/>
+ <address type='pci' domain='0x0000' bus='0x00'
slot='0x04' function='0x0'/>
+ </disk>
+ <controller type='usb' index='0'>
+ <address type='pci' domain='0x0000' bus='0x00'
slot='0x01' function='0x2'/>
+ </controller>
+ <controller type='ide' index='0'>
+ <address type='pci' domain='0x0000' bus='0x00'
slot='0x01' function='0x1'/>
+ </controller>
+ <controller type='pci' index='0' model='pci-root'/>
+ <input type='mouse' bus='ps2'/>
+ <input type='keyboard' bus='ps2'/>
+ <memballoon model='none'/>
+ </devices>
+ </domain>
+</domaincheckpoint>
diff --git a/tests/qemudomaincheckpointxml2xmlout/sample.xml
b/tests/qemudomaincheckpointxml2xmlout/sample.xml
new file mode 100644
index 0000000000..91cfac27df
--- /dev/null
+++ b/tests/qemudomaincheckpointxml2xmlout/sample.xml
@@ -0,0 +1,12 @@
+<domaincheckpoint>
+ <name>1525889631</name>
+ <description>Completion of updates after OS install</description>
+ <parent>
+ <name>1525111885</name>
+ </parent>
+ <creationTime>1525889631</creationTime>
+ <disks>
+ <disk name='vda' checkpoint='bitmap'
bitmap='1525889631'/>
+ <disk name='vdb' checkpoint='no'/>
+ </disks>
+</domaincheckpoint>
diff --git a/tests/qemudomaincheckpointxml2xmlout/size.xml
b/tests/qemudomaincheckpointxml2xmlout/size.xml
new file mode 100644
index 0000000000..4f11cfa680
--- /dev/null
+++ b/tests/qemudomaincheckpointxml2xmlout/size.xml
@@ -0,0 +1,11 @@
+<domaincheckpoint>
+ <name>c2</name>
+ <description>something fun</description>
+ <parent>
+ <name>1525111885</name>
+ </parent>
+ <creationTime>1553648510</creationTime>
+ <disks>
+ <disk name='vda' checkpoint='bitmap' bitmap='c2'
size='1048576'/>
+ </disks>
+</domaincheckpoint>
diff --git a/tests/virschematest.c b/tests/virschematest.c
index 56ee6ec77e..d5a56d3f96 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",
"qemudomaincheckpointxml2xmlin",
+ "qemudomaincheckpointxml2xmlout");
DO_TEST_DIR("domainsnapshot.rng", "qemudomainsnapshotxml2xmlin",
"qemudomainsnapshotxml2xmlout");
DO_TEST_DIR("interface.rng", "interfaceschemadata");
--
2.20.1