Zvirt takes snapshots of Libvirt domains using ZFS.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
Nicolas Massé 023618bf62 Let zfs-autobackup decide which domains are configured 3 weeks ago
packaging Let zfs-autobackup decide which domains are configured 3 weeks ago
src Let zfs-autobackup decide which domains are configured 3 weeks ago
.gitignore toward second release 10 months ago
Makefile Make the snapshot name format queryable 3 weeks ago
README.md Let zfs-autobackup decide which domains are configured 3 weeks ago

README.md

Zvirt = Libvirt ZFS snapshots

Purpose

Zvirt takes snapshots of Libvirt domains using ZFS. It supports both crash-consistent and live snapshots.

At the end, all components of a domain - Domain definition, TPM, NVRAM, VirtioFS, disks (either files on a ZFS dataset or raw zvols) - are captured as a set of consistent ZFS snapshots.

Features

  • Take snapshots of Libvirt domains using ZFS.
  • Support both crash-consistent and live snapshots.
  • Support batch mode (pause all domains, take snapshots, then resume all domains)

Selecting the domains to snapshot

snapshot-libvirt-domains iterates over the libvirt domains and hands each one to zfs-autobackup under the backup name libvirt-<domain>, that is, the ZFS property autobackup:libvirt-<domain>. Which datasets that property selects is zfs-autobackup's decision, not zvirt's: it looks the property up on every dataset, resolves inheritance, and tests its value:

Value Selected
true yes, on the dataset and everything inheriting it
false no, explicitly excluded
child only the datasets that inherit it, not this one
parent only this dataset, not the ones inheriting it

Inherited properties count, so the whole fleet can be configured on the parent dataset of all the domains:

$ zfs set autobackup:libvirt-quay=true data/domains/quay   # this domain and its children
$ zfs set autobackup:libvirt=true data/domains             # the shared property, for pruning

A domain that carries the property nowhere is skipped with a message on stderr and the run carries on with the next one, exiting 0 — configuring only some domains is a legitimate setup.

[!WARNING] The property selects datasets, not domains, and zvirt does not check that the selection actually covers a domain's storage. Set it on the domain's root dataset — set on a child only, the run reports success while the disks above it are never snapshotted. zfs-autobackup --test --no-send --no-thinning libvirt-<domain> prints the datasets it would select.

Snapshot retention

snapshot-libvirt-domains runs zfs-autobackup with --no-thinning: it only creates snapshots and never deletes any. Retention is left to a separate zfs-autobackup run in snapshot-only mode:

$ zfs-autobackup --no-snapshot --keep-source 1w1d,1m1w,1y1m \
                 --snapshot-format "$(snapshot-libvirt-domains --print-snapshot-format)" libvirt

That run must be given the very same snapshot name format zvirt snapshotted with: zfs-autobackup only thins snapshots whose name parses against the format it was given. On a mismatch it selects the right datasets, matches none of their snapshots, deletes nothing and still exits 0 with All operations completed successfully — so never hardcode the format, always query it.

Two ways to query it:

$ snapshot-libvirt-domains --print-snapshot-format
libvirt-%Y-%m-%d-%H:%M:%S

$ . /usr/share/zvirt/snapshot-format && echo "$ZVIRT_SNAPSHOT_FORMAT"
libvirt-%Y-%m-%d-%H:%M:%S

/usr/share/zvirt/snapshot-format is the single source of truth: snapshot-libvirt-domains sources it too, so the format cannot drift between the tool that writes the snapshots and the tool that prunes them.

The format deliberately carries no {} placeholder (zfs-autobackup's default is {}-%Y%m%d%H%M%S, where {} expands to the backup name). All domains therefore share a single snapshot name pattern, which is what allows one prune run over the shared autobackup:libvirt property to cover every domain at once, instead of one invocation per domain.

Pruning from a systemd unit

%Y, %m, %d, %H, %M and %S are systemd specifiers: written literally in an ExecStart= they are silently expanded into paths and hostnames, and systemd-analyze verify does not catch it. Either double them (%%Y, %%m, ...) or — better — let the unit call a wrapper that queries the format:

ExecStart=/bin/bash -c '. /usr/share/zvirt/snapshot-format; exec /usr/bin/zfs-autobackup --no-snapshot --keep-source 1w1d,1m1w,1y1m --snapshot-format "$ZVIRT_SNAPSHOT_FORMAT" libvirt'

License

MIT License

Author

Nicolas Massé