diff --git a/CHANGELOG.md b/CHANGELOG.md index 448c2da9b..299f81047 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,8 @@ ### Released packages +- vhd-lib v0.5.0 +- vhd-cli v0.2.0 - xen-api v0.24.0 - @xen-orchestra/fs v0.6.0 - xo-server v5.33.0 diff --git a/packages/vhd-cli/package.json b/packages/vhd-cli/package.json index 45da20552..5a6b77540 100644 --- a/packages/vhd-cli/package.json +++ b/packages/vhd-cli/package.json @@ -29,6 +29,7 @@ "@xen-orchestra/fs": "^0.5.0", "cli-progress": "^2.0.0", "exec-promise": "^0.7.0", + "getopts": "^2.2.3", "struct-fu": "^1.2.0", "vhd-lib": "^0.4.0" }, diff --git a/packages/vhd-cli/src/commands/check.js b/packages/vhd-cli/src/commands/check.js index fe806f39e..d887611f2 100644 --- a/packages/vhd-cli/src/commands/check.js +++ b/packages/vhd-cli/src/commands/check.js @@ -1,12 +1,24 @@ -import Vhd from 'vhd-lib' +import Vhd, { checkVhdChain } from 'vhd-lib' +import getopts from 'getopts' import { getHandler } from '@xen-orchestra/fs' import { resolve } from 'path' -export default async args => { +const checkVhd = (handler, path) => new Vhd(handler, path).readHeaderAndFooter() + +export default async rawArgs => { + const { chain, _: args } = getopts(rawArgs, { + boolean: ['chain'], + default: { + chain: false, + }, + }) + + const check = chain ? checkVhdChain : checkVhd + const handler = getHandler({ url: 'file:///' }) for (const vhd of args) { try { - await new Vhd(handler, resolve(vhd)).readHeaderAndFooter() + await check(handler, resolve(vhd)) console.log('ok:', vhd) } catch (error) { console.error('nok:', vhd, error) diff --git a/packages/vhd-lib/src/_resolveRelativeFromFile.js b/packages/vhd-lib/src/_resolveRelativeFromFile.js new file mode 100644 index 000000000..0dd60eb84 --- /dev/null +++ b/packages/vhd-lib/src/_resolveRelativeFromFile.js @@ -0,0 +1,6 @@ +import { dirname, resolve } from 'path' + +const resolveRelativeFromFile = (file, path) => + resolve('/', dirname(file), path).slice(1) + +export { resolveRelativeFromFile as default } diff --git a/packages/vhd-lib/src/checkChain.js b/packages/vhd-lib/src/checkChain.js new file mode 100644 index 000000000..0c242d113 --- /dev/null +++ b/packages/vhd-lib/src/checkChain.js @@ -0,0 +1,16 @@ +import Vhd from './vhd' +import resolveRelativeFromFile from './_resolveRelativeFromFile' +import { DISK_TYPE_DYNAMIC } from './_constants' + +export default async function checkChain(handler, path) { + while (true) { + const vhd = new Vhd(handler, path) + await vhd.readHeaderAndFooter() + + if (vhd.footer.diskType === DISK_TYPE_DYNAMIC) { + break + } + + path = resolveRelativeFromFile(path, vhd.header.parentUnicodeName) + } +} diff --git a/packages/vhd-lib/src/createSyntheticStream.js b/packages/vhd-lib/src/createSyntheticStream.js index c79995e09..beaffd172 100644 --- a/packages/vhd-lib/src/createSyntheticStream.js +++ b/packages/vhd-lib/src/createSyntheticStream.js @@ -1,5 +1,6 @@ import asyncIteratorToStream from 'async-iterator-to-stream' -import { dirname, resolve } from 'path' + +import resolveRelativeFromFile from './_resolveRelativeFromFile' import Vhd from './vhd' import { @@ -12,9 +13,6 @@ import { import { fuFooter, fuHeader, checksumStruct } from './_structs' import { test as mapTestBit } from './_bitmap' -const resolveRelativeFromFile = (file, path) => - resolve('/', dirname(file), path).slice(1) - export default async function createSyntheticStream(handler, path) { const fds = [] const cleanup = () => { diff --git a/packages/vhd-lib/src/index.js b/packages/vhd-lib/src/index.js index f7122aebf..dcbe20080 100644 --- a/packages/vhd-lib/src/index.js +++ b/packages/vhd-lib/src/index.js @@ -3,6 +3,7 @@ import 'core-js/features/symbol/async-iterator' export { default } from './vhd' export { default as chainVhd } from './chain' +export { default as checkVhdChain } from './checkChain' export { default as createContentStream } from './createContentStream' export { default as createReadableRawStream } from './createReadableRawStream' export { diff --git a/packages/xo-server/src/xo-mixins/backups-ng/index.js b/packages/xo-server/src/xo-mixins/backups-ng/index.js index b3478ef16..fa9283222 100644 --- a/packages/xo-server/src/xo-mixins/backups-ng/index.js +++ b/packages/xo-server/src/xo-mixins/backups-ng/index.js @@ -32,6 +32,7 @@ import { } from 'promise-toolbox' import Vhd, { chainVhd, + checkVhdChain, createSyntheticStream as createVhdReadStream, } from 'vhd-lib' @@ -1328,10 +1329,12 @@ export default class BackupNg { await asyncMap(files, async file => { if (file[0] !== '.') { try { - const vhd = new Vhd(handler, `${dir}/${file}`) + const path = `${dir}/${file}` + const vhd = new Vhd(handler, path) await vhd.readHeaderAndFooter() if (vhd.footer.uuid.equals(parseUuid(vdi.uuid))) { + await checkVhdChain(handler, path) full = false } diff --git a/yarn.lock b/yarn.lock index 6cd889827..244e507fc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5870,6 +5870,11 @@ get-value@^2.0.3, get-value@^2.0.6: resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= +getopts@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/getopts/-/getopts-2.2.3.tgz#11d229775e2ec2067ed8be6fcc39d9b4bf39cf7d" + integrity sha512-viEcb8TpgeG05+Nqo5EzZ8QR0hxdyrYDp6ZSTZqe2M/h53Bk036NmqG38Vhf5RGirC/Of9Xql+v66B2gp256SQ== + getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"