Compare commits

..

8 Commits

Author SHA1 Message Date
Julien Fontanet
e14fda6e8a feat(xen-api): 0.1.3 2018-06-16 17:05:27 +02:00
Julien Fontanet
ec48b77af3 feat(xen-api): add task record to task errors 2018-06-16 15:24:26 +02:00
Julien Fontanet
c7d6a19864 fix(xo-server/full backup NG): do not fork if 1 target 2018-06-16 15:24:26 +02:00
Julien Fontanet
7d714c8ce4 feat(xo-server): 5.20.2 2018-06-16 13:51:51 +02:00
Julien Fontanet
f70989c3a2 feat(delta NG): fix UUID of existing VHDs 2018-06-16 13:51:03 +02:00
Julien Fontanet
70490988b0 chore(xo-server/backupNg): add parseUuid util function 2018-06-16 13:51:03 +02:00
Julien Fontanet
d0795fdded feat(vhd-lib): make footer.{uuid,parentUuid)} a buffer 2018-06-16 13:51:03 +02:00
Julien Fontanet
1c736e9910 feat(xo-web): 5.20.2 2018-06-15 15:35:26 +02:00
9 changed files with 44 additions and 20 deletions

View File

@@ -29,7 +29,7 @@
"@xen-orchestra/fs": "^0.1.0",
"exec-promise": "^0.7.0",
"struct-fu": "^1.2.0",
"vhd-lib": "^0.1.2"
"vhd-lib": "^0.1.3"
},
"devDependencies": {
"@babel/cli": "^7.0.0-beta.49",

View File

@@ -1,6 +1,6 @@
{
"name": "vhd-lib",
"version": "0.1.2",
"version": "0.1.3",
"license": "AGPL-3.0",
"description": "Primitives for VHD file handling",
"keywords": [],

View File

@@ -33,7 +33,7 @@ export function createFooter (
currentSize: size,
diskGeometry: geometry,
diskType,
uuid: generateUuid(null, []),
uuid: generateUuid(null, Buffer.allocUnsafe(16)),
})
checksumStruct(footer, fuFooter)
return footer

View File

@@ -40,7 +40,7 @@ export const fuFooter = fu.struct([
]),
fu.uint32('diskType'), // 60 Disk type, must be equal to HARD_DISK_TYPE_DYNAMIC/HARD_DISK_TYPE_DIFFERENCING.
fu.uint32('checksum'), // 64
fu.uint8('uuid', 16), // 68
fu.byte('uuid', 16), // 68
fu.char('saved'), // 84
fu.char('hidden'), // 85 TODO: should probably be merged in reserved
fu.char('reserved', 426), // 86
@@ -55,7 +55,7 @@ export const fuHeader = fu.struct([
fu.uint32('maxTableEntries'), // Max entries in the Block Allocation Table.
fu.uint32('blockSize'), // Block size in bytes. Default (2097152 => 2MB)
fu.uint32('checksum'),
fu.uint8('parentUuid', 16),
fu.byte('parentUuid', 16),
fu.uint32('parentTimestamp'),
fu.uint32('reserved1'),
fu.char16be('parentUnicodeName', 512),

View File

@@ -96,6 +96,7 @@ class XapiError extends BaseError {
// slots than can be assigned later
this.method = undefined
this.url = undefined
this.task = undefined
}
}
@@ -188,7 +189,9 @@ const getTaskResult = task => {
return Promise.reject(new Cancel('task canceled'))
}
if (status === 'failure') {
return Promise.reject(wrapError(task.error_info))
const error = wrapError(task.error_info)
error.task = task
return Promise.reject(error)
}
if (status === 'success') {
// the result might be:

View File

@@ -1,6 +1,6 @@
{
"name": "xo-server",
"version": "5.20.1",
"version": "5.20.2",
"license": "AGPL-3.0",
"description": "Server part of Xen-Orchestra",
"keywords": [
@@ -111,7 +111,7 @@
"tmp": "^0.0.33",
"uuid": "^3.0.1",
"value-matcher": "^0.2.0",
"vhd-lib": "^0.1.2",
"vhd-lib": "^0.1.3",
"ws": "^5.0.0",
"xen-api": "^0.16.10",
"xml2js": "^0.4.19",

View File

@@ -255,6 +255,10 @@ const importers: $Dict<
},
}
const PARSE_UUID_RE = /-/g
const parseUuid = (uuid: string) =>
Buffer.from(uuid.replace(PARSE_UUID_RE, ''), 'hex')
const parseVmBackupId = (id: string) => {
const i = id.indexOf('/')
return {
@@ -687,7 +691,7 @@ export default class BackupNg {
// - [ ] display queued VMs
// - [ ] snapshots and files of an old job should be detected and removed
// - [ ] delta import should support mapVdisSrs
// - [ ] size of the path? (base64url(Buffer.from(uuid.split('-').join(''), 'hex')))
// - [ ] size of the path? (base64url(parseUuid(uuid)))
// - [ ] what does mean the vmTimeout with the new concurrency? a VM can take
// a very long time to finish if there are other VMs before…
// - [ ] detect and gc uncomplete replications
@@ -911,7 +915,7 @@ export default class BackupNg {
xva = xva.pipe(createSizeStream())
const forkExport =
nTargets === 0
nTargets === 1
? () => xva
: () => {
const fork = xva.pipe(new PassThrough())
@@ -1049,6 +1053,29 @@ export default class BackupNg {
$defer.onFailure.call(xapi, 'deleteVm', snapshot)
}
// JFT: TODO: remove when enough time has passed (~2018-09)
//
// Fix VHDs UUID (= VDI.uuid), which was not done before 2018-06-16.
await asyncMap(remotes, async ({ handler }) =>
asyncMap(
this._listVmBackups(handler, vmUuid, _ => _.mode === 'delta'),
({ _filename, vdis, vhds }) => {
const vmDir = dirname(_filename)
return asyncMap(vhds, async (vhdPath, vdiId) => {
const uuid = parseUuid(vdis[vdiId].uuid)
const vhd = new Vhd(handler, `${vmDir}/${vhdPath}`)
await vhd.readHeaderAndFooter()
if (!vhd.footer.uuid.equals(uuid)) {
vhd.footer.uuid = uuid
await vhd.readBlockAllocationTable()
await vhd.writeFooter()
}
})
}
)
)
let baseSnapshot, fullVdisRequired
await (async () => {
baseSnapshot = (last(snapshots): Vm | void)
@@ -1096,10 +1123,7 @@ export default class BackupNg {
const vhd = new Vhd(handler, `${dir}/${file}`)
await vhd.readHeaderAndFooter()
if (
Buffer.from(vhd.footer.uuid).toString('hex') ===
vdi.uuid.split('-').join('')
) {
if (vhd.footer.uuid.equals(parseUuid(vdi.uuid))) {
full = false
}
@@ -1277,10 +1301,7 @@ export default class BackupNg {
// set the correct UUID in the VHD
const vhd = new Vhd(handler, path)
await vhd.readHeaderAndFooter()
vhd.footer.uuid = Buffer.from(
vdi.uuid.split('-').join(''),
'hex'
)
vhd.footer.uuid = parseUuid(vdi.uuid)
await vhd.readBlockAllocationTable() // required by writeFooter()
await vhd.writeFooter()

View File

@@ -28,7 +28,7 @@
"pipette": "^0.9.3",
"promise-toolbox": "^0.9.5",
"tmp": "^0.0.33",
"vhd-lib": "^0.1.2"
"vhd-lib": "^0.1.3"
},
"devDependencies": {
"@babel/cli": "7.0.0-beta.49",

View File

@@ -1,7 +1,7 @@
{
"private": false,
"name": "xo-web",
"version": "5.20.1",
"version": "5.20.2",
"license": "AGPL-3.0",
"description": "Web interface client for Xen-Orchestra",
"keywords": [