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.
This commit is contained in:
parent
fdbe84cb1e
commit
f3527a44d7
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
- [Import VMDK] Fix `No position specified for vmdisk1` error (PR [#5255](https://github.com/vatesfr/xen-orchestra/pull/5255))
|
- [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))
|
- [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
|
### Packages to release
|
||||||
|
|
||||||
|
@ -79,6 +79,9 @@ test('An ova file is parsed correctly', async () => {
|
|||||||
return Buffer.from(buffer).toString(encoder)
|
return Buffer.from(buffer).toString(encoder)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
for (const fileName in data.tables) {
|
||||||
|
data.tables[fileName] = await data.tables[fileName]
|
||||||
|
}
|
||||||
expect(data).toEqual(expectedResult)
|
expect(data).toEqual(expectedResult)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import sum from 'lodash/sum'
|
|||||||
import xml2js, { processors } from 'xml2js'
|
import xml2js, { processors } from 'xml2js'
|
||||||
|
|
||||||
import { readVmdkGrainTable } from '.'
|
import { readVmdkGrainTable } from '.'
|
||||||
|
import { suppressUnhandledRejection } from './util'
|
||||||
|
|
||||||
/********
|
/********
|
||||||
*
|
*
|
||||||
@ -327,7 +328,9 @@ export async function parseOVAFile(
|
|||||||
const fileSlice = parsableFile.slice(offset, offset + header.fileSize)
|
const fileSlice = parsableFile.slice(offset, offset + header.fileSize)
|
||||||
const readFile = async (start, end) =>
|
const readFile = async (start, end) =>
|
||||||
fileSlice.slice(start, end).read()
|
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')) {
|
if (!skipVmdk && header.fileName.toLowerCase().endsWith('.vmdk.gz')) {
|
||||||
@ -342,7 +345,9 @@ export async function parseOVAFile(
|
|||||||
return parseGzipFromEnd(start, end, fileSlice, header)
|
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
|
offset += Math.ceil(header.fileSize / 512) * 512
|
||||||
}
|
}
|
||||||
|
4
packages/xo-vmdk-to-vhd/src/util.js
Normal file
4
packages/xo-vmdk-to-vhd/src/util.js
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export function suppressUnhandledRejection(p) {
|
||||||
|
p.catch(Function.prototype)
|
||||||
|
return p
|
||||||
|
}
|
@ -1,3 +1,5 @@
|
|||||||
|
import { suppressUnhandledRejection } from './util'
|
||||||
|
|
||||||
const SECTOR_SIZE = 512
|
const SECTOR_SIZE = 512
|
||||||
const HEADER_SIZE = 512
|
const HEADER_SIZE = 512
|
||||||
const FOOTER_POSITION = -1024
|
const FOOTER_POSITION = -1024
|
||||||
@ -138,5 +140,8 @@ export async function readCapacityAndGrainTable(fileAccessor) {
|
|||||||
return { grainLogicalAddressList: fragmentAddressList, grainFileOffsetList }
|
return { grainLogicalAddressList: fragmentAddressList, grainFileOffsetList }
|
||||||
}
|
}
|
||||||
|
|
||||||
return { tablePromise: readTable(), capacityBytes: capacity }
|
return {
|
||||||
|
tablePromise: suppressUnhandledRejection(readTable()),
|
||||||
|
capacityBytes: capacity,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,14 +21,9 @@ class BrowserParsableFile extends ParsableFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function parseTarFile(file) {
|
async function parseTarFile(file) {
|
||||||
document.body.style.cursor = 'wait'
|
return await parseOVAFile(new BrowserParsableFile(file), (buffer, encoding) =>
|
||||||
try {
|
|
||||||
return parseOVAFile(new BrowserParsableFile(file), (buffer, encoding) =>
|
|
||||||
new TextDecoder(encoding).decode(buffer)
|
new TextDecoder(encoding).decode(buffer)
|
||||||
)
|
)
|
||||||
} finally {
|
|
||||||
document.body.style.cursor = null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export { parseTarFile as default }
|
export { parseTarFile as default }
|
||||||
|
Loading…
Reference in New Issue
Block a user