feat(vm.deltaCopy): retention param (#597)

See vatesfr/xo-web#1692
This commit is contained in:
Julien Fontanet 2017-08-31 17:20:58 +02:00 committed by GitHub
parent 84d7ba5758
commit 5e11e87a0c
3 changed files with 34 additions and 16 deletions

View File

@ -755,12 +755,13 @@ exports.importDeltaBackup = importDeltaBackup
#--------------------------------------------------------------------- #---------------------------------------------------------------------
deltaCopy = ({ force, vm, sr }) -> @deltaCopyVm(vm, sr, force) deltaCopy = ({ force, vm, retention, sr }) -> @deltaCopyVm(vm, sr, force, retention)
deltaCopy.params = { deltaCopy.params = {
force: { type: 'boolean', optional: true },
id: { type: 'string' }, id: { type: 'string' },
sr: { type: 'string' }, retention: { type: 'number', optional: true },
force: { type: 'boolean', optional: true } sr: { type: 'string' }
} }
deltaCopy.resolve = { deltaCopy.resolve = {

View File

@ -894,18 +894,15 @@ export default class Xapi extends XapiBase {
vbds, vbds,
vdis, vdis,
vifs, vifs,
vm: baseVm && !disableBaseTags vm: {
? { ...vm,
...vm, other_config: baseVm && !disableBaseTags
other_config: { ? {
...vm.other_config, ...vm.other_config,
[TAG_BASE_DELTA]: baseVm.uuid [TAG_BASE_DELTA]: baseVm.uuid
} }
} : omit(vm.other_config, TAG_BASE_DELTA)
: { }
...vm,
other_config: omit(vm.other_config, TAG_BASE_DELTA)
}
}, 'streams', { }, 'streams', {
value: await streams::pAll() value: await streams::pAll()
}) })

View File

@ -51,6 +51,8 @@ import {
const DELTA_BACKUP_EXT = '.json' const DELTA_BACKUP_EXT = '.json'
const DELTA_BACKUP_EXT_LENGTH = DELTA_BACKUP_EXT.length const DELTA_BACKUP_EXT_LENGTH = DELTA_BACKUP_EXT.length
const TAG_SOURCE_VM = 'xo:source_vm'
const TAG_EXPORT_TIME = 'xo:export_time'
const shortDate = utcFormat('%Y-%m-%d') const shortDate = utcFormat('%Y-%m-%d')
@ -398,12 +400,12 @@ export default class {
// ----------------------------------------------------------------- // -----------------------------------------------------------------
@deferrable.onFailure @deferrable.onFailure
async deltaCopyVm ($onFailure, srcVm, targetSr, force = false) { async deltaCopyVm ($onFailure, srcVm, targetSr, force = false, retention = 1) {
const srcXapi = this._xo.getXapi(srcVm) const srcXapi = this._xo.getXapi(srcVm)
const targetXapi = this._xo.getXapi(targetSr) const targetXapi = this._xo.getXapi(targetSr)
// Get Xen objects from XO objects. // Get Xen objects from XO objects.
srcVm = srcXapi.getObject(srcVm._xapiId) const { uuid } = srcVm = srcXapi.getObject(srcVm._xapiId)
targetSr = targetXapi.getObject(targetSr._xapiId) targetSr = targetXapi.getObject(targetSr._xapiId)
// 1. Find the local base for this SR (if any). // 1. Find the local base for this SR (if any).
@ -426,7 +428,10 @@ export default class {
$onFailure(() => srcXapi.deleteVm(delta.vm.uuid)) $onFailure(() => srcXapi.deleteVm(delta.vm.uuid))
$onFailure(cancel) $onFailure(cancel)
delta.vm.name_label += ` (${shortDate(Date.now())})` const now = Date.now()
delta.vm.name_label += ` (${shortDate(now)})`
delta.vm.other_config[TAG_SOURCE_VM] = uuid
delta.vm.other_config[TAG_EXPORT_TIME] = safeDateFormat(now)
forEach(delta.vdis, (vdi, key) => { forEach(delta.vdis, (vdi, key) => {
const id = `${key}.vhd` const id = `${key}.vhd`
@ -436,10 +441,19 @@ export default class {
delta.streams[id] = delta.streams[id].pipe(sizeStream) delta.streams[id] = delta.streams[id].pipe(sizeStream)
}) })
let toRemove = filter(targetXapi.objects.all, obj =>
obj.$type === 'vm' &&
obj.other_config[TAG_SOURCE_VM] === uuid
)
const n = toRemove.length - retention + 1 // take into account the future copy
toRemove = n > 0
? sortBy(toRemove, _ => _.other_config[TAG_EXPORT_TIME]).slice(0, n)
: undefined
const promise = targetXapi.importDeltaVm( const promise = targetXapi.importDeltaVm(
delta, delta,
{ {
deleteBase: true, // Remove the remote base. deleteBase: toRemove.length === 0, // old replications are not captured in toRemove
srId: targetSr.$id srId: targetSr.$id
} }
) )
@ -450,6 +464,12 @@ export default class {
promise.then(() => srcXapi.deleteVm(localBaseUuid))::ignoreErrors() promise.then(() => srcXapi.deleteVm(localBaseUuid))::ignoreErrors()
} }
if (toRemove !== undefined) {
promise.then(() => asyncMap(toRemove, _ =>
targetXapi.deleteVm(_.$id))
)::ignoreErrors()
}
// (Asynchronously) Identify snapshot as future base. // (Asynchronously) Identify snapshot as future base.
promise.then(() => { promise.then(() => {
return srcXapi._updateObjectMapProperty(srcVm, 'other_config', { return srcXapi._updateObjectMapProperty(srcVm, 'other_config', {