@xen-orchestra/backups 0.16.0 → 0.16.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/RemoteAdapter.js CHANGED
@@ -5,7 +5,7 @@ const fromEvent = require('promise-toolbox/fromEvent.js')
5
5
  const pDefer = require('promise-toolbox/defer.js')
6
6
  const { dirname, join, normalize, resolve } = require('path')
7
7
  const { createLogger } = require('@xen-orchestra/log')
8
- const { VhdAbstract, createVhdDirectoryFromStream } = require('vhd-lib')
8
+ const { Constants, createVhdDirectoryFromStream, openVhd, VhdAbstract, VhdSynthetic } = require('vhd-lib')
9
9
  const { deduped } = require('@vates/disposable/deduped.js')
10
10
  const { execFile } = require('child_process')
11
11
  const { readdir, stat } = require('fs-extra')
@@ -469,10 +469,10 @@ class RemoteAdapter {
469
469
 
470
470
  async writeVhd(path, input, { checksum = true, validator = noop } = {}) {
471
471
  const handler = this._handler
472
- let dataPath = path
473
472
 
474
473
  if (path.endsWith('.alias.vhd')) {
475
- await createVhdDirectoryFromStream(handler, `${dirname(path)}/data/${uuidv4()}.vhd`, input, {
474
+ const dataPath = `${dirname(path)}/data/${uuidv4()}.vhd`
475
+ await createVhdDirectoryFromStream(handler, dataPath, input, {
476
476
  concurrency: 16,
477
477
  async validator() {
478
478
  await input.task
@@ -481,7 +481,7 @@ class RemoteAdapter {
481
481
  })
482
482
  await VhdAbstract.createAlias(handler, path, dataPath)
483
483
  } else {
484
- await this.outputStream(dataPath, input, { checksum, validator })
484
+ await this.outputStream(path, input, { checksum, validator })
485
485
  }
486
486
  }
487
487
 
@@ -497,17 +497,48 @@ class RemoteAdapter {
497
497
  }
498
498
 
499
499
  async _createSyntheticStream(handler, paths) {
500
+ let disposableVhds = []
501
+
502
+ // if it's a path : open all hierarchy of parent
503
+ if (typeof paths === 'string') {
504
+ let vhd,
505
+ vhdPath = paths
506
+ do {
507
+ const disposable = await openVhd(handler, vhdPath)
508
+ vhd = disposable.value
509
+ disposableVhds.push(disposable)
510
+ vhdPath = resolveRelativeFromFile(vhdPath, vhd.header.parentUnicodeName)
511
+ } while (vhd.footer.diskType !== Constants.DISK_TYPES.DYNAMIC)
512
+ } else {
513
+ // only open the list of path given
514
+ disposableVhds = paths.map(path => openVhd(handler, path))
515
+ }
516
+
500
517
  // I don't want the vhds to be disposed on return
501
518
  // but only when the stream is done ( or failed )
502
- const disposables = await Disposable.all(paths.map(path => openVhd(handler, path)))
519
+ const disposables = await Disposable.all(disposableVhds)
503
520
  const vhds = disposables.value
521
+
522
+ let disposed = false
523
+ const disposeOnce = async () => {
524
+ if (!disposed) {
525
+ disposed = true
526
+
527
+ try {
528
+ await disposables.dispose()
529
+ } catch (error) {
530
+ warn('_createSyntheticStream: failed to dispose VHDs', { error })
531
+ }
532
+ }
533
+ }
534
+
504
535
  const synthetic = new VhdSynthetic(vhds)
505
536
  await synthetic.readHeaderAndFooter()
506
537
  await synthetic.readBlockAllocationTable()
507
538
  const stream = await synthetic.stream()
508
- stream.on('end', () => disposables.dispose())
509
- stream.on('close', () => disposables.dispose())
510
- stream.on('error', () => disposables.dispose())
539
+ stream.on('end', disposeOnce)
540
+ stream.on('close', disposeOnce)
541
+ stream.on('error', disposeOnce)
511
542
  return stream
512
543
  }
513
544
 
package/_VmBackup.js CHANGED
@@ -333,13 +333,16 @@ exports.VmBackup = class VmBackup {
333
333
 
334
334
  const baseUuidToSrcVdi = new Map()
335
335
  await asyncMap(await baseVm.$getDisks(), async baseRef => {
336
- const snapshotOf = await xapi.getField('VDI', baseRef, 'snapshot_of')
336
+ const [baseUuid, snapshotOf] = await Promise.all([
337
+ xapi.getField('VDI', baseRef, 'uuid'),
338
+ xapi.getField('VDI', baseRef, 'snapshot_of'),
339
+ ])
337
340
  const srcVdi = srcVdis[snapshotOf]
338
341
  if (srcVdi !== undefined) {
339
- baseUuidToSrcVdi.set(await xapi.getField('VDI', baseRef, 'uuid'), srcVdi)
342
+ baseUuidToSrcVdi.set(baseUuid, srcVdi)
340
343
  } else {
341
- debug('no base VDI found', {
342
- vdi: srcVdi.uuid,
344
+ debug('ignore snapshot VDI because no longer present on VM', {
345
+ vdi: baseUuid,
343
346
  })
344
347
  }
345
348
  })
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.16.0",
11
+ "version": "0.16.1",
12
12
  "engines": {
13
13
  "node": ">=14.6"
14
14
  },
@@ -16,7 +16,7 @@
16
16
  "postversion": "npm publish --access public"
17
17
  },
18
18
  "dependencies": {
19
- "@vates/compose": "^2.0.0",
19
+ "@vates/compose": "^2.1.0",
20
20
  "@vates/disposable": "^0.1.1",
21
21
  "@vates/parse-duration": "^0.1.1",
22
22
  "@xen-orchestra/async-map": "^0.1.2",
@@ -36,11 +36,11 @@
36
36
  "proper-lockfile": "^4.1.2",
37
37
  "pump": "^3.0.0",
38
38
  "uuid": "^8.3.2",
39
- "vhd-lib": "^2.0.0",
39
+ "vhd-lib": "^2.0.2",
40
40
  "yazl": "^2.5.1"
41
41
  },
42
42
  "peerDependencies": {
43
- "@xen-orchestra/xapi": "^0.8.0"
43
+ "@xen-orchestra/xapi": "^0.8.4"
44
44
  },
45
45
  "license": "AGPL-3.0-or-later",
46
46
  "author": {