From f3527a44d7e96b67dc4721e097ee10a5ff747df3 Mon Sep 17 00:00:00 2001 From: Nicolas Raynaud Date: Sun, 27 Sep 2020 19:45:32 +0200 Subject: [PATCH] fix(vm/import): make the UI respond instantly to .ova file drop (#5274) When dropping a file on the import zone, the UI didn't acknowledge the file until the vmdk table were parsed. Now the UI parses the XML instantly, displays it on the UI, and start parsing the tables in the background. If the user clicks the "import" button, the system will finish parsing the tables and start the upload in when fell swoop. Hiding the parsing time in the upload time. --- CHANGELOG.unreleased.md | 1 + packages/xo-vmdk-to-vhd/src/ova.integ.spec.js | 3 +++ packages/xo-vmdk-to-vhd/src/ova.js | 9 +++++++-- packages/xo-vmdk-to-vhd/src/util.js | 4 ++++ packages/xo-vmdk-to-vhd/src/vmdk-read-table.js | 7 ++++++- packages/xo-web/src/xo-app/vm-import/ova/index.js | 11 +++-------- 6 files changed, 24 insertions(+), 11 deletions(-) create mode 100644 packages/xo-vmdk-to-vhd/src/util.js diff --git a/CHANGELOG.unreleased.md b/CHANGELOG.unreleased.md index 6606a1fef..0fe386118 100644 --- a/CHANGELOG.unreleased.md +++ b/CHANGELOG.unreleased.md @@ -20,6 +20,7 @@ - [Import VMDK] Fix `No position specified for vmdisk1` error (PR [#5255](https://github.com/vatesfr/xen-orchestra/pull/5255)) - [API] Fix `this.removeSubjectFromResourceSet is not a function` error on calling `resourceSet.removeSubject` via `xo-cli` [#5265](https://github.com/vatesfr/xen-orchestra/issues/5265) (PR [#5266](https://github.com/vatesfr/xen-orchestra/pull/5266)) +- [Import OVA] Fix frozen UI when dropping a big OVA on the page (PR [#5274](https://github.com/vatesfr/xen-orchestra/pull/5274)) ### Packages to release diff --git a/packages/xo-vmdk-to-vhd/src/ova.integ.spec.js b/packages/xo-vmdk-to-vhd/src/ova.integ.spec.js index b87215565..cef3eaad2 100644 --- a/packages/xo-vmdk-to-vhd/src/ova.integ.spec.js +++ b/packages/xo-vmdk-to-vhd/src/ova.integ.spec.js @@ -79,6 +79,9 @@ test('An ova file is parsed correctly', async () => { return Buffer.from(buffer).toString(encoder) } ) + for (const fileName in data.tables) { + data.tables[fileName] = await data.tables[fileName] + } expect(data).toEqual(expectedResult) }) diff --git a/packages/xo-vmdk-to-vhd/src/ova.js b/packages/xo-vmdk-to-vhd/src/ova.js index f6c06d90a..4bc2532b9 100644 --- a/packages/xo-vmdk-to-vhd/src/ova.js +++ b/packages/xo-vmdk-to-vhd/src/ova.js @@ -5,6 +5,7 @@ import sum from 'lodash/sum' import xml2js, { processors } from 'xml2js' import { readVmdkGrainTable } from '.' +import { suppressUnhandledRejection } from './util' /******** * @@ -327,7 +328,9 @@ export async function parseOVAFile( const fileSlice = parsableFile.slice(offset, offset + header.fileSize) const readFile = async (start, end) => fileSlice.slice(start, end).read() - data.tables[header.fileName] = await readVmdkGrainTable(readFile) + data.tables[header.fileName] = suppressUnhandledRejection( + readVmdkGrainTable(readFile) + ) } } if (!skipVmdk && header.fileName.toLowerCase().endsWith('.vmdk.gz')) { @@ -342,7 +345,9 @@ export async function parseOVAFile( return parseGzipFromEnd(start, end, fileSlice, header) } } - data.tables[header.fileName] = await readVmdkGrainTable(readFile) + data.tables[header.fileName] = suppressUnhandledRejection( + readVmdkGrainTable(readFile) + ) } offset += Math.ceil(header.fileSize / 512) * 512 } diff --git a/packages/xo-vmdk-to-vhd/src/util.js b/packages/xo-vmdk-to-vhd/src/util.js new file mode 100644 index 000000000..ed24b53d4 --- /dev/null +++ b/packages/xo-vmdk-to-vhd/src/util.js @@ -0,0 +1,4 @@ +export function suppressUnhandledRejection(p) { + p.catch(Function.prototype) + return p +} diff --git a/packages/xo-vmdk-to-vhd/src/vmdk-read-table.js b/packages/xo-vmdk-to-vhd/src/vmdk-read-table.js index 1916943bb..bd577fd97 100644 --- a/packages/xo-vmdk-to-vhd/src/vmdk-read-table.js +++ b/packages/xo-vmdk-to-vhd/src/vmdk-read-table.js @@ -1,3 +1,5 @@ +import { suppressUnhandledRejection } from './util' + const SECTOR_SIZE = 512 const HEADER_SIZE = 512 const FOOTER_POSITION = -1024 @@ -138,5 +140,8 @@ export async function readCapacityAndGrainTable(fileAccessor) { return { grainLogicalAddressList: fragmentAddressList, grainFileOffsetList } } - return { tablePromise: readTable(), capacityBytes: capacity } + return { + tablePromise: suppressUnhandledRejection(readTable()), + capacityBytes: capacity, + } } diff --git a/packages/xo-web/src/xo-app/vm-import/ova/index.js b/packages/xo-web/src/xo-app/vm-import/ova/index.js index 04bde69d3..9150ca9f3 100644 --- a/packages/xo-web/src/xo-app/vm-import/ova/index.js +++ b/packages/xo-web/src/xo-app/vm-import/ova/index.js @@ -21,14 +21,9 @@ class BrowserParsableFile extends ParsableFile { } async function parseTarFile(file) { - document.body.style.cursor = 'wait' - try { - return parseOVAFile(new BrowserParsableFile(file), (buffer, encoding) => - new TextDecoder(encoding).decode(buffer) - ) - } finally { - document.body.style.cursor = null - } + return await parseOVAFile(new BrowserParsableFile(file), (buffer, encoding) => + new TextDecoder(encoding).decode(buffer) + ) } export { parseTarFile as default }