fix(@xen-orchestra/backups/isValidXva): move as RemoteAdapter method (#5741)
This commit is contained in:
@@ -16,6 +16,7 @@ const { BACKUP_DIR } = require('./_getVmBackupDir')
|
||||
const { cleanVm } = require('./_cleanVm')
|
||||
const { getTmpDir } = require('./_getTmpDir')
|
||||
const { isMetadataFile, isVhdFile } = require('./_backupType')
|
||||
const { isValidXva } = require('./_isValidXva')
|
||||
const { listPartitions, LVM_PARTITION_TYPE } = require('./_listPartitions')
|
||||
const { lvs, pvs } = require('./_lvm')
|
||||
|
||||
@@ -551,8 +552,11 @@ class RemoteAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
RemoteAdapter.prototype.cleanVm = function (vmDir) {
|
||||
return Disposable.use(this._handler.lock(vmDir), () => cleanVm.apply(this, arguments))
|
||||
}
|
||||
Object.assign(RemoteAdapter.prototype, {
|
||||
cleanVm(vmDir) {
|
||||
return Disposable.use(this._handler.lock(vmDir), () => cleanVm.apply(this, arguments))
|
||||
},
|
||||
isValidXva,
|
||||
})
|
||||
|
||||
exports.RemoteAdapter = RemoteAdapter
|
||||
|
||||
@@ -5,7 +5,6 @@ const { default: Vhd, mergeVhd } = require('vhd-lib')
|
||||
const { dirname, resolve } = require('path')
|
||||
const { DISK_TYPE_DIFFERENCING } = require('vhd-lib/dist/_constants')
|
||||
const { isMetadataFile, isVhdFile, isXvaFile, isXvaSumFile } = require('./_backupType')
|
||||
const { isValidXva } = require('./isValidXva')
|
||||
|
||||
// chain is an array of VHDs from child to parent
|
||||
//
|
||||
@@ -184,7 +183,7 @@ exports.cleanVm = async function cleanVm(vmDir, { remove, merge, onLog = noop })
|
||||
await asyncMap(xvas, async path => {
|
||||
// check is not good enough to delete the file, the best we can do is report
|
||||
// it
|
||||
if (!(await isValidXva(path))) {
|
||||
if (!(await this.isValidXva(path))) {
|
||||
onLog(`the XVA with path ${path} is potentially broken`)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
const assert = require('assert')
|
||||
const fs = require('fs-extra')
|
||||
|
||||
const isGzipFile = async fd => {
|
||||
const isGzipFile = async (handler, fd) => {
|
||||
// https://tools.ietf.org/html/rfc1952.html#page-5
|
||||
const magicNumber = Buffer.allocUnsafe(2)
|
||||
assert.strictEqual((await fs.read(fd, magicNumber, 0, magicNumber.length, 0)).bytesRead, magicNumber.length)
|
||||
|
||||
assert.strictEqual((await handler.read(fd, magicNumber, 0)).bytesRead, magicNumber.length)
|
||||
return magicNumber[0] === 31 && magicNumber[1] === 139
|
||||
}
|
||||
|
||||
@@ -21,32 +21,33 @@ const isGzipFile = async fd => {
|
||||
// /^Ref:\d+/\d+\.checksum$/ and then validating the tar structure from it
|
||||
//
|
||||
// https://github.com/npm/node-tar/issues/234#issuecomment-538190295
|
||||
const isValidTar = async (size, fd) => {
|
||||
const isValidTar = async (handler, size, fd) => {
|
||||
if (size <= 1024 || size % 512 !== 0) {
|
||||
return false
|
||||
}
|
||||
|
||||
const buf = Buffer.allocUnsafe(1024)
|
||||
assert.strictEqual((await fs.read(fd, buf, 0, buf.length, size - buf.length)).bytesRead, buf.length)
|
||||
assert.strictEqual((await handler.read(fd, buf, size - buf.length)).bytesRead, buf.length)
|
||||
return buf.every(_ => _ === 0)
|
||||
}
|
||||
|
||||
// TODO: find an heuristic for compressed files
|
||||
const isValidXva = async path => {
|
||||
async function isValidXva(path) {
|
||||
const handler = this._handler
|
||||
try {
|
||||
const fd = await fs.open(path, 'r')
|
||||
const fd = await handler.openFile(path, 'r')
|
||||
try {
|
||||
const { size } = await fs.fstat(fd)
|
||||
const size = await handler.getSize(fd)
|
||||
if (size < 20) {
|
||||
// neither a valid gzip not tar
|
||||
return false
|
||||
}
|
||||
|
||||
return (await isGzipFile(fd))
|
||||
return (await isGzipFile(handler, fd))
|
||||
? true // gzip files cannot be validated at this time
|
||||
: await isValidTar(size, fd)
|
||||
: await isValidTar(handler, size, fd)
|
||||
} finally {
|
||||
fs.close(fd).catch(noop)
|
||||
handler.closeFile(fd).catch(noop)
|
||||
}
|
||||
} catch (error) {
|
||||
// never throw, log and report as valid to avoid side effects
|
||||
@@ -1,7 +1,6 @@
|
||||
const { formatFilenameDate } = require('../_filenameDate')
|
||||
const { getOldEntries } = require('../_getOldEntries')
|
||||
const { getVmBackupDir } = require('../_getVmBackupDir')
|
||||
const { isValidXva } = require('../isValidXva')
|
||||
const { Task } = require('../Task')
|
||||
|
||||
const { MixinBackupWriter } = require('./_MixinBackupWriter')
|
||||
@@ -68,11 +67,7 @@ exports.FullBackupWriter = class FullBackupWriter extends MixinBackupWriter(Abst
|
||||
|
||||
await Task.run({ name: 'transfer' }, async () => {
|
||||
await adapter.outputStream(dataFilename, stream, {
|
||||
validator: tmpPath => {
|
||||
if (handler._getFilePath !== undefined) {
|
||||
return isValidXva(handler._getFilePath('/' + tmpPath))
|
||||
}
|
||||
},
|
||||
validator: tmpPath => adapter.isValidXva(tmpPath),
|
||||
})
|
||||
return { size: sizeContainer.size }
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user