@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.
Files changed (65) hide show
  1. package/{Backup.js → Backup.mjs} +4 -6
  2. package/{DurablePartition.js → DurablePartition.mjs} +2 -4
  3. package/{HealthCheckVmBackup.js → HealthCheckVmBackup.mjs} +2 -4
  4. package/{ImportVmBackup.js → ImportVmBackup.mjs} +6 -8
  5. package/{RemoteAdapter.js → RemoteAdapter.mjs} +69 -76
  6. package/{RestoreMetadataBackup.js → RestoreMetadataBackup.mjs} +6 -5
  7. package/{Task.js → Task.mjs} +3 -6
  8. package/_backupType.mjs +4 -0
  9. package/{_backupWorker.js → _backupWorker.mjs} +22 -22
  10. package/{_cancelableMap.js → _cancelableMap.mjs} +3 -5
  11. package/{_cleanVm.js → _cleanVm.mjs} +16 -19
  12. package/_filenameDate.mjs +6 -0
  13. package/{_getOldEntries.js → _getOldEntries.mjs} +1 -3
  14. package/{_getTmpDir.js → _getTmpDir.mjs} +5 -7
  15. package/_getVmBackupDir.mjs +5 -0
  16. package/{_incrementalVm.js → _incrementalVm.mjs} +21 -20
  17. package/{_isValidXva.js → _isValidXva.mjs} +2 -5
  18. package/{_listPartitions.js → _listPartitions.mjs} +6 -9
  19. package/{_lvm.js → _lvm.mjs} +5 -7
  20. package/_runners/{Metadata.js → Metadata.mjs} +10 -12
  21. package/_runners/{VmsRemote.js → VmsRemote.mjs} +12 -14
  22. package/_runners/{VmsXapi.js → VmsXapi.mjs} +14 -15
  23. package/_runners/{_Abstract.js → _Abstract.mjs} +7 -9
  24. package/_runners/{_PoolMetadataBackup.js → _PoolMetadataBackup.mjs} +7 -10
  25. package/_runners/{_RemoteTimeoutError.js → _RemoteTimeoutError.mjs} +1 -3
  26. package/_runners/{_XoMetadataBackup.js → _XoMetadataBackup.mjs} +11 -9
  27. package/_runners/{_createStreamThrottle.js → _createStreamThrottle.mjs} +4 -6
  28. package/_runners/{_forkStreamUnpipe.js → _forkStreamUnpipe.mjs} +4 -5
  29. package/_runners/{_getAdaptersByRemote.js → _getAdaptersByRemote.mjs} +1 -3
  30. package/_runners/_runTask.mjs +5 -0
  31. package/_runners/_vmRunners/{FullRemote.js → FullRemote.mjs} +9 -12
  32. package/_runners/_vmRunners/{FullXapi.js → FullXapi.mjs} +7 -9
  33. package/_runners/_vmRunners/{IncrementalRemote.js → IncrementalRemote.mjs} +11 -12
  34. package/_runners/_vmRunners/{IncrementalXapi.js → IncrementalXapi.mjs} +18 -20
  35. package/_runners/_vmRunners/{_Abstract.js → _Abstract.mjs} +4 -6
  36. package/_runners/_vmRunners/{_AbstractRemote.js → _AbstractRemote.mjs} +6 -6
  37. package/_runners/_vmRunners/{_AbstractXapi.js → _AbstractXapi.mjs} +14 -17
  38. package/_runners/_vmRunners/_forkDeltaExport.mjs +11 -0
  39. package/_runners/_writers/{FullRemoteWriter.js → FullRemoteWriter.mjs} +6 -8
  40. package/_runners/_writers/{FullXapiWriter.js → FullXapiWriter.mjs} +10 -12
  41. package/_runners/_writers/{IncrementalRemoteWriter.js → IncrementalRemoteWriter.mjs} +31 -28
  42. package/_runners/_writers/{IncrementalXapiWriter.js → IncrementalXapiWriter.mjs} +11 -13
  43. package/_runners/_writers/{_AbstractFullWriter.js → _AbstractFullWriter.mjs} +2 -4
  44. package/_runners/_writers/{_AbstractIncrementalWriter.js → _AbstractIncrementalWriter.mjs} +2 -4
  45. package/_runners/_writers/{_AbstractWriter.js → _AbstractWriter.mjs} +3 -5
  46. package/_runners/_writers/{_MixinRemoteWriter.js → _MixinRemoteWriter.mjs} +10 -12
  47. package/_runners/_writers/_MixinXapiWriter.mjs +72 -0
  48. package/_runners/_writers/_checkVhd.mjs +6 -0
  49. package/_runners/_writers/{_listReplicatedVms.js → _listReplicatedVms.mjs} +1 -3
  50. package/_runners/_writers/{_packUuid.js → _packUuid.mjs} +1 -3
  51. package/{_watchStreamSize.js → _watchStreamSize.mjs} +1 -3
  52. package/{extractIdsFromSimplePattern.js → extractIdsFromSimplePattern.mjs} +1 -3
  53. package/{formatVmBackups.js → formatVmBackups.mjs} +3 -5
  54. package/merge-worker/{cli.js → cli.mjs} +9 -11
  55. package/merge-worker/{index.js → index.mjs} +6 -7
  56. package/package.json +10 -8
  57. package/{parseMetadataBackupId.js → parseMetadataBackupId.mjs} +2 -4
  58. package/{runBackupWorker.js → runBackupWorker.mjs} +4 -7
  59. package/_backupType.js +0 -6
  60. package/_filenameDate.js +0 -8
  61. package/_getVmBackupDir.js +0 -8
  62. package/_runners/_runTask.js +0 -6
  63. package/_runners/_vmRunners/_forkDeltaExport.js +0 -12
  64. package/_runners/_writers/_MixinXapiWriter.js +0 -46
  65. package/_runners/_writers/_checkVhd.js +0 -8
@@ -1,29 +1,27 @@
1
- 'use strict'
2
-
3
- const assert = require('assert')
4
- const map = require('lodash/map.js')
5
- const mapValues = require('lodash/mapValues.js')
6
- const ignoreErrors = require('promise-toolbox/ignoreErrors')
7
- const { asyncMap } = require('@xen-orchestra/async-map')
8
- const { chainVhd, checkVhdChain, openVhd, VhdAbstract } = require('vhd-lib')
9
- const { createLogger } = require('@xen-orchestra/log')
10
- const { decorateClass } = require('@vates/decorate-with')
11
- const { defer } = require('golike-defer')
12
- const { dirname } = require('path')
13
-
14
- const { formatFilenameDate } = require('../../_filenameDate.js')
15
- const { getOldEntries } = require('../../_getOldEntries.js')
16
- const { Task } = require('../../Task.js')
17
-
18
- const { MixinRemoteWriter } = require('./_MixinRemoteWriter.js')
19
- const { AbstractIncrementalWriter } = require('./_AbstractIncrementalWriter.js')
20
- const { checkVhd } = require('./_checkVhd.js')
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 Promise.all(
180
- map(deltaExport.vdis, async (vdi, id) => {
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
- exports.IncrementalRemoteWriter = decorateClass(IncrementalRemoteWriter, {
239
+ decorateClass(IncrementalRemoteWriter, {
237
240
  _transfer: defer,
238
241
  })
@@ -1,19 +1,17 @@
1
- 'use strict'
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
- const { asyncMap, asyncMapSettled } = require('@xen-orchestra/async-map')
4
- const ignoreErrors = require('promise-toolbox/ignoreErrors')
5
- const { formatDateTime } = require('@xen-orchestra/xapi')
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
- const { formatFilenameDate } = require('../../_filenameDate.js')
8
- const { getOldEntries } = require('../../_getOldEntries.js')
9
- const { importIncrementalVm, TAG_COPY_SRC } = require('../../_incrementalVm.js')
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
- const { AbstractIncrementalWriter } = require('./_AbstractIncrementalWriter.js')
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
- 'use strict'
1
+ import { AbstractWriter } from './_AbstractWriter.mjs'
2
2
 
3
- const { AbstractWriter } = require('./_AbstractWriter.js')
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
- 'use strict'
1
+ import { AbstractWriter } from './_AbstractWriter.mjs'
2
2
 
3
- const { AbstractWriter } = require('./_AbstractWriter.js')
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
- 'use strict'
1
+ import { formatFilenameDate } from '../../_filenameDate.mjs'
2
+ import { getVmBackupDir } from '../../_getVmBackupDir.mjs'
2
3
 
3
- const { formatFilenameDate } = require('../../_filenameDate')
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
- 'use strict'
1
+ import { createLogger } from '@xen-orchestra/log'
2
+ import { join } from 'node:path'
3
+ import assert from 'node:assert'
2
4
 
3
- const { createLogger } = require('@xen-orchestra/log')
4
- const { join } = require('path')
5
-
6
- const assert = require('assert')
7
- const { formatFilenameDate } = require('../../_filenameDate.js')
8
- const { getVmBackupDir } = require('../../_getVmBackupDir.js')
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
- exports.MixinRemoteWriter = (BaseClass = Object) =>
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
+ }
@@ -0,0 +1,6 @@
1
+ import { openVhd } from 'vhd-lib'
2
+ import Disposable from 'promise-toolbox/Disposable'
3
+
4
+ export async function checkVhd(handler, path) {
5
+ await Disposable.use(openVhd(handler, path), () => {})
6
+ }
@@ -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
- exports.listReplicatedVms = function listReplicatedVms(xapi, scheduleOrJobId, srUuid, vmUuid) {
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
- 'use strict'
2
-
3
1
  const PARSE_UUID_RE = /-/g
4
2
 
5
- exports.packUuid = function packUuid(uuid) {
3
+ export function packUuid(uuid) {
6
4
  return Buffer.from(uuid.replace(PARSE_UUID_RE, ''), 'hex')
7
5
  }
@@ -1,6 +1,4 @@
1
- 'use strict'
2
-
3
- exports.watchStreamSize = function watchStreamSize(stream, container = { size: 0 }) {
1
+ export function watchStreamSize(stream, container = { size: 0 }) {
4
2
  stream.on('data', data => {
5
3
  container.size += data.length
6
4
  })
@@ -1,6 +1,4 @@
1
- 'use strict'
2
-
3
- exports.extractIdsFromSimplePattern = function extractIdsFromSimplePattern(pattern) {
1
+ export function extractIdsFromSimplePattern(pattern) {
4
2
  if (pattern === undefined) {
5
3
  return []
6
4
  }
@@ -1,7 +1,5 @@
1
- 'use strict'
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
- exports.formatVmBackups = function formatVmBackups(backupsByVM) {
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
- 'use strict'
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
- const { catchGlobalErrors } = require('@xen-orchestra/log/configure')
8
- const { createLogger } = require('@xen-orchestra/log')
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
- const { getVmBackupDir } = require('../_getVmBackupDir.js')
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
- 'use strict'
1
+ import { join } from 'node:path'
2
+ import { spawn } from 'child_process'
3
+ import { check } from 'proper-lockfile'
2
4
 
3
- const { join, resolve } = require('path')
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 CLEAN_VM_QUEUE = (exports.CLEAN_VM_QUEUE = '/xo-vm-backups/.queue/clean-vm/')
7
+ const CLI_PATH = new URL('cli.mjs', import.meta.url).pathname
8
8
 
9
- const CLI_PATH = resolve(__dirname, 'cli.js')
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.38.3",
11
+ "version": "0.40.0",
12
12
  "engines": {
13
- "node": ">=14.6"
13
+ "node": ">=14.18"
14
14
  },
15
15
  "scripts": {
16
16
  "postversion": "npm publish --access public",
17
- "test-integration": "node--test *.integ.js"
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": "^1.0.0",
27
- "@vates/nbd-client": "^1.2.0",
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.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": "^2.2.1"
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
- 'use strict'
1
+ import { DIR_XO_CONFIG_BACKUPS, DIR_XO_POOL_METADATA_BACKUPS } from './RemoteAdapter.mjs'
2
2
 
3
- const { DIR_XO_CONFIG_BACKUPS, DIR_XO_POOL_METADATA_BACKUPS } = require('./RemoteAdapter.js')
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
- 'use strict'
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 = path.resolve(__dirname, '_backupWorker.js')
6
+ const PATH = new URL('_backupWorker.mjs', import.meta.url).pathname
10
7
 
11
- exports.runBackupWorker = function runBackupWorker(params, onLog) {
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')
@@ -1,8 +0,0 @@
1
- 'use strict'
2
-
3
- const BACKUP_DIR = 'xo-vm-backups'
4
- exports.BACKUP_DIR = BACKUP_DIR
5
-
6
- exports.getVmBackupDir = function getVmBackupDir(uuid) {
7
- return `${BACKUP_DIR}/${uuid}`
8
- }
@@ -1,6 +0,0 @@
1
- 'use strict'
2
- const { Task } = require('../Task.js')
3
- const noop = Function.prototype
4
- const runTask = (...args) => Task.run(...args).catch(noop) // errors are handled by logs
5
-
6
- exports.runTask = runTask
@@ -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
- }
@@ -1,8 +0,0 @@
1
- 'use strict'
2
-
3
- const openVhd = require('vhd-lib').openVhd
4
- const Disposable = require('promise-toolbox/Disposable')
5
-
6
- exports.checkVhd = async function checkVhd(handler, path) {
7
- await Disposable.use(openVhd(handler, path), () => {})
8
- }