xen-orchestra/@xen-orchestra/backups/_runners/_XoMetadataBackup.mjs

73 lines
2.2 KiB
JavaScript

import { asyncMap } from '@xen-orchestra/async-map'
import { join } from '@xen-orchestra/fs/path'
import { DIR_XO_CONFIG_BACKUPS } from '../RemoteAdapter.mjs'
import { formatFilenameDate } from '../_filenameDate.mjs'
import { Task } from '../Task.mjs'
export class XoMetadataBackup {
constructor({ config, job, remoteAdapters, schedule, settings }) {
this._config = config
this._job = job
this._remoteAdapters = remoteAdapters
this._schedule = schedule
this._settings = settings
}
async run() {
const timestamp = Date.now()
const { _job: job, _schedule: schedule } = this
const scheduleDir = `${DIR_XO_CONFIG_BACKUPS}/${schedule.id}`
const dir = `${scheduleDir}/${formatFilenameDate(timestamp)}`
const data = job.xoMetadata
let dataBaseName = './data'
// JSON data is sent as plain string, binary data is sent as an object with `data` and `encoding properties
const isJson = typeof data === 'string'
if (isJson) {
dataBaseName += '.json'
}
const metadata = JSON.stringify(
{
data: dataBaseName,
jobId: job.id,
jobName: job.name,
scheduleId: schedule.id,
scheduleName: schedule.name,
timestamp,
},
null,
2
)
const dataFileName = join(dir, dataBaseName)
const metaDataFileName = `${dir}/metadata.json`
await asyncMap(
Object.entries(this._remoteAdapters),
([remoteId, adapter]) =>
Task.run(
{
name: `Starting XO metadata backup for the remote (${remoteId}). (${job.id})`,
data: {
id: remoteId,
type: 'remote',
},
},
async () => {
const handler = adapter.handler
const dirMode = this._config.dirMode
await handler.outputFile(dataFileName, isJson ? data : Buffer.from(data.data, data.encoding), { dirMode })
await handler.outputFile(metaDataFileName, metadata, {
dirMode,
})
await adapter.deleteOldMetadataBackups(scheduleDir, this._settings.retentionXoMetadata)
}
).catch(() => {}) // errors are handled by logs
)
}
}