@xen-orchestra/backups 0.43.2 → 0.44.1
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/ImportVmBackup.mjs +48 -7
- package/_incrementalVm.mjs +14 -80
- package/_runners/_vmRunners/_forkDeltaExport.mjs +5 -5
- package/_runners/_writers/IncrementalRemoteWriter.mjs +2 -1
- package/_runners/_writers/IncrementalXapiWriter.mjs +53 -13
- package/_runners/_writers/_MixinRemoteWriter.mjs +3 -0
- package/_runners/_writers/_MixinXapiWriter.mjs +1 -1
- package/package.json +7 -7
package/ImportVmBackup.mjs
CHANGED
|
@@ -5,22 +5,57 @@ import { importIncrementalVm } from './_incrementalVm.mjs'
|
|
|
5
5
|
import { Task } from './Task.mjs'
|
|
6
6
|
import { watchStreamSize } from './_watchStreamSize.mjs'
|
|
7
7
|
|
|
8
|
+
async function resolveUuid(xapi, cache, uuid, type) {
|
|
9
|
+
if (uuid == null) {
|
|
10
|
+
return uuid
|
|
11
|
+
}
|
|
12
|
+
const ref = cache.get(uuid)
|
|
13
|
+
if (ref === undefined) {
|
|
14
|
+
cache.set(uuid, xapi.call(`${type}.get_by_uuid`, uuid))
|
|
15
|
+
}
|
|
16
|
+
return cache.get(uuid)
|
|
17
|
+
}
|
|
8
18
|
export class ImportVmBackup {
|
|
9
|
-
constructor({
|
|
19
|
+
constructor({
|
|
20
|
+
adapter,
|
|
21
|
+
metadata,
|
|
22
|
+
srUuid,
|
|
23
|
+
xapi,
|
|
24
|
+
settings: { additionnalVmTag, newMacAddresses, mapVdisSrs = {} } = {},
|
|
25
|
+
}) {
|
|
10
26
|
this._adapter = adapter
|
|
11
|
-
this._importIncrementalVmSettings = { newMacAddresses, mapVdisSrs }
|
|
27
|
+
this._importIncrementalVmSettings = { additionnalVmTag, newMacAddresses, mapVdisSrs }
|
|
12
28
|
this._metadata = metadata
|
|
13
29
|
this._srUuid = srUuid
|
|
14
30
|
this._xapi = xapi
|
|
15
31
|
}
|
|
16
32
|
|
|
33
|
+
async #decorateIncrementalVmMetadata(backup) {
|
|
34
|
+
const { additionnalVmTag, mapVdisSrs } = this._importIncrementalVmSettings
|
|
35
|
+
const xapi = this._xapi
|
|
36
|
+
|
|
37
|
+
const cache = new Map()
|
|
38
|
+
const mapVdisSrRefs = {}
|
|
39
|
+
if (additionnalVmTag !== undefined) {
|
|
40
|
+
backup.vm.tags.push(additionnalVmTag)
|
|
41
|
+
}
|
|
42
|
+
for (const [vdiUuid, srUuid] of Object.entries(mapVdisSrs)) {
|
|
43
|
+
mapVdisSrRefs[vdiUuid] = await resolveUuid(xapi, cache, srUuid, 'SR')
|
|
44
|
+
}
|
|
45
|
+
const srRef = await resolveUuid(xapi, cache, this._srUuid, 'SR')
|
|
46
|
+
Object.values(backup.vdis).forEach(vdi => {
|
|
47
|
+
vdi.SR = mapVdisSrRefs[vdi.uuid] ?? srRef
|
|
48
|
+
})
|
|
49
|
+
return backup
|
|
50
|
+
}
|
|
51
|
+
|
|
17
52
|
async run() {
|
|
18
53
|
const adapter = this._adapter
|
|
19
54
|
const metadata = this._metadata
|
|
20
55
|
const isFull = metadata.mode === 'full'
|
|
21
56
|
|
|
22
57
|
const sizeContainer = { size: 0 }
|
|
23
|
-
|
|
58
|
+
const { mapVdisSrs, newMacAddresses } = this._importIncrementalVmSettings
|
|
24
59
|
let backup
|
|
25
60
|
if (isFull) {
|
|
26
61
|
backup = await adapter.readFullVmBackup(metadata)
|
|
@@ -29,11 +64,11 @@ export class ImportVmBackup {
|
|
|
29
64
|
assert.strictEqual(metadata.mode, 'delta')
|
|
30
65
|
|
|
31
66
|
const ignoredVdis = new Set(
|
|
32
|
-
Object.entries(
|
|
67
|
+
Object.entries(mapVdisSrs)
|
|
33
68
|
.filter(([_, srUuid]) => srUuid === null)
|
|
34
69
|
.map(([vdiUuid]) => vdiUuid)
|
|
35
70
|
)
|
|
36
|
-
backup = await adapter.readIncrementalVmBackup(metadata, ignoredVdis)
|
|
71
|
+
backup = await this.#decorateIncrementalVmMetadata(await adapter.readIncrementalVmBackup(metadata, ignoredVdis))
|
|
37
72
|
Object.values(backup.streams).forEach(stream => watchStreamSize(stream, sizeContainer))
|
|
38
73
|
}
|
|
39
74
|
|
|
@@ -48,8 +83,7 @@ export class ImportVmBackup {
|
|
|
48
83
|
const vmRef = isFull
|
|
49
84
|
? await xapi.VM_import(backup, srRef)
|
|
50
85
|
: await importIncrementalVm(backup, await xapi.getRecord('SR', srRef), {
|
|
51
|
-
|
|
52
|
-
detectBase: false,
|
|
86
|
+
newMacAddresses,
|
|
53
87
|
})
|
|
54
88
|
|
|
55
89
|
await Promise.all([
|
|
@@ -59,6 +93,13 @@ export class ImportVmBackup {
|
|
|
59
93
|
vmRef,
|
|
60
94
|
`${metadata.vm.name_label} (${formatFilenameDate(metadata.timestamp)})`
|
|
61
95
|
),
|
|
96
|
+
xapi.call(
|
|
97
|
+
'VM.set_name_description',
|
|
98
|
+
vmRef,
|
|
99
|
+
`Restored on ${formatFilenameDate(+new Date())} from ${adapter._handler._remote.name} -
|
|
100
|
+
${metadata.vm.name_description}
|
|
101
|
+
`
|
|
102
|
+
),
|
|
62
103
|
])
|
|
63
104
|
|
|
64
105
|
return {
|
package/_incrementalVm.mjs
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import find from 'lodash/find.js'
|
|
2
1
|
import groupBy from 'lodash/groupBy.js'
|
|
3
2
|
import ignoreErrors from 'promise-toolbox/ignoreErrors'
|
|
4
3
|
import omit from 'lodash/omit.js'
|
|
@@ -12,24 +11,18 @@ import { cancelableMap } from './_cancelableMap.mjs'
|
|
|
12
11
|
import { Task } from './Task.mjs'
|
|
13
12
|
import pick from 'lodash/pick.js'
|
|
14
13
|
|
|
14
|
+
// in `other_config` of an incrementally replicated VM, contains the UUID of the source VM
|
|
15
15
|
export const TAG_BASE_DELTA = 'xo:base_delta'
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
// in `other_config` of an incrementally replicated VM, contains the UUID of the target SR used for replication
|
|
18
|
+
//
|
|
19
|
+
// added after the complete replication
|
|
20
|
+
export const TAG_BACKUP_SR = 'xo:backup:sr'
|
|
18
21
|
|
|
19
|
-
|
|
22
|
+
// in other_config of VDIs of an incrementally replicated VM, contains the UUID of the source VDI
|
|
23
|
+
export const TAG_COPY_SRC = 'xo:copy_of'
|
|
20
24
|
|
|
21
25
|
const ensureArray = value => (value === undefined ? [] : Array.isArray(value) ? value : [value])
|
|
22
|
-
const resolveUuid = async (xapi, cache, uuid, type) => {
|
|
23
|
-
if (uuid == null) {
|
|
24
|
-
return uuid
|
|
25
|
-
}
|
|
26
|
-
let ref = cache.get(uuid)
|
|
27
|
-
if (ref === undefined) {
|
|
28
|
-
ref = await xapi.call(`${type}.get_by_uuid`, uuid)
|
|
29
|
-
cache.set(uuid, ref)
|
|
30
|
-
}
|
|
31
|
-
return ref
|
|
32
|
-
}
|
|
33
26
|
|
|
34
27
|
export async function exportIncrementalVm(
|
|
35
28
|
vm,
|
|
@@ -147,7 +140,7 @@ export const importIncrementalVm = defer(async function importIncrementalVm(
|
|
|
147
140
|
$defer,
|
|
148
141
|
incrementalVm,
|
|
149
142
|
sr,
|
|
150
|
-
{ cancelToken = CancelToken.none,
|
|
143
|
+
{ cancelToken = CancelToken.none, newMacAddresses = false } = {}
|
|
151
144
|
) {
|
|
152
145
|
const { version } = incrementalVm
|
|
153
146
|
if (compareVersions(version, '1.0.0') < 0) {
|
|
@@ -157,35 +150,6 @@ export const importIncrementalVm = defer(async function importIncrementalVm(
|
|
|
157
150
|
const vmRecord = incrementalVm.vm
|
|
158
151
|
const xapi = sr.$xapi
|
|
159
152
|
|
|
160
|
-
let baseVm
|
|
161
|
-
if (detectBase) {
|
|
162
|
-
const remoteBaseVmUuid = vmRecord.other_config[TAG_BASE_DELTA]
|
|
163
|
-
if (remoteBaseVmUuid) {
|
|
164
|
-
baseVm = find(
|
|
165
|
-
xapi.objects.all,
|
|
166
|
-
obj => (obj = obj.other_config) && obj[TAG_COPY_SRC] === remoteBaseVmUuid && obj[TAG_BACKUP_SR] === sr.$id
|
|
167
|
-
)
|
|
168
|
-
|
|
169
|
-
if (!baseVm) {
|
|
170
|
-
throw new Error(`could not find the base VM (copy of ${remoteBaseVmUuid})`)
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
const cache = new Map()
|
|
176
|
-
const mapVdisSrRefs = {}
|
|
177
|
-
for (const [vdiUuid, srUuid] of Object.entries(mapVdisSrs)) {
|
|
178
|
-
mapVdisSrRefs[vdiUuid] = await resolveUuid(xapi, cache, srUuid, 'SR')
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
const baseVdis = {}
|
|
182
|
-
baseVm &&
|
|
183
|
-
baseVm.$VBDs.forEach(vbd => {
|
|
184
|
-
const vdi = vbd.$VDI
|
|
185
|
-
if (vdi !== undefined) {
|
|
186
|
-
baseVdis[vbd.VDI] = vbd.$VDI
|
|
187
|
-
}
|
|
188
|
-
})
|
|
189
153
|
const vdiRecords = incrementalVm.vdis
|
|
190
154
|
|
|
191
155
|
// 0. Create suspend_VDI
|
|
@@ -197,18 +161,7 @@ export const importIncrementalVm = defer(async function importIncrementalVm(
|
|
|
197
161
|
vm: pick(vmRecord, 'uuid', 'name_label', 'suspend_VDI'),
|
|
198
162
|
})
|
|
199
163
|
} else {
|
|
200
|
-
suspendVdi = await xapi.getRecord(
|
|
201
|
-
'VDI',
|
|
202
|
-
await xapi.VDI_create({
|
|
203
|
-
...vdi,
|
|
204
|
-
other_config: {
|
|
205
|
-
...vdi.other_config,
|
|
206
|
-
[TAG_BASE_DELTA]: undefined,
|
|
207
|
-
[TAG_COPY_SRC]: vdi.uuid,
|
|
208
|
-
},
|
|
209
|
-
sr: mapVdisSrRefs[vdi.uuid] ?? sr.$ref,
|
|
210
|
-
})
|
|
211
|
-
)
|
|
164
|
+
suspendVdi = await xapi.getRecord('VDI', await xapi.VDI_create(vdi))
|
|
212
165
|
$defer.onFailure(() => suspendVdi.$destroy())
|
|
213
166
|
}
|
|
214
167
|
}
|
|
@@ -226,10 +179,6 @@ export const importIncrementalVm = defer(async function importIncrementalVm(
|
|
|
226
179
|
ha_always_run: false,
|
|
227
180
|
is_a_template: false,
|
|
228
181
|
name_label: '[Importing…] ' + vmRecord.name_label,
|
|
229
|
-
other_config: {
|
|
230
|
-
...vmRecord.other_config,
|
|
231
|
-
[TAG_COPY_SRC]: vmRecord.uuid,
|
|
232
|
-
},
|
|
233
182
|
},
|
|
234
183
|
{
|
|
235
184
|
bios_strings: vmRecord.bios_strings,
|
|
@@ -250,14 +199,8 @@ export const importIncrementalVm = defer(async function importIncrementalVm(
|
|
|
250
199
|
const vdi = vdiRecords[vdiRef]
|
|
251
200
|
let newVdi
|
|
252
201
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
const baseVdi = find(baseVdis, vdi => vdi.other_config[TAG_COPY_SRC] === remoteBaseVdiUuid)
|
|
256
|
-
if (!baseVdi) {
|
|
257
|
-
throw new Error(`missing base VDI (copy of ${remoteBaseVdiUuid})`)
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
newVdi = await xapi.getRecord('VDI', await baseVdi.$clone())
|
|
202
|
+
if (vdi.baseVdi !== undefined) {
|
|
203
|
+
newVdi = await xapi.getRecord('VDI', await vdi.baseVdi.$clone())
|
|
261
204
|
$defer.onFailure(() => newVdi.$destroy())
|
|
262
205
|
|
|
263
206
|
await newVdi.update_other_config(TAG_COPY_SRC, vdi.uuid)
|
|
@@ -268,18 +211,7 @@ export const importIncrementalVm = defer(async function importIncrementalVm(
|
|
|
268
211
|
// suspendVDI has already created
|
|
269
212
|
newVdi = suspendVdi
|
|
270
213
|
} else {
|
|
271
|
-
newVdi = await xapi.getRecord(
|
|
272
|
-
'VDI',
|
|
273
|
-
await xapi.VDI_create({
|
|
274
|
-
...vdi,
|
|
275
|
-
other_config: {
|
|
276
|
-
...vdi.other_config,
|
|
277
|
-
[TAG_BASE_DELTA]: undefined,
|
|
278
|
-
[TAG_COPY_SRC]: vdi.uuid,
|
|
279
|
-
},
|
|
280
|
-
SR: mapVdisSrRefs[vdi.uuid] ?? sr.$ref,
|
|
281
|
-
})
|
|
282
|
-
)
|
|
214
|
+
newVdi = await xapi.getRecord('VDI', await xapi.VDI_create(vdi))
|
|
283
215
|
$defer.onFailure(() => newVdi.$destroy())
|
|
284
216
|
}
|
|
285
217
|
|
|
@@ -324,7 +256,9 @@ export const importIncrementalVm = defer(async function importIncrementalVm(
|
|
|
324
256
|
if (stream.length === undefined) {
|
|
325
257
|
stream = await createVhdStreamWithLength(stream)
|
|
326
258
|
}
|
|
259
|
+
await xapi.setField('VDI', vdi.$ref, 'name_label', `[Importing] ${vdiRecords[id].name_label}`)
|
|
327
260
|
await vdi.$importContent(stream, { cancelToken, format: 'vhd' })
|
|
261
|
+
await xapi.setField('VDI', vdi.$ref, 'name_label', vdiRecords[id].name_label)
|
|
328
262
|
}
|
|
329
263
|
}),
|
|
330
264
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
+
import cloneDeep from 'lodash/cloneDeep.js'
|
|
1
2
|
import mapValues from 'lodash/mapValues.js'
|
|
2
3
|
|
|
3
4
|
import { forkStreamUnpipe } from '../_forkStreamUnpipe.mjs'
|
|
4
5
|
|
|
5
6
|
export function forkDeltaExport(deltaExport) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
})
|
|
7
|
+
const { streams, ...rest } = deltaExport
|
|
8
|
+
const newMetadata = cloneDeep(rest)
|
|
9
|
+
newMetadata.streams = mapValues(streams, forkStreamUnpipe)
|
|
10
|
+
return newMetadata
|
|
11
11
|
}
|
|
@@ -11,6 +11,7 @@ import { dirname } from 'node:path'
|
|
|
11
11
|
|
|
12
12
|
import { formatFilenameDate } from '../../_filenameDate.mjs'
|
|
13
13
|
import { getOldEntries } from '../../_getOldEntries.mjs'
|
|
14
|
+
import { TAG_BASE_DELTA } from '../../_incrementalVm.mjs'
|
|
14
15
|
import { Task } from '../../Task.mjs'
|
|
15
16
|
|
|
16
17
|
import { MixinRemoteWriter } from './_MixinRemoteWriter.mjs'
|
|
@@ -195,7 +196,7 @@ export class IncrementalRemoteWriter extends MixinRemoteWriter(AbstractIncrement
|
|
|
195
196
|
assert.notStrictEqual(
|
|
196
197
|
parentPath,
|
|
197
198
|
undefined,
|
|
198
|
-
`missing parent of ${id} in ${dirname(path)}, looking for ${vdi.other_config[
|
|
199
|
+
`missing parent of ${id} in ${dirname(path)}, looking for ${vdi.other_config[TAG_BASE_DELTA]}`
|
|
199
200
|
)
|
|
200
201
|
|
|
201
202
|
parentPath = parentPath.slice(1) // remove leading slash
|
|
@@ -4,12 +4,13 @@ import { formatDateTime } from '@xen-orchestra/xapi'
|
|
|
4
4
|
|
|
5
5
|
import { formatFilenameDate } from '../../_filenameDate.mjs'
|
|
6
6
|
import { getOldEntries } from '../../_getOldEntries.mjs'
|
|
7
|
-
import { importIncrementalVm, TAG_COPY_SRC } from '../../_incrementalVm.mjs'
|
|
7
|
+
import { importIncrementalVm, TAG_BACKUP_SR, TAG_BASE_DELTA, TAG_COPY_SRC } from '../../_incrementalVm.mjs'
|
|
8
8
|
import { Task } from '../../Task.mjs'
|
|
9
9
|
|
|
10
10
|
import { AbstractIncrementalWriter } from './_AbstractIncrementalWriter.mjs'
|
|
11
11
|
import { MixinXapiWriter } from './_MixinXapiWriter.mjs'
|
|
12
12
|
import { listReplicatedVms } from './_listReplicatedVms.mjs'
|
|
13
|
+
import find from 'lodash/find.js'
|
|
13
14
|
|
|
14
15
|
export class IncrementalXapiWriter extends MixinXapiWriter(AbstractIncrementalWriter) {
|
|
15
16
|
async checkBaseVdis(baseUuidToSrcVdi, baseVm) {
|
|
@@ -81,6 +82,54 @@ export class IncrementalXapiWriter extends MixinXapiWriter(AbstractIncrementalWr
|
|
|
81
82
|
return asyncMapSettled(this._oldEntries, vm => vm.$destroy())
|
|
82
83
|
}
|
|
83
84
|
|
|
85
|
+
#decorateVmMetadata(backup) {
|
|
86
|
+
const { _warmMigration } = this._settings
|
|
87
|
+
const sr = this._sr
|
|
88
|
+
const xapi = sr.$xapi
|
|
89
|
+
const vm = backup.vm
|
|
90
|
+
vm.other_config[TAG_COPY_SRC] = vm.uuid
|
|
91
|
+
const remoteBaseVmUuid = vm.other_config[TAG_BASE_DELTA]
|
|
92
|
+
let baseVm
|
|
93
|
+
if (remoteBaseVmUuid) {
|
|
94
|
+
baseVm = find(
|
|
95
|
+
xapi.objects.all,
|
|
96
|
+
obj => (obj = obj.other_config) && obj[TAG_COPY_SRC] === remoteBaseVmUuid && obj[TAG_BACKUP_SR] === sr.$id
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
if (!baseVm) {
|
|
100
|
+
throw new Error(`could not find the base VM (copy of ${remoteBaseVmUuid})`)
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
const baseVdis = {}
|
|
104
|
+
baseVm?.$VBDs.forEach(vbd => {
|
|
105
|
+
const vdi = vbd.$VDI
|
|
106
|
+
if (vdi !== undefined) {
|
|
107
|
+
baseVdis[vbd.VDI] = vbd.$VDI
|
|
108
|
+
}
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
vm.other_config[TAG_COPY_SRC] = vm.uuid
|
|
112
|
+
if (!_warmMigration) {
|
|
113
|
+
vm.tags.push('Continuous Replication')
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
Object.values(backup.vdis).forEach(vdi => {
|
|
117
|
+
vdi.other_config[TAG_COPY_SRC] = vdi.uuid
|
|
118
|
+
vdi.SR = sr.$ref
|
|
119
|
+
// vdi.other_config[TAG_BASE_DELTA] is never defined on a suspend vdi
|
|
120
|
+
if (vdi.other_config[TAG_BASE_DELTA]) {
|
|
121
|
+
const remoteBaseVdiUuid = vdi.other_config[TAG_BASE_DELTA]
|
|
122
|
+
const baseVdi = find(baseVdis, vdi => vdi.other_config[TAG_COPY_SRC] === remoteBaseVdiUuid)
|
|
123
|
+
if (!baseVdi) {
|
|
124
|
+
throw new Error(`missing base VDI (copy of ${remoteBaseVdiUuid})`)
|
|
125
|
+
}
|
|
126
|
+
vdi.baseVdi = baseVdi
|
|
127
|
+
}
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
return backup
|
|
131
|
+
}
|
|
132
|
+
|
|
84
133
|
async _transfer({ timestamp, deltaExport, sizeContainers, vm }) {
|
|
85
134
|
const { _warmMigration } = this._settings
|
|
86
135
|
const sr = this._sr
|
|
@@ -91,16 +140,7 @@ export class IncrementalXapiWriter extends MixinXapiWriter(AbstractIncrementalWr
|
|
|
91
140
|
|
|
92
141
|
let targetVmRef
|
|
93
142
|
await Task.run({ name: 'transfer' }, async () => {
|
|
94
|
-
targetVmRef = await importIncrementalVm(
|
|
95
|
-
{
|
|
96
|
-
__proto__: deltaExport,
|
|
97
|
-
vm: {
|
|
98
|
-
...deltaExport.vm,
|
|
99
|
-
tags: _warmMigration ? deltaExport.vm.tags : [...deltaExport.vm.tags, 'Continuous Replication'],
|
|
100
|
-
},
|
|
101
|
-
},
|
|
102
|
-
sr
|
|
103
|
-
)
|
|
143
|
+
targetVmRef = await importIncrementalVm(this.#decorateVmMetadata(deltaExport), sr)
|
|
104
144
|
return {
|
|
105
145
|
size: Object.values(sizeContainers).reduce((sum, { size }) => sum + size, 0),
|
|
106
146
|
}
|
|
@@ -121,13 +161,13 @@ export class IncrementalXapiWriter extends MixinXapiWriter(AbstractIncrementalWr
|
|
|
121
161
|
)
|
|
122
162
|
),
|
|
123
163
|
targetVm.update_other_config({
|
|
124
|
-
|
|
164
|
+
[TAG_BACKUP_SR]: srUuid,
|
|
125
165
|
|
|
126
166
|
// these entries need to be added in case of offline backup
|
|
127
167
|
'xo:backup:datetime': formatDateTime(timestamp),
|
|
128
168
|
'xo:backup:job': job.id,
|
|
129
169
|
'xo:backup:schedule': scheduleId,
|
|
130
|
-
|
|
170
|
+
[TAG_BASE_DELTA]: vm.uuid,
|
|
131
171
|
}),
|
|
132
172
|
])
|
|
133
173
|
}
|
|
@@ -58,7 +58,7 @@ export const MixinXapiWriter = (BaseClass = Object) =>
|
|
|
58
58
|
)
|
|
59
59
|
}
|
|
60
60
|
const healthCheckVm = xapi.getObject(healthCheckVmRef) ?? (await xapi.waitObject(healthCheckVmRef))
|
|
61
|
-
|
|
61
|
+
await healthCheckVm.add_tag('xo:no-bak=Health Check')
|
|
62
62
|
await new HealthCheckVmBackup({
|
|
63
63
|
restoredVm: healthCheckVm,
|
|
64
64
|
xapi,
|
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.
|
|
11
|
+
"version": "0.44.1",
|
|
12
12
|
"engines": {
|
|
13
13
|
"node": ">=14.18"
|
|
14
14
|
},
|
|
@@ -23,12 +23,12 @@
|
|
|
23
23
|
"@vates/cached-dns.lookup": "^1.0.0",
|
|
24
24
|
"@vates/compose": "^2.1.0",
|
|
25
25
|
"@vates/decorate-with": "^2.0.0",
|
|
26
|
-
"@vates/disposable": "^0.1.
|
|
26
|
+
"@vates/disposable": "^0.1.5",
|
|
27
27
|
"@vates/fuse-vhd": "^2.0.0",
|
|
28
|
-
"@vates/nbd-client": "^2.0.
|
|
28
|
+
"@vates/nbd-client": "^2.0.1",
|
|
29
29
|
"@vates/parse-duration": "^0.1.1",
|
|
30
30
|
"@xen-orchestra/async-map": "^0.1.2",
|
|
31
|
-
"@xen-orchestra/fs": "^4.1.
|
|
31
|
+
"@xen-orchestra/fs": "^4.1.3",
|
|
32
32
|
"@xen-orchestra/log": "^0.6.0",
|
|
33
33
|
"@xen-orchestra/template": "^0.1.0",
|
|
34
34
|
"app-conf": "^2.3.0",
|
|
@@ -45,18 +45,18 @@
|
|
|
45
45
|
"tar": "^6.1.15",
|
|
46
46
|
"uuid": "^9.0.0",
|
|
47
47
|
"vhd-lib": "^4.6.1",
|
|
48
|
-
"xen-api": "^
|
|
48
|
+
"xen-api": "^2.0.0",
|
|
49
49
|
"yazl": "^2.5.1"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"fs-extra": "^11.1.0",
|
|
53
53
|
"rimraf": "^5.0.1",
|
|
54
|
-
"sinon": "^
|
|
54
|
+
"sinon": "^17.0.1",
|
|
55
55
|
"test": "^3.2.1",
|
|
56
56
|
"tmp": "^0.2.1"
|
|
57
57
|
},
|
|
58
58
|
"peerDependencies": {
|
|
59
|
-
"@xen-orchestra/xapi": "^
|
|
59
|
+
"@xen-orchestra/xapi": "^4.0.0"
|
|
60
60
|
},
|
|
61
61
|
"license": "AGPL-3.0-or-later",
|
|
62
62
|
"author": {
|