fix(xo-server/backups): no checksum files for VHDs (#2761)
Because keeping them up-to-date after chainings and merges is too expensive (requires reading the whole file). In legacy backups they were keeping up-to-date and great costs and never used for verification anyway.
This commit is contained in:
parent
474a765e1b
commit
433f445e99
@ -283,19 +283,20 @@ async function waitAll<T> (
|
||||
const writeStream = async (
|
||||
input: Readable | Promise<Readable>,
|
||||
handler: RemoteHandler,
|
||||
path: string
|
||||
path: string,
|
||||
{ checksum = true }: { checksum?: boolean } = {}
|
||||
): Promise<void> => {
|
||||
input = await input
|
||||
const tmpPath = `${dirname(path)}/.${basename(path)}`
|
||||
const output = await handler.createOutputStream(tmpPath, { checksum: true })
|
||||
const output = await handler.createOutputStream(tmpPath, { checksum })
|
||||
try {
|
||||
input.pipe(output)
|
||||
await output.checksumWritten
|
||||
// $FlowFixMe
|
||||
await input.task
|
||||
await handler.rename(tmpPath, path, { checksum: true })
|
||||
await handler.rename(tmpPath, path, { checksum })
|
||||
} catch (error) {
|
||||
await handler.unlink(tmpPath)
|
||||
await handler.unlink(tmpPath, { checksum })
|
||||
throw error
|
||||
}
|
||||
}
|
||||
@ -311,8 +312,7 @@ const writeStream = async (
|
||||
// │ └─ <job UUID>
|
||||
// │ └─ <VDI UUID>
|
||||
// │ ├─ index.json // TODO
|
||||
// │ ├─ <YYYYMMDD>T<HHmmss>.vhd
|
||||
// │ └─ <YYYYMMDD>T<HHmmss>.vhd.checksum (only for deltas)
|
||||
// │ └─ <YYYYMMDD>T<HHmmss>.vhd
|
||||
// ├─ <YYYYMMDD>T<HHmmss>.json // backup metadata
|
||||
// ├─ <YYYYMMDD>T<HHmmss>.xva
|
||||
// └─ <YYYYMMDD>T<HHmmss>.xva.checksum
|
||||
@ -929,7 +929,16 @@ export default class BackupNg {
|
||||
parentPath = `${vdiDir}/${parent}`
|
||||
}
|
||||
|
||||
await writeStream(fork.streams[`${id}.vhd`](), handler, path)
|
||||
await writeStream(
|
||||
fork.streams[`${id}.vhd`](),
|
||||
handler,
|
||||
path,
|
||||
{
|
||||
// no checksum for VHDs, because they will be invalidated by
|
||||
// merges and chainings
|
||||
checksum: false,
|
||||
}
|
||||
)
|
||||
$defer.onFailure.call(handler, 'unlink', path)
|
||||
|
||||
if (isDelta) {
|
||||
@ -1062,16 +1071,8 @@ export default class BackupNg {
|
||||
$defer.onFailure.call(handler, 'unlink', path)
|
||||
|
||||
const childPath = child.path
|
||||
|
||||
await Promise.all([
|
||||
mergeVhd(handler, path, handler, childPath),
|
||||
handler.unlink(path + '.checksum'),
|
||||
])
|
||||
|
||||
await Promise.all([
|
||||
handler.rename(path, childPath),
|
||||
handler.unlink(childPath + '.checksum'),
|
||||
])
|
||||
await mergeVhd(handler, path, handler, childPath)
|
||||
await handler.rename(path, childPath)
|
||||
}
|
||||
|
||||
async _deleteVms (xapi: Xapi, vms: Vm[]): Promise<void> {
|
||||
|
@ -101,30 +101,6 @@ const getDeltaBackupNameWithoutExt = name =>
|
||||
name.slice(0, -DELTA_BACKUP_EXT_LENGTH)
|
||||
const isDeltaBackup = name => endsWith(name, DELTA_BACKUP_EXT)
|
||||
|
||||
// Checksums have been corrupted between 5.2.6 and 5.2.7.
|
||||
//
|
||||
// For a short period of time, bad checksums will be regenerated
|
||||
// instead of rejected.
|
||||
//
|
||||
// TODO: restore when enough time has passed (a week/a month).
|
||||
async function checkFileIntegrity (handler, name) {
|
||||
await handler.refreshChecksum(name)
|
||||
// let stream
|
||||
//
|
||||
// try {
|
||||
// stream = await handler.createReadStream(name, { checksum: true })
|
||||
// } catch (error) {
|
||||
// if (error.code === 'ENOENT') {
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// throw error
|
||||
// }
|
||||
//
|
||||
// stream.resume()
|
||||
// await fromEvent(stream, 'finish')
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
const listPartitions = (() => {
|
||||
@ -545,15 +521,7 @@ export default class {
|
||||
const backups = await this._listVdiBackups(handler, dir)
|
||||
for (let i = 1; i < backups.length; i++) {
|
||||
const childPath = dir + '/' + backups[i]
|
||||
const modified = await chainVhd(
|
||||
handler,
|
||||
dir + '/' + backups[i - 1],
|
||||
handler,
|
||||
childPath
|
||||
)
|
||||
if (modified) {
|
||||
await handler.refreshChecksum(childPath)
|
||||
}
|
||||
await chainVhd(handler, dir + '/' + backups[i - 1], handler, childPath)
|
||||
}
|
||||
}
|
||||
|
||||
@ -569,8 +537,6 @@ export default class {
|
||||
const timestamp = getVdiTimestamp(backups[i])
|
||||
const newFullBackup = `${dir}/${timestamp}_full.vhd`
|
||||
|
||||
await checkFileIntegrity(handler, `${dir}/${backups[i]}`)
|
||||
|
||||
let j = i
|
||||
for (; j > 0 && isDeltaVdiBackup(backups[j]); j--);
|
||||
const fullBackupId = j
|
||||
@ -585,7 +551,6 @@ export default class {
|
||||
const backup = `${dir}/${backups[j]}`
|
||||
|
||||
try {
|
||||
await checkFileIntegrity(handler, backup)
|
||||
mergedDataSize += await vhdMerge(handler, parent, handler, backup)
|
||||
} catch (e) {
|
||||
console.error('Unable to use vhd-util.', e)
|
||||
@ -666,13 +631,7 @@ export default class {
|
||||
const sizeStream = createSizeStream()
|
||||
|
||||
try {
|
||||
const targetStream = await handler.createOutputStream(backupFullPath, {
|
||||
// FIXME: Checksum is not computed for full vdi backups.
|
||||
// The problem is in the merge case, a delta merged in a full vdi
|
||||
// backup forces us to browse the resulting file =>
|
||||
// Significant transfer time on the network !
|
||||
checksum: !isFull,
|
||||
})
|
||||
const targetStream = await handler.createOutputStream(backupFullPath)
|
||||
|
||||
stream.on('error', error => targetStream.emit('error', error))
|
||||
|
||||
@ -889,10 +848,7 @@ export default class {
|
||||
|
||||
streams[`${id}.vhd`] = await Promise.all(
|
||||
mapToArray(backups, async backup =>
|
||||
handler.createReadStream(`${vdisFolder}/${backup}`, {
|
||||
checksum: true,
|
||||
ignoreMissingChecksum: true,
|
||||
})
|
||||
handler.createReadStream(`${vdisFolder}/${backup}`)
|
||||
)
|
||||
)
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user