diff --git a/@xen-orchestra/backups/RemoteAdapter.js b/@xen-orchestra/backups/RemoteAdapter.js index 631f8a2b2..4de36ae88 100644 --- a/@xen-orchestra/backups/RemoteAdapter.js +++ b/@xen-orchestra/backups/RemoteAdapter.js @@ -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 diff --git a/@xen-orchestra/backups/_cleanVm.js b/@xen-orchestra/backups/_cleanVm.js index 085a77407..73ddfb2fe 100644 --- a/@xen-orchestra/backups/_cleanVm.js +++ b/@xen-orchestra/backups/_cleanVm.js @@ -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`) } }) diff --git a/@xen-orchestra/backups/isValidXva.js b/@xen-orchestra/backups/_isValidXva.js similarity index 70% rename from @xen-orchestra/backups/isValidXva.js rename to @xen-orchestra/backups/_isValidXva.js index 2949a324f..e38fb4a29 100644 --- a/@xen-orchestra/backups/isValidXva.js +++ b/@xen-orchestra/backups/_isValidXva.js @@ -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 diff --git a/@xen-orchestra/backups/writers/_FullBackupWriter.js b/@xen-orchestra/backups/writers/_FullBackupWriter.js index 6e8c32512..055704492 100644 --- a/@xen-orchestra/backups/writers/_FullBackupWriter.js +++ b/@xen-orchestra/backups/writers/_FullBackupWriter.js @@ -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 } })