@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.
Files changed (2) hide show
  1. package/_cleanVm.js +25 -9
  2. 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
- list.forEach(file => {
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
- interruptedVhds.set(`${vdiDir}/${res[1]}`, `${vdiDir}/${file}`)
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
- vhdChainsToMerge[parent] = [vhdChildren[parent], parent]
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[0]] // all the chain should have the same metada file
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.2",
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.3",
41
+ "vhd-lib": "^3.3.4",
42
42
  "yazl": "^2.5.1"
43
43
  },
44
44
  "devDependencies": {