From 669f5df1a6a00799053cfcbc8c7209f8f4afb233 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Mon, 17 Sep 2018 13:58:58 +0200 Subject: Improve VM descriütion file detection and parsing --- .../java/org/openslx/util/vm/QemuMetaData.java | 23 +++++--- src/main/java/org/openslx/util/vm/VboxConfig.java | 65 ++++++++++------------ .../java/org/openslx/util/vm/VboxMetaData.java | 2 - src/main/java/org/openslx/util/vm/VmMetaData.java | 41 ++++---------- 4 files changed, 55 insertions(+), 76 deletions(-) diff --git a/src/main/java/org/openslx/util/vm/QemuMetaData.java b/src/main/java/org/openslx/util/vm/QemuMetaData.java index ad02a96..dcb3b68 100644 --- a/src/main/java/org/openslx/util/vm/QemuMetaData.java +++ b/src/main/java/org/openslx/util/vm/QemuMetaData.java @@ -1,6 +1,8 @@ package org.openslx.util.vm; import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.List; @@ -10,6 +12,8 @@ import org.apache.log4j.Logger; import org.openslx.bwlp.thrift.iface.OperatingSystem; import org.openslx.bwlp.thrift.iface.Virtualizer; import org.openslx.thrifthelper.TConst; +import org.openslx.util.vm.DiskImage.ImageFormat; +import org.openslx.util.vm.DiskImage.UnknownImageFormatException; public class QemuMetaData extends VmMetaData { @@ -21,9 +25,18 @@ public class QemuMetaData extends VmMetaData osList, File file ) + public QemuMetaData( List osList, File file ) throws FileNotFoundException, IOException, UnsupportedVirtualizerFormatException { super( osList ); + DiskImage di; + try { + di = new DiskImage( file ); + } catch ( UnknownImageFormatException e ) { + di = null; + } + if ( di == null || di.format != ImageFormat.QCOW2 ) { + throw new UnsupportedVirtualizerFormatException( "This is not a qcow2 disk image" ); + } config = "qemu-system-i386 -enable-kvm \n\r qemu-system-x86_64 -enable-kvm"; displayName = file.getName().substring( 0, file.getName().indexOf( "." ) ); setOs( "anyOs" ); @@ -31,14 +44,6 @@ public class QemuMetaData extends VmMetaData osList, byte[] vmContent ) - { - super( osList ); - config = new String( vmContent ); - displayName = "QemuVM"; - setOs( "anyOs" ); - } - // initiates the arguments map with a default working sequence that will later be used in the definition array public void makeStartSequence() { diff --git a/src/main/java/org/openslx/util/vm/VboxConfig.java b/src/main/java/org/openslx/util/vm/VboxConfig.java index 4ef5cf2..fe85638 100644 --- a/src/main/java/org/openslx/util/vm/VboxConfig.java +++ b/src/main/java/org/openslx/util/vm/VboxConfig.java @@ -17,6 +17,7 @@ import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; import org.apache.log4j.Logger; +import org.openslx.util.Util; import org.openslx.util.XmlHelper; import org.openslx.util.vm.VmMetaData.DriveBusType; import org.openslx.util.vm.VmMetaData.HardDisk; @@ -35,7 +36,6 @@ public class VboxConfig private static final Logger LOGGER = Logger.getLogger( VboxConfig.class ); // key information set during initial parsing of the XML file - private String displayName = new String(); private String osName = new String(); private ArrayList hddsArray = new ArrayList(); @@ -101,13 +101,13 @@ public class VboxConfig } } catch ( SAXException e ) { LOGGER.error( "Selected vbox file was not validated against the XSD schema: " + e.getMessage() ); - throw new UnsupportedVirtualizerFormatException( "Invalid VirtualBox machine configuration file!" ); } // valid xml, try to create the DOM doc = XmlHelper.parseDocumentFromStream( new FileInputStream( file ) ); doc = XmlHelper.removeFormattingNodes( doc ); if ( doc == null ) throw new UnsupportedVirtualizerFormatException( "Could not create DOM from given VirtualBox machine configuration file!" ); + init(); } /** @@ -126,15 +126,19 @@ public class VboxConfig LOGGER.error( "Failed to create a DOM from given machine description." ); throw new UnsupportedVirtualizerFormatException( "Could not create DOM from given machine description as. byte array." ); } + init(); } /** * Main initialization functions parsing the document created during the constructor. + * @throws UnsupportedVirtualizerFormatException */ - public void init() + private void init() throws UnsupportedVirtualizerFormatException { + if ( Util.isEmptyString( getDisplayName() ) ) { + throw new UnsupportedVirtualizerFormatException( "Machine doesn't have a name" ); + } try { - setMachineName(); ensureHardwareUuid(); setOsType(); if ( checkForPlaceholders() ) { @@ -154,34 +158,33 @@ public class VboxConfig * believing in a hardware change. * * @throws XPathExpressionException + * @throws UnsupportedVirtualizerFormatException */ - private void ensureHardwareUuid() throws XPathExpressionException + private void ensureHardwareUuid() throws XPathExpressionException, UnsupportedVirtualizerFormatException { // we will need the machine uuid, so get it String machineUuid = XmlHelper.XPath.compile( "/VirtualBox/Machine/@uuid" ).evaluate( this.doc ); if ( machineUuid.isEmpty() ) { LOGGER.error( "Machine UUID empty, should never happen!" ); - return; + throw new UnsupportedVirtualizerFormatException( "XML doesn't contain a machine uuid" ); } NodeList hwNodes = findNodes( "/VirtualBox/Machine/Hardware" ); int count = hwNodes.getLength(); - if ( count == 1 ) { - Element hw = (Element)hwNodes.item( 0 ); - String hwUuid = hw.getAttribute( "uuid" ); - if ( !hwUuid.isEmpty() ) { - LOGGER.info( "Found hardware uuid: " + hwUuid ); + if ( count != 1 ) { + throw new UnsupportedVirtualizerFormatException( "Zero or more '/VirtualBox/Machine/Hardware' node were found, should never happen!" ); + } + Element hw = (Element)hwNodes.item( 0 ); + String hwUuid = hw.getAttribute( "uuid" ); + if ( !hwUuid.isEmpty() ) { + LOGGER.info( "Found hardware uuid: " + hwUuid ); + return; + } else { + if ( !addAttributeToNode( hw, "uuid", machineUuid ) ) { + LOGGER.error( "Failed to set machine UUID '" + machineUuid + "' as hardware UUID." ); return; - } else { - if ( !addAttributeToNode( hw, "uuid", machineUuid ) ) { - LOGGER.error( "Failed to set machine UUID '" + machineUuid + "' as hardware UUID." ); - return; - } - LOGGER.info( "Saved machine UUID as hardware UUID." ); } - } else { - // HACK: hijack XPathExpressionException ... - throw new XPathExpressionException( "Zero or more '/VirtualBox/Machine/Hardware' node were found, should never happen!" ); + LOGGER.info( "Saved machine UUID as hardware UUID." ); } } @@ -266,27 +269,17 @@ public class VboxConfig } /** - * Sets the display name set within the DOM expected at the - * given XPath path. - * - * @throws XPathExpressionException - */ - public void setMachineName() throws XPathExpressionException - { - String name = XmlHelper.XPath.compile( "/VirtualBox/Machine/@name" ).evaluate( this.doc ); - if ( name != null && !name.isEmpty() ) { - displayName = name; - } - } - - /** - * Getter for the parsed display name + * Getter for the display name * * @return the display name of this VM */ public String getDisplayName() { - return displayName; + try { + return XmlHelper.XPath.compile( "/VirtualBox/Machine/@name" ).evaluate( this.doc ); + } catch ( XPathExpressionException e ) { + return ""; + } } /** diff --git a/src/main/java/org/openslx/util/vm/VboxMetaData.java b/src/main/java/org/openslx/util/vm/VboxMetaData.java index e3acef4..00ca8ad 100644 --- a/src/main/java/org/openslx/util/vm/VboxMetaData.java +++ b/src/main/java/org/openslx/util/vm/VboxMetaData.java @@ -99,8 +99,6 @@ public class VboxMetaData extends VmMetaData * * @param osList List of supported operating systems * @param file VM's machine description file to get the metadata instance from - * @return VmMetaData object representing the relevant parts of the given machine description - * @throws IOException + * @return VmMetaData object representing the relevant parts of the given machine description */ - public static VmMetaData getInstance( List osList, File file ) throws IOException + public static VmMetaData getInstance( List osList, File file ) + throws IOException { - Exception errEx = null; try { return new VmwareMetaData( osList, file ); } catch ( UnsupportedVirtualizerFormatException e ) { - LOGGER.debug( "Disk file not .vmdk" ); - errEx = e; + LOGGER.info( "Not a VMware file", e ); } try { return new VboxMetaData( osList, file ); } catch ( UnsupportedVirtualizerFormatException e ) { - LOGGER.debug( "Disk file not .vdi" ); - errEx = e; + LOGGER.info( "Not a VirtualBox file", e ); } try { return new QemuMetaData( osList, file ); } catch ( Exception e ) { - LOGGER.debug( "Disk file not qemu supported format" ); - errEx = e; - } - if ( errEx != null ) { - LOGGER.error( "Unsupported disk file format!", errEx ); + LOGGER.info( "Not a QEmu file", e ); } + LOGGER.error( "Could not detect any known virtualizer format" ); return null; } @@ -300,29 +294,18 @@ public abstract class VmMetaData */ public static VmMetaData getInstance( List osList, byte[] vmContent, int length ) throws IOException { - Exception errEx = null; try { return new VmwareMetaData( osList, vmContent, length ); } catch ( UnsupportedVirtualizerFormatException e ) { - LOGGER.debug( "Machine description not in .vmx format." ); - errEx = e; + LOGGER.info( "Not a VMware file", e ); } try { return new VboxMetaData( osList, vmContent, length ); - } catch ( UnsupportedVirtualizerFormatException | NullPointerException e ) { - LOGGER.debug( "Machine description not in .vbox format." ); - errEx = e; - } - // how to do this check ?? - try { - return new QemuMetaData( osList, vmContent ); - } catch ( Exception e ) { - LOGGER.debug( "Machine description not in qemu supported format" ); - errEx = e; - } - if ( errEx != null ) { - LOGGER.error( "Machine description has an unknown format!", errEx ); + } catch ( UnsupportedVirtualizerFormatException e ) { + LOGGER.info( "Not a VirtualBox file", e ); } + // TODO QEmu -- hack above expects qcow2 file, so we can't do anything here yet + LOGGER.error( "Could not detect any known virtualizer format" ); return null; } -- cgit v1.2.3-55-g7522