fix(OVA import): allow import of .ova files generated by Red Hat (#5159)

See xoa-support#2713.

 - use <rasd:Address> when <rasd:AddressOnParent> is not available on disks
 - avoid dotfiles and pax headers in tar parser.
This commit is contained in:
Nicolas Raynaud 2020-07-27 08:24:01 +02:00 committed by GitHub
parent e1573069e4
commit 7c91524111
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 43 additions and 10 deletions

View File

@ -15,6 +15,7 @@
> Users must be able to say: “I had this issue, happy to know it's fixed”
- [Backup/Restore] Fixes `an error has occurred` when all backups for a specific VM have been deleted (PR [#5156](https://github.com/vatesfr/xen-orchestra/pull/5156))
- [OVA Import] fix import of Red Hat generated .ova files (PR [#5159](https://github.com/vatesfr/xen-orchestra/pull/5159))
### Packages to release
@ -33,4 +34,6 @@
>
> In case of conflict, the highest (lowest in previous list) `$version` wins.
- xo-vmdk-to-vhd patch
- xo-server patch
- xo-web minor

View File

@ -39,6 +39,7 @@ const RESOURCE_TYPE_TO_HANDLER = {
'17': (
{ disks },
{
Address: address,
AddressOnParent: position,
Description: description = 'No description',
ElementName: name,
@ -49,6 +50,27 @@ const RESOURCE_TYPE_TO_HANDLER = {
) => {
const diskId = resource.match(/^(?:ovf:)?\/disk\/(.+)$/)
const disk = diskId && disks[diskId[1]]
if (position === undefined && address !== undefined) {
// remove blanks
let parsed = address.replace(/\s+/g, '')
// expecting "{type=drive,bus=0,controller=0,target=0,unit=0}"
if (parsed[0] === '{' && parsed[parsed.length - 1] === '}') {
parsed = parsed.substring(1, parsed.length - 1)
// "type=drive,bus=0,controller=0,target=0,unit=0"
parsed = parsed.split(',')
// ["type=drive", "bus=0", "controller=0", "target=0", "unit=0"]
parsed = Object.fromEntries(parsed.map(couple => couple.split('=')))
// {type:"drive", bus:"0", controller:"0", target:"0",unit:"0"]
// 'target' seems to be the field we want
// https://www.ibm.com/support/knowledgecenter/linuxonibm/com.ibm.linux.z.ldva/ldva_r_XML_addressHostdev.html
if ('target' in parsed) {
position = +parsed.target
}
}
}
if (position === undefined) {
position = 0
}
if (disk) {
disk.descriptionLabel = description
disk.nameLabel = caption
@ -220,17 +242,25 @@ export async function parseOVAFile(
if (header === null) {
break
}
if (header.fileName.toLowerCase().endsWith('.ovf')) {
const res = await parseOVF(
parsableFile.slice(offset, offset + header.fileSize),
stringDeserializer
if (
!(
header.fileName.startsWith('PaxHeader/') ||
header.fileName.startsWith('.')
)
data = { ...data, ...res }
}
if (!skipVmdk && header.fileName.toLowerCase().endsWith('.vmdk')) {
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)
) {
if (header.fileName.toLowerCase().endsWith('.ovf')) {
const res = await parseOVF(
parsableFile.slice(offset, offset + header.fileSize),
stringDeserializer
)
data = { ...data, ...res }
}
if (!skipVmdk && header.fileName.toLowerCase().endsWith('.vmdk')) {
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)
}
}
offset += Math.ceil(header.fileSize / 512) * 512
}