@xen-orchestra/backups 0.53.1 → 0.54.0

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.
@@ -49,26 +49,25 @@ export class HealthCheckVmBackup {
49
49
  }
50
50
 
51
51
  // wait for the 'Running' event to be really stored in local xapi object cache
52
+
52
53
  restoredVm = await xapi.waitObjectState(restoredVm.$ref, vm => vm.power_state === 'Running', {
53
54
  timeout: remainingTimeout,
55
+ timeoutMessage: refOrUuid =>
56
+ `local xapi did not get Running state for VM ${refOrUuid} after ${timeout / 1000} second`,
54
57
  })
55
58
 
56
59
  const running = new Date()
57
60
  remainingTimeout -= running - started
58
61
 
59
- if (remainingTimeout < 0) {
60
- throw new Error(`local xapi did not get Running state for VM ${restoredId} after ${timeout / 1000} second`)
61
- }
62
62
  // wait for the guest tool version to be defined
63
63
  await xapi.waitObjectState(restoredVm.guest_metrics, gm => gm?.PV_drivers_version?.major !== undefined, {
64
64
  timeout: remainingTimeout,
65
+ timeoutMessage: refOrUuid =>
66
+ `timeout reached while waiting for ${refOrUuid} to report the driver version through the Xen tools. Please check or update the Xen tools.`,
65
67
  })
66
68
 
67
69
  const guestToolsReady = new Date()
68
70
  remainingTimeout -= guestToolsReady - running
69
- if (remainingTimeout < 0) {
70
- throw new Error(`local xapi did not get he guest tools check ${restoredId} after ${timeout / 1000} second`)
71
- }
72
71
 
73
72
  if (waitForScript) {
74
73
  const startedRestoredVm = await xapi.waitObjectState(
@@ -79,19 +78,10 @@ export class HealthCheckVmBackup {
79
78
  vm.xenstore_data['vm-data/xo-backup-health-check'] === 'failure'),
80
79
  {
81
80
  timeout: remainingTimeout,
81
+ timeoutMessage: refOrUuid =>
82
+ `timeout reached while waiting for ${refOrUuid} to report the startup script execution.`,
82
83
  }
83
84
  )
84
- const scriptOk = new Date()
85
- remainingTimeout -= scriptOk - guestToolsReady
86
- if (remainingTimeout < 0) {
87
- throw new Error(
88
- `Backup health check script did not update vm-data/xo-backup-health-check of ${restoredId} after ${
89
- timeout / 1000
90
- } second, got ${
91
- startedRestoredVm.xenstore_data['vm-data/xo-backup-health-check']
92
- } instead of 'success' or 'failure'`
93
- )
94
- }
95
85
 
96
86
  if (startedRestoredVm.xenstore_data['vm-data/xo-backup-health-check'] !== 'success') {
97
87
  const message = startedRestoredVm.xenstore_data['vm-data/xo-backup-health-check-error']
package/RemoteAdapter.mjs CHANGED
@@ -18,6 +18,7 @@ import fromEvent from 'promise-toolbox/fromEvent'
18
18
  import groupBy from 'lodash/groupBy.js'
19
19
  import pDefer from 'promise-toolbox/defer'
20
20
  import pickBy from 'lodash/pickBy.js'
21
+ import reduce from 'lodash/reduce.js'
21
22
  import tar from 'tar'
22
23
  import zlib from 'zlib'
23
24
 
@@ -826,6 +827,29 @@ export class RemoteAdapter {
826
827
  }
827
828
  return metadata
828
829
  }
830
+
831
+ #computeTotalBackupSizeRecursively(backups) {
832
+ return reduce(
833
+ backups,
834
+ (prev, backup) => {
835
+ const _backup = Array.isArray(backup) ? this.#computeTotalBackupSizeRecursively(backup) : backup
836
+ return {
837
+ onDisk: prev.onDisk + (_backup.onDisk ?? _backup.size),
838
+ }
839
+ },
840
+ { onDisk: 0 }
841
+ )
842
+ }
843
+
844
+ async getTotalVmBackupSize() {
845
+ return this.#computeTotalBackupSizeRecursively(await this.listAllVmBackups())
846
+ }
847
+
848
+ async getTotalBackupSize() {
849
+ const vmBackupSize = await this.getTotalVmBackupSize()
850
+ // @TODO: add `getTotalXoBackupSize` and `getTotalPoolBackupSize` once `size` is implemented by fs
851
+ return vmBackupSize
852
+ }
829
853
  }
830
854
 
831
855
  Object.assign(RemoteAdapter.prototype, {
@@ -3,7 +3,6 @@ import ignoreErrors from 'promise-toolbox/ignoreErrors'
3
3
  import { asyncMap } from '@xen-orchestra/async-map'
4
4
  import { CancelToken } from 'promise-toolbox'
5
5
  import { compareVersions } from 'compare-versions'
6
- import { createVhdStreamWithLength } from 'vhd-lib'
7
6
  import { defer } from 'golike-defer'
8
7
 
9
8
  import { cancelableMap } from './_cancelableMap.mjs'
@@ -227,9 +226,6 @@ export const importIncrementalVm = defer(async function importIncrementalVm(
227
226
  if (typeof stream === 'function') {
228
227
  stream = await stream()
229
228
  }
230
- if (stream.length === undefined) {
231
- stream = await createVhdStreamWithLength(stream)
232
- }
233
229
  await xapi.setField('VDI', vdi.$ref, 'name_label', `[Importing] ${vdiRecords[id].name_label}`)
234
230
  await vdi.$importContent(stream, { cancelToken, format: 'vhd' })
235
231
  await xapi.setField('VDI', vdi.$ref, 'name_label', vdiRecords[id].name_label)
@@ -293,7 +293,7 @@ export const AbstractXapi = class AbstractXapiVmBackupRunner extends Abstract {
293
293
  await this._xapi.VDI_dataDestroy(vdiRef)
294
294
  Task.info(`Snapshot data has been deleted`, { vdiRef })
295
295
  } catch (error) {
296
- Task.warning(`Couldn't deleted snapshot data`, { error, vdiRef })
296
+ Task.warning(`Couldn't delete snapshot data`, { error, vdiRef })
297
297
  }
298
298
  }
299
299
  }
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.53.1",
11
+ "version": "0.54.0",
12
12
  "engines": {
13
13
  "node": ">=14.18"
14
14
  },
@@ -48,7 +48,7 @@
48
48
  "uuid": "^9.0.0",
49
49
  "value-matcher": "^0.2.0",
50
50
  "vhd-lib": "^4.11.0",
51
- "xen-api": "^4.2.0",
51
+ "xen-api": "^4.3.0",
52
52
  "yazl": "^2.5.1"
53
53
  },
54
54
  "devDependencies": {
@@ -59,7 +59,7 @@
59
59
  "tmp": "^0.2.1"
60
60
  },
61
61
  "peerDependencies": {
62
- "@xen-orchestra/xapi": "^7.4.0"
62
+ "@xen-orchestra/xapi": "^7.5.0"
63
63
  },
64
64
  "license": "AGPL-3.0-or-later",
65
65
  "author": {