On 2/6/19 2:18 PM, Eric Blake wrote:
> Prepare for new checkpoint and backup APIs by describing the XML
> that will represent a checkpoint and backup. The checkpoint XML
> is modeled heavily after virDomainSnapshotPtr, since both represent
> a point in time of the guest (however, a snapshot exists with the
> intent to roll back to that point, while a checkpoint exists to
> facilitate later incremental backups). Meanwhile, the backup XML
> has enough information to represent both push model (the hypervisor
> writes the backup file to a location of the user's choice) and the
> pull model (the hypervisor needs local temporary storage, and also
> creates an NBD server that the user can use to read the backup via
> a third-party client).. But while a snapshot exists with the
s/../.
> intent of rolling back to that state, a checkpoint instead makes it
> possible to create an incremental backup at a later time.
>
I think most of the description beyond the first sentence or so is
covered in the docs and probably doesn't need to be in the commit.
Perhaps just " Prepare for new checkpoint and backup APIs by describing
the XML that will represent a checkpoint and backup. The checkpoint XML
is modeled heavily after virDomainSnapshotPtr, while the backup XML is
provides newer capabilities for both push and pull models.
> Add testsuite coverage for some minimal uses of both XML.
>
> Ultimately, I'd love for push model backups to target a network
> driver rather than just a local file or block device; but doing
> that got hairy (while <domain> uses <source> as the description
> of a host or network resource, I picked <target> as the description
> of a push model backup target [defaults to qcow2 but can also be
> raw or any other format], and <scratch> as the description
> of a pull model backup scratch space [must be qcow2]). The ideal
> refactoring would be a way to parameterize RNG to accept
> <disk type='FOO'>...</disk> so that the name of the subelement
> can be <source> for domain, or <target> or <scratch> as needed for
> backups. Future patches may improve this area of code.
Hmmm... Should this paragraph be in the commit message or under the ---?
BTW: Only after reading through all this does this partially make sense.
>
> Signed-off-by: Eric Blake <ebl...@redhat.com>
>
> ---
> v2: apply (some) wording changes from review
> ---
> docs/docs.html.in | 3 +-
> docs/domainstatecapture.html.in | 4 +-
> docs/format.html.in | 1 +
> docs/formatcheckpoint.html.in | 291 +++++++++++++++++++
> docs/index.html.in | 3 +-
> docs/schemas/domainbackup.rng | 185 ++++++++++++
> docs/schemas/domaincheckpoint.rng | 94 ++++++
> libvirt.spec.in | 2 +
> mingw-libvirt.spec.in | 4 +
> tests/Makefile.am | 6 +-
> tests/domainbackupxml2xmlin/backup-pull.xml | 9 +
> tests/domainbackupxml2xmlin/backup-push.xml | 9 +
> tests/domainbackupxml2xmlin/empty.xml | 1 +
> tests/domainbackupxml2xmlout/backup-pull.xml | 9 +
> tests/domainbackupxml2xmlout/backup-push.xml | 9 +
> tests/domainbackupxml2xmlout/empty.xml | 7 +
> tests/domaincheckpointxml2xmlin/empty.xml | 1 +
> tests/domaincheckpointxml2xmlin/sample.xml | 7 +
> tests/domaincheckpointxml2xmlout/empty.xml | 10 +
> tests/domaincheckpointxml2xmlout/sample.xml | 16 +
> tests/virschematest.c | 4 +
> 21 files changed, 670 insertions(+), 5 deletions(-)
> create mode 100644 docs/formatcheckpoint.html.in
> create mode 100644 docs/schemas/domainbackup.rng
> create mode 100644 docs/schemas/domaincheckpoint.rng
> create mode 100644 tests/domainbackupxml2xmlin/backup-pull.xml
> create mode 100644 tests/domainbackupxml2xmlin/backup-push.xml
> create mode 100644 tests/domainbackupxml2xmlin/empty.xml
> create mode 100644 tests/domainbackupxml2xmlout/backup-pull.xml
> create mode 100644 tests/domainbackupxml2xmlout/backup-push.xml
> create mode 100644 tests/domainbackupxml2xmlout/empty.xml
> 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
>
Lots of detail and files... I know they're related, but if there's a way
to split it may be nicer for review processing ;-)
> diff --git a/docs/docs.html.in b/docs/docs.html.in
> index 4c46b74980..4914e7dbed 100644
> --- a/docs/docs.html.in
> +++ b/docs/docs.html.in
> @@ -79,7 +79,8 @@
> <a href="formatdomaincaps.html">domain 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">backups and 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/domainstatecapture.html.in b/docs/domainstatecapture.html.in
> index f7f2fe0b98..9b890b4c0c 100644
> --- a/docs/domainstatecapture.html.in
> +++ b/docs/domainstatecapture.html.in
> @@ -259,9 +259,9 @@
> a checkpoint as a side-effect of starting a new incremental
> backup with <code>virDomainBackupBegin()</code>, since a
> second incremental backup is most useful when using the
> - checkpoint created during the first. <!--See also
> + checkpoint created during the first. See also
> the <a href="formatcheckpoint.html">XML details</a> used with
> - this command.--></dd>
> + this command.</dd>
>
> <dt>virDomainBackupBegin(), virDomainBackupEnd()</dt>
> <dd>This API wraps approaches for capturing the state of disks
> diff --git a/docs/format.html.in b/docs/format.html.in
> index 22b23e3fc7..8c4e15e079 100644
> --- a/docs/format.html.in
> +++ b/docs/format.html.in
> @@ -24,6 +24,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">Backups and 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..6d66bd0511
> --- /dev/null
> +++ b/docs/formatcheckpoint.html.in
> @@ -0,0 +1,291 @@
> +<?xml version="1.0" encoding="UTF-8"?>
> +<!DOCTYPE html>
> +<html xmlns="http://www.w3.org/1999/xhtml">
> + <body>
> + <h1>Checkpoint and Backup 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
QEMU
> + active layer; if other disk formats are in use, capturing disk
> + backups requires different libvirt APIs
> + (see <a href="domainstatecapture.html">domain state capture</a>
> + for a comparison between 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 concert with a backup
s/concert/conjunction
(although I understood concert, I think conjunction is more apropos)
> + via <code>virDomainBackupBegin()</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.
> + </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 or reverting to a checkpoint
> + sets that checkpoint as current, and the prior current checkpoint is
s/,//
> + the parent of the new checkpoint. Branches in the hierarchy can
> + be formed by reverting to a checkpoint with a child, then creating
> + another checkpoint.
> + </p>
> + <p>
> + The top-level <code>domaincheckpoint</code> element may contain
> + the following elements:
> + </p>
> + <dl>
> + <dt><code>name</code></dt>
> + <dd>The name for this checkpoint. If the name is specified when
The optional name
> + initially creating the checkpoint, then the checkpoint will have
> + that particular name. If the name is omitted when initially
> + creating the checkpoint, then libvirt will make up a name for
> + the checkpoint, based on the time when it was created.
I would think the description of what happens when a name is specified
would be obvious.
> + </dd>
> + <dt><code>description</code></dt>
> + <dd>A human-readable description of the checkpoint. If the
An optional human-...
> + 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
s/domain (/domain. In/
QEMU
> + disks, this element may be needed on input for excluding guest
> + disks that are not in qcow2 format); if the entire element was
s/); if/. If/
> + omitted on input, then all disks participate in the
> + checkpoint, but if individual disks were omitted from the
> + element, they will not be part of the checkpoint. On output,
> + this is fully populated to show the state of each disk in the
each disk participating in the checkpoint ?
Or perhaps "On output, this is the state of the domain's list of disks
relative to how the checkpoint is used for each." [ - or something like
that]
> + checkpoint. This element has a list of <code>disk</code>
> + sub-elements, describing anywhere from one to all of the disks
> + associated with the domain.
> + <dl>
> + <dt><code>disk</code></dt>
> + <dd>This sub-element describes the checkpoint properties of
> + a specific disk. The attribute <code>name</code> is
> + mandatory, and 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. The attribute <code>checkpoint</code> is
> + optional on input; 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, in
> + which case another attribute <code>bitmap</code> will be
> + the name of the tracking bitmap (defaulting to the
> + checkpoint name). On output, an additional
> + attribute <code>size</code> may be 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.
This is tough to read as one fairly long paragraph especially when it
comes to picking out the attributes, consider:
<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>The attribute <code>name</code> is mandatory and 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>The attribute <code>checkpoint</code> is optional on
input. 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>Optional attribute to define the name of the tracking
bitmap (defaulting to the checkpoint name) when the disk
is participating in the checkpoint processing.</dd>
<dt><code>size</code></dt>
<dd>On output, this attribute may be 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>The time this checkpoint was created. The time is specified
A readonly representation of the time this checkpoint was created.
> + in seconds since the Epoch, UTC (i.e. Unix time). Readonly.
> + </dd>
> + <dt><code>parent</code></dt>
> + <dd>The parent of this checkpoint. If present, this element
An optional readonly representation of the parent of this checkpoint.
> + contains exactly one child element, name. This specifies the
s/name/<code>name</code>
> + name of the parent checkpoint of this one, and is used to
> + represent trees of checkpoints. Readonly.
> + </dd>
> + <dt><code>domain</code></dt>
> + <dd>The inactive <a href="formatdomain.html">domain
A readonly representation of the inactive ...
> + configuration</a> at the time the checkpoint was created.
> + Readonly.
> + </dd>
And then just remove the Readonly single word.
> + </dl>
> +
> + <h2><a id="BackupAttributes">Backup XML</a></h2>
> +
> + <p>
> + Creating a backup, whether full or incremental, is done
> + via <code>virDomainBackupBegin()</code>, which takes an XML
> + description of the actions to perform. There are two general
> + modes for backups: a push mode (where the hypervisor writes out
> + the data to the destination file, which may be local or remote),
> + and a pull mode (where the hypervisor creates an NBD server that
> + a third-party client can then read as needed, and which requires
> + the use of temporary storage, typically local, until the backup
> + is complete).
> + </p>
> + <p>
> + The instructions for beginning a backup job are provided as
> + attributes and elements of the
> + top-level <code>domainbackup</code> element. This element
> + includes an optional attribute <code>mode</code> which can be
> + either "push" or "pull" (default push). Where elements are
> + optional on creation, <code>virDomainBackupGetXMLDesc()</code>
s/,/. The/
> + can be used to see the actual values selected (for example,
> + learning which port the NBD server is using in the pull model,
s/model,/model/
> + or what file names libvirt generated when none were supplied).
> + The following child elements are supported:
> + </p>
> + <dl>
> + <dt><code>incremental</code></dt>
> + <dd>Optional. If this element is present, it must name an
An optional element to describe the name of an existing checkpoint...
[one would hope we wouldn't have to give a link to the above named
checkpoints, but I suppose it would be possible - your call on that]
> + existing checkpoint of the domain, which will be used to make
> + this backup an incremental one (in the push model, only
s/one (in the/one. In the/
> + changes since the checkpoint are written to the destination;
s/;/./
> + in the pull model, the NBD server uses the
s/in/In/
> + NBD_OPT_SET_META_CONTEXT extension to advertise to the client
> + which portions of the export contain changes since the
> + checkpoint). If omitted, a full backup is performed.
s/)./.
> + </dd>
> + <dt><code>server</code></dt>
> + <dd>Present only for a pull mode backup. Contains the same
> + attributes as the <code>protocol</code> element of a disk
[could provide a link to the domain disk section if you feel it's
appropriate or necessary]
> + attached via NBD in the domain (such as transport, socket,
> + name, port, or tls), necessary to set up an NBD server that
> + exposes the content of each disk at the time the backup
> + started.
s/started/is started/
> + </dd>
> + <dt><code>disks</code></dt>
> + <dd>This is an optional listing of instructions for disks
An optional listing
> + participating in the backup (if omitted, all disks
> + participate, and libvirt attempts to generate filenames by
s/, and/ and/
> + appending the current timestamp as a suffix). When provided on
> + input, disks omitted from the list do not participate in the
> + backup. On output, the list is present but contains only the
> + disks participating in the backup job. This element has a
s/ job././
[job is an implementation detail]
> + list of <code>disk</code> sub-elements, describing anywhere
> + from one to all of the disks associated with the domain.
> + <dl>
> + <dt><code>disk</code></dt>
> + <dd>This sub-element describes the backup properties of
> + a specific disk. The attribute <code>name</code> is
> + mandatory, and 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. The optional attribute <code>type</code> can
> + be <code>file</code>, <code>block</code>,
> + or <code>network</code>, similar to a disk declaration for
> + a domain, controls what additional sub-elements are needed
> + to describe the destination (such as <code>protocol</code>
> + for a network destination). In push mode backups, the
> + primary sub-element is <code>target</code>; in pull mode,
> + the primary sub-element is <code>scratch</code>; but
> + either way, the primary sub-element describes the file
> + name to be used during the backup operation, similar to
> + the <code>source</code> sub-element of a domain disk. In
> + push mode, an optional sub-element <code>driver</code> can
> + also be used, with an attribute <code>type</code> to
> + specify a destination format different from
> + qcow2. Additionally, if a push backup is not
> + incremental, <code>target</code> may contain an optional
> + attribute <code>shallow="on"</code> so that the
> + destination file copies only the top-most source file in a
> + backing chain, rather than collapsing the entire chain
> + into the copy.
This one's harder to read than the other one...Consider:
<dt><code>disk</code></dt>
<dd>This sub-element describes the backup properties of
a specific disk with the following attributes:
<dl>
<dt><code>name</code></dt>
<dd>A mandatory attribute and 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>type</code></dt>
<dd>An optional attribute to describe the type of disk.
Valid values can be <code>file</code>, <code>block</code>,
or <code>network</code>. Similar to a disk declaration for
a domain, controls what additional sub-elements are needed
to describe the destination (such as <code>protocol</code>
for a network destination).</dd>
<dt><code>target</code></dt>
<dd>For push mode backups, this is the primary sub-element
to describe the file name to be used during the backup
operation similar to the <code>source</code> sub-element
of a domain disk. An optional sub-element <code>driver</code>
can also be used, with an attribute <code>type</code> to
specify a destination format different from qcow2.
Additionally, if the push backup is not incremental,
<code>target</code> may contain an optional attribute
<code>shallow="on"</code> so that the destination file
copies only the top-most source file in a backing chain,
rather than collapsing the entire chain into the copy.</dd>
<dt><code>scratch</code></dt>
<dd>For pull mode backups, this is the primary sub-element
to describe the file name to be used during the backup
operation similar to the <code>source</code> sub-element
of a domain disk.</dd>
</dl>
</dd>
> + </dd>
> + </dl>
> + </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>. Now, we
> + can make a subsequent call
> + to <code>virDomainBackupBegin()</code> to perform an incremental
> + backup of just this data, using the following XML to start a
> + pull model NBD export of the vda disk:
> + </p>
> + <pre>
> +<domainbackup mode="pull">
> + <incremental>1525889631</incremental>
> + <server transport="unix" socket="/path/to/server"/>
> + <disks/>
> + <disk name='vda' type='file'>
> + <scratch file='/path/to/file1.scratch'/>
> + </disk>
> + </disks/>
> +</domainbackup>
> + </pre>
> + </body>
Perhaps an example of mode="push" would be useful as that <target>
sub-element has a lot of "nuances" (kindly said ;-))
> +</html>
> diff --git a/docs/index.html.in b/docs/index.html.in
> index 1f9f448399..6c5d3a6dc3 100644
> --- a/docs/index.html.in
> +++ b/docs/index.html.in
> @@ -68,7 +68,8 @@
> <a href="formatdomaincaps.html">domain 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">backups and 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/domainbackup.rng b/docs/schemas/domainbackup.rng
> new file mode 100644
> index 0000000000..edc68a37cf
> --- /dev/null
> +++ b/docs/schemas/domainbackup.rng
> @@ -0,0 +1,185 @@
> +<?xml version="1.0"?>
> +<!-- A Relax NG schema for the libvirt domain backup properties XML format
> -->
> +<grammar xmlns="http://relaxng.org/ns/structure/1.0">
> + <start>
> + <ref name='domainbackup'/>
> + </start>
> +
> + <include href='domaincommon.rng'/>
> +
> + <define name='domainbackup'>
> + <element name='domainbackup'>
> + <optional>
> + <attribute name='id'>
> + <ref name="unsignedInt"/>
> + </attribute>
> + </optional>
The 'id' is not described in docs nor do I see it in any of your output.
Remnant or future?
> + <interleave>
> + <optional>
> + <element name='incremental'>
> + <text/>
> + </element>
> + </optional>
> + <choice>
> + <group>
> + <optional>
> + <attribute name='mode'>
> + <value>push</value>
> + </attribute>
> + </optional>
> + <ref name='backupDisksPush'/>
> + </group>
> + <group>
> + <attribute name='mode'>
> + <value>pull</value>
> + </attribute>
> + <interleave>
> + <element name='server'>
> + <choice>
> + <group>
> + <optional>
> + <attribute name='transport'>
> + <value>tcp</value>
> + </attribute>
> + </optional>
> + <attribute name='name'>
> + <choice>
> + <ref name='dnsName'/>
> + <ref name='ipAddr'/>
> + </choice>
> + </attribute>
> + <optional>
> + <attribute name='port'>
> + <ref name='unsignedInt'/>
> + </attribute>
> + </optional>
> + <!-- add tls? -->
More work? leaving a golden egg like this keeps me interested ;-)
> + </group>
> + <group>
> + <attribute name='transport'>
> + <value>unix</value>
> + </attribute>
> + <attribute name='socket'>
> + <ref name='absFilePath'/>
> + </attribute>
> + </group>
> + </choice>
> + </element>
Could something be done to create some "common" include file that would
allow for sharing w/ diskSourceNetworkHost so that when/if updating
domaincommon someone doesn't forget or neglect to update the
domainbackup? One difference I see would be rdma transport which would
need to be handled specially in domainbackup XML processing since I
assume it wouldn't be supported.
> + <ref name='backupDisksPull'/>
> + </interleave>
> + </group>
> + </choice>
> + </interleave>
> + </element>
> + </define>
> +
> + <define name='backupPushDriver'>
> + <optional>
> + <element name='driver'>
> + <attribute name='type'>
> + <ref name='storageFormat'/>
> + </attribute>
> + </element>
> + </optional>
> + </define>
> +
> + <define name='backupDisksPush'>
> + <optional>
> + <element name='disks'>
> + <oneOrMore>
> + <element name='disk'>
> + <attribute name='name'>
> + <choice>
> + <ref name='diskTarget'/>
> + <ref name='absFilePath'/>
> + </choice>
> + </attribute>
> + <choice>
> + <!-- FIXME allow push to a network location, by
> + refactoring 'diskSource' to take element name by a
> + per-grammar ref -->
Is there still work to be done here!
> + <group>
> + <optional>
> + <attribute name='type'>
> + <value>file</value>
> + </attribute>
> + </optional>
> + <interleave>
> + <optional>
> + <element name='target'>
> + <attribute name='file'>
> + <ref name='absFilePath'/>
> + </attribute>
> + </element>
> + </optional>
> + <ref name='backupPushDriver'/>
> + </interleave>
> + </group>
> + <group>
> + <attribute name='type'>
> + <value>disk</value>
So the docs describe attribute type having "file", "block", or "network"
and this is different. Things should match I would think.
> + </attribute>
> + <interleave>
> + <optional>
> + <element name='target'>
> + <attribute name='dev'>
> + <ref name='absFilePath'/>
> + </attribute>
Missing optional attribute "shallow" w/ OnOff as describe in docs.
> + </element>
> + </optional>
> + <ref name='backupPushDriver'/>
> + </interleave>
> + </group>
> + </choice>
> + </element>
> + </oneOrMore>
> + </element>
> + </optional>
> + </define>
> +
> + <define name='backupDisksPull'>
> + <optional>
> + <element name='disks'>
> + <oneOrMore>
> + <element name='disk'>
> + <attribute name='name'>
> + <choice>
> + <ref name='diskTarget'/>
> + <ref name='absFilePath'/>
> + </choice>
> + </attribute>
> + <choice>
> + <group>
> + <optional>
> + <attribute name='type'>
> + <value>file</value>
> + </attribute>
> + </optional>
> + <optional>
> + <element name='scratch'>
> + <attribute name='file'>
> + <ref name='absFilePath'/>
> + </attribute>
> + </element>
> + </optional>
> + </group>
> + <group>
> + <attribute name='type'>
> + <value>disk</value>
Same w/r/t to valid 'type' values.
> + </attribute>
> + <optional>
> + <element name='scratch'>
> + <attribute name='dev'>
> + <ref name='absFilePath'/>
> + </attribute>
> + </element>
> + </optional>
> + </group>
> + </choice>
> + </element>
> + </oneOrMore>
> + </element>
> + </optional>
> + </define>
> +
> +</grammar>
> 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"/>
I haven't looked ahead to conf processing, but I assume this is the same
type as whatever this gets read into. Whenever I see size in reference
to disks I'm thinking ULL's.
> + </attribute>
> + </optional>
> + </group>
> + </choice>
> + </element>
> + </define>
> +
> +</grammar>
> diff --git a/libvirt.spec.in b/libvirt.spec.in
> index c0e538d92d..2e9213510d 100644
> --- a/libvirt.spec.in
> +++ b/libvirt.spec.in
> @@ -1813,7 +1813,9 @@ exit 0
> %{_datadir}/libvirt/schemas/capability.rng
> %{_datadir}/libvirt/schemas/cputypes.rng
> %{_datadir}/libvirt/schemas/domain.rng
> +%{_datadir}/libvirt/schemas/domainbackup.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 249abb8475..a7b697d7bd 100644
> --- a/mingw-libvirt.spec.in
> +++ b/mingw-libvirt.spec.in
> @@ -239,7 +239,9 @@ rm -rf
> $RPM_BUILD_ROOT%{mingw64_libexecdir}/libvirt-guests.sh
> %{mingw32_datadir}/libvirt/schemas/capability.rng
> %{mingw32_datadir}/libvirt/schemas/cputypes.rng
> %{mingw32_datadir}/libvirt/schemas/domain.rng
> +%{mingw32_datadir}/libvirt/schemas/domainbackup.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
> @@ -326,7 +328,9 @@ rm -rf
> $RPM_BUILD_ROOT%{mingw64_libexecdir}/libvirt-guests.sh
> %{mingw64_datadir}/libvirt/schemas/capability.rng
> %{mingw64_datadir}/libvirt/schemas/cputypes.rng
> %{mingw64_datadir}/libvirt/schemas/domain.rng
> +%{mingw64_datadir}/libvirt/schemas/domainbackup.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 bdf7154fd5..9b835fa369 100644
> --- a/tests/Makefile.am
> +++ b/tests/Makefile.am
> @@ -1,6 +1,6 @@
> ## Process this file with automake to produce Makefile.in
>
> -## Copyright (C) 2005-2015 Red Hat, Inc.
> +## Copyright (C) 2005-2018 Red Hat, Inc.
> ##
> ## This library is free software; you can redistribute it and/or
> ## modify it under the terms of the GNU Lesser General Public
> @@ -92,7 +92,11 @@ EXTRA_DIST = \
> capabilityschemadata \
> commanddata \
> cputestdata \
> + domainbackupxml2xmlin \
> + domainbackupxml2xmlout \
> domaincapsschemadata \
> + domaincheckpointxml2xmlin \
> + domaincheckpointxml2xmlout \
> domainconfdata \
> domainschemadata \
> domainsnapshotxml2xmlin \
> diff --git a/tests/domainbackupxml2xmlin/backup-pull.xml
> b/tests/domainbackupxml2xmlin/backup-pull.xml
> new file mode 100644
> index 0000000000..2ce5cd6711
> --- /dev/null
> +++ b/tests/domainbackupxml2xmlin/backup-pull.xml
> @@ -0,0 +1,9 @@
> +<domainbackup mode="pull">
> + <incremental>1525889631</incremental>
> + <server transport='tcp' name='localhost' port='10809'/>
> + <disks>
> + <disk name='vda' type='file'>
> + <scratch file='/path/to/file'/>
> + </disk>
> + </disks>
> +</domainbackup>
> diff --git a/tests/domainbackupxml2xmlin/backup-push.xml
> b/tests/domainbackupxml2xmlin/backup-push.xml
> new file mode 100644
> index 0000000000..1b7d3061fd
> --- /dev/null
> +++ b/tests/domainbackupxml2xmlin/backup-push.xml
> @@ -0,0 +1,9 @@
> +<domainbackup mode="push">
> + <incremental>1525889631</incremental>
> + <disks>
> + <disk name='vda' type='file'>
> + <driver type='raw'/>
> + <target file='/path/to/file'/>
> + </disk>
> + </disks>
> +</domainbackup>
> diff --git a/tests/domainbackupxml2xmlin/empty.xml
> b/tests/domainbackupxml2xmlin/empty.xml
> new file mode 100644
> index 0000000000..7ed511f97b
> --- /dev/null
> +++ b/tests/domainbackupxml2xmlin/empty.xml
> @@ -0,0 +1 @@
> +<domainbackup/>
Should add a 'block' and 'network' example too for completeness - of
course that depends on the matching between docs and rng.
Should add target w/ shallow=on for completeness.
Yes, I recall the commit message indicating essentially minimal.
> diff --git a/tests/domainbackupoml2xmlout/backup-pull.xml
> b/tests/domainbackupxml2xmlout/backup-pull.xml
> new file mode 100644
> index 0000000000..2ce5cd6711
> --- /dev/null
> +++ b/tests/domainbackupxml2xmlout/backup-pull.xml
> @@ -0,0 +1,9 @@
> +<domainbackup mode="pull">
> + <incremental>1525889631</incremental>
> + <server transport='tcp' name='localhost' port='10809'/>
> + <disks>
> + <disk name='vda' type='file'>
> + <scratch file='/path/to/file'/>
> + </disk>
> + </disks>
> +</domainbackup>
> diff --git a/tests/domainbackupxml2xmlout/backup-push.xml
> b/tests/domainbackupxml2xmlout/backup-push.xml
> new file mode 100644
> index 0000000000..1b7d3061fd
> --- /dev/null
> +++ b/tests/domainbackupxml2xmlout/backup-push.xml
> @@ -0,0 +1,9 @@
> +<domainbackup mode="push">
> + <incremental>1525889631</incremental>
> + <disks>
> + <disk name='vda' type='file'>
> + <driver type='raw'/>
> + <target file='/path/to/file'/>
> + </disk>
> + </disks>
> +</domainbackup>
> diff --git a/tests/domainbackupxml2xmlout/empty.xml
> b/tests/domainbackupxml2xmlout/empty.xml
> new file mode 100644
> index 0000000000..13600fbb1c
> --- /dev/null
> +++ b/tests/domainbackupxml2xmlout/empty.xml
> @@ -0,0 +1,7 @@
> +<domainbackup mode="push">
> + <disks>
> + <disk name="vda" type="file">
> + <target file="/path/to/file1.copy"/>
> + </disk>
> + </disks>
> +</domainbackup>
> 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>
This looks strange without the name... and the domain type like the
sample.xml output has
> + </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'/>
Maybe this one should show the size attribute too...
I need to stop here for the day, but will continue...
John
> + <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 d1bcdeac9c..c3b41d5bbc 100644
> --- a/tests/virschematest.c
> +++ b/tests/virschematest.c
> @@ -221,7 +221,11 @@ mymain(void)
> "lxcxml2xmloutdata", "bhyvexml2argvdata",
> "genericxml2xmlindata",
> "genericxml2xmloutdata", "xlconfigdata",
> "libxlxml2domconfigdata",
> "qemuhotplugtestdomains");
> + DO_TEST_DIR("domainbackup.rng", "domainbackupxml2xmlin",
> + "domainbackupxml2xmlout");
> 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");
>
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list