@xen-orchestra/backups 0.46.1 → 0.48.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.
package/_backupWorker.mjs CHANGED
@@ -2,7 +2,10 @@ import { createLogger } from '@xen-orchestra/log'
2
2
  import { catchGlobalErrors } from '@xen-orchestra/log/configure'
3
3
 
4
4
  import Disposable from 'promise-toolbox/Disposable'
5
+ import humanFormat from 'human-format'
5
6
  import ignoreErrors from 'promise-toolbox/ignoreErrors'
7
+ import mapValues from 'lodash/mapValues.js'
8
+ import ms from 'ms'
6
9
  import { compose } from '@vates/compose'
7
10
  import { createCachedLookup } from '@vates/cached-dns.lookup'
8
11
  import { createDebounceResource } from '@vates/disposable/debounceResource.js'
@@ -20,7 +23,7 @@ createCachedLookup().patchGlobal()
20
23
 
21
24
  const logger = createLogger('xo:backups:worker')
22
25
  catchGlobalErrors(logger)
23
- const { debug } = logger
26
+ const { debug, info } = logger
24
27
 
25
28
  class BackupWorker {
26
29
  #config
@@ -149,6 +152,27 @@ process.on('message', async message => {
149
152
  debug('message received', { message })
150
153
 
151
154
  if (message.action === 'run') {
155
+ const resourceStart = process.resourceUsage()
156
+ const timeStart = process.hrtime.bigint()
157
+ info('starting backup')
158
+
159
+ process.on('exit', exitCode => {
160
+ const resourceUsage = mapValues(process.resourceUsage(), (end, key) => end - resourceStart[key])
161
+ const cpuTotal = resourceUsage.userCPUTime + resourceUsage.systemCPUTime
162
+ const duration = Number((process.hrtime.bigint() - timeStart) / 1000n) // in μs
163
+
164
+ info('process will exit', {
165
+ duration,
166
+ exitCode,
167
+ resourceUsage,
168
+ summary: {
169
+ duration: ms(duration / 1000),
170
+ cpuUsage: Math.round((100 * cpuTotal) / duration) + '%',
171
+ memoryUsage: humanFormat.bytes(resourceUsage.maxRSS * 1024),
172
+ },
173
+ })
174
+ })
175
+
152
176
  const backupWorker = new BackupWorker(message.data)
153
177
  try {
154
178
  const result = message.runWithLogs
@@ -177,6 +201,7 @@ process.on('message', async message => {
177
201
  status: 'failure',
178
202
  })
179
203
  } finally {
204
+ info('backup has ended')
180
205
  await ignoreErrors.call(backupWorker.debounceResource.flushAll())
181
206
  process.disconnect()
182
207
  }
@@ -19,6 +19,7 @@ const DEFAULT_REMOTE_VM_SETTINGS = {
19
19
  exportRetention: 0,
20
20
  healthCheckSr: undefined,
21
21
  healthCheckVmsWithTags: [],
22
+ healthCheckTimeout: '10m',
22
23
  maxExportRate: 0,
23
24
  maxMergedDeltasPerRun: Infinity,
24
25
  nRetriesVmBackupFailures: 0,
@@ -24,6 +24,7 @@ const DEFAULT_XAPI_VM_SETTINGS = {
24
24
  fullInterval: 0,
25
25
  healthCheckSr: undefined,
26
26
  healthCheckVmsWithTags: [],
27
+ healthCheckTimeout: '10m',
27
28
  maxExportRate: 0,
28
29
  maxMergedDeltasPerRun: Infinity,
29
30
  nRetriesVmBackupFailures: 0,
@@ -8,6 +8,7 @@ import { HealthCheckVmBackup } from '../../HealthCheckVmBackup.mjs'
8
8
  import { ImportVmBackup } from '../../ImportVmBackup.mjs'
9
9
  import { Task } from '../../Task.mjs'
10
10
  import * as MergeWorker from '../../merge-worker/index.mjs'
11
+ import ms from 'ms'
11
12
 
12
13
  const { info, warn } = createLogger('xo:backups:MixinBackupWriter')
13
14
 
@@ -107,8 +108,10 @@ export const MixinRemoteWriter = (BaseClass = Object) =>
107
108
  restoredVm = await xapi.waitObject(restoredId)
108
109
  }
109
110
  try {
111
+ const timeout = ms(this._settings.healthCheckTimeout)
110
112
  await new HealthCheckVmBackup({
111
113
  restoredVm,
114
+ timeout,
112
115
  xapi,
113
116
  }).run()
114
117
  } finally {
@@ -3,6 +3,7 @@ import assert from 'node:assert/strict'
3
3
 
4
4
  import { HealthCheckVmBackup } from '../../HealthCheckVmBackup.mjs'
5
5
  import { Task } from '../../Task.mjs'
6
+ import ms from 'ms'
6
7
 
7
8
  export const MixinXapiWriter = (BaseClass = Object) =>
8
9
  class MixinXapiWriter extends BaseClass {
@@ -70,8 +71,10 @@ export const MixinXapiWriter = (BaseClass = Object) =>
70
71
  const healthCheckVm =
71
72
  xapi.getObject(healthCheckVmRef, undefined) ?? (await xapi.waitObject(healthCheckVmRef))
72
73
  await healthCheckVm.add_tags('xo:no-bak=Health Check')
74
+ const timeout = ms(this._settings.healthCheckTimeout)
73
75
  await new HealthCheckVmBackup({
74
76
  restoredVm: healthCheckVm,
77
+ timeout,
75
78
  xapi,
76
79
  }).run()
77
80
  } finally {
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.46.1",
11
+ "version": "0.48.0",
12
12
  "engines": {
13
13
  "node": ">=14.18"
14
14
  },
@@ -36,8 +36,10 @@
36
36
  "d3-time-format": "^4.1.0",
37
37
  "decorator-synchronized": "^0.6.0",
38
38
  "golike-defer": "^0.5.1",
39
+ "human-format": "^1.2.0",
39
40
  "limit-concurrency-decorator": "^0.5.0",
40
41
  "lodash": "^4.17.20",
42
+ "ms": "^2.1.3",
41
43
  "node-zone": "^0.4.0",
42
44
  "parse-pairs": "^2.0.0",
43
45
  "promise-toolbox": "^0.21.0",
@@ -56,7 +58,7 @@
56
58
  "tmp": "^0.2.1"
57
59
  },
58
60
  "peerDependencies": {
59
- "@xen-orchestra/xapi": "^5.0.0"
61
+ "@xen-orchestra/xapi": "^5.0.1"
60
62
  },
61
63
  "license": "AGPL-3.0-or-later",
62
64
  "author": {