@xen-orchestra/backups 0.38.3 → 0.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{Backup.js → Backup.mjs} +4 -6
- package/{DurablePartition.js → DurablePartition.mjs} +2 -4
- package/{HealthCheckVmBackup.js → HealthCheckVmBackup.mjs} +2 -4
- package/{ImportVmBackup.js → ImportVmBackup.mjs} +6 -8
- package/{RemoteAdapter.js → RemoteAdapter.mjs} +69 -76
- package/{RestoreMetadataBackup.js → RestoreMetadataBackup.mjs} +6 -5
- package/{Task.js → Task.mjs} +3 -6
- package/_backupType.mjs +4 -0
- package/{_backupWorker.js → _backupWorker.mjs} +22 -22
- package/{_cancelableMap.js → _cancelableMap.mjs} +3 -5
- package/{_cleanVm.js → _cleanVm.mjs} +16 -19
- package/_filenameDate.mjs +6 -0
- package/{_getOldEntries.js → _getOldEntries.mjs} +1 -3
- package/{_getTmpDir.js → _getTmpDir.mjs} +5 -7
- package/_getVmBackupDir.mjs +5 -0
- package/{_incrementalVm.js → _incrementalVm.mjs} +21 -20
- package/{_isValidXva.js → _isValidXva.mjs} +2 -5
- package/{_listPartitions.js → _listPartitions.mjs} +6 -9
- package/{_lvm.js → _lvm.mjs} +5 -7
- package/_runners/{Metadata.js → Metadata.mjs} +10 -12
- package/_runners/{VmsRemote.js → VmsRemote.mjs} +12 -14
- package/_runners/{VmsXapi.js → VmsXapi.mjs} +14 -15
- package/_runners/{_Abstract.js → _Abstract.mjs} +7 -9
- package/_runners/{_PoolMetadataBackup.js → _PoolMetadataBackup.mjs} +7 -10
- package/_runners/{_RemoteTimeoutError.js → _RemoteTimeoutError.mjs} +1 -3
- package/_runners/{_XoMetadataBackup.js → _XoMetadataBackup.mjs} +11 -9
- package/_runners/{_createStreamThrottle.js → _createStreamThrottle.mjs} +4 -6
- package/_runners/{_forkStreamUnpipe.js → _forkStreamUnpipe.mjs} +4 -5
- package/_runners/{_getAdaptersByRemote.js → _getAdaptersByRemote.mjs} +1 -3
- package/_runners/_runTask.mjs +5 -0
- package/_runners/_vmRunners/{FullRemote.js → FullRemote.mjs} +9 -12
- package/_runners/_vmRunners/{FullXapi.js → FullXapi.mjs} +7 -9
- package/_runners/_vmRunners/{IncrementalRemote.js → IncrementalRemote.mjs} +11 -12
- package/_runners/_vmRunners/{IncrementalXapi.js → IncrementalXapi.mjs} +18 -20
- package/_runners/_vmRunners/{_Abstract.js → _Abstract.mjs} +4 -6
- package/_runners/_vmRunners/{_AbstractRemote.js → _AbstractRemote.mjs} +6 -6
- package/_runners/_vmRunners/{_AbstractXapi.js → _AbstractXapi.mjs} +14 -17
- package/_runners/_vmRunners/_forkDeltaExport.mjs +11 -0
- package/_runners/_writers/{FullRemoteWriter.js → FullRemoteWriter.mjs} +6 -8
- package/_runners/_writers/{FullXapiWriter.js → FullXapiWriter.mjs} +10 -12
- package/_runners/_writers/{IncrementalRemoteWriter.js → IncrementalRemoteWriter.mjs} +31 -28
- package/_runners/_writers/{IncrementalXapiWriter.js → IncrementalXapiWriter.mjs} +11 -13
- package/_runners/_writers/{_AbstractFullWriter.js → _AbstractFullWriter.mjs} +2 -4
- package/_runners/_writers/{_AbstractIncrementalWriter.js → _AbstractIncrementalWriter.mjs} +2 -4
- package/_runners/_writers/{_AbstractWriter.js → _AbstractWriter.mjs} +3 -5
- package/_runners/_writers/{_MixinRemoteWriter.js → _MixinRemoteWriter.mjs} +10 -12
- package/_runners/_writers/_MixinXapiWriter.mjs +72 -0
- package/_runners/_writers/_checkVhd.mjs +6 -0
- package/_runners/_writers/{_listReplicatedVms.js → _listReplicatedVms.mjs} +1 -3
- package/_runners/_writers/{_packUuid.js → _packUuid.mjs} +1 -3
- package/{_watchStreamSize.js → _watchStreamSize.mjs} +1 -3
- package/{extractIdsFromSimplePattern.js → extractIdsFromSimplePattern.mjs} +1 -3
- package/{formatVmBackups.js → formatVmBackups.mjs} +3 -5
- package/merge-worker/{cli.js → cli.mjs} +9 -11
- package/merge-worker/{index.js → index.mjs} +6 -7
- package/package.json +10 -8
- package/{parseMetadataBackupId.js → parseMetadataBackupId.mjs} +2 -4
- package/{runBackupWorker.js → runBackupWorker.mjs} +4 -7
- package/_backupType.js +0 -6
- package/_filenameDate.js +0 -8
- package/_getVmBackupDir.js +0 -8
- package/_runners/_runTask.js +0 -6
- package/_runners/_vmRunners/_forkDeltaExport.js +0 -12
- package/_runners/_writers/_MixinXapiWriter.js +0 -46
- package/_runners/_writers/_checkVhd.js +0 -8
|
@@ -1,29 +1,27 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const { packUuid } = require('./_packUuid.js')
|
|
22
|
-
const { Disposable } = require('promise-toolbox')
|
|
1
|
+
import assert from 'node:assert'
|
|
2
|
+
import mapValues from 'lodash/mapValues.js'
|
|
3
|
+
import ignoreErrors from 'promise-toolbox/ignoreErrors'
|
|
4
|
+
import { asyncEach } from '@vates/async-each'
|
|
5
|
+
import { asyncMap } from '@xen-orchestra/async-map'
|
|
6
|
+
import { chainVhd, checkVhdChain, openVhd, VhdAbstract } from 'vhd-lib'
|
|
7
|
+
import { createLogger } from '@xen-orchestra/log'
|
|
8
|
+
import { decorateClass } from '@vates/decorate-with'
|
|
9
|
+
import { defer } from 'golike-defer'
|
|
10
|
+
import { dirname } from 'node:path'
|
|
11
|
+
|
|
12
|
+
import { formatFilenameDate } from '../../_filenameDate.mjs'
|
|
13
|
+
import { getOldEntries } from '../../_getOldEntries.mjs'
|
|
14
|
+
import { Task } from '../../Task.mjs'
|
|
15
|
+
|
|
16
|
+
import { MixinRemoteWriter } from './_MixinRemoteWriter.mjs'
|
|
17
|
+
import { AbstractIncrementalWriter } from './_AbstractIncrementalWriter.mjs'
|
|
18
|
+
import { checkVhd } from './_checkVhd.mjs'
|
|
19
|
+
import { packUuid } from './_packUuid.mjs'
|
|
20
|
+
import { Disposable } from 'promise-toolbox'
|
|
23
21
|
|
|
24
22
|
const { warn } = createLogger('xo:backups:DeltaBackupWriter')
|
|
25
23
|
|
|
26
|
-
class IncrementalRemoteWriter extends MixinRemoteWriter(AbstractIncrementalWriter) {
|
|
24
|
+
export class IncrementalRemoteWriter extends MixinRemoteWriter(AbstractIncrementalWriter) {
|
|
27
25
|
async checkBaseVdis(baseUuidToSrcVdi) {
|
|
28
26
|
const { handler } = this._adapter
|
|
29
27
|
const adapter = this._adapter
|
|
@@ -138,7 +136,7 @@ class IncrementalRemoteWriter extends MixinRemoteWriter(AbstractIncrementalWrite
|
|
|
138
136
|
const adapter = this._adapter
|
|
139
137
|
const job = this._job
|
|
140
138
|
const scheduleId = this._scheduleId
|
|
141
|
-
|
|
139
|
+
const settings = this._settings
|
|
142
140
|
const jobId = job.id
|
|
143
141
|
const handler = adapter.handler
|
|
144
142
|
|
|
@@ -176,8 +174,9 @@ class IncrementalRemoteWriter extends MixinRemoteWriter(AbstractIncrementalWrite
|
|
|
176
174
|
}
|
|
177
175
|
const { size } = await Task.run({ name: 'transfer' }, async () => {
|
|
178
176
|
let transferSize = 0
|
|
179
|
-
await
|
|
180
|
-
|
|
177
|
+
await asyncEach(
|
|
178
|
+
Object.entries(deltaExport.vdis),
|
|
179
|
+
async ([id, vdi]) => {
|
|
181
180
|
const path = `${this._vmBackupDir}/${vhds[id]}`
|
|
182
181
|
|
|
183
182
|
const isDelta = differentialVhds[`${id}.vhd`]
|
|
@@ -223,8 +222,12 @@ class IncrementalRemoteWriter extends MixinRemoteWriter(AbstractIncrementalWrite
|
|
|
223
222
|
await vhd.readBlockAllocationTable() // required by writeFooter()
|
|
224
223
|
await vhd.writeFooter()
|
|
225
224
|
})
|
|
226
|
-
}
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
concurrency: settings.diskPerVmConcurrency,
|
|
228
|
+
}
|
|
227
229
|
)
|
|
230
|
+
|
|
228
231
|
return { size: transferSize }
|
|
229
232
|
})
|
|
230
233
|
metadataContent.size = size
|
|
@@ -233,6 +236,6 @@ class IncrementalRemoteWriter extends MixinRemoteWriter(AbstractIncrementalWrite
|
|
|
233
236
|
// TODO: run cleanup?
|
|
234
237
|
}
|
|
235
238
|
}
|
|
236
|
-
|
|
239
|
+
decorateClass(IncrementalRemoteWriter, {
|
|
237
240
|
_transfer: defer,
|
|
238
241
|
})
|
|
@@ -1,19 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
import { asyncMap, asyncMapSettled } from '@xen-orchestra/async-map'
|
|
2
|
+
import ignoreErrors from 'promise-toolbox/ignoreErrors'
|
|
3
|
+
import { formatDateTime } from '@xen-orchestra/xapi'
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
import { formatFilenameDate } from '../../_filenameDate.mjs'
|
|
6
|
+
import { getOldEntries } from '../../_getOldEntries.mjs'
|
|
7
|
+
import { importIncrementalVm, TAG_COPY_SRC } from '../../_incrementalVm.mjs'
|
|
8
|
+
import { Task } from '../../Task.mjs'
|
|
6
9
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const { Task } = require('../../Task.js')
|
|
10
|
+
import { AbstractIncrementalWriter } from './_AbstractIncrementalWriter.mjs'
|
|
11
|
+
import { MixinXapiWriter } from './_MixinXapiWriter.mjs'
|
|
12
|
+
import { listReplicatedVms } from './_listReplicatedVms.mjs'
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
const { MixinXapiWriter } = require('./_MixinXapiWriter.js')
|
|
14
|
-
const { listReplicatedVms } = require('./_listReplicatedVms.js')
|
|
15
|
-
|
|
16
|
-
exports.IncrementalXapiWriter = class IncrementalXapiWriter extends MixinXapiWriter(AbstractIncrementalWriter) {
|
|
14
|
+
export class IncrementalXapiWriter extends MixinXapiWriter(AbstractIncrementalWriter) {
|
|
17
15
|
async checkBaseVdis(baseUuidToSrcVdi, baseVm) {
|
|
18
16
|
const sr = this._sr
|
|
19
17
|
const replicatedVm = listReplicatedVms(sr.$xapi, this._job.id, sr.uuid, this._vmUuid).find(
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import { AbstractWriter } from './_AbstractWriter.mjs'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
exports.AbstractFullWriter = class AbstractFullWriter extends AbstractWriter {
|
|
3
|
+
export class AbstractFullWriter extends AbstractWriter {
|
|
6
4
|
async run({ timestamp, sizeContainer, stream, vm, vmSnapshot }) {
|
|
7
5
|
try {
|
|
8
6
|
return await this._run({ timestamp, sizeContainer, stream, vm, vmSnapshot })
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import { AbstractWriter } from './_AbstractWriter.mjs'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
exports.AbstractIncrementalWriter = class AbstractIncrementalWriter extends AbstractWriter {
|
|
3
|
+
export class AbstractIncrementalWriter extends AbstractWriter {
|
|
6
4
|
checkBaseVdis(baseUuidToSrcVdi, baseVm) {
|
|
7
5
|
throw new Error('Not implemented')
|
|
8
6
|
}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import { formatFilenameDate } from '../../_filenameDate.mjs'
|
|
2
|
+
import { getVmBackupDir } from '../../_getVmBackupDir.mjs'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
const { getVmBackupDir } = require('../../_getVmBackupDir')
|
|
5
|
-
|
|
6
|
-
exports.AbstractWriter = class AbstractWriter {
|
|
4
|
+
export class AbstractWriter {
|
|
7
5
|
constructor({ config, healthCheckSr, job, vmUuid, scheduleId, settings }) {
|
|
8
6
|
this._config = config
|
|
9
7
|
this._healthCheckSr = healthCheckSr
|
|
@@ -1,19 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
import { createLogger } from '@xen-orchestra/log'
|
|
2
|
+
import { join } from 'node:path'
|
|
3
|
+
import assert from 'node:assert'
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const { HealthCheckVmBackup } = require('../../HealthCheckVmBackup.js')
|
|
10
|
-
const { ImportVmBackup } = require('../../ImportVmBackup.js')
|
|
11
|
-
const { Task } = require('../../Task.js')
|
|
12
|
-
const MergeWorker = require('../../merge-worker/index.js')
|
|
5
|
+
import { formatFilenameDate } from '../../_filenameDate.mjs'
|
|
6
|
+
import { getVmBackupDir } from '../../_getVmBackupDir.mjs'
|
|
7
|
+
import { HealthCheckVmBackup } from '../../HealthCheckVmBackup.mjs'
|
|
8
|
+
import { ImportVmBackup } from '../../ImportVmBackup.mjs'
|
|
9
|
+
import { Task } from '../../Task.mjs'
|
|
10
|
+
import * as MergeWorker from '../../merge-worker/index.mjs'
|
|
13
11
|
|
|
14
12
|
const { info, warn } = createLogger('xo:backups:MixinBackupWriter')
|
|
15
13
|
|
|
16
|
-
|
|
14
|
+
export const MixinRemoteWriter = (BaseClass = Object) =>
|
|
17
15
|
class MixinRemoteWriter extends BaseClass {
|
|
18
16
|
#lock
|
|
19
17
|
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { extractOpaqueRef } from '@xen-orchestra/xapi'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
3
|
+
|
|
4
|
+
import { HealthCheckVmBackup } from '../../HealthCheckVmBackup.mjs'
|
|
5
|
+
import { Task } from '../../Task.mjs'
|
|
6
|
+
|
|
7
|
+
export const MixinXapiWriter = (BaseClass = Object) =>
|
|
8
|
+
class MixinXapiWriter extends BaseClass {
|
|
9
|
+
constructor({ sr, ...rest }) {
|
|
10
|
+
super(rest)
|
|
11
|
+
|
|
12
|
+
this._sr = sr
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// check if the base Vm has all its disk on health check sr
|
|
16
|
+
async #isAlreadyOnHealthCheckSr(baseVm) {
|
|
17
|
+
const xapi = baseVm.$xapi
|
|
18
|
+
const vdiRefs = await xapi.VM_getDisks(baseVm.$ref)
|
|
19
|
+
for (const vdiRef of vdiRefs) {
|
|
20
|
+
const vdi = xapi.getObject(vdiRef)
|
|
21
|
+
if (vdi.$SR.uuid !== this._heathCheckSr.uuid) {
|
|
22
|
+
return false
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return true
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
healthCheck() {
|
|
29
|
+
const sr = this._healthCheckSr
|
|
30
|
+
assert.notStrictEqual(sr, undefined, 'SR should be defined before making a health check')
|
|
31
|
+
assert.notEqual(this._targetVmRef, undefined, 'A vm should have been transfered to be health checked')
|
|
32
|
+
// copy VM
|
|
33
|
+
return Task.run(
|
|
34
|
+
{
|
|
35
|
+
name: 'health check',
|
|
36
|
+
},
|
|
37
|
+
async () => {
|
|
38
|
+
const { $xapi: xapi } = sr
|
|
39
|
+
let healthCheckVmRef
|
|
40
|
+
try {
|
|
41
|
+
const baseVm = xapi.getObject(this._targetVmRef) ?? (await xapi.waitObject(this._targetVmRef))
|
|
42
|
+
|
|
43
|
+
if (await this.#isAlreadyOnHealthCheckSr(baseVm)) {
|
|
44
|
+
healthCheckVmRef = await Task.run(
|
|
45
|
+
{ name: 'cloning-vm' },
|
|
46
|
+
async () =>
|
|
47
|
+
await xapi
|
|
48
|
+
.callAsync('VM.clone', this._targetVmRef, `Health Check - ${baseVm.name_label}`)
|
|
49
|
+
.then(extractOpaqueRef)
|
|
50
|
+
)
|
|
51
|
+
} else {
|
|
52
|
+
healthCheckVmRef = await Task.run(
|
|
53
|
+
{ name: 'copying-vm' },
|
|
54
|
+
async () =>
|
|
55
|
+
await xapi
|
|
56
|
+
.callAsync('VM.copy', this._targetVmRef, `Health Check - ${baseVm.name_label}`, sr.$ref)
|
|
57
|
+
.then(extractOpaqueRef)
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
const healthCheckVm = xapi.getObject(healthCheckVmRef) ?? (await xapi.waitObject(healthCheckVmRef))
|
|
61
|
+
|
|
62
|
+
await new HealthCheckVmBackup({
|
|
63
|
+
restoredVm: healthCheckVm,
|
|
64
|
+
xapi,
|
|
65
|
+
}).run()
|
|
66
|
+
} finally {
|
|
67
|
+
healthCheckVmRef && (await xapi.VM_destroy(healthCheckVmRef))
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
1
|
const getReplicatedVmDatetime = vm => {
|
|
4
2
|
const { 'xo:backup:datetime': datetime = vm.name_label.slice(-17, -1) } = vm.other_config
|
|
5
3
|
return datetime
|
|
@@ -7,7 +5,7 @@ const getReplicatedVmDatetime = vm => {
|
|
|
7
5
|
|
|
8
6
|
const compareReplicatedVmDatetime = (a, b) => (getReplicatedVmDatetime(a) < getReplicatedVmDatetime(b) ? -1 : 1)
|
|
9
7
|
|
|
10
|
-
|
|
8
|
+
export function listReplicatedVms(xapi, scheduleOrJobId, srUuid, vmUuid) {
|
|
11
9
|
const { all } = xapi.objects
|
|
12
10
|
const vms = {}
|
|
13
11
|
for (const key in all) {
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const mapValues = require('lodash/mapValues.js')
|
|
4
|
-
const { dirname } = require('path')
|
|
1
|
+
import mapValues from 'lodash/mapValues.js'
|
|
2
|
+
import { dirname } from 'node:path'
|
|
5
3
|
|
|
6
4
|
function formatVmBackup(backup) {
|
|
7
5
|
return {
|
|
@@ -31,6 +29,6 @@ function formatVmBackup(backup) {
|
|
|
31
29
|
}
|
|
32
30
|
|
|
33
31
|
// format all backups as returned by RemoteAdapter#listAllVmBackups()
|
|
34
|
-
|
|
32
|
+
export function formatVmBackups(backupsByVM) {
|
|
35
33
|
return mapValues(backupsByVM, backups => backups.map(formatVmBackup))
|
|
36
34
|
}
|
|
@@ -2,19 +2,17 @@
|
|
|
2
2
|
// eslint-disable-next-line eslint-comments/disable-enable-pair
|
|
3
3
|
/* eslint-disable n/shebang */
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
import { catchGlobalErrors } from '@xen-orchestra/log/configure'
|
|
6
|
+
import { createLogger } from '@xen-orchestra/log'
|
|
7
|
+
import { getSyncedHandler } from '@xen-orchestra/fs'
|
|
8
|
+
import { join } from 'node:path'
|
|
9
|
+
import Disposable from 'promise-toolbox/Disposable'
|
|
10
|
+
import min from 'lodash/min.js'
|
|
6
11
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const { getSyncedHandler } = require('@xen-orchestra/fs')
|
|
10
|
-
const { join } = require('path')
|
|
11
|
-
const Disposable = require('promise-toolbox/Disposable')
|
|
12
|
-
const min = require('lodash/min')
|
|
12
|
+
import { getVmBackupDir } from '../_getVmBackupDir.mjs'
|
|
13
|
+
import { RemoteAdapter } from '../RemoteAdapter.mjs'
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
const { RemoteAdapter } = require('../RemoteAdapter.js')
|
|
16
|
-
|
|
17
|
-
const { CLEAN_VM_QUEUE } = require('./index.js')
|
|
15
|
+
import { CLEAN_VM_QUEUE } from './index.mjs'
|
|
18
16
|
|
|
19
17
|
// -------------------------------------------------------------------
|
|
20
18
|
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
import { join } from 'node:path'
|
|
2
|
+
import { spawn } from 'child_process'
|
|
3
|
+
import { check } from 'proper-lockfile'
|
|
2
4
|
|
|
3
|
-
const
|
|
4
|
-
const { spawn } = require('child_process')
|
|
5
|
-
const { check } = require('proper-lockfile')
|
|
5
|
+
export const CLEAN_VM_QUEUE = '/xo-vm-backups/.queue/clean-vm/'
|
|
6
6
|
|
|
7
|
-
const
|
|
7
|
+
const CLI_PATH = new URL('cli.mjs', import.meta.url).pathname
|
|
8
8
|
|
|
9
|
-
const
|
|
10
|
-
exports.run = async function runMergeWorker(remotePath) {
|
|
9
|
+
export const run = async function runMergeWorker(remotePath) {
|
|
11
10
|
try {
|
|
12
11
|
// TODO: find a way to pass the acquire the lock and then pass it down the worker
|
|
13
12
|
if (await check(join(remotePath, CLEAN_VM_QUEUE))) {
|
package/package.json
CHANGED
|
@@ -8,13 +8,13 @@
|
|
|
8
8
|
"type": "git",
|
|
9
9
|
"url": "https://github.com/vatesfr/xen-orchestra.git"
|
|
10
10
|
},
|
|
11
|
-
"version": "0.
|
|
11
|
+
"version": "0.40.0",
|
|
12
12
|
"engines": {
|
|
13
|
-
"node": ">=14.
|
|
13
|
+
"node": ">=14.18"
|
|
14
14
|
},
|
|
15
15
|
"scripts": {
|
|
16
16
|
"postversion": "npm publish --access public",
|
|
17
|
-
"test-integration": "node--test *.integ.
|
|
17
|
+
"test-integration": "node--test *.integ.mjs"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"@kldzj/stream-throttle": "^1.1.1",
|
|
@@ -23,17 +23,16 @@
|
|
|
23
23
|
"@vates/compose": "^2.1.0",
|
|
24
24
|
"@vates/decorate-with": "^2.0.0",
|
|
25
25
|
"@vates/disposable": "^0.1.4",
|
|
26
|
-
"@vates/fuse-vhd": "^
|
|
27
|
-
"@vates/nbd-client": "^
|
|
26
|
+
"@vates/fuse-vhd": "^2.0.0",
|
|
27
|
+
"@vates/nbd-client": "^2.0.0",
|
|
28
28
|
"@vates/parse-duration": "^0.1.1",
|
|
29
29
|
"@xen-orchestra/async-map": "^0.1.2",
|
|
30
|
-
"@xen-orchestra/fs": "^4.0.
|
|
30
|
+
"@xen-orchestra/fs": "^4.0.1",
|
|
31
31
|
"@xen-orchestra/log": "^0.6.0",
|
|
32
32
|
"@xen-orchestra/template": "^0.1.0",
|
|
33
33
|
"compare-versions": "^5.0.1",
|
|
34
34
|
"d3-time-format": "^3.0.0",
|
|
35
35
|
"decorator-synchronized": "^0.6.0",
|
|
36
|
-
"fs-extra": "^11.1.0",
|
|
37
36
|
"golike-defer": "^0.5.1",
|
|
38
37
|
"limit-concurrency-decorator": "^0.5.0",
|
|
39
38
|
"lodash": "^4.17.20",
|
|
@@ -41,18 +40,21 @@
|
|
|
41
40
|
"parse-pairs": "^2.0.0",
|
|
42
41
|
"promise-toolbox": "^0.21.0",
|
|
43
42
|
"proper-lockfile": "^4.1.2",
|
|
43
|
+
"tar": "^6.1.15",
|
|
44
44
|
"uuid": "^9.0.0",
|
|
45
45
|
"vhd-lib": "^4.5.0",
|
|
46
|
+
"xen-api": "^1.3.4",
|
|
46
47
|
"yazl": "^2.5.1"
|
|
47
48
|
},
|
|
48
49
|
"devDependencies": {
|
|
50
|
+
"fs-extra": "^11.1.0",
|
|
49
51
|
"rimraf": "^5.0.1",
|
|
50
52
|
"sinon": "^15.0.1",
|
|
51
53
|
"test": "^3.2.1",
|
|
52
54
|
"tmp": "^0.2.1"
|
|
53
55
|
},
|
|
54
56
|
"peerDependencies": {
|
|
55
|
-
"@xen-orchestra/xapi": "^
|
|
57
|
+
"@xen-orchestra/xapi": "^3.0.0"
|
|
56
58
|
},
|
|
57
59
|
"license": "AGPL-3.0-or-later",
|
|
58
60
|
"author": {
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import { DIR_XO_CONFIG_BACKUPS, DIR_XO_POOL_METADATA_BACKUPS } from './RemoteAdapter.mjs'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
exports.parseMetadataBackupId = function parseMetadataBackupId(backupId) {
|
|
3
|
+
export function parseMetadataBackupId(backupId) {
|
|
6
4
|
const [dir, ...rest] = backupId.split('/')
|
|
7
5
|
if (dir === DIR_XO_CONFIG_BACKUPS) {
|
|
8
6
|
const [scheduleId, timestamp] = rest
|
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const path = require('path')
|
|
4
|
-
const { createLogger } = require('@xen-orchestra/log')
|
|
5
|
-
const { fork } = require('child_process')
|
|
1
|
+
import { createLogger } from '@xen-orchestra/log'
|
|
2
|
+
import { fork } from 'child_process'
|
|
6
3
|
|
|
7
4
|
const { warn } = createLogger('xo:backups:backupWorker')
|
|
8
5
|
|
|
9
|
-
const PATH =
|
|
6
|
+
const PATH = new URL('_backupWorker.mjs', import.meta.url).pathname
|
|
10
7
|
|
|
11
|
-
|
|
8
|
+
export function runBackupWorker(params, onLog) {
|
|
12
9
|
return new Promise((resolve, reject) => {
|
|
13
10
|
const worker = fork(PATH)
|
|
14
11
|
|
package/_backupType.js
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
exports.isMetadataFile = filename => filename.endsWith('.json')
|
|
4
|
-
exports.isVhdFile = filename => filename.endsWith('.vhd')
|
|
5
|
-
exports.isXvaFile = filename => filename.endsWith('.xva')
|
|
6
|
-
exports.isXvaSumFile = filename => filename.endsWith('.xva.checksum')
|
package/_filenameDate.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { utcFormat, utcParse } = require('d3-time-format')
|
|
4
|
-
|
|
5
|
-
// Format a date in ISO 8601 in a safe way to be used in filenames
|
|
6
|
-
// (even on Windows).
|
|
7
|
-
exports.formatFilenameDate = utcFormat('%Y%m%dT%H%M%SZ')
|
|
8
|
-
exports.parseFilenameDate = utcParse('%Y%m%dT%H%M%SZ')
|
package/_getVmBackupDir.js
DELETED
package/_runners/_runTask.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { mapValues } = require('lodash')
|
|
4
|
-
const { forkStreamUnpipe } = require('../_forkStreamUnpipe')
|
|
5
|
-
|
|
6
|
-
exports.forkDeltaExport = function forkDeltaExport(deltaExport) {
|
|
7
|
-
return Object.create(deltaExport, {
|
|
8
|
-
streams: {
|
|
9
|
-
value: mapValues(deltaExport.streams, forkStreamUnpipe),
|
|
10
|
-
},
|
|
11
|
-
})
|
|
12
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { extractOpaqueRef } = require('@xen-orchestra/xapi')
|
|
4
|
-
|
|
5
|
-
const { Task } = require('../../Task')
|
|
6
|
-
const assert = require('node:assert/strict')
|
|
7
|
-
const { HealthCheckVmBackup } = require('../../HealthCheckVmBackup')
|
|
8
|
-
|
|
9
|
-
exports.MixinXapiWriter = (BaseClass = Object) =>
|
|
10
|
-
class MixinXapiWriter extends BaseClass {
|
|
11
|
-
constructor({ sr, ...rest }) {
|
|
12
|
-
super(rest)
|
|
13
|
-
|
|
14
|
-
this._sr = sr
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
healthCheck() {
|
|
18
|
-
const sr = this._healthCheckSr
|
|
19
|
-
assert.notStrictEqual(sr, undefined, 'SR should be defined before making a health check')
|
|
20
|
-
assert.notEqual(this._targetVmRef, undefined, 'A vm should have been transfered to be health checked')
|
|
21
|
-
// copy VM
|
|
22
|
-
return Task.run(
|
|
23
|
-
{
|
|
24
|
-
name: 'health check',
|
|
25
|
-
},
|
|
26
|
-
async () => {
|
|
27
|
-
const { $xapi: xapi } = sr
|
|
28
|
-
let clonedVm
|
|
29
|
-
try {
|
|
30
|
-
const baseVm = xapi.getObject(this._targetVmRef) ?? (await xapi.waitObject(this._targetVmRef))
|
|
31
|
-
const clonedRef = await xapi
|
|
32
|
-
.callAsync('VM.clone', this._targetVmRef, `Health Check - ${baseVm.name_label}`)
|
|
33
|
-
.then(extractOpaqueRef)
|
|
34
|
-
clonedVm = xapi.getObject(clonedRef) ?? (await xapi.waitObject(clonedRef))
|
|
35
|
-
|
|
36
|
-
await new HealthCheckVmBackup({
|
|
37
|
-
restoredVm: clonedVm,
|
|
38
|
-
xapi,
|
|
39
|
-
}).run()
|
|
40
|
-
} finally {
|
|
41
|
-
clonedVm && (await xapi.VM_destroy(clonedVm.$ref))
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
)
|
|
45
|
-
}
|
|
46
|
-
}
|