@xen-orchestra/backups 0.36.1 → 0.38.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 (40) hide show
  1. package/Backup.js +14 -302
  2. package/ImportVmBackup.js +6 -6
  3. package/RemoteAdapter.js +20 -13
  4. package/RestoreMetadataBackup.js +1 -1
  5. package/_backupWorker.js +2 -2
  6. package/{_deltaVm.js → _incrementalVm.js} +11 -11
  7. package/_runners/Metadata.js +134 -0
  8. package/_runners/VmsRemote.js +98 -0
  9. package/_runners/VmsXapi.js +138 -0
  10. package/_runners/_Abstract.js +51 -0
  11. package/{_PoolMetadataBackup.js → _runners/_PoolMetadataBackup.js} +3 -3
  12. package/_runners/_RemoteTimeoutError.js +8 -0
  13. package/{_XoMetadataBackup.js → _runners/_XoMetadataBackup.js} +3 -3
  14. package/_runners/_getAdaptersByRemote.js +9 -0
  15. package/_runners/_runTask.js +6 -0
  16. package/_runners/_vmRunners/FullRemote.js +53 -0
  17. package/_runners/_vmRunners/FullXapi.js +65 -0
  18. package/_runners/_vmRunners/IncrementalRemote.js +67 -0
  19. package/_runners/_vmRunners/IncrementalXapi.js +175 -0
  20. package/_runners/_vmRunners/_Abstract.js +95 -0
  21. package/_runners/_vmRunners/_AbstractRemote.js +86 -0
  22. package/_runners/_vmRunners/_AbstractXapi.js +257 -0
  23. package/_runners/_vmRunners/_forkDeltaExport.js +12 -0
  24. package/{writers/FullBackupWriter.js → _runners/_writers/FullRemoteWriter.js} +15 -13
  25. package/{writers/FullReplicationWriter.js → _runners/_writers/FullXapiWriter.js} +8 -7
  26. package/{writers/DeltaBackupWriter.js → _runners/_writers/IncrementalRemoteWriter.js} +28 -22
  27. package/{writers/DeltaReplicationWriter.js → _runners/_writers/IncrementalXapiWriter.js} +19 -16
  28. package/{writers → _runners/_writers}/_AbstractFullWriter.js +2 -2
  29. package/{writers/_AbstractDeltaWriter.js → _runners/_writers/_AbstractIncrementalWriter.js} +3 -3
  30. package/_runners/_writers/_AbstractWriter.js +31 -0
  31. package/{writers/_MixinBackupWriter.js → _runners/_writers/_MixinRemoteWriter.js} +30 -16
  32. package/{writers/_MixinReplicationWriter.js → _runners/_writers/_MixinXapiWriter.js} +9 -13
  33. package/package.json +5 -5
  34. package/_VmBackup.js +0 -515
  35. package/writers/_AbstractWriter.js +0 -14
  36. /package/{_createStreamThrottle.js → _runners/_createStreamThrottle.js} +0 -0
  37. /package/{_forkStreamUnpipe.js → _runners/_forkStreamUnpipe.js} +0 -0
  38. /package/{writers → _runners/_writers}/_checkVhd.js +0 -0
  39. /package/{writers → _runners/_writers}/_listReplicatedVms.js +0 -0
  40. /package/{writers → _runners/_writers}/_packUuid.js +0 -0
@@ -4,15 +4,15 @@ const ignoreErrors = require('promise-toolbox/ignoreErrors')
4
4
  const { asyncMap, asyncMapSettled } = require('@xen-orchestra/async-map')
5
5
  const { formatDateTime } = require('@xen-orchestra/xapi')
6
6
 
7
- const { formatFilenameDate } = require('../_filenameDate.js')
8
- const { getOldEntries } = require('../_getOldEntries.js')
9
- const { Task } = require('../Task.js')
7
+ const { formatFilenameDate } = require('../../_filenameDate.js')
8
+ const { getOldEntries } = require('../../_getOldEntries.js')
9
+ const { Task } = require('../../Task.js')
10
10
 
11
11
  const { AbstractFullWriter } = require('./_AbstractFullWriter.js')
12
- const { MixinReplicationWriter } = require('./_MixinReplicationWriter.js')
12
+ const { MixinXapiWriter } = require('./_MixinXapiWriter.js')
13
13
  const { listReplicatedVms } = require('./_listReplicatedVms.js')
14
14
 
15
- exports.FullReplicationWriter = class FullReplicationWriter extends MixinReplicationWriter(AbstractFullWriter) {
15
+ exports.FullXapiWriter = class FullXapiWriter extends MixinXapiWriter(AbstractFullWriter) {
16
16
  constructor(props) {
17
17
  super(props)
18
18
 
@@ -32,10 +32,11 @@ exports.FullReplicationWriter = class FullReplicationWriter extends MixinReplica
32
32
  )
33
33
  }
34
34
 
35
- async _run({ timestamp, sizeContainer, stream }) {
35
+ async _run({ timestamp, sizeContainer, stream, vm }) {
36
36
  const sr = this._sr
37
37
  const settings = this._settings
38
- const { job, scheduleId, vm } = this._backup
38
+ const job = this._job
39
+ const scheduleId = this.scheduleId
39
40
 
40
41
  const { uuid: srUuid, $xapi: xapi } = sr
41
42
 
@@ -11,25 +11,24 @@ const { decorateClass } = require('@vates/decorate-with')
11
11
  const { defer } = require('golike-defer')
12
12
  const { dirname } = require('path')
13
13
 
14
- const { formatFilenameDate } = require('../_filenameDate.js')
15
- const { getOldEntries } = require('../_getOldEntries.js')
16
- const { Task } = require('../Task.js')
14
+ const { formatFilenameDate } = require('../../_filenameDate.js')
15
+ const { getOldEntries } = require('../../_getOldEntries.js')
16
+ const { Task } = require('../../Task.js')
17
17
 
18
- const { MixinBackupWriter } = require('./_MixinBackupWriter.js')
19
- const { AbstractDeltaWriter } = require('./_AbstractDeltaWriter.js')
18
+ const { MixinRemoteWriter } = require('./_MixinRemoteWriter.js')
19
+ const { AbstractIncrementalWriter } = require('./_AbstractIncrementalWriter.js')
20
20
  const { checkVhd } = require('./_checkVhd.js')
21
21
  const { packUuid } = require('./_packUuid.js')
22
22
  const { Disposable } = require('promise-toolbox')
23
23
 
24
24
  const { warn } = createLogger('xo:backups:DeltaBackupWriter')
25
25
 
26
- class DeltaBackupWriter extends MixinBackupWriter(AbstractDeltaWriter) {
26
+ class IncrementalRemoteWriter extends MixinRemoteWriter(AbstractIncrementalWriter) {
27
27
  async checkBaseVdis(baseUuidToSrcVdi) {
28
28
  const { handler } = this._adapter
29
- const backup = this._backup
30
29
  const adapter = this._adapter
31
30
 
32
- const vdisDir = `${this._vmBackupDir}/vdis/${backup.job.id}`
31
+ const vdisDir = `${this._vmBackupDir}/vdis/${this._job.id}`
33
32
 
34
33
  await asyncMap(baseUuidToSrcVdi, async ([baseUuid, srcVdi]) => {
35
34
  let found = false
@@ -91,11 +90,12 @@ class DeltaBackupWriter extends MixinBackupWriter(AbstractDeltaWriter) {
91
90
  async _prepare() {
92
91
  const adapter = this._adapter
93
92
  const settings = this._settings
94
- const { scheduleId, vm } = this._backup
93
+ const scheduleId = this._scheduleId
94
+ const vmUuid = this._vmUuid
95
95
 
96
96
  const oldEntries = getOldEntries(
97
97
  settings.exportRetention - 1,
98
- await adapter.listVmBackups(vm.uuid, _ => _.mode === 'delta' && _.scheduleId === scheduleId)
98
+ await adapter.listVmBackups(vmUuid, _ => _.mode === 'delta' && _.scheduleId === scheduleId)
99
99
  )
100
100
  this._oldEntries = oldEntries
101
101
 
@@ -134,16 +134,19 @@ class DeltaBackupWriter extends MixinBackupWriter(AbstractDeltaWriter) {
134
134
  }
135
135
  }
136
136
 
137
- async _transfer($defer, { timestamp, deltaExport }) {
137
+ async _transfer($defer, { differentialVhds, timestamp, deltaExport, vm, vmSnapshot }) {
138
138
  const adapter = this._adapter
139
- const backup = this._backup
140
-
141
- const { job, scheduleId, vm } = backup
139
+ const job = this._job
140
+ const scheduleId = this._scheduleId
142
141
 
143
142
  const jobId = job.id
144
143
  const handler = adapter.handler
145
144
 
146
- // TODO: clean VM backup directory
145
+ let metadataContent = await this._isAlreadyTransferred(timestamp)
146
+ if (metadataContent !== undefined) {
147
+ // @todo : should skip backup while being vigilant to not stuck the forked stream
148
+ Task.info('This backup has already been transfered')
149
+ }
147
150
 
148
151
  const basename = formatFilenameDate(timestamp)
149
152
  const vhds = mapValues(
@@ -158,7 +161,7 @@ class DeltaBackupWriter extends MixinBackupWriter(AbstractDeltaWriter) {
158
161
  }/${adapter.getVhdFileName(basename)}`
159
162
  )
160
163
 
161
- const metadataContent = {
164
+ metadataContent = {
162
165
  jobId,
163
166
  mode: job.mode,
164
167
  scheduleId,
@@ -169,16 +172,15 @@ class DeltaBackupWriter extends MixinBackupWriter(AbstractDeltaWriter) {
169
172
  vifs: deltaExport.vifs,
170
173
  vhds,
171
174
  vm,
172
- vmSnapshot: this._backup.exportedVm,
175
+ vmSnapshot,
173
176
  }
174
-
175
177
  const { size } = await Task.run({ name: 'transfer' }, async () => {
176
178
  let transferSize = 0
177
179
  await Promise.all(
178
180
  map(deltaExport.vdis, async (vdi, id) => {
179
181
  const path = `${this._vmBackupDir}/${vhds[id]}`
180
182
 
181
- const isDelta = vdi.other_config['xo:base_delta'] !== undefined
183
+ const isDelta = differentialVhds[`${id}.vhd`]
182
184
  let parentPath
183
185
  if (isDelta) {
184
186
  const vdiDir = dirname(path)
@@ -191,7 +193,11 @@ class DeltaBackupWriter extends MixinBackupWriter(AbstractDeltaWriter) {
191
193
  .sort()
192
194
  .pop()
193
195
 
194
- assert.notStrictEqual(parentPath, undefined, `missing parent of ${id}`)
196
+ assert.notStrictEqual(
197
+ parentPath,
198
+ undefined,
199
+ `missing parent of ${id} in ${dirname(path)}, looking for ${vdi.other_config['xo:base_delta']}`
200
+ )
195
201
 
196
202
  parentPath = parentPath.slice(1) // remove leading slash
197
203
 
@@ -204,7 +210,7 @@ class DeltaBackupWriter extends MixinBackupWriter(AbstractDeltaWriter) {
204
210
  // merges and chainings
205
211
  checksum: false,
206
212
  validator: tmpPath => checkVhd(handler, tmpPath),
207
- writeBlockConcurrency: this._backup.config.writeBlockConcurrency,
213
+ writeBlockConcurrency: this._config.writeBlockConcurrency,
208
214
  })
209
215
 
210
216
  if (isDelta) {
@@ -227,6 +233,6 @@ class DeltaBackupWriter extends MixinBackupWriter(AbstractDeltaWriter) {
227
233
  // TODO: run cleanup?
228
234
  }
229
235
  }
230
- exports.DeltaBackupWriter = decorateClass(DeltaBackupWriter, {
236
+ exports.IncrementalRemoteWriter = decorateClass(IncrementalRemoteWriter, {
231
237
  _transfer: defer,
232
238
  })
@@ -4,19 +4,19 @@ const { asyncMap, asyncMapSettled } = require('@xen-orchestra/async-map')
4
4
  const ignoreErrors = require('promise-toolbox/ignoreErrors')
5
5
  const { formatDateTime } = require('@xen-orchestra/xapi')
6
6
 
7
- const { formatFilenameDate } = require('../_filenameDate.js')
8
- const { getOldEntries } = require('../_getOldEntries.js')
9
- const { importDeltaVm, TAG_COPY_SRC } = require('../_deltaVm.js')
10
- const { Task } = require('../Task.js')
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')
11
11
 
12
- const { AbstractDeltaWriter } = require('./_AbstractDeltaWriter.js')
13
- const { MixinReplicationWriter } = require('./_MixinReplicationWriter.js')
12
+ const { AbstractIncrementalWriter } = require('./_AbstractIncrementalWriter.js')
13
+ const { MixinXapiWriter } = require('./_MixinXapiWriter.js')
14
14
  const { listReplicatedVms } = require('./_listReplicatedVms.js')
15
15
 
16
- exports.DeltaReplicationWriter = class DeltaReplicationWriter extends MixinReplicationWriter(AbstractDeltaWriter) {
16
+ exports.IncrementalXapiWriter = class IncrementalXapiWriter extends MixinXapiWriter(AbstractIncrementalWriter) {
17
17
  async checkBaseVdis(baseUuidToSrcVdi, baseVm) {
18
18
  const sr = this._sr
19
- const replicatedVm = listReplicatedVms(sr.$xapi, this._backup.job.id, sr.uuid, this._backup.vm.uuid).find(
19
+ const replicatedVm = listReplicatedVms(sr.$xapi, this._job.id, sr.uuid, this._vmUuid).find(
20
20
  vm => vm.other_config[TAG_COPY_SRC] === baseVm.uuid
21
21
  )
22
22
  if (replicatedVm === undefined) {
@@ -49,9 +49,10 @@ exports.DeltaReplicationWriter = class DeltaReplicationWriter extends MixinRepli
49
49
  type: 'SR',
50
50
  },
51
51
  })
52
+ const hasHealthCheckSr = this._healthCheckSr !== undefined
52
53
  this.transfer = task.wrapFn(this.transfer)
53
- this.cleanup = task.wrapFn(this.cleanup)
54
- this.healthCheck = task.wrapFn(this.healthCheck, true)
54
+ this.cleanup = task.wrapFn(this.cleanup, !hasHealthCheckSr)
55
+ this.healthCheck = task.wrapFn(this.healthCheck, hasHealthCheckSr)
55
56
 
56
57
  return task.run(() => this._prepare())
57
58
  }
@@ -59,12 +60,13 @@ exports.DeltaReplicationWriter = class DeltaReplicationWriter extends MixinRepli
59
60
  async _prepare() {
60
61
  const settings = this._settings
61
62
  const { uuid: srUuid, $xapi: xapi } = this._sr
62
- const { scheduleId, vm } = this._backup
63
+ const vmUuid = this._vmUuid
64
+ const scheduleId = this._scheduleId
63
65
 
64
66
  // delete previous interrupted copies
65
- ignoreErrors.call(asyncMapSettled(listReplicatedVms(xapi, scheduleId, undefined, vm.uuid), vm => vm.$destroy))
67
+ ignoreErrors.call(asyncMapSettled(listReplicatedVms(xapi, scheduleId, undefined, vmUuid), vm => vm.$destroy))
66
68
 
67
- this._oldEntries = getOldEntries(settings.copyRetention - 1, listReplicatedVms(xapi, scheduleId, srUuid, vm.uuid))
69
+ this._oldEntries = getOldEntries(settings.copyRetention - 1, listReplicatedVms(xapi, scheduleId, srUuid, vmUuid))
68
70
 
69
71
  if (settings.deleteFirst) {
70
72
  await this._deleteOldEntries()
@@ -81,16 +83,17 @@ exports.DeltaReplicationWriter = class DeltaReplicationWriter extends MixinRepli
81
83
  return asyncMapSettled(this._oldEntries, vm => vm.$destroy())
82
84
  }
83
85
 
84
- async _transfer({ timestamp, deltaExport, sizeContainers }) {
86
+ async _transfer({ timestamp, deltaExport, sizeContainers, vm }) {
85
87
  const { _warmMigration } = this._settings
86
88
  const sr = this._sr
87
- const { job, scheduleId, vm } = this._backup
89
+ const job = this._job
90
+ const scheduleId = this._scheduleId
88
91
 
89
92
  const { uuid: srUuid, $xapi: xapi } = sr
90
93
 
91
94
  let targetVmRef
92
95
  await Task.run({ name: 'transfer' }, async () => {
93
- targetVmRef = await importDeltaVm(
96
+ targetVmRef = await importIncrementalVm(
94
97
  {
95
98
  __proto__: deltaExport,
96
99
  vm: {
@@ -3,9 +3,9 @@
3
3
  const { AbstractWriter } = require('./_AbstractWriter.js')
4
4
 
5
5
  exports.AbstractFullWriter = class AbstractFullWriter extends AbstractWriter {
6
- async run({ timestamp, sizeContainer, stream }) {
6
+ async run({ timestamp, sizeContainer, stream, vm, vmSnapshot }) {
7
7
  try {
8
- return await this._run({ timestamp, sizeContainer, stream })
8
+ return await this._run({ timestamp, sizeContainer, stream, vm, vmSnapshot })
9
9
  } finally {
10
10
  // ensure stream is properly closed
11
11
  stream.destroy()
@@ -2,7 +2,7 @@
2
2
 
3
3
  const { AbstractWriter } = require('./_AbstractWriter.js')
4
4
 
5
- exports.AbstractDeltaWriter = class AbstractDeltaWriter extends AbstractWriter {
5
+ exports.AbstractIncrementalWriter = class AbstractIncrementalWriter extends AbstractWriter {
6
6
  checkBaseVdis(baseUuidToSrcVdi, baseVm) {
7
7
  throw new Error('Not implemented')
8
8
  }
@@ -15,9 +15,9 @@ exports.AbstractDeltaWriter = class AbstractDeltaWriter extends AbstractWriter {
15
15
  throw new Error('Not implemented')
16
16
  }
17
17
 
18
- async transfer({ timestamp, deltaExport, sizeContainers }) {
18
+ async transfer({ deltaExport, ...other }) {
19
19
  try {
20
- return await this._transfer({ timestamp, deltaExport, sizeContainers })
20
+ return await this._transfer({ deltaExport, ...other })
21
21
  } finally {
22
22
  // ensure all streams are properly closed
23
23
  for (const stream of Object.values(deltaExport.streams)) {
@@ -0,0 +1,31 @@
1
+ 'use strict'
2
+
3
+ const { formatFilenameDate } = require('../../_filenameDate')
4
+ const { getVmBackupDir } = require('../../_getVmBackupDir')
5
+
6
+ exports.AbstractWriter = class AbstractWriter {
7
+ constructor({ config, healthCheckSr, job, vmUuid, scheduleId, settings }) {
8
+ this._config = config
9
+ this._healthCheckSr = healthCheckSr
10
+ this._job = job
11
+ this._scheduleId = scheduleId
12
+ this._settings = settings
13
+ this._vmUuid = vmUuid
14
+ }
15
+
16
+ beforeBackup() {}
17
+
18
+ afterBackup() {}
19
+
20
+ healthCheck(sr) {}
21
+
22
+ _isAlreadyTransferred(timestamp) {
23
+ const vmUuid = this._vmUuid
24
+ const adapter = this._adapter
25
+ const backupDir = getVmBackupDir(vmUuid)
26
+ try {
27
+ const actualMetadata = JSON.parse(adapter._handler.readFile(`${backupDir}/${formatFilenameDate(timestamp)}.json`))
28
+ return actualMetadata
29
+ } catch (error) {}
30
+ }
31
+ }
@@ -4,26 +4,26 @@ const { createLogger } = require('@xen-orchestra/log')
4
4
  const { join } = require('path')
5
5
 
6
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')
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')
13
13
 
14
14
  const { info, warn } = createLogger('xo:backups:MixinBackupWriter')
15
15
 
16
- exports.MixinBackupWriter = (BaseClass = Object) =>
17
- class MixinBackupWriter extends BaseClass {
16
+ exports.MixinRemoteWriter = (BaseClass = Object) =>
17
+ class MixinRemoteWriter extends BaseClass {
18
18
  #lock
19
19
 
20
- constructor({ remoteId, ...rest }) {
20
+ constructor({ remoteId, adapter, ...rest }) {
21
21
  super(rest)
22
22
 
23
- this._adapter = rest.backup.remoteAdapters[remoteId]
23
+ this._adapter = adapter
24
24
  this._remoteId = remoteId
25
25
 
26
- this._vmBackupDir = getVmBackupDir(this._backup.vm.uuid)
26
+ this._vmBackupDir = getVmBackupDir(rest.vmUuid)
27
27
  }
28
28
 
29
29
  async _cleanVm(options) {
@@ -38,7 +38,7 @@ exports.MixinBackupWriter = (BaseClass = Object) =>
38
38
  Task.warning(message, data)
39
39
  },
40
40
  lock: false,
41
- mergeBlockConcurrency: this._backup.config.mergeBlockConcurrency,
41
+ mergeBlockConcurrency: this._config.mergeBlockConcurrency,
42
42
  })
43
43
  })
44
44
  } catch (error) {
@@ -55,10 +55,10 @@ exports.MixinBackupWriter = (BaseClass = Object) =>
55
55
  }
56
56
 
57
57
  async afterBackup() {
58
- const { disableMergeWorker } = this._backup.config
58
+ const { disableMergeWorker } = this._config
59
59
  // merge worker only compatible with local remotes
60
60
  const { handler } = this._adapter
61
- const willMergeInWorker = !disableMergeWorker && typeof handler._getRealPath === 'function'
61
+ const willMergeInWorker = !disableMergeWorker && typeof handler.getRealPath === 'function'
62
62
 
63
63
  const { merge } = await this._cleanVm({ remove: true, merge: !willMergeInWorker })
64
64
  await this.#lock.dispose()
@@ -71,12 +71,14 @@ exports.MixinBackupWriter = (BaseClass = Object) =>
71
71
  Math.random().toString(36).slice(2)
72
72
 
73
73
  await handler.outputFile(taskFile, this._backup.vm.uuid)
74
- const remotePath = handler._getRealPath()
74
+ const remotePath = handler.getRealPath()
75
75
  await MergeWorker.run(remotePath)
76
76
  }
77
77
  }
78
78
 
79
- healthCheck(sr) {
79
+ healthCheck() {
80
+ const sr = this._healthCheckSr
81
+ assert.notStrictEqual(sr, undefined, 'SR should be defined before making a health check')
80
82
  assert.notStrictEqual(
81
83
  this._metadataFileName,
82
84
  undefined,
@@ -109,4 +111,16 @@ exports.MixinBackupWriter = (BaseClass = Object) =>
109
111
  }
110
112
  )
111
113
  }
114
+
115
+ _isAlreadyTransferred(timestamp) {
116
+ const vmUuid = this._vmUuid
117
+ const adapter = this._adapter
118
+ const backupDir = getVmBackupDir(vmUuid)
119
+ try {
120
+ const actualMetadata = JSON.parse(
121
+ adapter._handler.readFile(`${backupDir}/${formatFilenameDate(timestamp)}.json`)
122
+ )
123
+ return actualMetadata
124
+ } catch (error) {}
125
+ }
112
126
  }
@@ -1,26 +1,22 @@
1
1
  'use strict'
2
2
 
3
- const { Task } = require('../Task')
3
+ const { extractOpaqueRef } = require('@xen-orchestra/xapi')
4
+
5
+ const { Task } = require('../../Task')
4
6
  const assert = require('node:assert/strict')
5
- const { HealthCheckVmBackup } = require('../HealthCheckVmBackup')
7
+ const { HealthCheckVmBackup } = require('../../HealthCheckVmBackup')
6
8
 
7
- function extractOpaqueRef(str) {
8
- const OPAQUE_REF_RE = /OpaqueRef:[0-9a-z-]+/
9
- const matches = OPAQUE_REF_RE.exec(str)
10
- if (!matches) {
11
- throw new Error('no opaque ref found')
12
- }
13
- return matches[0]
14
- }
15
- exports.MixinReplicationWriter = (BaseClass = Object) =>
16
- class MixinReplicationWriter extends BaseClass {
9
+ exports.MixinXapiWriter = (BaseClass = Object) =>
10
+ class MixinXapiWriter extends BaseClass {
17
11
  constructor({ sr, ...rest }) {
18
12
  super(rest)
19
13
 
20
14
  this._sr = sr
21
15
  }
22
16
 
23
- healthCheck(sr) {
17
+ healthCheck() {
18
+ const sr = this._healthCheckSr
19
+ assert.notStrictEqual(sr, undefined, 'SR should be defined before making a health check')
24
20
  assert.notEqual(this._targetVmRef, undefined, 'A vm should have been transfered to be health checked')
25
21
  // copy VM
26
22
  return Task.run(
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "type": "git",
9
9
  "url": "https://github.com/vatesfr/xen-orchestra.git"
10
10
  },
11
- "version": "0.36.1",
11
+ "version": "0.38.0",
12
12
  "engines": {
13
13
  "node": ">=14.6"
14
14
  },
@@ -27,7 +27,7 @@
27
27
  "@vates/nbd-client": "^1.2.0",
28
28
  "@vates/parse-duration": "^0.1.1",
29
29
  "@xen-orchestra/async-map": "^0.1.2",
30
- "@xen-orchestra/fs": "^3.3.4",
30
+ "@xen-orchestra/fs": "^4.0.0",
31
31
  "@xen-orchestra/log": "^0.6.0",
32
32
  "@xen-orchestra/template": "^0.1.0",
33
33
  "compare-versions": "^5.0.1",
@@ -42,17 +42,17 @@
42
42
  "promise-toolbox": "^0.21.0",
43
43
  "proper-lockfile": "^4.1.2",
44
44
  "uuid": "^9.0.0",
45
- "vhd-lib": "^4.4.0",
45
+ "vhd-lib": "^4.5.0",
46
46
  "yazl": "^2.5.1"
47
47
  },
48
48
  "devDependencies": {
49
- "rimraf": "^4.1.1",
49
+ "rimraf": "^5.0.1",
50
50
  "sinon": "^15.0.1",
51
51
  "test": "^3.2.1",
52
52
  "tmp": "^0.2.1"
53
53
  },
54
54
  "peerDependencies": {
55
- "@xen-orchestra/xapi": "^2.2.0"
55
+ "@xen-orchestra/xapi": "^2.2.1"
56
56
  },
57
57
  "license": "AGPL-3.0-or-later",
58
58
  "author": {