Compare commits

...

2 Commits

Author SHA1 Message Date
Florent Beauchamp
13d9edf4ce fix 2022-07-04 14:29:35 +02:00
Florent Beauchamp
64a6b624b7 feat(cleanVm): add recovery method for duplicated vhd uuid containing the same data 2022-07-04 09:42:15 +02:00
4 changed files with 62 additions and 0 deletions

View File

@@ -189,6 +189,7 @@ exports.cleanVm = async function cleanVm(
const vhdsToJSons = new Set()
const vhdParents = { __proto__: null }
const vhdChildren = { __proto__: null }
const vhdById = new Map()
const { vhds, interruptedVhds, aliases } = await listVhds(handler, vmDir)
@@ -208,6 +209,18 @@ exports.cleanVm = async function cleanVm(
}
vhdChildren[parent] = path
}
const duplicate = vhdById.get(vhd.footer.uuid)
if (duplicate !== undefined) {
logWarn('uuid is duplicated', { uuid: vhd.footer.uuid })
if (duplicate.containsAllDataOf(vhd)) {
logWarn(`should delete ${path}`)
} else if (vhd.containsAllDataOf(duplicate)) {
logWarn(`should delete ${duplicate._path}`)
} else {
logWarn(`same ids but different content`)
}
}
vhdById.set(vhd.footer.uuid, vhd)
})
} catch (error) {
vhds.delete(path)
@@ -218,6 +231,9 @@ exports.cleanVm = async function cleanVm(
}
}
})
// the vhd are closed at the end of the disposable
// it's unsafe to use them later
vhdById.clear()
// remove interrupted merge states for missing VHDs
for (const interruptedVhd of interruptedVhds.keys()) {

View File

@@ -29,6 +29,8 @@
<!--packages-start-->
- @xen-orchestra/backups minor
- xo-web minor
- vhd-lib minor
<!--packages-end-->

View File

@@ -275,3 +275,26 @@ it('can stream content', async () => {
}
})
})
it('can check vhd contained in on another', async () => {
const rawFile = `${tempDir}/contained`
await createRandomFile(rawFile, 4)
const containedVhdFileName = `${tempDir}/contained.vhd`
await convertFromRawToVhd(rawFile, containedVhdFileName)
const after = `${tempDir}/after`
await createRandomFile(after, 4)
fs.appendFile(rawFile, await fs.readFile(after))
const cnotainerVhdFileName = `${tempDir}/container.vhd`
await convertFromRawToVhd(rawFile, cnotainerVhdFileName)
await Disposable.use(async function* () {
const handler = yield getSyncedHandler({ url: 'file://' + tempDir })
const contained = yield openVhd(handler, 'contained.vhd')
const container = yield openVhd(handler, 'container.vhd')
expect(await contained.contains(container)).toEqual(false)
expect(await container.contains(contained)).toEqual(true)
})
})

View File

@@ -334,4 +334,25 @@ exports.VhdAbstract = class VhdAbstract {
stream.length = footer.currentSize
return stream
}
/*
* check if all the data of a child are already contained in this vhd
*/
async containsAllDataOf(child) {
await this.readBlockAllocationTable()
await child.readBlockAllocationTable()
for await (const block of child.blocks()) {
const { id, data: childData } = block
// block is in child not in parent
if (!this.containsBlock(id)) {
return false
}
const { data: parentData } = await this.readBlock(id)
if (!childData.equals(parentData)) {
return false
}
}
return true
}
}