From 9ca3f3df266105ef13662d01ad35027fa11d2cbc Mon Sep 17 00:00:00 2001 From: Florent BEAUCHAMP Date: Wed, 15 Nov 2023 16:23:33 +0100 Subject: [PATCH] fix(xo-vmdk-to-vhd): improve compatibilty of ova with disk bigger than 8.2GB (#7183) following #7047, from https://xcp-ng.org/forum/topic/7946/ova-export-not-functional?_=1700051758755 ova exported from xo with more than 8.2G data per disk can't be imported in virtual box tar-stream@3 pack and entry are now streams --- CHANGELOG.unreleased.md | 2 ++ packages/xo-vmdk-to-vhd/package.json | 4 +-- packages/xo-vmdk-to-vhd/src/ova-generate.js | 28 ++++++++------------- 3 files changed, 14 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.unreleased.md b/CHANGELOG.unreleased.md index daf3888aa..21501db3a 100644 --- a/CHANGELOG.unreleased.md +++ b/CHANGELOG.unreleased.md @@ -15,6 +15,7 @@ - [Backup/Restore] In case of snapshot with memory, create the suspend VDI on the correct SR instead of the default one - [Import/ESXi] Handle `Cannot read properties of undefined (reading 'perDatastoreUsage')` error when importing VM without storage (PR [#7168](https://github.com/vatesfr/xen-orchestra/pull/7168)) +- [Export/OVA] Handle export with resulting disk larger than 8.2GB (PR [#7183](https://github.com/vatesfr/xen-orchestra/pull/7183)) ### Packages to release @@ -36,6 +37,7 @@ - @xen-orchestra/backups patch - @xen-orchestra/vmware-explorer patch - xo-server-netbox minor +- xo-vmdk-to-vhd patch - xo-web patch diff --git a/packages/xo-vmdk-to-vhd/package.json b/packages/xo-vmdk-to-vhd/package.json index 8972f6cd0..0fa04df8c 100644 --- a/packages/xo-vmdk-to-vhd/package.json +++ b/packages/xo-vmdk-to-vhd/package.json @@ -18,14 +18,14 @@ "preferGlobal": false, "main": "dist/", "engines": { - "node": ">=12" + "node": ">=12.3" }, "dependencies": { "child-process-promise": "^2.0.3", "lodash": "^4.17.15", "pako": "^2.0.4", "promise-toolbox": "^0.21.0", - "tar-stream": "^2.2.0", + "tar-stream": "^3.1.6", "vhd-lib": "^4.6.1", "xml2js": "^0.4.23" }, diff --git a/packages/xo-vmdk-to-vhd/src/ova-generate.js b/packages/xo-vmdk-to-vhd/src/ova-generate.js index 29fdba012..b74d19c34 100644 --- a/packages/xo-vmdk-to-vhd/src/ova-generate.js +++ b/packages/xo-vmdk-to-vhd/src/ova-generate.js @@ -1,12 +1,13 @@ import tar from 'tar-stream' import { computeVmdkLength, vhdToVMDKIterator } from '.' import { fromCallback } from 'promise-toolbox' +import { pipeline } from 'stream' // WE MIGHT WANT TO HAVE A LOOK HERE: https://opennodecloud.com/howto/2013/12/25/howto-ON-ovf-reference.html /** * - * @param writeStream + * @param outStream * @param vmName * @param vmDescription * @param disks [{name, fileName, capacityMB, getStream}] @@ -16,19 +17,13 @@ import { fromCallback } from 'promise-toolbox' * @returns readStream */ export async function writeOvaOn( - writeStream, + outStream, { vmName, vmDescription = '', disks = [], firmware = 'bios', nics = [], vmMemoryMB = 64, cpuCount = 1 } ) { const ovf = createOvf(vmName, vmDescription, disks, nics, vmMemoryMB, cpuCount, firmware) - const pack = tar.pack() - const pipe = pack.pipe(writeStream) - await fromCallback.call(pack, pack.entry, { name: `metadata.ovf` }, Buffer.from(ovf, 'utf8')) - - async function writeDisk(entry, blockIterator) { - for await (const block of blockIterator) { - await fromCallback.call(entry, entry.write, block) - } - } + const tarStream = tar.pack() + pipeline(tarStream, outStream, () => {}) + await fromCallback.call(tarStream, tarStream.entry, { name: `metadata.ovf` }, Buffer.from(ovf, 'utf8')) // https://github.com/mafintosh/tar-stream/issues/24#issuecomment-558358268 async function pushDisk(disk) { @@ -38,23 +33,20 @@ export async function writeOvaOn( } disk.fileSize = size return new Promise((resolve, reject) => { - const entry = pack.entry({ name: `${disk.name}.vmdk`, size }, err => { + const entryWriteStream = tarStream.entry({ name: `${disk.name}.vmdk`, size, type: 'file' }, err => { if (err == null) { return resolve() } else return reject(err) }) - return writeDisk(entry, iterator).then( - () => entry.end(), - e => reject(e) - ) + pipeline(iterator, entryWriteStream, () => {}) }) } for (const disk of disks) { await pushDisk(disk) } - pack.finalize() - return pipe + tarStream.finalize() + return outStream } function createDiskSections(disks) {