@xen-orchestra/backups 0.27.2 → 0.27.3
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/_cleanVm.js +25 -9
- package/package.json +2 -2
package/_cleanVm.js
CHANGED
|
@@ -13,6 +13,7 @@ const { limitConcurrency } = require('limit-concurrency-decorator')
|
|
|
13
13
|
|
|
14
14
|
const { Task } = require('./Task.js')
|
|
15
15
|
const { Disposable } = require('promise-toolbox')
|
|
16
|
+
const handlerPath = require('@xen-orchestra/fs/path')
|
|
16
17
|
|
|
17
18
|
// checking the size of a vhd directory is costly
|
|
18
19
|
// 1 Http Query per 1000 blocks
|
|
@@ -86,7 +87,7 @@ async function mergeVhdChain(chain, { handler, logInfo, remove, merge }) {
|
|
|
86
87
|
const noop = Function.prototype
|
|
87
88
|
|
|
88
89
|
const INTERRUPTED_VHDS_REG = /^\.(.+)\.merge.json$/
|
|
89
|
-
const listVhds = async (handler, vmDir) => {
|
|
90
|
+
const listVhds = async (handler, vmDir, logWarn) => {
|
|
90
91
|
const vhds = new Set()
|
|
91
92
|
const aliases = {}
|
|
92
93
|
const interruptedVhds = new Map()
|
|
@@ -106,12 +107,23 @@ const listVhds = async (handler, vmDir) => {
|
|
|
106
107
|
filter: file => isVhdFile(file) || INTERRUPTED_VHDS_REG.test(file),
|
|
107
108
|
})
|
|
108
109
|
aliases[vdiDir] = list.filter(vhd => isVhdAlias(vhd)).map(file => `${vdiDir}/${file}`)
|
|
109
|
-
|
|
110
|
+
|
|
111
|
+
await asyncMap(list, async file => {
|
|
110
112
|
const res = INTERRUPTED_VHDS_REG.exec(file)
|
|
111
113
|
if (res === null) {
|
|
112
114
|
vhds.add(`${vdiDir}/${file}`)
|
|
113
115
|
} else {
|
|
114
|
-
|
|
116
|
+
try {
|
|
117
|
+
const mergeState = JSON.parse(await handler.readFile(file))
|
|
118
|
+
interruptedVhds.set(`${vdiDir}/${res[1]}`, {
|
|
119
|
+
statePath: `${vdiDir}/${file}`,
|
|
120
|
+
chain: mergeState.chain,
|
|
121
|
+
})
|
|
122
|
+
} catch (error) {
|
|
123
|
+
// fall back to a non resuming merge
|
|
124
|
+
vhds.add(`${vdiDir}/${file}`)
|
|
125
|
+
logWarn('failed to read existing merge state', { path: file, error })
|
|
126
|
+
}
|
|
115
127
|
}
|
|
116
128
|
})
|
|
117
129
|
}
|
|
@@ -197,7 +209,7 @@ exports.cleanVm = async function cleanVm(
|
|
|
197
209
|
const vhdParents = { __proto__: null }
|
|
198
210
|
const vhdChildren = { __proto__: null }
|
|
199
211
|
|
|
200
|
-
const { vhds, interruptedVhds, aliases } = await listVhds(handler, vmDir)
|
|
212
|
+
const { vhds, interruptedVhds, aliases } = await listVhds(handler, vmDir, logWarn)
|
|
201
213
|
|
|
202
214
|
// remove broken VHDs
|
|
203
215
|
await asyncMap(vhds, async path => {
|
|
@@ -232,8 +244,6 @@ exports.cleanVm = async function cleanVm(
|
|
|
232
244
|
} else {
|
|
233
245
|
logWarn('same ids but different content')
|
|
234
246
|
}
|
|
235
|
-
} else {
|
|
236
|
-
logInfo('not duplicate', UUID.stringify(vhd.footer.uuid), path)
|
|
237
247
|
}
|
|
238
248
|
vhdById.set(UUID.stringify(vhdKept.footer.uuid), vhdKept)
|
|
239
249
|
})
|
|
@@ -250,7 +260,7 @@ exports.cleanVm = async function cleanVm(
|
|
|
250
260
|
// remove interrupted merge states for missing VHDs
|
|
251
261
|
for (const interruptedVhd of interruptedVhds.keys()) {
|
|
252
262
|
if (!vhds.has(interruptedVhd)) {
|
|
253
|
-
const statePath = interruptedVhds.get(interruptedVhd)
|
|
263
|
+
const { statePath } = interruptedVhds.get(interruptedVhd)
|
|
254
264
|
interruptedVhds.delete(interruptedVhd)
|
|
255
265
|
|
|
256
266
|
logWarn('orphan merge state', {
|
|
@@ -432,7 +442,13 @@ exports.cleanVm = async function cleanVm(
|
|
|
432
442
|
|
|
433
443
|
// merge interrupted VHDs
|
|
434
444
|
for (const parent of interruptedVhds.keys()) {
|
|
435
|
-
|
|
445
|
+
// before #6349 the chain wasn't in the mergeState
|
|
446
|
+
const { chain, statePath } = interruptedVhds.get(parent)
|
|
447
|
+
if (chain === undefined) {
|
|
448
|
+
vhdChainsToMerge[parent] = [parent, vhdChildren[parent]]
|
|
449
|
+
} else {
|
|
450
|
+
vhdChainsToMerge[parent] = chain.map(vhdPath => handlerPath.resolveFromFile(statePath, vhdPath))
|
|
451
|
+
}
|
|
436
452
|
}
|
|
437
453
|
|
|
438
454
|
Object.values(vhdChainsToMerge).forEach(chain => {
|
|
@@ -447,7 +463,7 @@ exports.cleanVm = async function cleanVm(
|
|
|
447
463
|
await asyncMap(toMerge, async chain => {
|
|
448
464
|
const merged = await limitedMergeVhdChain(chain, { handler, logInfo, logWarn, remove, merge })
|
|
449
465
|
if (merged !== undefined) {
|
|
450
|
-
const metadataPath = vhdsToJSons[chain[
|
|
466
|
+
const metadataPath = vhdsToJSons[chain[chain.length - 1]] // all the chain should have the same metada file
|
|
451
467
|
metadataWithMergedVhd[metadataPath] = true
|
|
452
468
|
}
|
|
453
469
|
})
|
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.27.
|
|
11
|
+
"version": "0.27.3",
|
|
12
12
|
"engines": {
|
|
13
13
|
"node": ">=14.6"
|
|
14
14
|
},
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"promise-toolbox": "^0.21.0",
|
|
39
39
|
"proper-lockfile": "^4.1.2",
|
|
40
40
|
"uuid": "^8.3.2",
|
|
41
|
-
"vhd-lib": "^3.3.
|
|
41
|
+
"vhd-lib": "^3.3.4",
|
|
42
42
|
"yazl": "^2.5.1"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|