diff --git a/docs/formatbackup.rst b/docs/formatbackup.rst index 17431fe51a..1b9e6ebb22 100644 --- a/docs/formatbackup.rst +++ b/docs/formatbackup.rst @@ -69,6 +69,17 @@ were supplied). The following child elements and attributes are supported: should take part in the backup and using ``no`` excludes the disk from the backup. + ``backupmode`` + This attribute overrides the implied backup mode inherited from the + definition of the backup itself. Value ``full`` forces a full backup + even if the backup calls for an incremental backup, and ``incremental`` + coupled with the attribute ``incremental='CHECKPOINTNAME`` for the disk + forces an incremental backup from ``CHECKPOINTNAME``. + + ``incremental`` + An optional attribute giving the name of an existing checkpoint of the + domain which overrides the one set by the ```` element. + ``exportname`` Allows modification of the NBD export name for the given disk. By default equal to disk target. Valid only for pull mode backups. diff --git a/docs/schemas/domainbackup.rng b/docs/schemas/domainbackup.rng index c0e17f512b..579b62a658 100644 --- a/docs/schemas/domainbackup.rng +++ b/docs/schemas/domainbackup.rng @@ -96,6 +96,27 @@ + + + + + + full + + + + + incremental + + + + + + + + + + @@ -134,6 +155,7 @@ + @@ -203,6 +225,7 @@ + diff --git a/src/conf/backup_conf.c b/src/conf/backup_conf.c index 5e4144d371..02319f7245 100644 --- a/src/conf/backup_conf.c +++ b/src/conf/backup_conf.c @@ -56,6 +56,13 @@ VIR_ENUM_IMPL(virDomainBackupDiskState, "cancelling", "cancelled"); +VIR_ENUM_DECL(virDomainBackupDiskBackupMode); +VIR_ENUM_IMPL(virDomainBackupDiskBackupMode, + VIR_DOMAIN_BACKUP_DISK_BACKUP_MODE_LAST, + "", + "full", + "incremental"); + void virDomainBackupDefFree(virDomainBackupDefPtr def) { @@ -100,6 +107,7 @@ virDomainBackupDiskDefParseXML(xmlNodePtr node, g_autofree char *driver = NULL; g_autofree char *backup = NULL; g_autofree char *state = NULL; + g_autofree char *backupmode = NULL; int tmp; xmlNodePtr srcNode; unsigned int storageSourceParseFlags = 0; @@ -137,6 +145,19 @@ virDomainBackupDiskDefParseXML(xmlNodePtr node, def->exportbitmap = virXMLPropString(node, "exportbitmap"); } + if ((backupmode = virXMLPropString(node, "backupmode"))) { + if ((tmp = virDomainBackupDiskBackupModeTypeFromString(backupmode)) < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("invalid backupmode '%s' of disk '%s'"), + backupmode, def->name); + return -1; + } + + def->backupmode = tmp; + } + + def->incremental = virXMLPropString(node, "incremental"); + if (internal) { if (!(state = virXMLPropString(node, "state")) || (tmp = virDomainBackupDiskStateTypeFromString(state)) < 0) { @@ -376,6 +397,13 @@ virDomainBackupDiskDefFormat(virBufferPtr buf, if (disk->backup == VIR_TRISTATE_BOOL_YES) { virBufferAsprintf(&attrBuf, " type='%s'", virStorageTypeToString(disk->store->type)); + if (disk->backupmode != VIR_DOMAIN_BACKUP_DISK_BACKUP_MODE_DEFAULT) { + virBufferAsprintf(&attrBuf, " backupmode='%s'", + virDomainBackupDiskBackupModeTypeToString(disk->backupmode)); + } + + virBufferEscapeString(&attrBuf, " incremental='%s'", disk->incremental); + virBufferEscapeString(&attrBuf, " exportname='%s'", disk->exportname); virBufferEscapeString(&attrBuf, " exportbitmap='%s'", disk->exportbitmap); @@ -524,6 +552,16 @@ virDomainBackupAlignDisks(virDomainBackupDefPtr def, return -1; } + if (backupdisk->backupmode == VIR_DOMAIN_BACKUP_DISK_BACKUP_MODE_INCREMENTAL && + !backupdisk->incremental && + !def->incremental) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("'incremental' backup mode of disk '%s' requires setting 'incremental' field for disk or backup"), + backupdisk->name); + return -1; + } + + if (backupdisk->backup == VIR_TRISTATE_BOOL_YES && virDomainBackupDefAssignStore(backupdisk, domdisk->src, suffix) < 0) return -1; @@ -561,7 +599,16 @@ virDomainBackupAlignDisks(virDomainBackupDefPtr def, for (i = 0; i < def->ndisks; i++) { virDomainBackupDiskDefPtr backupdisk = &def->disks[i]; - if (def->incremental && !backupdisk->incremental) + if (backupdisk->backupmode == VIR_DOMAIN_BACKUP_DISK_BACKUP_MODE_DEFAULT) { + if (def->incremental || backupdisk->incremental) { + backupdisk->backupmode = VIR_DOMAIN_BACKUP_DISK_BACKUP_MODE_INCREMENTAL; + } else { + backupdisk->backupmode = VIR_DOMAIN_BACKUP_DISK_BACKUP_MODE_FULL; + } + } + + if (!backupdisk->incremental && + backupdisk->backupmode == VIR_DOMAIN_BACKUP_DISK_BACKUP_MODE_INCREMENTAL) backupdisk->incremental = g_strdup(def->incremental); } diff --git a/src/conf/backup_conf.h b/src/conf/backup_conf.h index aa2d6d4b68..bda2bdcfe4 100644 --- a/src/conf/backup_conf.h +++ b/src/conf/backup_conf.h @@ -45,12 +45,23 @@ typedef enum { VIR_DOMAIN_BACKUP_DISK_STATE_LAST } virDomainBackupDiskState; + +typedef enum { + VIR_DOMAIN_BACKUP_DISK_BACKUP_MODE_DEFAULT = 0, + VIR_DOMAIN_BACKUP_DISK_BACKUP_MODE_FULL, + VIR_DOMAIN_BACKUP_DISK_BACKUP_MODE_INCREMENTAL, + + VIR_DOMAIN_BACKUP_DISK_BACKUP_MODE_LAST +} virDomainBackupDiskBackupMode; + + /* Stores disk-backup information */ typedef struct _virDomainBackupDiskDef virDomainBackupDiskDef; typedef virDomainBackupDiskDef *virDomainBackupDiskDefPtr; struct _virDomainBackupDiskDef { char *name; /* name matching the + + + + + + + + + + + + diff --git a/tests/domainbackupxml2xmlout/backup-pull-encrypted.xml b/tests/domainbackupxml2xmlout/backup-pull-encrypted.xml index 3c3042111d..42051d1d24 100644 --- a/tests/domainbackupxml2xmlout/backup-pull-encrypted.xml +++ b/tests/domainbackupxml2xmlout/backup-pull-encrypted.xml @@ -2,7 +2,7 @@ 1525889631 - + @@ -10,7 +10,7 @@ - + @@ -18,7 +18,7 @@ - + diff --git a/tests/domainbackupxml2xmlout/backup-pull-internal-invalid.xml b/tests/domainbackupxml2xmlout/backup-pull-internal-invalid.xml index 9702978ce0..092b6bf8a7 100644 --- a/tests/domainbackupxml2xmlout/backup-pull-internal-invalid.xml +++ b/tests/domainbackupxml2xmlout/backup-pull-internal-invalid.xml @@ -2,7 +2,7 @@ 1525889631 - + @@ -10,7 +10,7 @@ - + @@ -18,7 +18,7 @@ - + diff --git a/tests/domainbackupxml2xmlout/backup-pull-seclabel.xml b/tests/domainbackupxml2xmlout/backup-pull-seclabel.xml index 38330394f7..385d949ae3 100644 --- a/tests/domainbackupxml2xmlout/backup-pull-seclabel.xml +++ b/tests/domainbackupxml2xmlout/backup-pull-seclabel.xml @@ -2,13 +2,13 @@ 1525889631 - + - + diff --git a/tests/domainbackupxml2xmlout/backup-pull.xml b/tests/domainbackupxml2xmlout/backup-pull.xml index 4952270a5a..1762ba72b5 100644 --- a/tests/domainbackupxml2xmlout/backup-pull.xml +++ b/tests/domainbackupxml2xmlout/backup-pull.xml @@ -2,10 +2,22 @@ 1525889631 - + + + + + + + + + + + + + diff --git a/tests/domainbackupxml2xmlout/backup-push-encrypted.xml b/tests/domainbackupxml2xmlout/backup-push-encrypted.xml index 2a5aad93cd..3b664b0dcb 100644 --- a/tests/domainbackupxml2xmlout/backup-push-encrypted.xml +++ b/tests/domainbackupxml2xmlout/backup-push-encrypted.xml @@ -1,7 +1,7 @@ 1525889631 - + @@ -9,7 +9,7 @@ - + @@ -17,7 +17,7 @@ - + diff --git a/tests/domainbackupxml2xmlout/backup-push-seclabel.xml b/tests/domainbackupxml2xmlout/backup-push-seclabel.xml index 59af3e6a6c..9a0d2b3061 100644 --- a/tests/domainbackupxml2xmlout/backup-push-seclabel.xml +++ b/tests/domainbackupxml2xmlout/backup-push-seclabel.xml @@ -1,13 +1,13 @@ 1525889631 - + - + diff --git a/tests/domainbackupxml2xmlout/backup-push.xml b/tests/domainbackupxml2xmlout/backup-push.xml index bc11a93d94..317dcf6e47 100644 --- a/tests/domainbackupxml2xmlout/backup-push.xml +++ b/tests/domainbackupxml2xmlout/backup-push.xml @@ -1,7 +1,7 @@ 1525889631 - + diff --git a/tests/domainbackupxml2xmlout/empty.xml b/tests/domainbackupxml2xmlout/empty.xml index 52d2b4f0af..b1cbd154ab 100644 --- a/tests/domainbackupxml2xmlout/empty.xml +++ b/tests/domainbackupxml2xmlout/empty.xml @@ -1,6 +1,6 @@ - +