parent
5c06ebc9c8
commit
1dfb50fefd
@ -140,6 +140,7 @@ const defaultSettings: Settings = {
|
|||||||
concurrency: 0,
|
concurrency: 0,
|
||||||
deleteFirst: false,
|
deleteFirst: false,
|
||||||
exportRetention: 0,
|
exportRetention: 0,
|
||||||
|
fullInterval: 0,
|
||||||
offlineSnapshot: false,
|
offlineSnapshot: false,
|
||||||
reportWhen: 'failure',
|
reportWhen: 'failure',
|
||||||
snapshotRetention: 0,
|
snapshotRetention: 0,
|
||||||
@ -475,10 +476,11 @@ const disableVmHighAvailability = async (xapi: Xapi, vm: Vm) => {
|
|||||||
//
|
//
|
||||||
// - `other_config`:
|
// - `other_config`:
|
||||||
// - `xo:backup:datetime` = snapshot.snapshot_time (allow sorting replicated VMs)
|
// - `xo:backup:datetime` = snapshot.snapshot_time (allow sorting replicated VMs)
|
||||||
|
// - `xo:backup:deltaChainLength` = n (number of delta copies/replicated since a full)
|
||||||
|
// - `xo:backup:exported` = 'true' (added at the end of the backup)
|
||||||
// - `xo:backup:job` = job.id
|
// - `xo:backup:job` = job.id
|
||||||
// - `xo:backup:schedule` = schedule.id
|
// - `xo:backup:schedule` = schedule.id
|
||||||
// - `xo:backup:vm` = vm.uuid
|
// - `xo:backup:vm` = vm.uuid
|
||||||
// - `xo:backup:exported` = 'true' (added at the end of the backup)
|
|
||||||
//
|
//
|
||||||
// Attributes of created VMs:
|
// Attributes of created VMs:
|
||||||
//
|
//
|
||||||
@ -937,6 +939,7 @@ export default class BackupNg {
|
|||||||
},
|
},
|
||||||
xapi._updateObjectMapProperty(vm, 'other_config', {
|
xapi._updateObjectMapProperty(vm, 'other_config', {
|
||||||
'xo:backup:datetime': null,
|
'xo:backup:datetime': null,
|
||||||
|
'xo:backup:deltaChainLength': null,
|
||||||
'xo:backup:exported': null,
|
'xo:backup:exported': null,
|
||||||
'xo:backup:job': null,
|
'xo:backup:job': null,
|
||||||
'xo:backup:schedule': null,
|
'xo:backup:schedule': null,
|
||||||
@ -1293,12 +1296,31 @@ export default class BackupNg {
|
|||||||
$defer.onSuccess.call(xapi, 'deleteVm', baseSnapshot)
|
$defer.onSuccess.call(xapi, 'deleteVm', baseSnapshot)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let deltaChainLength = 0
|
||||||
let fullVdisRequired
|
let fullVdisRequired
|
||||||
await (async () => {
|
await (async () => {
|
||||||
if (baseSnapshot === undefined) {
|
if (baseSnapshot === undefined) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let prevDeltaChainLength = +baseSnapshot.other_config[
|
||||||
|
'xo:backup:deltaChainLength'
|
||||||
|
]
|
||||||
|
if (Number.isNaN(prevDeltaChainLength)) {
|
||||||
|
prevDeltaChainLength = 0
|
||||||
|
}
|
||||||
|
deltaChainLength = prevDeltaChainLength + 1
|
||||||
|
|
||||||
|
const fullInterval = getSetting(settings, 'fullInterval', [
|
||||||
|
vmUuid,
|
||||||
|
scheduleId,
|
||||||
|
'',
|
||||||
|
])
|
||||||
|
if (fullInterval !== 0 && fullInterval <= deltaChainLength) {
|
||||||
|
baseSnapshot = undefined
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const fullRequired = { __proto__: null }
|
const fullRequired = { __proto__: null }
|
||||||
const vdis: $Dict<Vdi> = getVmDisks(baseSnapshot)
|
const vdis: $Dict<Vdi> = getVmDisks(baseSnapshot)
|
||||||
|
|
||||||
@ -1626,6 +1648,15 @@ export default class BackupNg {
|
|||||||
],
|
],
|
||||||
noop // errors are handled in logs
|
noop // errors are handled in logs
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (!isFull) {
|
||||||
|
ignoreErrors.call(
|
||||||
|
snapshot.update_other_config(
|
||||||
|
'xo:backup:deltaChainLength',
|
||||||
|
String(deltaChainLength)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`no exporter for backup mode ${mode}`)
|
throw new Error(`no exporter for backup mode ${mode}`)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user