@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 +39 -8
- package/_VmBackup.js +7 -4
- package/package.json +4 -4
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 {
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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',
|
|
509
|
-
stream.on('close',
|
|
510
|
-
stream.on('error',
|
|
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
|
|
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(
|
|
342
|
+
baseUuidToSrcVdi.set(baseUuid, srcVdi)
|
|
340
343
|
} else {
|
|
341
|
-
debug('
|
|
342
|
-
vdi:
|
|
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.
|
|
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.
|
|
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.
|
|
39
|
+
"vhd-lib": "^2.0.2",
|
|
40
40
|
"yazl": "^2.5.1"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
|
-
"@xen-orchestra/xapi": "^0.8.
|
|
43
|
+
"@xen-orchestra/xapi": "^0.8.4"
|
|
44
44
|
},
|
|
45
45
|
"license": "AGPL-3.0-or-later",
|
|
46
46
|
"author": {
|