feat(backups/cleanVm): detection of interrupted merges

This commit is contained in:
badrAZ 2021-04-30 11:43:21 +02:00 committed by Julien Fontanet
parent b590e29608
commit 57ef531be0
2 changed files with 33 additions and 11 deletions

View File

@ -76,8 +76,11 @@ const mergeVhdChain = limitConcurrency(1)(async function mergeVhdChain(chain, {
const noop = Function.prototype const noop = Function.prototype
const INTERRUPTED_VHDS_REG = /^(?:(.+)\/)?\.(.+)\.merge.json$/
const listVhds = async (handler, vmDir) => { const listVhds = async (handler, vmDir) => {
const vhds = [] const vhds = []
const interruptedVhds = new Set()
await asyncMap( await asyncMap(
await handler.list(`${vmDir}/vdis`, { await handler.list(`${vmDir}/vdis`, {
ignoreMissing: true, ignoreMissing: true,
@ -88,16 +91,26 @@ const listVhds = async (handler, vmDir) => {
await handler.list(jobDir, { await handler.list(jobDir, {
prependDir: true, prependDir: true,
}), }),
async vdiDir => async vdiDir => {
vhds.push( const list = await handler.list(vdiDir, {
...(await handler.list(vdiDir, { filter: file => isVhdFile(file) || INTERRUPTED_VHDS_REG.test(file),
filter: isVhdFile, prependDir: true,
prependDir: true, })
}))
) list.forEach(file => {
const res = INTERRUPTED_VHDS_REG.exec(file)
if (res === null) {
vhds.push(file)
} else {
const [, dir, file] = res
interruptedVhds.add(`${dir}/${file}`)
}
})
}
) )
) )
return vhds
return { vhds, interruptedVhds }
} }
exports.cleanVm = async function cleanVm(vmDir, { remove, merge, onLog = noop }) { exports.cleanVm = async function cleanVm(vmDir, { remove, merge, onLog = noop }) {
@ -107,11 +120,13 @@ exports.cleanVm = async function cleanVm(vmDir, { remove, merge, onLog = noop })
const vhdParents = { __proto__: null } const vhdParents = { __proto__: null }
const vhdChildren = { __proto__: null } const vhdChildren = { __proto__: null }
const vhdsList = await listVhds(handler, vmDir)
// remove broken VHDs // remove broken VHDs
await asyncMap(await listVhds(handler, vmDir), async path => { await asyncMap(vhdsList.vhds, async path => {
try { try {
const vhd = new Vhd(handler, path) const vhd = new Vhd(handler, path)
await vhd.readHeaderAndFooter() await vhd.readHeaderAndFooter(!vhdsList.interruptedVhds.has(path))
vhds.add(path) vhds.add(path)
if (vhd.footer.diskType === DISK_TYPE_DIFFERENCING) { if (vhd.footer.diskType === DISK_TYPE_DIFFERENCING) {
const parent = resolve('/', dirname(path), vhd.header.parentUnicodeName) const parent = resolve('/', dirname(path), vhd.header.parentUnicodeName)
@ -279,6 +294,13 @@ exports.cleanVm = async function cleanVm(vmDir, { remove, merge, onLog = noop })
vhdChainsToMerge[vhd] = getUsedChildChainOrDelete(vhd) vhdChainsToMerge[vhd] = getUsedChildChainOrDelete(vhd)
}) })
// merge interrupted VHDs
if (merge) {
vhdsList.interruptedVhds.forEach(parent => {
vhdChainsToMerge[parent] = [vhdChildren[parent], parent]
})
}
Object.keys(vhdChainsToMerge).forEach(key => { Object.keys(vhdChainsToMerge).forEach(key => {
const chain = vhdChainsToMerge[key] const chain = vhdChainsToMerge[key]
if (chain !== undefined) { if (chain !== undefined) {

View File

@ -29,4 +29,4 @@
> In case of conflict, the highest (lowest in previous list) `$version` wins. > In case of conflict, the highest (lowest in previous list) `$version` wins.
- @xen-orchestra/fs minor - @xen-orchestra/fs minor
- @xen-orchestra/backups patch - @xen-orchestra/backups minor