@xen-orchestra/backups 0.19.1 → 0.21.1

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/ImportVmBackup.js CHANGED
@@ -8,9 +8,9 @@ const { Task } = require('./Task.js')
8
8
  const { watchStreamSize } = require('./_watchStreamSize.js')
9
9
 
10
10
  exports.ImportVmBackup = class ImportVmBackup {
11
- constructor({ adapter, metadata, srUuid, xapi, settings: { newMacAddresses } = {} }) {
11
+ constructor({ adapter, metadata, srUuid, xapi, settings: { newMacAddresses, mapVdisSrs = {} } = {} }) {
12
12
  this._adapter = adapter
13
- this._importDeltaVmSettings = { newMacAddresses }
13
+ this._importDeltaVmSettings = { newMacAddresses, mapVdisSrs }
14
14
  this._metadata = metadata
15
15
  this._srUuid = srUuid
16
16
  this._xapi = xapi
@@ -30,7 +30,12 @@ exports.ImportVmBackup = class ImportVmBackup {
30
30
  } else {
31
31
  assert.strictEqual(metadata.mode, 'delta')
32
32
 
33
- backup = await adapter.readDeltaVmBackup(metadata)
33
+ const ignoredVdis = new Set(
34
+ Object.entries(this._importDeltaVmSettings.mapVdisSrs)
35
+ .filter(([_, srUuid]) => srUuid === null)
36
+ .map(([vdiUuid]) => vdiUuid)
37
+ )
38
+ backup = await adapter.readDeltaVmBackup(metadata, ignoredVdis)
34
39
  Object.values(backup.streams).forEach(stream => watchStreamSize(stream, sizeContainer))
35
40
  }
36
41
 
package/RemoteAdapter.js CHANGED
@@ -6,6 +6,7 @@ const fromCallback = require('promise-toolbox/fromCallback')
6
6
  const fromEvent = require('promise-toolbox/fromEvent')
7
7
  const pDefer = require('promise-toolbox/defer')
8
8
  const groupBy = require('lodash/groupBy.js')
9
+ const pickBy = require('lodash/pickBy.js')
9
10
  const { dirname, join, normalize, resolve } = require('path')
10
11
  const { createLogger } = require('@xen-orchestra/log')
11
12
  const { Constants, createVhdDirectoryFromStream, openVhd, VhdAbstract, VhdDirectory, VhdSynthetic } = require('vhd-lib')
@@ -576,14 +577,15 @@ class RemoteAdapter {
576
577
  return stream
577
578
  }
578
579
 
579
- async readDeltaVmBackup(metadata) {
580
+ async readDeltaVmBackup(metadata, ignoredVdis) {
580
581
  const handler = this._handler
581
- const { vbds, vdis, vhds, vifs, vm } = metadata
582
+ const { vbds, vhds, vifs, vm } = metadata
582
583
  const dir = dirname(metadata._filename)
584
+ const vdis = ignoredVdis === undefined ? metadata.vdis : pickBy(metadata.vdis, vdi => !ignoredVdis.has(vdi.uuid))
583
585
 
584
586
  const streams = {}
585
- await asyncMapSettled(Object.keys(vdis), async id => {
586
- streams[`${id}.vhd`] = await this._createSyntheticStream(handler, join(dir, vhds[id]))
587
+ await asyncMapSettled(Object.keys(vdis), async ref => {
588
+ streams[`${ref}.vhd`] = await this._createSyntheticStream(handler, join(dir, vhds[ref]))
587
589
  })
588
590
 
589
591
  return {
package/_backupType.js CHANGED
@@ -3,4 +3,4 @@
3
3
  exports.isMetadataFile = filename => filename.endsWith('.json')
4
4
  exports.isVhdFile = filename => filename.endsWith('.vhd')
5
5
  exports.isXvaFile = filename => filename.endsWith('.xva')
6
- exports.isXvaSumFile = filename => filename.endsWith('.xva.cheksum')
6
+ exports.isXvaSumFile = filename => filename.endsWith('.xva.checksum')
package/_backupWorker.js CHANGED
@@ -4,6 +4,8 @@ require('@xen-orchestra/log/configure.js').catchGlobalErrors(
4
4
  require('@xen-orchestra/log').createLogger('xo:backups:worker')
5
5
  )
6
6
 
7
+ require('@vates/cached-dns.lookup').createCachedLookup().patchGlobal()
8
+
7
9
  const Disposable = require('promise-toolbox/Disposable')
8
10
  const ignoreErrors = require('promise-toolbox/ignoreErrors')
9
11
  const { compose } = require('@vates/compose')
package/_deltaVm.js CHANGED
@@ -11,6 +11,8 @@ const { createVhdStreamWithLength } = require('vhd-lib')
11
11
  const { defer } = require('golike-defer')
12
12
 
13
13
  const { cancelableMap } = require('./_cancelableMap.js')
14
+ const { Task } = require('./Task.js')
15
+ const { pick } = require('lodash')
14
16
 
15
17
  const TAG_BASE_DELTA = 'xo:base_delta'
16
18
  exports.TAG_BASE_DELTA = TAG_BASE_DELTA
@@ -19,6 +21,17 @@ const TAG_COPY_SRC = 'xo:copy_of'
19
21
  exports.TAG_COPY_SRC = TAG_COPY_SRC
20
22
 
21
23
  const ensureArray = value => (value === undefined ? [] : Array.isArray(value) ? value : [value])
24
+ const resolveUuid = async (xapi, cache, uuid, type) => {
25
+ if (uuid == null) {
26
+ return uuid
27
+ }
28
+ let ref = cache.get(uuid)
29
+ if (ref === undefined) {
30
+ ref = await xapi.call(`${type}.get_by_uuid`, uuid)
31
+ cache.set(uuid, ref)
32
+ }
33
+ return ref
34
+ }
22
35
 
23
36
  exports.exportDeltaVm = async function exportDeltaVm(
24
37
  vm,
@@ -167,6 +180,12 @@ exports.importDeltaVm = defer(async function importDeltaVm(
167
180
  }
168
181
  }
169
182
 
183
+ const cache = new Map()
184
+ const mapVdisSrRefs = {}
185
+ for (const [vdiUuid, srUuid] of Object.entries(mapVdisSrs)) {
186
+ mapVdisSrRefs[vdiUuid] = await resolveUuid(xapi, cache, srUuid, 'SR')
187
+ }
188
+
170
189
  const baseVdis = {}
171
190
  baseVm &&
172
191
  baseVm.$VBDs.forEach(vbd => {
@@ -181,19 +200,25 @@ exports.importDeltaVm = defer(async function importDeltaVm(
181
200
  let suspendVdi
182
201
  if (vmRecord.power_state === 'Suspended') {
183
202
  const vdi = vdiRecords[vmRecord.suspend_VDI]
184
- suspendVdi = await xapi.getRecord(
185
- 'VDI',
186
- await xapi.VDI_create({
187
- ...vdi,
188
- other_config: {
189
- ...vdi.other_config,
190
- [TAG_BASE_DELTA]: undefined,
191
- [TAG_COPY_SRC]: vdi.uuid,
192
- },
193
- sr: mapVdisSrs[vdi.uuid] ?? sr.$ref,
203
+ if (vdi === undefined) {
204
+ Task.warning('Suspend VDI not available for this suspended VM', {
205
+ vm: pick(vmRecord, 'uuid', 'name_label'),
194
206
  })
195
- )
196
- $defer.onFailure(() => suspendVdi.$destroy())
207
+ } else {
208
+ suspendVdi = await xapi.getRecord(
209
+ 'VDI',
210
+ await xapi.VDI_create({
211
+ ...vdi,
212
+ other_config: {
213
+ ...vdi.other_config,
214
+ [TAG_BASE_DELTA]: undefined,
215
+ [TAG_COPY_SRC]: vdi.uuid,
216
+ },
217
+ sr: mapVdisSrRefs[vdi.uuid] ?? sr.$ref,
218
+ })
219
+ )
220
+ $defer.onFailure(() => suspendVdi.$destroy())
221
+ }
197
222
  }
198
223
 
199
224
  // 1. Create the VM.
@@ -257,7 +282,7 @@ exports.importDeltaVm = defer(async function importDeltaVm(
257
282
  [TAG_BASE_DELTA]: undefined,
258
283
  [TAG_COPY_SRC]: vdi.uuid,
259
284
  },
260
- SR: mapVdisSrs[vdi.uuid] ?? sr.$ref,
285
+ SR: mapVdisSrRefs[vdi.uuid] ?? sr.$ref,
261
286
  })
262
287
  )
263
288
  $defer.onFailure(() => newVdi.$destroy())
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.19.1",
11
+ "version": "0.21.1",
12
12
  "engines": {
13
13
  "node": ">=14.6"
14
14
  },
@@ -16,12 +16,13 @@
16
16
  "postversion": "npm publish --access public"
17
17
  },
18
18
  "dependencies": {
19
+ "@vates/cached-dns.lookup": "^1.0.0",
19
20
  "@vates/compose": "^2.1.0",
20
- "@vates/decorate-with": "^1.0.0",
21
+ "@vates/decorate-with": "^2.0.0",
21
22
  "@vates/disposable": "^0.1.1",
22
23
  "@vates/parse-duration": "^0.1.1",
23
24
  "@xen-orchestra/async-map": "^0.1.2",
24
- "@xen-orchestra/fs": "^0.20.0",
25
+ "@xen-orchestra/fs": "^1.0.1",
25
26
  "@xen-orchestra/log": "^0.3.0",
26
27
  "@xen-orchestra/template": "^0.1.0",
27
28
  "compare-versions": "^4.0.1",
@@ -39,8 +40,12 @@
39
40
  "vhd-lib": "^3.1.0",
40
41
  "yazl": "^2.5.1"
41
42
  },
43
+ "devDependencies": {
44
+ "rimraf": "^3.0.2",
45
+ "tmp": "^0.2.1"
46
+ },
42
47
  "peerDependencies": {
43
- "@xen-orchestra/xapi": "^0.9.0"
48
+ "@xen-orchestra/xapi": "^0.10.0"
44
49
  },
45
50
  "license": "AGPL-3.0-or-later",
46
51
  "author": {