@xen-orchestra/backups 0.38.3 → 0.39.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/RestoreMetadataBackup.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const { join, resolve } = require('node:path/posix')
|
|
4
|
+
|
|
3
5
|
const { DIR_XO_POOL_METADATA_BACKUPS } = require('./RemoteAdapter.js')
|
|
4
6
|
const { PATH_DB_DUMP } = require('./_runners/_PoolMetadataBackup.js')
|
|
5
7
|
|
|
@@ -20,7 +22,8 @@ exports.RestoreMetadataBackup = class RestoreMetadataBackup {
|
|
|
20
22
|
task: xapi.task_create('Import pool metadata'),
|
|
21
23
|
})
|
|
22
24
|
} else {
|
|
23
|
-
|
|
25
|
+
const metadata = JSON.parse(await handler.readFile(join(backupId, 'metadata.json')))
|
|
26
|
+
return String(await handler.readFile(resolve(backupId, metadata.data ?? 'data.json')))
|
|
24
27
|
}
|
|
25
28
|
}
|
|
26
29
|
}
|
package/_runners/VmsXapi.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { asyncMap } = require('@xen-orchestra/async-map')
|
|
4
|
+
const { join } = require('@xen-orchestra/fs/path')
|
|
4
5
|
|
|
5
6
|
const { DIR_XO_CONFIG_BACKUPS } = require('../RemoteAdapter.js')
|
|
6
7
|
const { formatFilenameDate } = require('../_filenameDate.js')
|
|
@@ -23,10 +24,11 @@ exports.XoMetadataBackup = class XoMetadataBackup {
|
|
|
23
24
|
const dir = `${scheduleDir}/${formatFilenameDate(timestamp)}`
|
|
24
25
|
|
|
25
26
|
const data = job.xoMetadata
|
|
26
|
-
const
|
|
27
|
+
const dataBaseName = './data.json'
|
|
27
28
|
|
|
28
29
|
const metadata = JSON.stringify(
|
|
29
30
|
{
|
|
31
|
+
data: dataBaseName,
|
|
30
32
|
jobId: job.id,
|
|
31
33
|
jobName: job.name,
|
|
32
34
|
scheduleId: schedule.id,
|
|
@@ -36,6 +38,8 @@ exports.XoMetadataBackup = class XoMetadataBackup {
|
|
|
36
38
|
null,
|
|
37
39
|
2
|
|
38
40
|
)
|
|
41
|
+
|
|
42
|
+
const dataFileName = join(dir, dataBaseName)
|
|
39
43
|
const metaDataFileName = `${dir}/metadata.json`
|
|
40
44
|
|
|
41
45
|
await asyncMap(
|
|
@@ -52,7 +56,7 @@ exports.XoMetadataBackup = class XoMetadataBackup {
|
|
|
52
56
|
async () => {
|
|
53
57
|
const handler = adapter.handler
|
|
54
58
|
const dirMode = this._config.dirMode
|
|
55
|
-
await handler.outputFile(
|
|
59
|
+
await handler.outputFile(dataFileName, data, { dirMode })
|
|
56
60
|
await handler.outputFile(metaDataFileName, metadata, {
|
|
57
61
|
dirMode,
|
|
58
62
|
})
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const assert = require('assert')
|
|
4
|
-
const map = require('lodash/map.js')
|
|
5
4
|
const mapValues = require('lodash/mapValues.js')
|
|
6
5
|
const ignoreErrors = require('promise-toolbox/ignoreErrors')
|
|
6
|
+
const { asyncEach } = require('@vates/async-each')
|
|
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')
|
|
@@ -138,7 +138,7 @@ class IncrementalRemoteWriter extends MixinRemoteWriter(AbstractIncrementalWrite
|
|
|
138
138
|
const adapter = this._adapter
|
|
139
139
|
const job = this._job
|
|
140
140
|
const scheduleId = this._scheduleId
|
|
141
|
-
|
|
141
|
+
const settings = this._settings
|
|
142
142
|
const jobId = job.id
|
|
143
143
|
const handler = adapter.handler
|
|
144
144
|
|
|
@@ -176,8 +176,9 @@ class IncrementalRemoteWriter extends MixinRemoteWriter(AbstractIncrementalWrite
|
|
|
176
176
|
}
|
|
177
177
|
const { size } = await Task.run({ name: 'transfer' }, async () => {
|
|
178
178
|
let transferSize = 0
|
|
179
|
-
await
|
|
180
|
-
|
|
179
|
+
await asyncEach(
|
|
180
|
+
Object.entries(deltaExport.vdis),
|
|
181
|
+
async ([id, vdi]) => {
|
|
181
182
|
const path = `${this._vmBackupDir}/${vhds[id]}`
|
|
182
183
|
|
|
183
184
|
const isDelta = differentialVhds[`${id}.vhd`]
|
|
@@ -223,8 +224,12 @@ class IncrementalRemoteWriter extends MixinRemoteWriter(AbstractIncrementalWrite
|
|
|
223
224
|
await vhd.readBlockAllocationTable() // required by writeFooter()
|
|
224
225
|
await vhd.writeFooter()
|
|
225
226
|
})
|
|
226
|
-
}
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
concurrency: settings.diskPerVmConcurrency,
|
|
230
|
+
}
|
|
227
231
|
)
|
|
232
|
+
|
|
228
233
|
return { size: transferSize }
|
|
229
234
|
})
|
|
230
235
|
metadataContent.size = size
|
|
@@ -14,6 +14,19 @@ exports.MixinXapiWriter = (BaseClass = Object) =>
|
|
|
14
14
|
this._sr = sr
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
// check if the base Vm has all its disk on health check sr
|
|
18
|
+
async #isAlreadyOnHealthCheckSr(baseVm) {
|
|
19
|
+
const xapi = baseVm.$xapi
|
|
20
|
+
const vdiRefs = await xapi.VM_getDisks(baseVm.$ref)
|
|
21
|
+
for (const vdiRef of vdiRefs) {
|
|
22
|
+
const vdi = xapi.getObject(vdiRef)
|
|
23
|
+
if (vdi.$SR.uuid !== this._heathCheckSr.uuid) {
|
|
24
|
+
return false
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return true
|
|
28
|
+
}
|
|
29
|
+
|
|
17
30
|
healthCheck() {
|
|
18
31
|
const sr = this._healthCheckSr
|
|
19
32
|
assert.notStrictEqual(sr, undefined, 'SR should be defined before making a health check')
|
|
@@ -25,20 +38,35 @@ exports.MixinXapiWriter = (BaseClass = Object) =>
|
|
|
25
38
|
},
|
|
26
39
|
async () => {
|
|
27
40
|
const { $xapi: xapi } = sr
|
|
28
|
-
let
|
|
41
|
+
let healthCheckVmRef
|
|
29
42
|
try {
|
|
30
43
|
const baseVm = xapi.getObject(this._targetVmRef) ?? (await xapi.waitObject(this._targetVmRef))
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
.
|
|
34
|
-
|
|
44
|
+
|
|
45
|
+
if (await this.#isAlreadyOnHealthCheckSr(baseVm)) {
|
|
46
|
+
healthCheckVmRef = await Task.run(
|
|
47
|
+
{ name: 'cloning-vm' },
|
|
48
|
+
async () =>
|
|
49
|
+
await xapi
|
|
50
|
+
.callAsync('VM.clone', this._targetVmRef, `Health Check - ${baseVm.name_label}`)
|
|
51
|
+
.then(extractOpaqueRef)
|
|
52
|
+
)
|
|
53
|
+
} else {
|
|
54
|
+
healthCheckVmRef = await Task.run(
|
|
55
|
+
{ name: 'copying-vm' },
|
|
56
|
+
async () =>
|
|
57
|
+
await xapi
|
|
58
|
+
.callAsync('VM.copy', this._targetVmRef, `Health Check - ${baseVm.name_label}`, sr.$ref)
|
|
59
|
+
.then(extractOpaqueRef)
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
const healthCheckVm = xapi.getObject(healthCheckVmRef) ?? (await xapi.waitObject(healthCheckVmRef))
|
|
35
63
|
|
|
36
64
|
await new HealthCheckVmBackup({
|
|
37
|
-
restoredVm:
|
|
65
|
+
restoredVm: healthCheckVm,
|
|
38
66
|
xapi,
|
|
39
67
|
}).run()
|
|
40
68
|
} finally {
|
|
41
|
-
|
|
69
|
+
healthCheckVmRef && (await xapi.VM_destroy(healthCheckVmRef))
|
|
42
70
|
}
|
|
43
71
|
}
|
|
44
72
|
)
|
package/package.json
CHANGED
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
"type": "git",
|
|
9
9
|
"url": "https://github.com/vatesfr/xen-orchestra.git"
|
|
10
10
|
},
|
|
11
|
-
"version": "0.
|
|
11
|
+
"version": "0.39.0",
|
|
12
12
|
"engines": {
|
|
13
|
-
"node": ">=14.
|
|
13
|
+
"node": ">=14.18"
|
|
14
14
|
},
|
|
15
15
|
"scripts": {
|
|
16
16
|
"postversion": "npm publish --access public",
|
|
@@ -24,10 +24,10 @@
|
|
|
24
24
|
"@vates/decorate-with": "^2.0.0",
|
|
25
25
|
"@vates/disposable": "^0.1.4",
|
|
26
26
|
"@vates/fuse-vhd": "^1.0.0",
|
|
27
|
-
"@vates/nbd-client": "^1.2.
|
|
27
|
+
"@vates/nbd-client": "^1.2.1",
|
|
28
28
|
"@vates/parse-duration": "^0.1.1",
|
|
29
29
|
"@xen-orchestra/async-map": "^0.1.2",
|
|
30
|
-
"@xen-orchestra/fs": "^4.0.
|
|
30
|
+
"@xen-orchestra/fs": "^4.0.1",
|
|
31
31
|
"@xen-orchestra/log": "^0.6.0",
|
|
32
32
|
"@xen-orchestra/template": "^0.1.0",
|
|
33
33
|
"compare-versions": "^5.0.1",
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"proper-lockfile": "^4.1.2",
|
|
44
44
|
"uuid": "^9.0.0",
|
|
45
45
|
"vhd-lib": "^4.5.0",
|
|
46
|
+
"xen-api": "^1.3.3",
|
|
46
47
|
"yazl": "^2.5.1"
|
|
47
48
|
},
|
|
48
49
|
"devDependencies": {
|