@xen-orchestra/backups 0.29.3 → 0.29.5

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 CHANGED
@@ -38,7 +38,7 @@ const DEFAULT_VM_SETTINGS = {
38
38
  fullInterval: 0,
39
39
  healthCheckSr: undefined,
40
40
  healthCheckVmsWithTags: [],
41
- maxMergedDeltasPerRun: 2,
41
+ maxMergedDeltasPerRun: Infinity,
42
42
  offlineBackup: false,
43
43
  offlineSnapshot: false,
44
44
  snapshotRetention: 0,
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
- await this.outputStream(path, input, { checksum, validator })
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)} fn
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
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- require('@xen-orchestra/log/configure.js').catchGlobalErrors(
3
+ require('@xen-orchestra/log/configure').catchGlobalErrors(
4
4
  require('@xen-orchestra/log').createLogger('xo:backups:worker')
5
5
  )
6
6
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  'use strict'
6
6
 
7
- const { catchGlobalErrors } = require('@xen-orchestra/log/configure.js')
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.3",
11
+ "version": "0.29.5",
12
12
  "engines": {
13
13
  "node": ">=14.6"
14
14
  },
@@ -21,38 +21,38 @@
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.3",
24
+ "@vates/disposable": "^0.1.4",
25
25
  "@vates/fuse-vhd": "^1.0.0",
26
26
  "@vates/nbd-client": "*",
27
27
  "@vates/parse-duration": "^0.1.1",
28
28
  "@xen-orchestra/async-map": "^0.1.2",
29
- "@xen-orchestra/fs": "^3.3.0",
30
- "@xen-orchestra/log": "^0.5.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
35
  "end-of-stream": "^1.4.4",
36
- "fs-extra": "^10.0.0",
36
+ "fs-extra": "^11.1.0",
37
37
  "golike-defer": "^0.5.1",
38
38
  "limit-concurrency-decorator": "^0.5.0",
39
39
  "lodash": "^4.17.20",
40
40
  "node-zone": "^0.4.0",
41
- "parse-pairs": "^1.1.0",
41
+ "parse-pairs": "^2.0.0",
42
42
  "promise-toolbox": "^0.21.0",
43
43
  "proper-lockfile": "^4.1.2",
44
44
  "uuid": "^9.0.0",
45
- "vhd-lib": "^4.2.0",
45
+ "vhd-lib": "^4.2.1",
46
46
  "yazl": "^2.5.1"
47
47
  },
48
48
  "devDependencies": {
49
- "rimraf": "^3.0.2",
50
- "sinon": "^14.0.1",
49
+ "rimraf": "^4.1.1",
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": "^1.5.3"
55
+ "@xen-orchestra/xapi": "^1.6.0"
56
56
  },
57
57
  "license": "AGPL-3.0-or-later",
58
58
  "author": {
@@ -11,7 +11,6 @@ const { dirname } = require('path')
11
11
 
12
12
  const { formatFilenameDate } = require('../_filenameDate.js')
13
13
  const { getOldEntries } = require('../_getOldEntries.js')
14
- const { getVmBackupDir } = require('../_getVmBackupDir.js')
15
14
  const { Task } = require('../Task.js')
16
15
 
17
16
  const { MixinBackupWriter } = require('./_MixinBackupWriter.js')
@@ -21,7 +20,7 @@ const { packUuid } = require('./_packUuid.js')
21
20
  const { Disposable } = require('promise-toolbox')
22
21
  const NbdClient = require('@vates/nbd-client')
23
22
 
24
- const { debug, warn } = createLogger('xo:backups:DeltaBackupWriter')
23
+ const { debug, warn, info } = createLogger('xo:backups:DeltaBackupWriter')
25
24
 
26
25
  exports.DeltaBackupWriter = class DeltaBackupWriter extends MixinBackupWriter(AbstractDeltaWriter) {
27
26
  async checkBaseVdis(baseUuidToSrcVdi) {
@@ -29,8 +28,7 @@ exports.DeltaBackupWriter = class DeltaBackupWriter extends MixinBackupWriter(Ab
29
28
  const backup = this._backup
30
29
  const adapter = this._adapter
31
30
 
32
- const backupDir = getVmBackupDir(backup.vm.uuid)
33
- const vdisDir = `${backupDir}/vdis/${backup.job.id}`
31
+ const vdisDir = `${this._vmBackupDir}/vdis/${backup.job.id}`
34
32
 
35
33
  await asyncMap(baseUuidToSrcVdi, async ([baseUuid, srcVdi]) => {
36
34
  let found = false
@@ -135,7 +133,7 @@ exports.DeltaBackupWriter = class DeltaBackupWriter extends MixinBackupWriter(Ab
135
133
  }
136
134
  }
137
135
 
138
- async _transfer({ timestamp, deltaExport, sizeContainers }) {
136
+ async _transfer({ timestamp, deltaExport }) {
139
137
  const adapter = this._adapter
140
138
  const backup = this._backup
141
139
 
@@ -143,7 +141,6 @@ exports.DeltaBackupWriter = class DeltaBackupWriter extends MixinBackupWriter(Ab
143
141
 
144
142
  const jobId = job.id
145
143
  const handler = adapter.handler
146
- const backupDir = getVmBackupDir(vm.uuid)
147
144
 
148
145
  // TODO: clean VM backup directory
149
146
 
@@ -175,9 +172,10 @@ exports.DeltaBackupWriter = class DeltaBackupWriter extends MixinBackupWriter(Ab
175
172
  }
176
173
 
177
174
  const { size } = await Task.run({ name: 'transfer' }, async () => {
175
+ let transferSize = 0
178
176
  await Promise.all(
179
177
  map(deltaExport.vdis, async (vdi, id) => {
180
- const path = `${backupDir}/${vhds[id]}`
178
+ const path = `${this._vmBackupDir}/${vhds[id]}`
181
179
 
182
180
  const isDelta = vdi.other_config['xo:base_delta'] !== undefined
183
181
  let parentPath
@@ -203,21 +201,25 @@ exports.DeltaBackupWriter = class DeltaBackupWriter extends MixinBackupWriter(Ab
203
201
  const vdiRef = vm.$xapi.getObject(vdi.uuid).$ref
204
202
 
205
203
  let nbdClient
206
- if (!this._backup.config.useNbd) {
204
+ if (this._backup.config.useNbd) {
205
+ debug('useNbd is enabled', { vdi: id, path })
207
206
  // get nbd if possible
208
207
  try {
209
208
  // this will always take the first host in the list
210
209
  const [nbdInfo] = await vm.$xapi.call('VDI.get_nbd_info', vdiRef)
210
+ debug('got NBD info', { nbdInfo, vdi: id, path })
211
211
  nbdClient = new NbdClient(nbdInfo)
212
212
  await nbdClient.connect()
213
- debug(`got nbd connection `, { vdi: vdi.uuid })
213
+ info('NBD client ready', { vdi: id, path })
214
214
  } catch (error) {
215
215
  nbdClient = undefined
216
- debug(`can't connect to nbd server or no server available`, { error })
216
+ warn('error connecting to NBD server', { error, vdi: id, path })
217
217
  }
218
+ } else {
219
+ debug('useNbd is disabled', { vdi: id, path })
218
220
  }
219
221
 
220
- await adapter.writeVhd(path, deltaExport.streams[`${id}.vhd`], {
222
+ transferSize += await adapter.writeVhd(path, deltaExport.streams[`${id}.vhd`], {
221
223
  // no checksum for VHDs, because they will be invalidated by
222
224
  // merges and chainings
223
225
  checksum: false,
@@ -238,9 +240,7 @@ exports.DeltaBackupWriter = class DeltaBackupWriter extends MixinBackupWriter(Ab
238
240
  })
239
241
  })
240
242
  )
241
- return {
242
- size: Object.values(sizeContainers).reduce((sum, { size }) => sum + size, 0),
243
- }
243
+ return { size: transferSize }
244
244
  })
245
245
  metadataContent.size = size
246
246
  this._metadataFileName = await adapter.writeVmBackupMetadata(vm.uuid, metadataContent)
@@ -2,7 +2,6 @@
2
2
 
3
3
  const { formatFilenameDate } = require('../_filenameDate.js')
4
4
  const { getOldEntries } = require('../_getOldEntries.js')
5
- const { getVmBackupDir } = require('../_getVmBackupDir.js')
6
5
  const { Task } = require('../Task.js')
7
6
 
8
7
  const { MixinBackupWriter } = require('./_MixinBackupWriter.js')
@@ -34,7 +33,6 @@ exports.FullBackupWriter = class FullBackupWriter extends MixinBackupWriter(Abst
34
33
  const { job, scheduleId, vm } = backup
35
34
 
36
35
  const adapter = this._adapter
37
- const backupDir = getVmBackupDir(vm.uuid)
38
36
 
39
37
  // TODO: clean VM backup directory
40
38
 
@@ -47,7 +45,7 @@ exports.FullBackupWriter = class FullBackupWriter extends MixinBackupWriter(Abst
47
45
  const basename = formatFilenameDate(timestamp)
48
46
 
49
47
  const dataBasename = basename + '.xva'
50
- const dataFilename = backupDir + '/' + dataBasename
48
+ const dataFilename = this._vmBackupDir + '/' + dataBasename
51
49
 
52
50
  const metadata = {
53
51
  jobId: job.id,
@@ -16,7 +16,6 @@ const { info, warn } = createLogger('xo:backups:MixinBackupWriter')
16
16
  exports.MixinBackupWriter = (BaseClass = Object) =>
17
17
  class MixinBackupWriter extends BaseClass {
18
18
  #lock
19
- #vmBackupDir
20
19
 
21
20
  constructor({ remoteId, ...rest }) {
22
21
  super(rest)
@@ -24,13 +23,13 @@ exports.MixinBackupWriter = (BaseClass = Object) =>
24
23
  this._adapter = rest.backup.remoteAdapters[remoteId]
25
24
  this._remoteId = remoteId
26
25
 
27
- this.#vmBackupDir = getVmBackupDir(this._backup.vm.uuid)
26
+ this._vmBackupDir = getVmBackupDir(this._backup.vm.uuid)
28
27
  }
29
28
 
30
29
  async _cleanVm(options) {
31
30
  try {
32
31
  return await Task.run({ name: 'clean-vm' }, () => {
33
- return this._adapter.cleanVm(this.#vmBackupDir, {
32
+ return this._adapter.cleanVm(this._vmBackupDir, {
34
33
  ...options,
35
34
  fixMetadata: true,
36
35
  logInfo: info,
@@ -50,7 +49,7 @@ exports.MixinBackupWriter = (BaseClass = Object) =>
50
49
 
51
50
  async beforeBackup() {
52
51
  const { handler } = this._adapter
53
- const vmBackupDir = this.#vmBackupDir
52
+ const vmBackupDir = this._vmBackupDir
54
53
  await handler.mktree(vmBackupDir)
55
54
  this.#lock = await handler.lock(vmBackupDir)
56
55
  }