@xen-orchestra/backups 0.39.0 → 0.41.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 (67) 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.mjs +32 -0
  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} +13 -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} +14 -10
  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} +22 -24
  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.js → _MixinXapiWriter.mjs} +6 -8
  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.mjs +103 -0
  55. package/merge-worker/config.toml +1 -0
  56. package/merge-worker/{index.js → index.mjs} +6 -7
  57. package/package.json +12 -9
  58. package/{parseMetadataBackupId.js → parseMetadataBackupId.mjs} +2 -4
  59. package/{runBackupWorker.js → runBackupWorker.mjs} +4 -7
  60. package/RestoreMetadataBackup.js +0 -29
  61. package/_backupType.js +0 -6
  62. package/_filenameDate.js +0 -8
  63. package/_getVmBackupDir.js +0 -8
  64. package/_runners/_runTask.js +0 -6
  65. package/_runners/_vmRunners/_forkDeltaExport.js +0 -12
  66. package/_runners/_writers/_checkVhd.js +0 -8
  67. package/merge-worker/cli.js +0 -92
@@ -1,29 +1,27 @@
1
- 'use strict'
2
-
3
- const assert = require('assert')
4
- const mapValues = require('lodash/mapValues.js')
5
- const ignoreErrors = require('promise-toolbox/ignoreErrors')
6
- const { asyncEach } = require('@vates/async-each')
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
@@ -238,6 +236,6 @@ class IncrementalRemoteWriter extends MixinRemoteWriter(AbstractIncrementalWrite
238
236
  // TODO: run cleanup?
239
237
  }
240
238
  }
241
- exports.IncrementalRemoteWriter = decorateClass(IncrementalRemoteWriter, {
239
+ decorateClass(IncrementalRemoteWriter, {
242
240
  _transfer: defer,
243
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
 
@@ -1,12 +1,10 @@
1
- 'use strict'
1
+ import { extractOpaqueRef } from '@xen-orchestra/xapi'
2
+ import assert from 'node:assert/strict'
2
3
 
3
- const { extractOpaqueRef } = require('@xen-orchestra/xapi')
4
+ import { HealthCheckVmBackup } from '../../HealthCheckVmBackup.mjs'
5
+ import { Task } from '../../Task.mjs'
4
6
 
5
- const { Task } = require('../../Task')
6
- const assert = require('node:assert/strict')
7
- const { HealthCheckVmBackup } = require('../../HealthCheckVmBackup')
8
-
9
- exports.MixinXapiWriter = (BaseClass = Object) =>
7
+ export const MixinXapiWriter = (BaseClass = Object) =>
10
8
  class MixinXapiWriter extends BaseClass {
11
9
  constructor({ sr, ...rest }) {
12
10
  super(rest)
@@ -20,7 +18,7 @@ exports.MixinXapiWriter = (BaseClass = Object) =>
20
18
  const vdiRefs = await xapi.VM_getDisks(baseVm.$ref)
21
19
  for (const vdiRef of vdiRefs) {
22
20
  const vdi = xapi.getObject(vdiRef)
23
- if (vdi.$SR.uuid !== this._heathCheckSr.uuid) {
21
+ if (vdi.$SR.uuid !== this._healthCheckSr.uuid) {
24
22
  return false
25
23
  }
26
24
  }
@@ -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
  }
@@ -0,0 +1,103 @@
1
+ #!/usr/bin/env node
2
+ // eslint-disable-next-line eslint-comments/disable-enable-pair
3
+ /* eslint-disable n/shebang */
4
+
5
+ import { asyncEach } from '@vates/async-each'
6
+ import { catchGlobalErrors } from '@xen-orchestra/log/configure'
7
+ import { createLogger } from '@xen-orchestra/log'
8
+ import { getSyncedHandler } from '@xen-orchestra/fs'
9
+ import { join } from 'node:path'
10
+ import { load as loadConfig } from 'app-conf'
11
+ import Disposable from 'promise-toolbox/Disposable'
12
+
13
+ import { getVmBackupDir } from '../_getVmBackupDir.mjs'
14
+ import { RemoteAdapter } from '../RemoteAdapter.mjs'
15
+
16
+ import { CLEAN_VM_QUEUE } from './index.mjs'
17
+
18
+ const APP_NAME = 'xo-merge-worker'
19
+ const APP_DIR = new URL('.', import.meta.url).pathname
20
+ // -------------------------------------------------------------------
21
+
22
+ catchGlobalErrors(createLogger('xo:backups:mergeWorker'))
23
+
24
+ const { fatal, info, warn } = createLogger('xo:backups:mergeWorker')
25
+
26
+ // -------------------------------------------------------------------
27
+
28
+ const main = Disposable.wrap(async function* main(args) {
29
+ const handler = yield getSyncedHandler({ url: 'file://' + process.cwd() })
30
+
31
+ yield handler.lock(CLEAN_VM_QUEUE)
32
+
33
+ const adapter = new RemoteAdapter(handler)
34
+
35
+ const listRetry = async () => {
36
+ const timeoutResolver = resolve => setTimeout(resolve, 10e3)
37
+ for (let i = 0; i < 10; ++i) {
38
+ const entries = await handler.list(CLEAN_VM_QUEUE)
39
+ if (entries.length !== 0) {
40
+ entries.sort()
41
+ return entries
42
+ }
43
+ await new Promise(timeoutResolver)
44
+ }
45
+ }
46
+
47
+ let taskFiles
48
+ while ((taskFiles = await listRetry()) !== undefined) {
49
+ const { concurrency } = await loadConfig(APP_NAME, {
50
+ appDir: APP_DIR,
51
+ ignoreUnknownFormats: true,
52
+ })
53
+ await asyncEach(
54
+ taskFiles,
55
+ async taskFileBasename => {
56
+ const previousTaskFile = join(CLEAN_VM_QUEUE, taskFileBasename)
57
+ const taskFile = join(CLEAN_VM_QUEUE, '_' + taskFileBasename)
58
+
59
+ // move this task to the end
60
+ try {
61
+ await handler.rename(previousTaskFile, taskFile)
62
+ } catch (error) {
63
+ // this error occurs if the task failed too many times (i.e. too many `_` prefixes)
64
+ // there is nothing more that can be done
65
+ if (error.code === 'ENAMETOOLONG') {
66
+ await handler.unlink(previousTaskFile)
67
+ }
68
+
69
+ throw error
70
+ }
71
+
72
+ try {
73
+ const vmDir = getVmBackupDir(String(await handler.readFile(taskFile)))
74
+ try {
75
+ await adapter.cleanVm(vmDir, { merge: true, logInfo: info, logWarn: warn, remove: true })
76
+ } catch (error) {
77
+ // consider the clean successful if the VM dir is missing
78
+ if (error.code !== 'ENOENT') {
79
+ throw error
80
+ }
81
+ }
82
+
83
+ handler.unlink(taskFile).catch(error => warn('deleting task failure', { error }))
84
+ } catch (error) {
85
+ warn('failure handling task', { error })
86
+ }
87
+ },
88
+ { concurrency }
89
+ )
90
+ }
91
+ })
92
+
93
+ info('starting')
94
+ main(process.argv.slice(2)).then(
95
+ () => {
96
+ info('bye :-)')
97
+ },
98
+ error => {
99
+ fatal(error)
100
+
101
+ process.exit(1)
102
+ }
103
+ )
@@ -0,0 +1 @@
1
+ concurrency = 1
@@ -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,32 +8,33 @@
8
8
  "type": "git",
9
9
  "url": "https://github.com/vatesfr/xen-orchestra.git"
10
10
  },
11
- "version": "0.39.0",
11
+ "version": "0.41.0",
12
12
  "engines": {
13
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
+ "@iarna/toml": "^2.2.5",
20
21
  "@kldzj/stream-throttle": "^1.1.1",
21
22
  "@vates/async-each": "^1.0.0",
22
23
  "@vates/cached-dns.lookup": "^1.0.0",
23
24
  "@vates/compose": "^2.1.0",
24
25
  "@vates/decorate-with": "^2.0.0",
25
26
  "@vates/disposable": "^0.1.4",
26
- "@vates/fuse-vhd": "^1.0.0",
27
- "@vates/nbd-client": "^1.2.1",
27
+ "@vates/fuse-vhd": "^2.0.0",
28
+ "@vates/nbd-client": "^2.0.0",
28
29
  "@vates/parse-duration": "^0.1.1",
29
30
  "@xen-orchestra/async-map": "^0.1.2",
30
31
  "@xen-orchestra/fs": "^4.0.1",
31
32
  "@xen-orchestra/log": "^0.6.0",
32
33
  "@xen-orchestra/template": "^0.1.0",
33
- "compare-versions": "^5.0.1",
34
- "d3-time-format": "^3.0.0",
34
+ "app-conf": "^2.3.0",
35
+ "compare-versions": "^6.0.0",
36
+ "d3-time-format": "^4.1.0",
35
37
  "decorator-synchronized": "^0.6.0",
36
- "fs-extra": "^11.1.0",
37
38
  "golike-defer": "^0.5.1",
38
39
  "limit-concurrency-decorator": "^0.5.0",
39
40
  "lodash": "^4.17.20",
@@ -41,19 +42,21 @@
41
42
  "parse-pairs": "^2.0.0",
42
43
  "promise-toolbox": "^0.21.0",
43
44
  "proper-lockfile": "^4.1.2",
45
+ "tar": "^6.1.15",
44
46
  "uuid": "^9.0.0",
45
47
  "vhd-lib": "^4.5.0",
46
- "xen-api": "^1.3.3",
48
+ "xen-api": "^1.3.5",
47
49
  "yazl": "^2.5.1"
48
50
  },
49
51
  "devDependencies": {
52
+ "fs-extra": "^11.1.0",
50
53
  "rimraf": "^5.0.1",
51
54
  "sinon": "^15.0.1",
52
55
  "test": "^3.2.1",
53
56
  "tmp": "^0.2.1"
54
57
  },
55
58
  "peerDependencies": {
56
- "@xen-orchestra/xapi": "^2.2.1"
59
+ "@xen-orchestra/xapi": "^3.0.1"
57
60
  },
58
61
  "license": "AGPL-3.0-or-later",
59
62
  "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
 
@@ -1,29 +0,0 @@
1
- 'use strict'
2
-
3
- const { join, resolve } = require('node:path/posix')
4
-
5
- const { DIR_XO_POOL_METADATA_BACKUPS } = require('./RemoteAdapter.js')
6
- const { PATH_DB_DUMP } = require('./_runners/_PoolMetadataBackup.js')
7
-
8
- exports.RestoreMetadataBackup = class RestoreMetadataBackup {
9
- constructor({ backupId, handler, xapi }) {
10
- this._backupId = backupId
11
- this._handler = handler
12
- this._xapi = xapi
13
- }
14
-
15
- async run() {
16
- const backupId = this._backupId
17
- const handler = this._handler
18
- const xapi = this._xapi
19
-
20
- if (backupId.split('/')[0] === DIR_XO_POOL_METADATA_BACKUPS) {
21
- return xapi.putResource(await handler.createReadStream(`${backupId}/data`), PATH_DB_DUMP, {
22
- task: xapi.task_create('Import pool metadata'),
23
- })
24
- } else {
25
- const metadata = JSON.parse(await handler.readFile(join(backupId, 'metadata.json')))
26
- return String(await handler.readFile(resolve(backupId, metadata.data ?? 'data.json')))
27
- }
28
- }
29
- }
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,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
- }