@xen-orchestra/backups 0.50.0 → 0.51.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.
|
@@ -146,18 +146,9 @@ export const AbstractXapi = class AbstractXapiVmBackupRunner extends Abstract {
|
|
|
146
146
|
if (!settings.bypassVdiChainsCheck) {
|
|
147
147
|
await vm.$assertHealthyVdiChains()
|
|
148
148
|
}
|
|
149
|
-
if (settings.preferNbd) {
|
|
150
|
-
try {
|
|
151
|
-
// enable CBT on all disks if possible
|
|
152
|
-
const diskRefs = await xapi.VM_getDisks(vm.$ref)
|
|
153
|
-
await Promise.all(diskRefs.map(diskRef => xapi.call('VDI.enable_cbt', diskRef)))
|
|
154
|
-
} catch (error) {
|
|
155
|
-
Task.info(`couldn't enable CBT`, error)
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
149
|
|
|
159
150
|
const snapshotRef = await vm[settings.checkpointSnapshot ? '$checkpoint' : '$snapshot']({
|
|
160
|
-
|
|
151
|
+
ignoredVdisTag: '[NOBAK]',
|
|
161
152
|
name_label: this._getSnapshotNameLabel(vm),
|
|
162
153
|
unplugVusbs: true,
|
|
163
154
|
})
|
|
@@ -169,6 +160,7 @@ export const AbstractXapi = class AbstractXapiVmBackupRunner extends Abstract {
|
|
|
169
160
|
vmUuid: vm.uuid,
|
|
170
161
|
})
|
|
171
162
|
this._exportedVm = await xapi.getRecord('VM', snapshotRef)
|
|
163
|
+
|
|
172
164
|
return this._exportedVm.uuid
|
|
173
165
|
})
|
|
174
166
|
} else {
|
|
@@ -216,7 +208,7 @@ export const AbstractXapi = class AbstractXapiVmBackupRunner extends Abstract {
|
|
|
216
208
|
|
|
217
209
|
const snapshotsPerSchedule = groupBy(this._jobSnapshotVdis, _ => _.other_config[SCHEDULE_ID])
|
|
218
210
|
const xapi = this._xapi
|
|
219
|
-
await asyncMap(Object.entries(snapshotsPerSchedule),
|
|
211
|
+
await asyncMap(Object.entries(snapshotsPerSchedule), ([scheduleId, snapshots]) => {
|
|
220
212
|
const snapshotPerDatetime = groupBy(snapshots, _ => _.other_config[DATETIME])
|
|
221
213
|
|
|
222
214
|
const datetimes = Object.keys(snapshotPerDatetime)
|
|
@@ -230,7 +222,7 @@ export const AbstractXapi = class AbstractXapiVmBackupRunner extends Abstract {
|
|
|
230
222
|
// ensure we never delete the last one
|
|
231
223
|
const retention = Math.max(settings.snapshotRetention ?? 0, 1)
|
|
232
224
|
|
|
233
|
-
|
|
225
|
+
return asyncMap(getOldEntries(retention, datetimes), async datetime => {
|
|
234
226
|
const vdis = snapshotPerDatetime[datetime]
|
|
235
227
|
|
|
236
228
|
let vmRef
|
|
@@ -242,8 +234,8 @@ export const AbstractXapi = class AbstractXapiVmBackupRunner extends Abstract {
|
|
|
242
234
|
// this will throw error for VDI still attached to control domain
|
|
243
235
|
assert.strictEqual(vbds.length, 1, 'VDI must be free or attached to exactly one VM')
|
|
244
236
|
const vm = vbds[0].$VM
|
|
245
|
-
assert.strictEqual(vm.is_control_domain, false, `Disk is still attached to DOM0 VM`) // don't delete a VM (especially a control domain)
|
|
246
237
|
assert.strictEqual(vm.is_a_snapshot, true, `VM must be a snapshot`) // don't delete a VM (especially a control domain)
|
|
238
|
+
assert.strictEqual(vm.is_control_domain, false, `VM can't be a DOM0 VM`) // don't delete a VM (especially a control domain)
|
|
247
239
|
|
|
248
240
|
const vmRefVdi = vm.$ref
|
|
249
241
|
// same vm than other vdi of the same batch
|
|
@@ -265,33 +257,6 @@ export const AbstractXapi = class AbstractXapiVmBackupRunner extends Abstract {
|
|
|
265
257
|
}
|
|
266
258
|
})
|
|
267
259
|
})
|
|
268
|
-
|
|
269
|
-
// now that we use CBT, we can destroy the data of the snapshot used for this backup
|
|
270
|
-
// going back to a previous version of XO not supporting CBT will create a full backup
|
|
271
|
-
// this will only do something after snapshot and transfer
|
|
272
|
-
if (
|
|
273
|
-
// don't modify the VM
|
|
274
|
-
this._exportedVm?.is_a_snapshot &&
|
|
275
|
-
// user don't want to keep the snapshot data
|
|
276
|
-
this._settings.snapshotRetention === 0 &&
|
|
277
|
-
// preferNbd is not a guarantee that the backup used NBD, depending on the network configuration
|
|
278
|
-
this._settings.preferNbd &&
|
|
279
|
-
// only delete snapshost data if the config allows it
|
|
280
|
-
this.config.purgeSnapshotData
|
|
281
|
-
) {
|
|
282
|
-
Task.info('will delete snapshot data')
|
|
283
|
-
const vdiRefs = await this._xapi.VM_getDisks(this._exportedVm?.$ref)
|
|
284
|
-
await xapi.call('VM.destroy', this._exportedVm.$ref)
|
|
285
|
-
for (const vdiRef of vdiRefs) {
|
|
286
|
-
try {
|
|
287
|
-
// data_destroy will fail with a VDI_NO_CBT_METADATA error if CBT is not enabled on this VDI
|
|
288
|
-
await xapi.VDI_dataDestroy(vdiRef)
|
|
289
|
-
Task.info(`Snapshot data has been deleted`, { vdiRef })
|
|
290
|
-
} catch (error) {
|
|
291
|
-
Task.warning(`Couldn't deleted snapshot data`, { error, vdiRef })
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
260
|
}
|
|
296
261
|
|
|
297
262
|
async copy() {
|
|
@@ -52,10 +52,10 @@ export class IncrementalXapiWriter extends MixinXapiWriter(AbstractIncrementalWr
|
|
|
52
52
|
this.cleanup = task.wrapFn(this.cleanup, !hasHealthCheckSr)
|
|
53
53
|
this.healthCheck = task.wrapFn(this.healthCheck, hasHealthCheckSr)
|
|
54
54
|
|
|
55
|
-
return task.run(() => this._prepare())
|
|
55
|
+
return task.run(() => this._prepare(isFull))
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
async _prepare() {
|
|
58
|
+
async _prepare(isFull) {
|
|
59
59
|
const settings = this._settings
|
|
60
60
|
const { uuid: srUuid, $xapi: xapi } = this._sr
|
|
61
61
|
const vmUuid = this._vmUuid
|
|
@@ -67,14 +67,19 @@ export class IncrementalXapiWriter extends MixinXapiWriter(AbstractIncrementalWr
|
|
|
67
67
|
this._oldEntries = getOldEntries(settings.copyRetention - 1, listReplicatedVms(xapi, scheduleId, srUuid, vmUuid))
|
|
68
68
|
|
|
69
69
|
if (settings.deleteFirst) {
|
|
70
|
+
// we want to keep the baseVM when copying a delta
|
|
71
|
+
// even if we want to keep only one after
|
|
72
|
+
let mostRecentEntry
|
|
73
|
+
if (this._oldEntries.length > 1 && settings.copyRetention === 1 && !isFull) {
|
|
74
|
+
mostRecentEntry = this._oldEntries.pop()
|
|
75
|
+
}
|
|
70
76
|
await this._deleteOldEntries()
|
|
77
|
+
this._oldEntries = mostRecentEntry !== undefined ? [mostRecentEntry] : []
|
|
71
78
|
}
|
|
72
79
|
}
|
|
73
80
|
|
|
74
81
|
async cleanup() {
|
|
75
|
-
|
|
76
|
-
await this._deleteOldEntries()
|
|
77
|
-
}
|
|
82
|
+
await this._deleteOldEntries()
|
|
78
83
|
}
|
|
79
84
|
|
|
80
85
|
async _deleteOldEntries() {
|
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.51.0",
|
|
12
12
|
"engines": {
|
|
13
13
|
"node": ">=14.18"
|
|
14
14
|
},
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"tmp": "^0.2.1"
|
|
59
59
|
},
|
|
60
60
|
"peerDependencies": {
|
|
61
|
-
"@xen-orchestra/xapi": "^
|
|
61
|
+
"@xen-orchestra/xapi": "^7.0.0"
|
|
62
62
|
},
|
|
63
63
|
"license": "AGPL-3.0-or-later",
|
|
64
64
|
"author": {
|