Backup Libvirt Integration#
Overview#
KubeVirt's backup libvirt integration lives in pkg/virt-launcher/virtwrap/storage/backup.go. It is the lowest layer of the backup pipeline: the virt-launcher process receives a gRPC Backup command from the controller and translates it into libvirt API calls. Two libvirt primitives are involved—a backup XML document and a checkpoint XML document—both submitted together via a single dom.BackupBegin() call .
The feature is gated by the IncrementalBackup feature gate (Alpha, v1.6.0) and requires Changed Block Tracking to be active on the VMI .
Entry Point: backup()#
backup() is the core internal function:
- Looks up the libvirt domain by name .
- Reads all current domain disks from the live domain XML via
util.GetAllDomainDisks(). - Calls
generateDomainBackup()to build both XML documents and a volume-info list. - Marshals both documents to XML strings .
- Optionally freezes (quiesces) the guest filesystem before submitting to libvirt; thaws it after
BackupBeginreturns . - Calls
dom.BackupBegin(backupXML, checkpointXML, 0)— both strings are lowercased withstrings.ToLowerbefore submission .
Logging gap: The generated XML is marshalled and submitted without being logged at any verbosity level. By contrast, checkpoint redefinition logs its XML at
V(3). There is no pre-flight inspection of the submitted XML in the backup path.
Backup XML Construction (generateDomainBackup)#
generateDomainBackup() builds two structs that are marshalled into XML:
DomainBackup#
Defined in schema.go to mirror libvirt's backup XML format:
Mode:"push"or"pull".Incremental: set to the previous checkpoint name for incremental backups .Server: pull mode only — points to a Unix NBD socket at/var/run/kubevirt/sockets/backup-nbd-sock.
Per-Disk Entries: Hardcoded type='file'#
For each disk returned by GetAllDomainDisks(), a BackupDisk entry is produced :
- Disks with a data store (
DiskHasDataStore()returns true) getbackup="yes"andtype="file"(hardcoded unconditionally, regardless of actual underlying storage type) . - Disks without a data store (e.g., CDROMs) get
backup="no".
For push mode, a BackupTarget <target file="..."/> element points to a QCOW2 file on the backup PVC. For pull mode, a BackupScratch <scratch file="..."/> element is used and exportname/exportbitmap attributes are also set for NBD export .
DomainCheckpoint#
Defined in schema.go. The checkpoint name follows the format {backupName}-{timestamp} (e.g., vmbackup-fedora-2026-07-04_15-41-59) . Each disk with a data store gets checkpoint="bitmap"; others get checkpoint="no" .
Quiesce / Guest Freeze#
If SkipQuiesce is false, the function calls FreezeVMI() before BackupBegin and records the outcome (QuiesceSucceeded or QuiesceFailed) in the metadata cache. The VM is always thawed after BackupBegin returns . Freeze failure is non-fatal — the backup proceeds regardless.
Completion Handling#
HandleBackupJobCompletedEvent() receives libvirt's DomainEventJobCompleted event and maps the job type to success/failure in the in-memory metadata cache:
| libvirt job type | Result |
|---|---|
DOMAIN_JOB_COMPLETED | success |
DOMAIN_JOB_CANCELLED (push mode) | failure ("backup aborted") |
DOMAIN_JOB_CANCELLED (pull mode) | success (NBD teardown is normal) |
DOMAIN_JOB_FAILED | failure |
The "Operation canceled" error message from pull-mode cancellation is explicitly suppressed . Final stats are retrieved via domain.GetJobStats(DOMAIN_JOB_STATS_COMPLETED) to confirm the terminal job type .
Logging Gaps#
| Location | What is logged | What is missing |
|---|---|---|
backup() before BackupBegin | "Backup begin called", "Initializing backup", "Backup started" | Generated backup XML and checkpoint XML |
generateDomainBackup() | Incremental checkpoint name at Info | Full XML content |
RedefineCheckpoint() | Checkpoint XML at V(3) | (already logged) |
Adding a V(3) log of the marshalled XML in backup() (after line 166) would align it with the redefinition path and make debugging submission failures significantly easier.
Key Source Files#
| File | Role |
|---|---|
pkg/virt-launcher/virtwrap/storage/backup.go | All libvirt backup/checkpoint logic: BackupVirtualMachine, backup, generateDomainBackup, HandleBackupJobCompletedEvent, RedefineCheckpoint |
pkg/virt-launcher/virtwrap/api/schema.go | Go structs for DomainBackup, BackupDisk, DomainCheckpoint, etc. |
pkg/storage/cbt/backup.go | Controller-side backup lifecycle orchestration; issues gRPC Backup calls to virt-launcher |