feat(@xen-orchestra/backups): clean VM backups on run (#5727)
This commit is contained in:
@@ -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) {
|
||||
|
||||
19
@xen-orchestra/backups/writers/_AbstractDeltaWriter.js
Normal file
19
@xen-orchestra/backups/writers/_AbstractDeltaWriter.js
Normal 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')
|
||||
}
|
||||
}
|
||||
7
@xen-orchestra/backups/writers/_AbstractFullWriter.js
Normal file
7
@xen-orchestra/backups/writers/_AbstractFullWriter.js
Normal file
@@ -0,0 +1,7 @@
|
||||
const { AbstractWriter } = require('./_AbstractWriter')
|
||||
|
||||
exports.AbstractFullWriter = class AbstractFullWriter extends AbstractWriter {
|
||||
run({ timestamp, sizeContainer, stream }) {
|
||||
throw new Error('Not implemented')
|
||||
}
|
||||
}
|
||||
8
@xen-orchestra/backups/writers/_AbstractWriter.js
Normal file
8
@xen-orchestra/backups/writers/_AbstractWriter.js
Normal file
@@ -0,0 +1,8 @@
|
||||
exports.AbstractWriter = class AbstractWriter {
|
||||
constructor({ backup, settings }) {
|
||||
this._backup = backup
|
||||
this._settings = settings
|
||||
}
|
||||
|
||||
beforeBackup() {}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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(
|
||||
@@ -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)
|
||||
|
||||
@@ -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?
|
||||
25
@xen-orchestra/backups/writers/_MixinBackupWriter.js
Normal file
25
@xen-orchestra/backups/writers/_MixinBackupWriter.js
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
exports.MixinReplicationWriter = (BaseClass = Object) =>
|
||||
class MixinReplicationWriter extends BaseClass {
|
||||
constructor({ sr, ...rest }) {
|
||||
super(rest)
|
||||
|
||||
this._sr = sr
|
||||
}
|
||||
}
|
||||
7
@xen-orchestra/backups/writers/index.js
Normal file
7
@xen-orchestra/backups/writers/index.js
Normal file
@@ -0,0 +1,7 @@
|
||||
Object.assign(
|
||||
exports,
|
||||
require('./_DeltaBackupWriter'),
|
||||
require('./_DeltaReplicationWriter'),
|
||||
require('./_FullBackupWriter'),
|
||||
require('./_FullReplicationWriter')
|
||||
)
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user