@xen-orchestra/backups 0.29.4 → 0.29.6
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/Backup.js +1 -1
- package/README.md +2 -2
- package/RemoteAdapter.js +6 -2
- package/Task.js +1 -1
- package/_backupWorker.js +1 -1
- package/_deltaVm.js +3 -0
- package/_forkStreamUnpipe.js +15 -16
- package/merge-worker/cli.js +1 -1
- package/package.json +11 -12
- package/writers/DeltaBackupWriter.js +23 -10
package/Backup.js
CHANGED
package/README.md
CHANGED
package/RemoteAdapter.js
CHANGED
|
@@ -28,6 +28,7 @@ const { isMetadataFile } = require('./_backupType.js')
|
|
|
28
28
|
const { isValidXva } = require('./_isValidXva.js')
|
|
29
29
|
const { listPartitions, LVM_PARTITION_TYPE } = require('./_listPartitions.js')
|
|
30
30
|
const { lvs, pvs } = require('./_lvm.js')
|
|
31
|
+
const { watchStreamSize } = require('./_watchStreamSize')
|
|
31
32
|
// @todo : this import is marked extraneous , sould be fixed when lib is published
|
|
32
33
|
const { mount } = require('@vates/fuse-vhd')
|
|
33
34
|
const { asyncEach } = require('@vates/async-each')
|
|
@@ -661,7 +662,7 @@ class RemoteAdapter {
|
|
|
661
662
|
const handler = this._handler
|
|
662
663
|
if (this.#useVhdDirectory()) {
|
|
663
664
|
const dataPath = `${dirname(path)}/data/${uuidv4()}.vhd`
|
|
664
|
-
await createVhdDirectoryFromStream(handler, dataPath, input, {
|
|
665
|
+
const size = await createVhdDirectoryFromStream(handler, dataPath, input, {
|
|
665
666
|
concurrency: writeBlockConcurrency,
|
|
666
667
|
compression: this.#getCompressionType(),
|
|
667
668
|
async validator() {
|
|
@@ -671,12 +672,14 @@ class RemoteAdapter {
|
|
|
671
672
|
nbdClient,
|
|
672
673
|
})
|
|
673
674
|
await VhdAbstract.createAlias(handler, path, dataPath)
|
|
675
|
+
return size
|
|
674
676
|
} else {
|
|
675
|
-
|
|
677
|
+
return this.outputStream(path, input, { checksum, validator })
|
|
676
678
|
}
|
|
677
679
|
}
|
|
678
680
|
|
|
679
681
|
async outputStream(path, input, { checksum = true, validator = noop } = {}) {
|
|
682
|
+
const container = watchStreamSize(input)
|
|
680
683
|
await this._handler.outputStream(path, input, {
|
|
681
684
|
checksum,
|
|
682
685
|
dirMode: this._dirMode,
|
|
@@ -685,6 +688,7 @@ class RemoteAdapter {
|
|
|
685
688
|
return validator.apply(this, arguments)
|
|
686
689
|
},
|
|
687
690
|
})
|
|
691
|
+
return container.size
|
|
688
692
|
}
|
|
689
693
|
|
|
690
694
|
// open the hierarchy of ancestors until we find a full one
|
package/Task.js
CHANGED
|
@@ -100,7 +100,7 @@ class Task {
|
|
|
100
100
|
* In case of error, the task will be failed.
|
|
101
101
|
*
|
|
102
102
|
* @typedef Result
|
|
103
|
-
* @param {() => Result
|
|
103
|
+
* @param {() => Result} fn
|
|
104
104
|
* @param {boolean} last - Whether the task should succeed if there is no error
|
|
105
105
|
* @returns Result
|
|
106
106
|
*/
|
package/_backupWorker.js
CHANGED
package/_deltaVm.js
CHANGED
|
@@ -258,6 +258,9 @@ exports.importDeltaVm = defer(async function importDeltaVm(
|
|
|
258
258
|
$defer.onFailure(() => newVdi.$destroy())
|
|
259
259
|
|
|
260
260
|
await newVdi.update_other_config(TAG_COPY_SRC, vdi.uuid)
|
|
261
|
+
if (vdi.virtual_size > newVdi.virtual_size) {
|
|
262
|
+
await newVdi.$callAsync('resize', vdi.virtual_size)
|
|
263
|
+
}
|
|
261
264
|
} else if (vdiRef === vmRecord.suspend_VDI) {
|
|
262
265
|
// suspendVDI has already created
|
|
263
266
|
newVdi = suspendVdi
|
package/_forkStreamUnpipe.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const { PassThrough } = require('stream')
|
|
3
|
+
const { finished, PassThrough } = require('node:stream')
|
|
5
4
|
|
|
6
5
|
const { debug } = require('@xen-orchestra/log').createLogger('xo:backups:forkStreamUnpipe')
|
|
7
6
|
|
|
@@ -9,29 +8,29 @@ const { debug } = require('@xen-orchestra/log').createLogger('xo:backups:forkStr
|
|
|
9
8
|
//
|
|
10
9
|
// in case of error in the new readable stream, it will simply be unpiped
|
|
11
10
|
// from the original one
|
|
12
|
-
exports.forkStreamUnpipe = function forkStreamUnpipe(
|
|
13
|
-
const { forks = 0 } =
|
|
14
|
-
|
|
11
|
+
exports.forkStreamUnpipe = function forkStreamUnpipe(source) {
|
|
12
|
+
const { forks = 0 } = source
|
|
13
|
+
source.forks = forks + 1
|
|
15
14
|
|
|
16
|
-
debug('forking', { forks:
|
|
15
|
+
debug('forking', { forks: source.forks })
|
|
17
16
|
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
const fork = new PassThrough()
|
|
18
|
+
source.pipe(fork)
|
|
19
|
+
finished(source, { writable: false }, error => {
|
|
21
20
|
if (error !== undefined) {
|
|
22
21
|
debug('error on original stream, destroying fork', { error })
|
|
23
|
-
|
|
22
|
+
fork.destroy(error)
|
|
24
23
|
}
|
|
25
24
|
})
|
|
26
|
-
|
|
27
|
-
debug('end of stream, unpiping', { error, forks: --
|
|
25
|
+
finished(fork, { readable: false }, error => {
|
|
26
|
+
debug('end of stream, unpiping', { error, forks: --source.forks })
|
|
28
27
|
|
|
29
|
-
|
|
28
|
+
source.unpipe(fork)
|
|
30
29
|
|
|
31
|
-
if (
|
|
30
|
+
if (source.forks === 0) {
|
|
32
31
|
debug('no more forks, destroying original stream')
|
|
33
|
-
|
|
32
|
+
source.destroy(new Error('no more consumers for this stream'))
|
|
34
33
|
}
|
|
35
34
|
})
|
|
36
|
-
return
|
|
35
|
+
return fork
|
|
37
36
|
}
|
package/merge-worker/cli.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
'use strict'
|
|
6
6
|
|
|
7
|
-
const { catchGlobalErrors } = require('@xen-orchestra/log/configure
|
|
7
|
+
const { catchGlobalErrors } = require('@xen-orchestra/log/configure')
|
|
8
8
|
const { createLogger } = require('@xen-orchestra/log')
|
|
9
9
|
const { getSyncedHandler } = require('@xen-orchestra/fs')
|
|
10
10
|
const { join } = require('path')
|
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.29.
|
|
11
|
+
"version": "0.29.6",
|
|
12
12
|
"engines": {
|
|
13
13
|
"node": ">=14.6"
|
|
14
14
|
},
|
|
@@ -21,38 +21,37 @@
|
|
|
21
21
|
"@vates/cached-dns.lookup": "^1.0.0",
|
|
22
22
|
"@vates/compose": "^2.1.0",
|
|
23
23
|
"@vates/decorate-with": "^2.0.0",
|
|
24
|
-
"@vates/disposable": "^0.1.
|
|
24
|
+
"@vates/disposable": "^0.1.4",
|
|
25
25
|
"@vates/fuse-vhd": "^1.0.0",
|
|
26
|
-
"@vates/nbd-client": "
|
|
26
|
+
"@vates/nbd-client": "^1.0.1",
|
|
27
27
|
"@vates/parse-duration": "^0.1.1",
|
|
28
28
|
"@xen-orchestra/async-map": "^0.1.2",
|
|
29
|
-
"@xen-orchestra/fs": "^3.3.
|
|
30
|
-
"@xen-orchestra/log": "^0.
|
|
29
|
+
"@xen-orchestra/fs": "^3.3.1",
|
|
30
|
+
"@xen-orchestra/log": "^0.6.0",
|
|
31
31
|
"@xen-orchestra/template": "^0.1.0",
|
|
32
32
|
"compare-versions": "^5.0.1",
|
|
33
33
|
"d3-time-format": "^3.0.0",
|
|
34
34
|
"decorator-synchronized": "^0.6.0",
|
|
35
|
-
"
|
|
36
|
-
"fs-extra": "^10.0.0",
|
|
35
|
+
"fs-extra": "^11.1.0",
|
|
37
36
|
"golike-defer": "^0.5.1",
|
|
38
37
|
"limit-concurrency-decorator": "^0.5.0",
|
|
39
38
|
"lodash": "^4.17.20",
|
|
40
39
|
"node-zone": "^0.4.0",
|
|
41
|
-
"parse-pairs": "^
|
|
40
|
+
"parse-pairs": "^2.0.0",
|
|
42
41
|
"promise-toolbox": "^0.21.0",
|
|
43
42
|
"proper-lockfile": "^4.1.2",
|
|
44
43
|
"uuid": "^9.0.0",
|
|
45
|
-
"vhd-lib": "^4.2.
|
|
44
|
+
"vhd-lib": "^4.2.1",
|
|
46
45
|
"yazl": "^2.5.1"
|
|
47
46
|
},
|
|
48
47
|
"devDependencies": {
|
|
49
|
-
"rimraf": "^
|
|
50
|
-
"sinon": "^
|
|
48
|
+
"rimraf": "^4.1.1",
|
|
49
|
+
"sinon": "^15.0.1",
|
|
51
50
|
"test": "^3.2.1",
|
|
52
51
|
"tmp": "^0.2.1"
|
|
53
52
|
},
|
|
54
53
|
"peerDependencies": {
|
|
55
|
-
"@xen-orchestra/xapi": "^1.6.
|
|
54
|
+
"@xen-orchestra/xapi": "^1.6.1"
|
|
56
55
|
},
|
|
57
56
|
"license": "AGPL-3.0-or-later",
|
|
58
57
|
"author": {
|
|
@@ -7,6 +7,8 @@ const ignoreErrors = require('promise-toolbox/ignoreErrors')
|
|
|
7
7
|
const { asyncMap } = require('@xen-orchestra/async-map')
|
|
8
8
|
const { chainVhd, checkVhdChain, openVhd, VhdAbstract } = require('vhd-lib')
|
|
9
9
|
const { createLogger } = require('@xen-orchestra/log')
|
|
10
|
+
const { decorateClass } = require('@vates/decorate-with')
|
|
11
|
+
const { defer } = require('golike-defer')
|
|
10
12
|
const { dirname } = require('path')
|
|
11
13
|
|
|
12
14
|
const { formatFilenameDate } = require('../_filenameDate.js')
|
|
@@ -20,9 +22,9 @@ const { packUuid } = require('./_packUuid.js')
|
|
|
20
22
|
const { Disposable } = require('promise-toolbox')
|
|
21
23
|
const NbdClient = require('@vates/nbd-client')
|
|
22
24
|
|
|
23
|
-
const { debug, warn } = createLogger('xo:backups:DeltaBackupWriter')
|
|
25
|
+
const { debug, warn, info } = createLogger('xo:backups:DeltaBackupWriter')
|
|
24
26
|
|
|
25
|
-
|
|
27
|
+
class DeltaBackupWriter extends MixinBackupWriter(AbstractDeltaWriter) {
|
|
26
28
|
async checkBaseVdis(baseUuidToSrcVdi) {
|
|
27
29
|
const { handler } = this._adapter
|
|
28
30
|
const backup = this._backup
|
|
@@ -133,7 +135,7 @@ exports.DeltaBackupWriter = class DeltaBackupWriter extends MixinBackupWriter(Ab
|
|
|
133
135
|
}
|
|
134
136
|
}
|
|
135
137
|
|
|
136
|
-
async _transfer({ timestamp, deltaExport
|
|
138
|
+
async _transfer($defer, { timestamp, deltaExport }) {
|
|
137
139
|
const adapter = this._adapter
|
|
138
140
|
const backup = this._backup
|
|
139
141
|
|
|
@@ -172,6 +174,7 @@ exports.DeltaBackupWriter = class DeltaBackupWriter extends MixinBackupWriter(Ab
|
|
|
172
174
|
}
|
|
173
175
|
|
|
174
176
|
const { size } = await Task.run({ name: 'transfer' }, async () => {
|
|
177
|
+
let transferSize = 0
|
|
175
178
|
await Promise.all(
|
|
176
179
|
map(deltaExport.vdis, async (vdi, id) => {
|
|
177
180
|
const path = `${this._vmBackupDir}/${vhds[id]}`
|
|
@@ -200,21 +203,30 @@ exports.DeltaBackupWriter = class DeltaBackupWriter extends MixinBackupWriter(Ab
|
|
|
200
203
|
const vdiRef = vm.$xapi.getObject(vdi.uuid).$ref
|
|
201
204
|
|
|
202
205
|
let nbdClient
|
|
203
|
-
if (
|
|
206
|
+
if (this._backup.config.useNbd) {
|
|
207
|
+
debug('useNbd is enabled', { vdi: id, path })
|
|
204
208
|
// get nbd if possible
|
|
205
209
|
try {
|
|
206
210
|
// this will always take the first host in the list
|
|
207
211
|
const [nbdInfo] = await vm.$xapi.call('VDI.get_nbd_info', vdiRef)
|
|
212
|
+
debug('got NBD info', { nbdInfo, vdi: id, path })
|
|
208
213
|
nbdClient = new NbdClient(nbdInfo)
|
|
209
214
|
await nbdClient.connect()
|
|
210
|
-
|
|
215
|
+
|
|
216
|
+
// this will inform the xapi that we don't need this anymore
|
|
217
|
+
// and will detach the vdi from dom0
|
|
218
|
+
$defer(() => nbdClient.disconnect())
|
|
219
|
+
|
|
220
|
+
info('NBD client ready', { vdi: id, path })
|
|
211
221
|
} catch (error) {
|
|
212
222
|
nbdClient = undefined
|
|
213
|
-
|
|
223
|
+
warn('error connecting to NBD server', { error, vdi: id, path })
|
|
214
224
|
}
|
|
225
|
+
} else {
|
|
226
|
+
debug('useNbd is disabled', { vdi: id, path })
|
|
215
227
|
}
|
|
216
228
|
|
|
217
|
-
await adapter.writeVhd(path, deltaExport.streams[`${id}.vhd`], {
|
|
229
|
+
transferSize += await adapter.writeVhd(path, deltaExport.streams[`${id}.vhd`], {
|
|
218
230
|
// no checksum for VHDs, because they will be invalidated by
|
|
219
231
|
// merges and chainings
|
|
220
232
|
checksum: false,
|
|
@@ -235,9 +247,7 @@ exports.DeltaBackupWriter = class DeltaBackupWriter extends MixinBackupWriter(Ab
|
|
|
235
247
|
})
|
|
236
248
|
})
|
|
237
249
|
)
|
|
238
|
-
return {
|
|
239
|
-
size: Object.values(sizeContainers).reduce((sum, { size }) => sum + size, 0),
|
|
240
|
-
}
|
|
250
|
+
return { size: transferSize }
|
|
241
251
|
})
|
|
242
252
|
metadataContent.size = size
|
|
243
253
|
this._metadataFileName = await adapter.writeVmBackupMetadata(vm.uuid, metadataContent)
|
|
@@ -245,3 +255,6 @@ exports.DeltaBackupWriter = class DeltaBackupWriter extends MixinBackupWriter(Ab
|
|
|
245
255
|
// TODO: run cleanup?
|
|
246
256
|
}
|
|
247
257
|
}
|
|
258
|
+
exports.DeltaBackupWriter = decorateClass(DeltaBackupWriter, {
|
|
259
|
+
_transfer: defer,
|
|
260
|
+
})
|