feat(@xen-orchestra/backups): clean VM backups on run (#5727)

This commit is contained in:
badrAZ
2021-04-21 13:27:33 +02:00
committed by GitHub
parent efc3f45ef6
commit e0d6b501c7
15 changed files with 122 additions and 55 deletions

View File

@@ -7,15 +7,12 @@ const { asyncMap } = require('@xen-orchestra/async-map')
const { createLogger } = require('@xen-orchestra/log')
const { formatDateTime } = require('@xen-orchestra/xapi')
const { ContinuousReplicationWriter } = require('./_ContinuousReplicationWriter')
const { DeltaBackupWriter } = require('./_DeltaBackupWriter')
const { DisasterRecoveryWriter } = require('./_DisasterRecoveryWriter')
const { exportDeltaVm } = require('./_deltaVm')
const { forkStreamUnpipe } = require('./_forkStreamUnpipe')
const { FullBackupWriter } = require('./_FullBackupWriter')
const { getOldEntries } = require('./_getOldEntries')
const { Task } = require('./Task')
const { watchStreamSize } = require('./_watchStreamSize')
const { DeltaReplicationWriter, DeltaBackupWriter, FullReplicationWriter, FullBackupWriter } = require('./writers')
const { debug, warn } = createLogger('xo:backups:VmBackup')
@@ -67,8 +64,8 @@ exports.VmBackup = class VmBackup {
this._writers = writers
const [BackupWriter, ReplicationWriter] = this._isDelta
? [DeltaBackupWriter, ContinuousReplicationWriter]
: [FullBackupWriter, DisasterRecoveryWriter]
? [DeltaBackupWriter, DeltaReplicationWriter]
: [FullBackupWriter, FullReplicationWriter]
const allSettings = job.settings
@@ -78,7 +75,7 @@ exports.VmBackup = class VmBackup {
...allSettings[remoteId],
}
if (targetSettings.exportRetention !== 0) {
writers.push(new BackupWriter(this, remoteId, targetSettings))
writers.push(new BackupWriter({ backup: this, remoteId, settings: targetSettings }))
}
})
srs.forEach(sr => {
@@ -87,7 +84,7 @@ exports.VmBackup = class VmBackup {
...allSettings[sr.uuid],
}
if (targetSettings.copyRetention !== 0) {
writers.push(new ReplicationWriter(this, sr, targetSettings))
writers.push(new ReplicationWriter({ backup: this, sr, settings: targetSettings }))
}
})
}
@@ -328,6 +325,8 @@ exports.VmBackup = class VmBackup {
'offlineBackup is not compatible with snapshotRetention'
)
await asyncMap(this._writers, writer => writer.beforeBackup())
await this._fetchJobSnapshots()
if (this._isDelta) {

View File

@@ -0,0 +1,19 @@
const { AbstractWriter } = require('./_AbstractWriter')
exports.AbstractDeltaWriter = class AbstractDeltaWriter extends AbstractWriter {
checkBaseVdis(baseUuidToSrcVdi, baseVm) {
throw new Error('Not implemented')
}
cleanup() {
throw new Error('Not implemented')
}
prepare({ isFull }) {
throw new Error('Not implemented')
}
transfer({ timestamp, deltaExport, sizeContainers }) {
throw new Error('Not implemented')
}
}

View File

@@ -0,0 +1,7 @@
const { AbstractWriter } = require('./_AbstractWriter')
exports.AbstractFullWriter = class AbstractFullWriter extends AbstractWriter {
run({ timestamp, sizeContainer, stream }) {
throw new Error('Not implemented')
}
}

View File

@@ -0,0 +1,8 @@
exports.AbstractWriter = class AbstractWriter {
constructor({ backup, settings }) {
this._backup = backup
this._settings = settings
}
beforeBackup() {}
}

View File

@@ -7,23 +7,19 @@ const { chainVhd, checkVhdChain, default: Vhd } = require('vhd-lib')
const { createLogger } = require('@xen-orchestra/log')
const { dirname } = require('path')
const { formatFilenameDate } = require('../_filenameDate')
const { getOldEntries } = require('../_getOldEntries')
const { getVmBackupDir } = require('../_getVmBackupDir')
const { Task } = require('../Task')
const { MixinBackupWriter } = require('./_MixinBackupWriter')
const { AbstractDeltaWriter } = require('./_AbstractDeltaWriter')
const { checkVhd } = require('./_checkVhd')
const { formatFilenameDate } = require('./_filenameDate')
const { getOldEntries } = require('./_getOldEntries')
const { getVmBackupDir } = require('./_getVmBackupDir')
const { packUuid } = require('./_packUuid')
const { Task } = require('./Task')
const { warn } = createLogger('xo:backups:DeltaBackupWriter')
exports.DeltaBackupWriter = class DeltaBackupWriter {
constructor(backup, remoteId, settings) {
this._adapter = backup.remoteAdapters[remoteId]
this._backup = backup
this._remoteId = remoteId
this._settings = settings
}
exports.DeltaBackupWriter = class DeltaBackupWriter extends MixinBackupWriter(AbstractDeltaWriter) {
async checkBaseVdis(baseUuidToSrcVdi) {
const { handler } = this._adapter
const backup = this._backup

View File

@@ -2,19 +2,16 @@ const { asyncMap, asyncMapSettled } = require('@xen-orchestra/async-map')
const ignoreErrors = require('promise-toolbox/ignoreErrors')
const { formatDateTime } = require('@xen-orchestra/xapi')
const { formatFilenameDate } = require('./_filenameDate')
const { getOldEntries } = require('./_getOldEntries')
const { importDeltaVm, TAG_COPY_SRC } = require('./_deltaVm')
const { formatFilenameDate } = require('../_filenameDate')
const { getOldEntries } = require('../_getOldEntries')
const { importDeltaVm, TAG_COPY_SRC } = require('../_deltaVm')
const { Task } = require('../Task')
const { AbstractDeltaWriter } = require('./_AbstractDeltaWriter')
const { MixinReplicationWriter } = require('./_MixinReplicationWriter')
const { listReplicatedVms } = require('./_listReplicatedVms')
const { Task } = require('./Task')
exports.ContinuousReplicationWriter = class ContinuousReplicationWriter {
constructor(backup, sr, settings) {
this._backup = backup
this._settings = settings
this._sr = sr
}
exports.DeltaReplicationWriter = class DeltaReplicationWriter extends MixinReplicationWriter(AbstractDeltaWriter) {
async checkBaseVdis(baseUuidToSrcVdi, baseVm) {
const sr = this._sr
const replicatedVm = listReplicatedVms(sr.$xapi, this._backup.job.id, sr.uuid, this._backup.vm.uuid).find(

View File

@@ -1,20 +1,21 @@
const { formatFilenameDate } = require('./_filenameDate')
const { getOldEntries } = require('./_getOldEntries')
const { getVmBackupDir } = require('./_getVmBackupDir')
const { isValidXva } = require('./isValidXva')
const { Task } = require('./Task')
const { formatFilenameDate } = require('../_filenameDate')
const { getOldEntries } = require('../_getOldEntries')
const { getVmBackupDir } = require('../_getVmBackupDir')
const { isValidXva } = require('../isValidXva')
const { Task } = require('../Task')
exports.FullBackupWriter = class FullBackupWriter {
constructor(backup, remoteId, settings) {
this._backup = backup
this._remoteId = remoteId
this._settings = settings
const { MixinBackupWriter } = require('./_MixinBackupWriter')
const { AbstractFullWriter } = require('./_AbstractFullWriter')
exports.FullBackupWriter = class FullBackupWriter extends MixinBackupWriter(AbstractFullWriter) {
constructor(props) {
super(props)
this.run = Task.wrapFn(
{
name: 'export',
data: {
id: remoteId,
id: props.remoteId,
type: 'remote',
// necessary?
@@ -27,12 +28,11 @@ exports.FullBackupWriter = class FullBackupWriter {
async run({ timestamp, sizeContainer, stream }) {
const backup = this._backup
const remoteId = this._remoteId
const settings = this._settings
const { job, scheduleId, vm } = backup
const adapter = backup.remoteAdapters[remoteId]
const adapter = this._adapter
const handler = adapter.handler
const backupDir = getVmBackupDir(vm.uuid)

View File

@@ -2,22 +2,23 @@ const ignoreErrors = require('promise-toolbox/ignoreErrors')
const { asyncMapSettled } = require('@xen-orchestra/async-map')
const { formatDateTime } = require('@xen-orchestra/xapi')
const { formatFilenameDate } = require('./_filenameDate')
const { getOldEntries } = require('./_getOldEntries')
const { listReplicatedVms } = require('./_listReplicatedVms')
const { Task } = require('./Task')
const { formatFilenameDate } = require('../_filenameDate')
const { getOldEntries } = require('../_getOldEntries')
const { Task } = require('../Task')
exports.DisasterRecoveryWriter = class DisasterRecoveryWriter {
constructor(backup, sr, settings) {
this._backup = backup
this._settings = settings
this._sr = sr
const { AbstractFullWriter } = require('./_AbstractFullWriter')
const { MixinReplicationWriter } = require('./_MixinReplicationWriter')
const { listReplicatedVms } = require('./_listReplicatedVms')
exports.FullReplicationWriter = class FullReplicationWriter extends MixinReplicationWriter(AbstractFullWriter) {
constructor(props) {
super(props)
this.run = Task.wrapFn(
{
name: 'export',
data: {
id: sr.uuid,
id: props.sr.uuid,
type: 'SR',
// necessary?

View File

@@ -0,0 +1,25 @@
const { createLogger } = require('@xen-orchestra/log')
const { getVmBackupDir } = require('../_getVmBackupDir')
const { debug } = createLogger('xo:backups:MixinBackupWriter')
exports.MixinBackupWriter = (BaseClass = Object) =>
class MixinBackupWriter extends BaseClass {
constructor({ remoteId, ...rest }) {
super(rest)
this._adapter = rest.backup.remoteAdapters[remoteId]
this._remoteId = remoteId
}
async beforeBackup() {
try {
await this._adapter.cleanVm(getVmBackupDir(this._backup.vm.uuid), { remove: true, merge: true, onLog: debug })
} catch (error) {
if (error?.code !== 'ENOENT') {
throw error
}
}
}
}

View File

@@ -0,0 +1,8 @@
exports.MixinReplicationWriter = (BaseClass = Object) =>
class MixinReplicationWriter extends BaseClass {
constructor({ sr, ...rest }) {
super(rest)
this._sr = sr
}
}

View File

@@ -0,0 +1,7 @@
Object.assign(
exports,
require('./_DeltaBackupWriter'),
require('./_DeltaReplicationWriter'),
require('./_FullBackupWriter'),
require('./_FullReplicationWriter')
)

View File

@@ -35,7 +35,7 @@
- @xen-orchestra/fs minor
- @xen-orchestra/xapi patch
- @xen-orchestra/backups patch
- @xen-orchestra/backups minor
- @xen-orchestra/backups-cli patch
- @xen-orchestra/mixins minor
- xo-server minor