fix(xo-web): strip XML prefixes in OVA import parser (#3974)

Fixes #3962

- Parses the OVF XML without taking into account any namespace.
- Empty the import screen when we drop a new file on the drop zone to avoid displaying stale information during long parsing.
This commit is contained in:
Nicolas Raynaud 2019-02-21 01:24:01 -07:00 committed by Pierre Donias
parent 58175a4f5e
commit dc34f3478d
3 changed files with 26 additions and 23 deletions

View File

@ -11,6 +11,7 @@
- [Host] Fix multipathing status for XenServer < 7.5 [#3956](https://github.com/vatesfr/xen-orchestra/issues/3956) (PR [#3961](https://github.com/vatesfr/xen-orchestra/pull/3961)) - [Host] Fix multipathing status for XenServer < 7.5 [#3956](https://github.com/vatesfr/xen-orchestra/issues/3956) (PR [#3961](https://github.com/vatesfr/xen-orchestra/pull/3961))
- [Home/VM] Show creation date of the VM on if it available [#3953](https://github.com/vatesfr/xen-orchestra/issues/3953) (PR [#3959](https://github.com/vatesfr/xen-orchestra/pull/3959)) - [Home/VM] Show creation date of the VM on if it available [#3953](https://github.com/vatesfr/xen-orchestra/issues/3953) (PR [#3959](https://github.com/vatesfr/xen-orchestra/pull/3959))
- [Notifications] Fix invalid notifications when not registered (PR [#3966](https://github.com/vatesfr/xen-orchestra/pull/3966)) - [Notifications] Fix invalid notifications when not registered (PR [#3966](https://github.com/vatesfr/xen-orchestra/pull/3966))
- [Import] Fix import of some OVA files [#3962](https://github.com/vatesfr/xen-orchestra/issues/3962) (PR [##3974](https://github.com/vatesfr/xen-orchestra/pull/3974))
### Released packages ### Released packages

View File

@ -264,6 +264,10 @@ export default class Import extends Component {
} }
_handleDrop = async files => { _handleDrop = async files => {
this.setState({
vms: [],
})
const vms = await Promise.all( const vms = await Promise.all(
mapPlus(files, (file, push) => { mapPlus(files, (file, push) => {
const { name } = file const { name } = file

View File

@ -1,7 +1,7 @@
import find from 'lodash/find' import find from 'lodash/find'
import forEach from 'lodash/forEach' import forEach from 'lodash/forEach'
import fromEvent from 'promise-toolbox/fromEvent' import fromEvent from 'promise-toolbox/fromEvent'
import xml2js from 'xml2js' import xml2js, { processors } from 'xml2js'
import { ensureArray } from 'utils' import { ensureArray } from 'utils'
import { readVmdkGrainTable } from 'xo-vmdk-to-vhd' import { readVmdkGrainTable } from 'xo-vmdk-to-vhd'
@ -22,21 +22,15 @@ const MEMORY_UNIT_TO_FACTOR = {
const RESOURCE_TYPE_TO_HANDLER = { const RESOURCE_TYPE_TO_HANDLER = {
// CPU. // CPU.
'3': (data, { 'rasd:VirtualQuantity': nCpus }) => { '3': (data, { VirtualQuantity: nCpus }) => {
data.nCpus = +nCpus data.nCpus = +nCpus
}, },
// RAM. // RAM.
'4': ( '4': (data, { AllocationUnits: unit, VirtualQuantity: quantity }) => {
data,
{ 'rasd:AllocationUnits': unit, 'rasd:VirtualQuantity': quantity }
) => {
data.memory = quantity * allocationUnitsToFactor(unit) data.memory = quantity * allocationUnitsToFactor(unit)
}, },
// Network. // Network.
'10': ( '10': ({ networks }, { AutomaticAllocation: enabled, Connection: name }) => {
{ networks },
{ 'rasd:AutomaticAllocation': enabled, 'rasd:Connection': name }
) => {
if (enabled) { if (enabled) {
networks.push(name) networks.push(name)
} }
@ -45,10 +39,10 @@ const RESOURCE_TYPE_TO_HANDLER = {
'17': ( '17': (
{ disks }, { disks },
{ {
'rasd:AddressOnParent': position, AddressOnParent: position,
'rasd:Description': description = 'No description', Description: description = 'No description',
'rasd:ElementName': name, ElementName: name,
'rasd:HostResource': resource, HostResource: resource,
} }
) => { ) => {
const diskId = resource.match(/^(?:ovf:)?\/disk\/(.+)$/) const diskId = resource.match(/^(?:ovf:)?\/disk\/(.+)$/)
@ -127,7 +121,12 @@ async function parseOVF(fileFragment) {
return new Promise((resolve, reject) => return new Promise((resolve, reject) =>
xml2js.parseString( xml2js.parseString(
xmlString, xmlString,
{ mergeAttrs: true, explicitArray: false }, {
mergeAttrs: true,
explicitArray: false,
tagNameProcessors: [processors.stripPrefix],
attrNameProcessors: [processors.stripPrefix],
},
(err, res) => { (err, res) => {
if (err) { if (err) {
reject(err) reject(err)
@ -149,7 +148,7 @@ async function parseOVF(fileFragment) {
const hardware = system.VirtualHardwareSection const hardware = system.VirtualHardwareSection
// Get VM name/description. // Get VM name/description.
data.nameLabel = hardware.System['vssd:VirtualSystemIdentifier'] data.nameLabel = hardware.System.VirtualSystemIdentifier
data.descriptionLabel = data.descriptionLabel =
(system.AnnotationSection && system.AnnotationSection.Annotation) || (system.AnnotationSection && system.AnnotationSection.Annotation) ||
(system.OperatingSystemSection && (system.OperatingSystemSection &&
@ -159,21 +158,20 @@ async function parseOVF(fileFragment) {
forEach(ensureArray(disks), disk => { forEach(ensureArray(disks), disk => {
const file = find( const file = find(
ensureArray(files), ensureArray(files),
file => file['ovf:id'] === disk['ovf:fileRef'] file => file.id === disk.fileRef
) )
const unit = disk['ovf:capacityAllocationUnits'] const unit = disk.capacityAllocationUnits
data.disks[disk['ovf:diskId']] = { data.disks[disk.diskId] = {
capacity: capacity:
disk['ovf:capacity'] * disk.capacity * ((unit && allocationUnitsToFactor(unit)) || 1),
((unit && allocationUnitsToFactor(unit)) || 1), path: file && file.href,
path: file && file['ovf:href'],
} }
}) })
// Get hardware info: CPU, RAM, disks, networks... // Get hardware info: CPU, RAM, disks, networks...
forEach(ensureArray(hardware.Item), item => { forEach(ensureArray(hardware.Item), item => {
const handler = RESOURCE_TYPE_TO_HANDLER[item['rasd:ResourceType']] const handler = RESOURCE_TYPE_TO_HANDLER[item.ResourceType]
if (!handler) { if (!handler) {
return return
} }