@xen-orchestra/backups 0.71.0 → 0.71.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.
@@ -56,62 +56,77 @@ export class IncrementalXapiWriter extends MixinXapiWriter(AbstractIncrementalWr
56
56
  })
57
57
  debug('checkBaseVdis, got snapshot candidates,', snapshotCandidates.length)
58
58
 
59
- // ensure no data have been written since this snapshot
60
- // but there may be have some other snapshot for another job
61
- let targetVmRef
62
- let canChainToTargetVm = true
63
- await asyncEach(
64
- snapshotCandidates,
65
- async snapshot => {
66
- let diffDisk
67
- try {
68
- const activeVdi = sr.$xapi.getObject(snapshot.$snapshot_of)
69
- const userVbds = activeVdi.$VBDs?.filter(vbd => vbd.$VM && !vbd.$VM.is_control_domain) ?? []
70
- if (userVbds.length !== 1) {
71
- debug('checkBaseVdis, share vbd ', { ref: snapshot.$ref, userVbds })
72
- // shared vdi ignore
73
- return
74
- }
75
- const vm = userVbds[0].$VM
76
- if (!('start' in vm.blocked_operations)) {
77
- debug('checkBaseVdis, vm not blocked', { vmRef: vm.$ref })
78
- // vm start unlocked
79
- // not really an issue since we have check the delta
80
- // but it indicates the users played with the blocked operations
81
- return
82
- }
83
- diffDisk = new XapiDiskSource({ xapi: sr.$xapi, vdiRef: activeVdi.$ref, baseRef: snapshot.$ref })
84
- await diffDisk.init()
85
- if (diffDisk.getBlockIndexes().length === 0) {
86
- const sourceUuid = snapshot.other_config?.[COPY_OF]
87
- if (sourceUuid) {
88
- this.#baseVdisBySourceUuid.set(sourceUuid, activeVdi)
59
+ if (snapshotCandidates.length > 0) {
60
+ // New snapshot-based flow (6.3+): verify no data was written between
61
+ // the target snapshot and its active VDI.
62
+ let targetVmRef
63
+ let canChainToTargetVm = true
64
+ await asyncEach(
65
+ snapshotCandidates,
66
+ async snapshot => {
67
+ let diffDisk
68
+ try {
69
+ const activeVdi = sr.$xapi.getObject(snapshot.$snapshot_of)
70
+ const userVbds = activeVdi.$VBDs?.filter(vbd => vbd.$VM && !vbd.$VM.is_control_domain) ?? []
71
+ if (userVbds.length !== 1) {
72
+ debug('checkBaseVdis, share vbd ', { ref: snapshot.$ref, userVbds })
73
+ // shared vdi ignore
74
+ return
75
+ }
76
+ const vm = userVbds[0].$VM
77
+ if (!('start' in vm.blocked_operations)) {
78
+ debug('checkBaseVdis, vm not blocked', { vmRef: vm.$ref })
79
+ // vm start unlocked
80
+ // not really an issue since we have check the delta
81
+ // but it indicates the users played with the blocked operations
82
+ return
89
83
  }
90
- // Track the target VM (the replicated VM to update on the next transfer).
91
- targetVmRef = vm.$ref
92
- } else {
93
- // not empty, we will create a new VM
94
- canChainToTargetVm = false
95
- debug('checkBaseVdis, data between snapshot and active disk', {
96
- vdiRef: snapshot.$ref,
97
- nbBlocks: diffDisk.getBlockIndexes().length,
98
- })
84
+ diffDisk = new XapiDiskSource({ xapi: sr.$xapi, vdiRef: activeVdi.$ref, baseRef: snapshot.$ref })
85
+ await diffDisk.init()
86
+ if (diffDisk.getBlockIndexes().length === 0) {
87
+ const sourceUuid = snapshot.other_config?.[COPY_OF]
88
+ if (sourceUuid) {
89
+ this.#baseVdisBySourceUuid.set(sourceUuid, activeVdi)
90
+ }
91
+ // Track the target VM (the replicated VM to update on the next transfer).
92
+ targetVmRef = vm.$ref
93
+ } else {
94
+ // not empty, we will create a new VM
95
+ canChainToTargetVm = false
96
+ debug('checkBaseVdis, data between snapshot and active disk', {
97
+ vdiRef: snapshot.$ref,
98
+ nbBlocks: diffDisk.getBlockIndexes().length,
99
+ })
100
+ }
101
+ } catch (error) {
102
+ debug('checkBaseVdis, skipping snapshot', { ref: snapshot.$ref, error })
103
+ return
104
+ } finally {
105
+ await diffDisk?.close().catch(error => debug('checkBaseVdis, error closing', error))
99
106
  }
100
- } catch (error) {
101
- debug('checkBaseVdis, skipping snapshot', { ref: snapshot.$ref, error })
102
- return
103
- } finally {
104
- await diffDisk?.close().catch(error => debug('checkBaseVdis, error closing', error))
107
+ },
108
+ {
109
+ concurrency: 4,
105
110
  }
106
- },
107
- {
108
- concurrency: 4,
109
- }
110
- )
111
+ )
111
112
 
112
- if (canChainToTargetVm && targetVmRef !== undefined) {
113
- debug('checkBaseVdis,got a valid vm target', targetVmRef)
114
- this._targetVmRef = targetVmRef
113
+ if (canChainToTargetVm && targetVmRef !== undefined) {
114
+ debug('checkBaseVdis,got a valid vm target', targetVmRef)
115
+ this._targetVmRef = targetVmRef
116
+ }
117
+ } else {
118
+ // Legacy fallback (upgrade from pre-6.3): no target snapshots exist yet,
119
+ // look for active (non-snapshot) VDIs with matching COPY_OF, like the old code did.
120
+ debug('checkBaseVdis, no snapshot candidates, falling back to legacy active VDI lookup')
121
+ const legacyVdis = sr.$VDIs.filter(vdi => {
122
+ return vdi?.managed && !vdi?.is_a_snapshot && baseUuidToSrcVdi.has(vdi?.other_config[COPY_OF])
123
+ })
124
+ for (const vdi of legacyVdis) {
125
+ const sourceUuid = vdi.other_config[COPY_OF]
126
+ if (sourceUuid) {
127
+ this.#baseVdisBySourceUuid.set(sourceUuid, vdi)
128
+ }
129
+ }
115
130
  }
116
131
 
117
132
  for (const uuid of baseUuidToSrcVdi.keys()) {
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.71.0",
11
+ "version": "0.71.1",
12
12
  "engines": {
13
13
  "node": ">=14.18"
14
14
  },