feat(xo-server/backup NG): check complete VHD chain (#3820)
This triggers a full export if the chain appears incomplete.
This commit is contained in:
parent
2ab820d511
commit
7f85935e43
@ -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
|
||||
|
@ -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"
|
||||
},
|
||||
|
@ -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)
|
||||
|
6
packages/vhd-lib/src/_resolveRelativeFromFile.js
Normal file
6
packages/vhd-lib/src/_resolveRelativeFromFile.js
Normal file
@ -0,0 +1,6 @@
|
||||
import { dirname, resolve } from 'path'
|
||||
|
||||
const resolveRelativeFromFile = (file, path) =>
|
||||
resolve('/', dirname(file), path).slice(1)
|
||||
|
||||
export { resolveRelativeFromFile as default }
|
16
packages/vhd-lib/src/checkChain.js
Normal file
16
packages/vhd-lib/src/checkChain.js
Normal file
@ -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)
|
||||
}
|
||||
}
|
@ -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 = () => {
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user