diff options
Diffstat (limited to 'src/main/java')
67 files changed, 5379 insertions, 1282 deletions
diff --git a/src/main/java/org/openslx/libvirt/capabilities/Capabilities.java b/src/main/java/org/openslx/libvirt/capabilities/Capabilities.java new file mode 100644 index 0000000..7987371 --- /dev/null +++ b/src/main/java/org/openslx/libvirt/capabilities/Capabilities.java @@ -0,0 +1,155 @@ +package org.openslx.libvirt.capabilities; + +import java.io.File; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +import org.openslx.libvirt.capabilities.cpu.Cpu; +import org.openslx.libvirt.capabilities.guest.Guest; +import org.openslx.libvirt.xml.LibvirtXmlDocument; +import org.openslx.libvirt.xml.LibvirtXmlDocumentException; +import org.openslx.libvirt.xml.LibvirtXmlNode; +import org.openslx.libvirt.xml.LibvirtXmlResources; +import org.openslx.libvirt.xml.LibvirtXmlSerializationException; +import org.openslx.libvirt.xml.LibvirtXmlValidationException; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; + +/** + * Implementation of the Libvirt capabilities XML document. + * + * The Libvirt capabilities XML document is used to describe the configuration and capabilities of + * the hypervisor's host. + * + * @author Manuel Bentele + * @version 1.0 + */ +public class Capabilities extends LibvirtXmlDocument +{ + /** + * Creates Libvirt capabilities XML document from {@link String} providing Libvirt capabilities + * XML content. + * + * @param xml {@link String} with Libvirt capabilities XML content. + * + * @throws LibvirtXmlDocumentException creation of XML context failed. + * @throws LibvirtXmlSerializationException serialization of the capabilities XML content failed. + * @throws LibvirtXmlValidationException XML content is not a valid capabilities XML document. + */ + public Capabilities( String xml ) + throws LibvirtXmlDocumentException, LibvirtXmlSerializationException, LibvirtXmlValidationException + { + super( xml, LibvirtXmlResources.getLibvirtRng( "capabilities.rng" ) ); + } + + /** + * Creates Libvirt capabilities XML document from {@link File} containing Libvirt capabilities + * XML content. + * + * @param xml existing {@link File} containing Libvirt capabilities XML content. + * + * @throws LibvirtXmlDocumentException creation of XML context failed. + * @throws LibvirtXmlSerializationException serialization of the capabilities XML content failed. + * @throws LibvirtXmlValidationException XML content is not a valid capabilities XML document. + */ + public Capabilities( File xml ) + throws LibvirtXmlDocumentException, LibvirtXmlSerializationException, LibvirtXmlValidationException + { + super( xml, LibvirtXmlResources.getLibvirtRng( "capabilities.rng" ) ); + } + + /** + * Creates Libvirt capabilities XML document from {@link InputStream} providing Libvirt + * capabilities XML content. + * + * @param xml {@link InputStream} providing Libvirt capabilities XML content. + * + * @throws LibvirtXmlDocumentException creation of XML context failed. + * @throws LibvirtXmlSerializationException serialization of the capabilities XML content failed. + * @throws LibvirtXmlValidationException XML content is not a valid capabilities XML document. + */ + public Capabilities( InputStream xml ) + throws LibvirtXmlDocumentException, LibvirtXmlSerializationException, LibvirtXmlValidationException + { + super( xml, LibvirtXmlResources.getLibvirtRng( "capabilities.rng" ) ); + } + + /** + * Creates Libvirt capabilities XML document from {@link InputSource} providing Libvirt + * capabilities XML content. + * + * @param xml {@link InputSource} providing Libvirt capabilities XML content. + * + * @throws LibvirtXmlDocumentException creation of XML context failed. + * @throws LibvirtXmlSerializationException serialization of the capabilities XML content failed. + * @throws LibvirtXmlValidationException XML content is not a valid capabilities XML document. + */ + public Capabilities( InputSource xml ) + throws LibvirtXmlDocumentException, LibvirtXmlSerializationException, LibvirtXmlValidationException + { + super( xml, LibvirtXmlResources.getLibvirtRng( "capabilities.rng" ) ); + } + + /** + * Returns UUID of the Libvirt host machine. + * + * @return UUID of the host machine. + */ + public String getHostUuid() + { + return this.getRootXmlNode().getXmlElementValue( "host/uuid" ); + } + + /** + * Returns CPU capabilities of the host machine. + * + * @return CPU capabilities of the host machine. + */ + public Cpu getHostCpu() + { + final Node hostCpuNode = this.getRootXmlNode().getXmlElement( "host/cpu" ); + + if ( hostCpuNode == null ) { + return null; + } else { + final LibvirtXmlNode hostCpuXmlNode = new LibvirtXmlNode( this.getRootXmlNode().getXmlDocument(), + hostCpuNode ); + return Cpu.newInstance( hostCpuXmlNode ); + } + } + + /** + * Checks whether the Libvirt host machine has IOMMU support. + * + * @return State of the IOMMU support. + */ + public boolean hasHostIommuSupport() + { + return this.getRootXmlNode().getXmlElementAttributeValueAsBool( "host/iommu", "support" ); + } + + /** + * Returns capabilities of all possible guest machines. + * + * @return capabilities of all possible guest machines. + */ + public List<Guest> getGuests() + { + final List<Guest> guestList = new ArrayList<Guest>(); + final NodeList guestNodes = this.getRootXmlNode().getXmlNodes( "guest" ); + + for ( int i = 0; i < guestNodes.getLength(); i++ ) { + final LibvirtXmlNode guestNode = new LibvirtXmlNode( this.getRootXmlNode().getXmlDocument(), + guestNodes.item( i ) ); + final Guest guest = Guest.newInstance( guestNode ); + + if ( guest != null ) { + guestList.add( guest ); + } + } + + return guestList; + } +} diff --git a/src/main/java/org/openslx/libvirt/capabilities/cpu/Cpu.java b/src/main/java/org/openslx/libvirt/capabilities/cpu/Cpu.java new file mode 100644 index 0000000..dc5fbd0 --- /dev/null +++ b/src/main/java/org/openslx/libvirt/capabilities/cpu/Cpu.java @@ -0,0 +1,165 @@ +package org.openslx.libvirt.capabilities.cpu; + +import java.util.ArrayList; +import java.util.List; + +import org.openslx.libvirt.xml.LibvirtXmlNode; +import org.w3c.dom.NodeList; + +/** + * Implementation of the host CPU capabilities as part of the Libvirt capabilities XML document. + * + * @author Manuel Bentele + * @version 1.0 + */ +public class Cpu extends LibvirtXmlNode +{ + /** + * Creates an empty host CPU capabilities instance. + */ + public Cpu() + { + super(); + } + + /** + * Creates a host CPU capabilities instance representing an existing Libvirt XML host CPU + * capabilities element. + * + * @param xmlNode existing Libvirt XML host CPU capabilities element. + */ + public Cpu( LibvirtXmlNode xmlNode ) + { + super( xmlNode ); + } + + /** + * Returns the architecture name of the host CPU. + * + * @return architecture name of the host CPU. + */ + public String getArch() + { + return this.getXmlElementValue( "arch" ); + } + + /** + * Returns the model name of the host CPU. + * + * @return model name of the host CPU. + */ + public String getModel() + { + return this.getXmlElementValue( "model" ); + } + + /** + * Returns the vendor name of the host CPU. + * + * @return vendor name of the host CPU. + */ + public String getVendor() + { + return this.getXmlElementValue( "vendor" ); + } + + /** + * Returns the number of sockets of the host CPU. + * + * @return number of sockets of the host CPU. + */ + public int getTopologySockets() + { + final String numSockets = this.getXmlElementAttributeValue( "topology", "sockets" ); + return Integer.parseInt( numSockets ); + } + + /** + * Returns the number of dies of the host CPU. + * + * @return number of dies of the host CPU. + */ + public int getTopologyDies() + { + final String numDies = this.getXmlElementAttributeValue( "topology", "dies" ); + return Integer.parseInt( numDies ); + } + + /** + * Returns the number of cores of the host CPU. + * + * @return number of cores of the host CPU. + */ + public int getTopologyCores() + { + final String numCores = this.getXmlElementAttributeValue( "topology", "cores" ); + return Integer.parseInt( numCores ); + } + + /** + * Returns the number of threads of the host CPU. + * + * @return number of threads of the host CPU. + */ + public int getTopologyThreads() + { + final String numThreads = this.getXmlElementAttributeValue( "topology", "threads" ); + return Integer.parseInt( numThreads ); + } + + /** + * Returns the supported features of the host CPU. + * + * @return supported features of the host CPU. + */ + public List<Feature> getFeatures() + { + final List<Feature> featureList = new ArrayList<Feature>(); + final NodeList featureNodes = this.getXmlNodes( "feature" ); + + for ( int i = 0; i < featureNodes.getLength(); i++ ) { + final LibvirtXmlNode featureNode = new LibvirtXmlNode( this.getXmlDocument(), featureNodes.item( i ) ); + final Feature feature = Feature.newInstance( featureNode ); + + if ( feature != null ) { + featureList.add( feature ); + } + } + + return featureList; + } + + /** + * Returns the supported memory pages of the host CPU. + * + * @return supported memory pages of the host CPU. + */ + public List<Pages> getPages() + { + final List<Pages> pagesList = new ArrayList<Pages>(); + final NodeList pagesNodes = this.getXmlNodes( "pages" ); + + for ( int i = 0; i < pagesNodes.getLength(); i++ ) { + final LibvirtXmlNode pagesNode = new LibvirtXmlNode( this.getXmlDocument(), pagesNodes.item( i ) ); + final Pages pages = Pages.newInstance( pagesNode ); + + if ( pages != null ) { + pagesList.add( pages ); + } + } + + return pagesList; + } + + /** + * Creates a host CPU capabilities instance representing an existing Libvirt XML host CPU + * capabilities element. + * + * @param xmlNode existing Libvirt XML host CPU capabilities element. + * @return host CPU capabilities instance. + */ + public static Cpu newInstance( LibvirtXmlNode xmlNode ) + { + return new Cpu( xmlNode ); + } +} diff --git a/src/main/java/org/openslx/libvirt/capabilities/cpu/Feature.java b/src/main/java/org/openslx/libvirt/capabilities/cpu/Feature.java new file mode 100644 index 0000000..96c77d5 --- /dev/null +++ b/src/main/java/org/openslx/libvirt/capabilities/cpu/Feature.java @@ -0,0 +1,51 @@ +package org.openslx.libvirt.capabilities.cpu; + +import org.openslx.libvirt.xml.LibvirtXmlNode; + +/** + * Implementation of a host CPU feature as part of the Libvirt capabilities XML document. + * + * @author Manuel Bentele + * @version 1.0 + */ +public class Feature extends LibvirtXmlNode +{ + /** + * Creates an empty host CPU feature instance. + */ + public Feature() + { + super(); + } + + /** + * Creates an host CPU feature representing an existing Libvirt XML host CPU feature element. + * + * @param xmlNode existing Libvirt XML host CPU feature element. + */ + public Feature( LibvirtXmlNode xmlNode ) + { + super( xmlNode ); + } + + /** + * Returns the name of the host CPU feature. + * + * @return name of the host CPU feature. + */ + public String getName() + { + return this.getXmlElementAttributeValue( "name" ); + } + + /** + * Creates an host CPU feature representing an existing Libvirt XML host CPU feature element. + * + * @param xmlNode existing Libvirt XML host CPU feature element. + * @return host CPU feature instance. + */ + public static Feature newInstance( LibvirtXmlNode xmlNode ) + { + return new Feature( xmlNode ); + } +} diff --git a/src/main/java/org/openslx/libvirt/capabilities/cpu/Pages.java b/src/main/java/org/openslx/libvirt/capabilities/cpu/Pages.java new file mode 100644 index 0000000..eea5a36 --- /dev/null +++ b/src/main/java/org/openslx/libvirt/capabilities/cpu/Pages.java @@ -0,0 +1,60 @@ +package org.openslx.libvirt.capabilities.cpu; + +import java.math.BigInteger; + +import org.openslx.libvirt.domain.DomainUtils; +import org.openslx.libvirt.xml.LibvirtXmlNode; + +/** + * Implementation of a host CPU memory pages instance as part of the Libvirt capabilities XML + * document. + * + * @author Manuel Bentele + * @version 1.0 + */ +public class Pages extends LibvirtXmlNode +{ + /** + * Creates an empty host CPU memory pages instance. + */ + public Pages() + { + super(); + } + + /** + * Creates a host CPU memory pages instance representing an existing Libvirt XML host CPU pages + * element. + * + * @param xmlNode existing Libvirt XML host CPU pages element. + */ + public Pages( LibvirtXmlNode xmlNode ) + { + super( xmlNode ); + } + + /** + * Returns size of the memory pages instance. + * + * @return size of the memory pages instance. + */ + public BigInteger getSize() + { + final String pagesValue = this.getXmlElementAttributeValue( "size" ); + final String pagesUnit = this.getXmlElementAttributeValue( "unit" ); + + return DomainUtils.decodeMemory( pagesValue, pagesUnit ); + } + + /** + * Creates a host CPU memory pages instance representing an existing Libvirt XML host CPU pages + * element. + * + * @param xmlNode existing Libvirt XML host CPU pages element. + * @return host CPU memory pages instance. + */ + public static Pages newInstance( LibvirtXmlNode xmlNode ) + { + return new Pages( xmlNode ); + } +} diff --git a/src/main/java/org/openslx/libvirt/capabilities/guest/Domain.java b/src/main/java/org/openslx/libvirt/capabilities/guest/Domain.java new file mode 100644 index 0000000..8716064 --- /dev/null +++ b/src/main/java/org/openslx/libvirt/capabilities/guest/Domain.java @@ -0,0 +1,53 @@ +package org.openslx.libvirt.capabilities.guest; + +import org.openslx.libvirt.domain.Domain.Type; +import org.openslx.libvirt.xml.LibvirtXmlNode; + +/** + * Implementation of a guest domain as part of the Libvirt capabilities XML capabilities document. + * + * @author Manuel Bentele + * @version 1.0 + */ +public class Domain extends LibvirtXmlNode +{ + /** + * Creates an empty guest domain instance. + */ + public Domain() + { + super(); + } + + /** + * Creates a guest domain representing an existing Libvirt XML guest domain element. + * + * @param xmlNode existing Libvirt XML guest domain element. + */ + public Domain( LibvirtXmlNode xmlNode ) + { + super( xmlNode ); + } + + /** + * Returns the domain type of the guest domain. + * + * @return type of the guest domain. + */ + public Type getType() + { + final String type = this.getXmlElementAttributeValue( "type" ); + return Type.fromString( type ); + } + + /** + * Creates a guest domain representing an existing Libvirt XML guest domain element. + * + * @param xmlNode existing Libvirt XML guest domain element. + * @return guest domain instance. + */ + public static Domain newInstance( LibvirtXmlNode xmlNode ) + { + return new Domain( xmlNode ); + } +} diff --git a/src/main/java/org/openslx/libvirt/capabilities/guest/Guest.java b/src/main/java/org/openslx/libvirt/capabilities/guest/Guest.java new file mode 100644 index 0000000..2471180 --- /dev/null +++ b/src/main/java/org/openslx/libvirt/capabilities/guest/Guest.java @@ -0,0 +1,127 @@ +package org.openslx.libvirt.capabilities.guest; + +import java.util.ArrayList; +import java.util.List; + +import org.openslx.libvirt.domain.Domain.OsType; +import org.openslx.libvirt.xml.LibvirtXmlNode; +import org.w3c.dom.NodeList; + +/** + * Implementation of the guest capabilities as part of the Libvirt capabilities XML document. + * + * @author Manuel Bentele + * @version 1.0 + */ +public class Guest extends LibvirtXmlNode +{ + /** + * Creates an empty guest instance. + */ + public Guest() + { + super(); + } + + /** + * Creates a guest representing an existing Libvirt XML guest capabilities element. + * + * @param xmlNode existing Libvirt XML guest capabilities element. + */ + public Guest( LibvirtXmlNode xmlNode ) + { + super( xmlNode ); + } + + /** + * Return OS type of the guest. + * + * @return OS type of the guest. + */ + public OsType getOsType() + { + final String osType = this.getXmlElementValue( "os_type" ); + return OsType.fromString( osType ); + } + + /** + * Returns the architecture name of the guest. + * + * @return architecture name of the guest. + */ + public String getArchName() + { + return this.getXmlElementAttributeValue( "arch", "name" ); + } + + /** + * Return word size of the guest's architecture. + * + * @return word size of the guest's architecture. + */ + public int getArchWordSize() + { + final String archWordSize = this.getXmlElementValue( "arch/wordsize" ); + return Integer.parseInt( archWordSize ); + } + + public String getArchEmulator() + { + return this.getXmlElementValue( "arch/emulator" ); + } + + /** + * Returns the available machines of the guest's architecture. + * + * @return available machines of the guest's architecture. + */ + public List<Machine> getArchMachines() + { + final List<Machine> machinesList = new ArrayList<Machine>(); + final NodeList machineNodes = this.getXmlNodes( "arch/machine" ); + + for ( int i = 0; i < machineNodes.getLength(); i++ ) { + final LibvirtXmlNode machineNode = new LibvirtXmlNode( this.getXmlDocument(), machineNodes.item( i ) ); + final Machine machine = Machine.newInstance( machineNode ); + + if ( machine != null ) { + machinesList.add( machine ); + } + } + + return machinesList; + } + + /** + * Returns the supported domains of the guest. + * + * @return supported domains of the guest. + */ + public List<Domain> getArchDomains() + { + final List<Domain> domainList = new ArrayList<Domain>(); + final NodeList domainNodes = this.getXmlNodes( "arch/domain" ); + + for ( int i = 0; i < domainNodes.getLength(); i++ ) { + final LibvirtXmlNode domainNode = new LibvirtXmlNode( this.getXmlDocument(), domainNodes.item( i ) ); + final Domain domain = Domain.newInstance( domainNode ); + + if ( domain != null ) { + domainList.add( domain ); + } + } + + return domainList; + } + + /** + * Creates a guest representing an existing Libvirt XML guest capabilities element. + * + * @param xmlNode existing Libvirt XML guest capabilities element. + * @return guest capabilities instance. + */ + public static Guest newInstance( LibvirtXmlNode xmlNode ) + { + return new Guest( xmlNode ); + } +} diff --git a/src/main/java/org/openslx/libvirt/capabilities/guest/Machine.java b/src/main/java/org/openslx/libvirt/capabilities/guest/Machine.java new file mode 100644 index 0000000..dfe6362 --- /dev/null +++ b/src/main/java/org/openslx/libvirt/capabilities/guest/Machine.java @@ -0,0 +1,72 @@ +package org.openslx.libvirt.capabilities.guest; + +import org.openslx.libvirt.xml.LibvirtXmlNode; + +/** + * Implementation of a guest machine as part of the Libvirt XML capabilities document. + * + * @author Manuel Bentele + * @version 1.0 + */ +public class Machine extends LibvirtXmlNode +{ + /** + * Creates an empty guest machine instance. + */ + public Machine() + { + super(); + } + + /** + * Creates an guest machine representing an existing Libvirt XML guest machine element. + * + * @param xmlNode existing Libvirt XML guest machine element. + */ + public Machine( LibvirtXmlNode xmlNode ) + { + super( xmlNode ); + } + + /** + * Returns the canonical machine name. + * + * @return canonical machine name. + */ + public String getCanonicalMachine() + { + return this.getXmlElementAttributeValue( "canonical" ); + } + + /** + * Returns the maximum number of CPUs supported by the guest machine. + * + * @return maximum number of CPUs supported by the guest machine. + */ + public int getMaxCpus() + { + final String numMaxCpus = this.getXmlElementAttributeValue( "maxCpus" ); + return Integer.parseUnsignedInt( numMaxCpus ); + } + + /** + * Returns the name of the guest machine. + * + * @return name of the guest machine. + */ + public String getName() + { + return this.getXmlElementValue( null ); + } + + /** + * Creates an guest machine representing an existing Libvirt XML guest machine element. + * + * @param xmlNode existing Libvirt XML guest machine element. + * @return guest machine instance. + */ + public static Machine newInstance( LibvirtXmlNode xmlNode ) + { + return new Machine( xmlNode ); + } +} diff --git a/src/main/java/org/openslx/libvirt/domain/Domain.java b/src/main/java/org/openslx/libvirt/domain/Domain.java index 4e15ec1..50d0811 100644 --- a/src/main/java/org/openslx/libvirt/domain/Domain.java +++ b/src/main/java/org/openslx/libvirt/domain/Domain.java @@ -20,6 +20,7 @@ import org.openslx.libvirt.domain.device.Disk; import org.openslx.libvirt.domain.device.DiskCdrom; import org.openslx.libvirt.domain.device.DiskFloppy; import org.openslx.libvirt.domain.device.DiskStorage; +import org.openslx.libvirt.domain.device.FileSystem; import org.openslx.libvirt.domain.device.Graphics; import org.openslx.libvirt.domain.device.GraphicsSdl; import org.openslx.libvirt.domain.device.GraphicsSpice; @@ -28,6 +29,8 @@ import org.openslx.libvirt.domain.device.Hostdev; import org.openslx.libvirt.domain.device.Interface; import org.openslx.libvirt.domain.device.InterfaceBridge; import org.openslx.libvirt.domain.device.InterfaceNetwork; +import org.openslx.libvirt.domain.device.Parallel; +import org.openslx.libvirt.domain.device.Serial; import org.openslx.libvirt.domain.device.Sound; import org.openslx.libvirt.domain.device.Video; import org.openslx.libvirt.xml.LibvirtXmlDocument; @@ -258,6 +261,17 @@ public class Domain extends LibvirtXmlDocument } /** + * Returns the libosinfo operating system identifier. + * + * @return libosinfo operating system identifier. + */ + public String getLibOsInfoOsId() + { + return this.getRootXmlNode() + .getXmlElementAttributeValue( "metadata/*[local-name()='libosinfo']/*[local-name()='os']", "id" ); + } + + /** * Returns virtual machine UUID defined in the Libvirt domain XML document. * * @return UUID of virtual machine. @@ -353,6 +367,122 @@ public class Domain extends LibvirtXmlDocument } /** + * Returns OS type defined in the Libvirt domain XML document. + * + * @return OS type of the virtual machine. + */ + public OsType getOsType() + { + final String osType = this.getRootXmlNode().getXmlElementValue( "os/type" ); + return OsType.fromString( osType ); + } + + /** + * Set OS type in the Libvirt domain XML document. + * + * @param type OS type for the virtual machine. + */ + public void setOsType( OsType type ) + { + this.getRootXmlNode().setXmlElementValue( "os/type", type.toString() ); + } + + /** + * Returns OS architecture defined in the Libvirt domain XML document. + * + * @return OS architecture of the virtual machine. + */ + public String getOsArch() + { + return this.getRootXmlNode().getXmlElementAttributeValue( "os/type", "arch" ); + } + + /** + * Set OS architecture in the Libvirt domain XML document. + * + * @param arch OS architecture for the virtual machine. + */ + public void setOsArch( String arch ) + { + this.getRootXmlNode().setXmlElementAttributeValue( "os/type", "arch", arch ); + } + + /** + * Returns OS machine defined in the Libvirt domain XML document. + * + * @return OS machine of the virtual machine. + */ + public String getOsMachine() + { + return this.getRootXmlNode().getXmlElementAttributeValue( "os/type", "machine" ); + } + + /** + * Set OS machine in the Libvirt domain XML document. + * + * @param machine OS machine for the virtual machine. + */ + public void setOsMachine( String machine ) + { + this.getRootXmlNode().setXmlElementAttributeValue( "os/type", "machine", machine ); + } + + /** + * Operating system types specifiable for a virtual machine in the Libvirt domain XML document. + * + * @author Manuel Bentele + * @version 1.0 + */ + public enum OsType + { + // @formatter:off + XEN ( "xen" ), + LINUX( "linux" ), + HVM ( "hvm" ), + EXE ( "exe" ), + UML ( "uml" ); + // @formatter:on + + /** + * Name of the OS type in a Libvirt domain XML document. + */ + private final String osType; + + /** + * Creates an OS type. + * + * @param osType valid name of the OS type in the Libvirt domain XML document. + */ + OsType( String osType ) + { + this.osType = osType; + } + + @Override + public String toString() + { + return this.osType; + } + + /** + * Creates an OS type from its name with error check. + * + * @param osType name of the OS type in the Libvirt domain XML document. + * @return valid OS type. + */ + public static OsType fromString( String osType ) + { + for ( OsType t : OsType.values() ) { + if ( t.osType.equalsIgnoreCase( osType ) ) { + return t; + } + } + + return null; + } + } + + /** * Returns virtual machine CPU model defined in the Libvirt domain XML document. * * @return CPU model of virtual machine. @@ -484,7 +614,7 @@ public class Domain extends LibvirtXmlDocument /** * Creates a CPU check from its name with error check. * - * @param mode name of the CPU check in the Libvirt domain XML document. + * @param check name of the CPU check in the Libvirt domain XML document. * @return valid CPU check. */ public static CpuCheck fromString( String check ) @@ -521,6 +651,26 @@ public class Domain extends LibvirtXmlDocument } /** + * Returns the file name of the emulator binary defined in the Libvirt domain XML document. + * + * @return file name of the emulator binary. + */ + public String getDevicesEmulator() + { + return this.getRootXmlNode().getXmlElementValue( "devices/emulator" ); + } + + /** + * Sets the file name of the emulator binary in the Libvirt domain XML document. + * + * @param emulator file name of the emulator binary. + */ + public void setDevicesEmulator( String emulator ) + { + this.getRootXmlNode().setXmlElementValue( "devices/emulator", emulator ); + } + + /** * Returns virtual machine devices defined in the Libvirt domain XML document. * * @return devices of the virtual machine. @@ -535,12 +685,14 @@ public class Domain extends LibvirtXmlDocument NodeList devicesElements = devicesNode.getChildNodes(); for ( int i = 0; i < devicesElements.getLength(); i++ ) { - LibvirtXmlNode deviceNode = null; - deviceNode = new LibvirtXmlNode( this.getRootXmlNode().getXmlDocument(), devicesElements.item( i ) ); - Device device = Device.newInstance( deviceNode ); - - if ( device != null ) { - devices.add( device ); + final Node childNode = devicesElements.item( i ); + if ( childNode.getNodeType() == Node.ELEMENT_NODE ) { + LibvirtXmlNode deviceNode = new LibvirtXmlNode( this.getRootXmlNode().getXmlDocument(), childNode ); + Device device = Device.newInstance( deviceNode ); + + if ( device != null ) { + devices.add( device ); + } } } } @@ -687,6 +839,17 @@ public class Domain extends LibvirtXmlDocument } /** + * Returns list of virtual machine file system devices specified in the Libvirt domain XML + * document. + * + * @return list of virtual machine file system devices. + */ + public ArrayList<FileSystem> getFileSystemDevices() + { + return Domain.filterDevices( FileSystem.class, this.getDevices() ); + } + + /** * Returns list of virtual machine hostdev devices specified in the Libvirt domain XML document. * * @return list of virtual machine hostdev devices. @@ -718,6 +881,28 @@ public class Domain extends LibvirtXmlDocument } /** + * Returns list of virtual machine parallel port devices specified in the Libvirt domain XML + * document. + * + * @return list of virtual machine parallel port devices. + */ + public ArrayList<Parallel> getParallelDevices() + { + return Domain.filterDevices( Parallel.class, this.getDevices() ); + } + + /** + * Returns list of virtual machine serial port devices specified in the Libvirt domain XML + * document. + * + * @return list of virtual machine serial port devices. + */ + public ArrayList<Serial> getSerialDevices() + { + return Domain.filterDevices( Serial.class, this.getDevices() ); + } + + /** * Returns list of virtual machine sound devices specified in the Libvirt domain XML document. * * @return list of virtual machine sound devices. @@ -871,6 +1056,16 @@ public class Domain extends LibvirtXmlDocument } /** + * Adds a virtual machine file system device to the Libvirt domain XML document. + * + * @return reference to the added file system device if creation was successful. + */ + public FileSystem addFileSystemDevice() + { + return FileSystem.class.cast( this.addDevice( new FileSystem() ) ); + } + + /** * Adds a virtual machine disk device to the Libvirt domain XML document. * * @return reference to the added disk device if creation was successful. @@ -951,6 +1146,26 @@ public class Domain extends LibvirtXmlDocument } /** + * Adds a virtual machine parallel port device to the Libvirt domain XML document. + * + * @return reference to the added parallel port device if creation was successful. + */ + public Parallel addParallelDevice() + { + return Parallel.class.cast( this.addDevice( new Parallel() ) ); + } + + /** + * Adds a virtual machine serial port device to the Libvirt domain XML document. + * + * @return reference to the added serial port device if creation was successful. + */ + public Serial addSerialDevice() + { + return Serial.class.cast( this.addDevice( new Serial() ) ); + } + + /** * Adds a virtual machine sound device to the Libvirt domain XML document. * * @return reference to the added sound device if creation was successful. @@ -1012,7 +1227,8 @@ public class Domain extends LibvirtXmlDocument public void removeInterfaceDevicesSource() { for ( Interface interfaceDevice : this.getInterfaceDevices() ) { - interfaceDevice.removeSource(); + // set empty source to preserve the XML attribute (to prevent XML validation errors) + interfaceDevice.setSource( "" ); } } } diff --git a/src/main/java/org/openslx/libvirt/domain/device/ControllerUsb.java b/src/main/java/org/openslx/libvirt/domain/device/ControllerUsb.java index 695167c..1798027 100644 --- a/src/main/java/org/openslx/libvirt/domain/device/ControllerUsb.java +++ b/src/main/java/org/openslx/libvirt/domain/device/ControllerUsb.java @@ -122,7 +122,7 @@ public class ControllerUsb extends Controller /** * Creates USB controller device model from its name with error check. * - * @param type name of the USB controller device model in a Libvirt domain XML document. + * @param model name of the USB controller device model in a Libvirt domain XML document. * @return valid USB controller device model. */ public static Model fromString( String model ) diff --git a/src/main/java/org/openslx/libvirt/domain/device/Device.java b/src/main/java/org/openslx/libvirt/domain/device/Device.java index 5c26c55..151592a 100644 --- a/src/main/java/org/openslx/libvirt/domain/device/Device.java +++ b/src/main/java/org/openslx/libvirt/domain/device/Device.java @@ -77,6 +77,9 @@ public class Device extends LibvirtXmlNode } else if ( device instanceof Disk ) { LibvirtXmlNode xmlNode = Device.createDeviceElement( xmlParentNode, Type.DISK ); createdDevice = Disk.createInstance( Disk.class.cast( device ), xmlNode ); + } else if ( device instanceof FileSystem ) { + LibvirtXmlNode xmlNode = Device.createDeviceElement( xmlParentNode, Type.FILESYSTEM ); + createdDevice = FileSystem.createInstance( FileSystem.class.cast( device ), xmlNode ); } else if ( device instanceof Hostdev ) { LibvirtXmlNode xmlNode = Device.createDeviceElement( xmlParentNode, Type.HOSTDEV ); createdDevice = Hostdev.createInstance( Hostdev.class.cast( device ), xmlNode ); @@ -86,6 +89,12 @@ public class Device extends LibvirtXmlNode } else if ( device instanceof Graphics ) { LibvirtXmlNode xmlNode = Device.createDeviceElement( xmlParentNode, Type.GRAPHICS ); createdDevice = Graphics.createInstance( Graphics.class.cast( device ), xmlNode ); + } else if ( device instanceof Parallel ) { + LibvirtXmlNode xmlNode = Device.createDeviceElement( xmlParentNode, Type.PARALLEL ); + createdDevice = Parallel.createInstance( xmlNode ); + } else if ( device instanceof Serial ) { + LibvirtXmlNode xmlNode = Device.createDeviceElement( xmlParentNode, Type.SERIAL ); + createdDevice = Serial.createInstance( xmlNode ); } else if ( device instanceof Sound ) { LibvirtXmlNode xmlNode = Device.createDeviceElement( xmlParentNode, Type.SOUND ); createdDevice = Sound.createInstance( xmlNode ); @@ -125,6 +134,9 @@ public class Device extends LibvirtXmlNode case DISK: device = Disk.newInstance( xmlNode ); break; + case FILESYSTEM: + device = FileSystem.newInstance( xmlNode ); + break; case HOSTDEV: device = Hostdev.newInstance( xmlNode ); break; @@ -134,6 +146,12 @@ public class Device extends LibvirtXmlNode case GRAPHICS: device = Graphics.newInstance( xmlNode ); break; + case PARALLEL: + device = Parallel.newInstance( xmlNode ); + break; + case SERIAL: + device = Serial.newInstance( xmlNode ); + break; case SOUND: device = Sound.newInstance( xmlNode ); break; @@ -157,9 +175,12 @@ public class Device extends LibvirtXmlNode // @formatter:off CONTROLLER( "controller" ), DISK ( "disk" ), + FILESYSTEM( "filesystem" ), HOSTDEV ( "hostdev" ), INTERFACE ( "interface" ), GRAPHICS ( "graphics" ), + PARALLEL ( "parallel" ), + SERIAL ( "serial" ), SOUND ( "sound" ), VIDEO ( "video" ); // @formatter:on diff --git a/src/main/java/org/openslx/libvirt/domain/device/Disk.java b/src/main/java/org/openslx/libvirt/domain/device/Disk.java index 464e7b6..7694538 100644 --- a/src/main/java/org/openslx/libvirt/domain/device/Disk.java +++ b/src/main/java/org/openslx/libvirt/domain/device/Disk.java @@ -68,7 +68,7 @@ public class Disk extends Device storageSource = this.getXmlElementAttributeValue( "source", "file" ); break; case BLOCK: - storageSource = this.getXmlElementAttributeValue( "source", "bdev" ); + storageSource = this.getXmlElementAttributeValue( "source", "dev" ); break; } @@ -96,7 +96,7 @@ public class Disk extends Device this.setXmlElementAttributeValue( "source", "file", source ); break; case BLOCK: - this.setXmlElementAttributeValue( "source", "bdev", source ); + this.setXmlElementAttributeValue( "source", "dev", source ); break; } } @@ -195,7 +195,7 @@ public class Disk extends Device /** * Sets target device for the disk device. * - * @param target device for the disk device. + * @param targetDevice target device for the disk device. */ public void setTargetDevice( String targetDevice ) { diff --git a/src/main/java/org/openslx/libvirt/domain/device/FileSystem.java b/src/main/java/org/openslx/libvirt/domain/device/FileSystem.java new file mode 100644 index 0000000..9ec8caf --- /dev/null +++ b/src/main/java/org/openslx/libvirt/domain/device/FileSystem.java @@ -0,0 +1,292 @@ +package org.openslx.libvirt.domain.device; + +import org.openslx.libvirt.xml.LibvirtXmlNode; + +/** + * A file system device node in a Libvirt domain XML document. + * + * @author Manuel Bentele + * @version 1.0 + */ +public class FileSystem extends Device +{ + /** + * Creates an empty file system device. + */ + public FileSystem() + { + super(); + } + + /** + * Creates a file system device representing an existing Libvirt XML file system device element. + * + * @param xmlNode existing Libvirt XML file system device element. + */ + public FileSystem( LibvirtXmlNode xmlNode ) + { + super( xmlNode ); + } + + /** + * Returns access mode of the file system device. + * + * @return access mode of the file system device. + */ + public AccessMode getAccessMode() + { + final String mode = this.getXmlElementAttributeValue( "accessmode" ); + return AccessMode.fromString( mode ); + } + + /** + * Sets access mode for the file system device. + * + * @param mode access mode for the file system device. + */ + public void setAccessMode( AccessMode mode ) + { + this.setXmlElementAttributeValue( "accessmode", mode.toString() ); + } + + /** + * Returns type of the file system device. + * + * @return type of the file system device. + */ + public Type getType() + { + final String type = this.getXmlElementAttributeValue( "type" ); + return Type.fromString( type ); + } + + /** + * Sets type for the file system device. + * + * @param type type for the file system device. + */ + public void setType( Type type ) + { + this.setXmlElementAttributeValue( "type", type.toString() ); + } + + /** + * Returns source of the file system device. + * + * @return source of the file system device. + */ + public String getSource() + { + final Type type = this.getType(); + String source = null; + + switch ( type ) { + case BIND: + source = this.getXmlElementAttributeValue( "source", "dir" ); + break; + case BLOCK: + source = this.getXmlElementAttributeValue( "source", "dev" ); + break; + case FILE: + source = this.getXmlElementAttributeValue( "source", "file" ); + break; + case MOUNT: + source = this.getXmlElementAttributeValue( "source", "dir" ); + break; + case RAM: + source = this.getXmlElementAttributeValue( "source", "usage" ); + break; + case TEMPLATE: + source = this.getXmlElementAttributeValue( "source", "name" ); + break; + } + + return source; + } + + /** + * Sets source for the file system device. + * + * @param source source for the file system device. + */ + public void setSource( String source ) + { + Type type = this.getType(); + + // remove all attributes from sub-element 'source' + this.removeXmlElementAttributes( "source" ); + + switch ( type ) { + case BIND: + this.setXmlElementAttributeValue( "source", "dir", source ); + break; + case BLOCK: + this.setXmlElementAttributeValue( "source", "dev", source ); + break; + case FILE: + this.setXmlElementAttributeValue( "source", "file", source ); + break; + case MOUNT: + this.setXmlElementAttributeValue( "source", "dir", source ); + break; + case RAM: + this.setXmlElementAttributeValue( "source", "usage", source ); + break; + case TEMPLATE: + this.setXmlElementAttributeValue( "source", "name", source ); + break; + } + } + + /** + * Returns target of the file system device. + * + * @return target of the file system device. + */ + public String getTarget() + { + return this.getXmlElementAttributeValue( "target", "dir" ); + } + + /** + * Sets target for the file system device. + * + * @param target target for the file system device. + */ + public void setTarget( String target ) + { + this.setXmlElementAttributeValue( "target", "dir", target ); + } + + /** + * Creates a non-existent file system device as Libvirt XML device element. + * + * @param xmlNode Libvirt XML node of the Libvirt XML device that is created. + * @return created file system device instance. + */ + public static FileSystem createInstance( LibvirtXmlNode xmlNode ) + { + return FileSystem.newInstance( xmlNode ); + } + + /** + * Creates a file system device representing an existing Libvirt XML file system device element. + * + * @param xmlNode existing Libvirt XML file system device element. + * @return file system device instance. + */ + public static FileSystem newInstance( LibvirtXmlNode xmlNode ) + { + return new FileSystem( xmlNode ); + } + + /** + * Access mode for the file system device. + * + * @author Manuel Bentele + * @version 1.0 + */ + public enum AccessMode + { + // @formatter:off + PASSTHROUGH( "passthrough" ), + MAPPED ( "mapped" ), + SQUASH ( "squash" ); + // @formatter:on + + /** + * Name of the file system device access mode. + */ + private String mode; + + /** + * Creates file system device access mode. + * + * @param mode valid name of the file system device access mode in a Libvirt domain XML + * document. + */ + AccessMode( String mode ) + { + this.mode = mode; + } + + @Override + public String toString() + { + return this.mode; + } + + /** + * Creates file system device access mode from its name with error check. + * + * @param mode name of the file system device access mode in a Libvirt domain XML document. + * @return valid file system device access mode. + */ + public static AccessMode fromString( String mode ) + { + for ( AccessMode a : AccessMode.values() ) { + if ( a.mode.equalsIgnoreCase( mode ) ) { + return a; + } + } + + return null; + } + } + + /** + * Type of file system device. + * + * @author Manuel Bentele + * @version 1.0 + */ + public enum Type + { + // @formatter:off + MOUNT ( "mount" ), + TEMPLATE( "template" ), + FILE ( "file" ), + BLOCK ( "block" ), + RAM ( "ram" ), + BIND ( "bind" ); + // @formatter:on + + /** + * Name of the file system device type. + */ + private String type; + + /** + * Creates file system device type. + * + * @param type valid name of the file system device type in a Libvirt domain XML document. + */ + Type( String type ) + { + this.type = type; + } + + @Override + public String toString() + { + return this.type; + } + + /** + * Creates file system device type from its name with error check. + * + * @param type name of the file system device type in a Libvirt domain XML document. + * @return valid file system device type. + */ + public static Type fromString( String type ) + { + for ( Type t : Type.values() ) { + if ( t.type.equalsIgnoreCase( type ) ) { + return t; + } + } + + return null; + } + } +} diff --git a/src/main/java/org/openslx/libvirt/domain/device/HostdevPci.java b/src/main/java/org/openslx/libvirt/domain/device/HostdevPci.java index 3b26fb0..a0563f2 100644 --- a/src/main/java/org/openslx/libvirt/domain/device/HostdevPci.java +++ b/src/main/java/org/openslx/libvirt/domain/device/HostdevPci.java @@ -48,7 +48,7 @@ public class HostdevPci extends Hostdev * detached from the host before being passed on to the guest and reattached to the host after * the guest exits. * - * @return state whether PCI hostdev device is managed. + * @param managed state whether PCI hostdev device is managed or not. */ public void setManaged( boolean managed ) { diff --git a/src/main/java/org/openslx/libvirt/domain/device/Interface.java b/src/main/java/org/openslx/libvirt/domain/device/Interface.java index b09c7da..44b8e4c 100644 --- a/src/main/java/org/openslx/libvirt/domain/device/Interface.java +++ b/src/main/java/org/openslx/libvirt/domain/device/Interface.java @@ -59,16 +59,16 @@ public class Interface extends Device { return Type.fromString( this.getXmlElementAttributeValue( "type" ) ); } - + /** * Sets type of the network device. - * - * @return type of the network device. + * + * @param type network device type. */ - public void setType(Type type) + public void setType( Type type ) { String source = this.getSource(); - + // change type and set source again this.setXmlElementAttributeValue( "type", type.toString() ); this.setSource( source ); @@ -119,6 +119,26 @@ public class Interface extends Device } /** + * Returns MAC address of the network device. + * + * @return MAC address of the network device. + */ + public String getMacAddress() + { + return this.getXmlElementAttributeValue( "mac", "address" ); + } + + /** + * Sets MAC address of the network device. + * + * @param macAddress MAC address for the network device. + */ + public void setMacAddress( String macAddress ) + { + this.setXmlElementAttributeValue( "mac", "address", macAddress ); + } + + /** * Removes boot oder entry of the network interface device. */ public void removeBootOrder() @@ -135,6 +155,14 @@ public class Interface extends Device } /** + * Removes MAC address of the network interface device. + */ + public void removeMacAddress() + { + this.removeXmlElement( "mac" ); + } + + /** * Creates a non-existent network interface device as Libvirt XML device element. * * @param iface network device that is created. @@ -299,7 +327,7 @@ public class Interface extends Device /** * Creates network interface device model from its name with error check. * - * @param type name of the network interface device model in a Libvirt domain XML document. + * @param model name of the network interface device model in a Libvirt domain XML document. * @return valid network interface device model. */ public static Model fromString( String model ) diff --git a/src/main/java/org/openslx/libvirt/domain/device/Parallel.java b/src/main/java/org/openslx/libvirt/domain/device/Parallel.java new file mode 100644 index 0000000..7db60ca --- /dev/null +++ b/src/main/java/org/openslx/libvirt/domain/device/Parallel.java @@ -0,0 +1,158 @@ +package org.openslx.libvirt.domain.device; + +import org.openslx.libvirt.xml.LibvirtXmlNode; + +/** + * A parallel port device node in a Libvirt domain XML document. + * + * @author Manuel Bentele + * @version 1.0 + */ +public class Parallel extends Device +{ + /** + * Creates an empty parallel port device. + */ + public Parallel() + { + super(); + } + + /** + * Creates a parallel port device representing an existing Libvirt XML parallel port device + * element. + * + * @param xmlNode existing Libvirt XML parallel port device element. + */ + public Parallel( LibvirtXmlNode xmlNode ) + { + super( xmlNode ); + } + + /** + * Returns the type of the parallel port device. + * + * @return type of the parallel port device. + */ + public Type getType() + { + final String type = this.getXmlElementAttributeValue( "type" ); + return Type.fromString( type ); + } + + /** + * Sets the type for the parallel port device. + * + * @param type type for the parallel port device. + */ + public void setType( Type type ) + { + this.setXmlElementAttributeValue( "type", type.toString() ); + } + + /** + * Returns the source of the parallel port device. + * + * @return source of the parallel port device. + */ + public String getSource() + { + return this.getXmlElementAttributeValue( "source", "path" ); + } + + /** + * Sets the source for the parallel port device. + * + * @param source source for the parallel port device. + */ + public void setSource( String source ) + { + this.setXmlElementAttributeValue( "source", "path", source ); + } + + /** + * Creates a non-existent parallel port device as Libvirt XML parallel port device element. + * + * @param xmlNode Libvirt XML node of the Libvirt XML parallel port device that is created. + * @return created parallel port device instance. + */ + public static Parallel createInstance( LibvirtXmlNode xmlNode ) + { + return Parallel.newInstance( xmlNode ); + } + + /** + * Creates a parallel port device representing an existing Libvirt XML parallel port device + * element. + * + * @param xmlNode existing Libvirt XML parallel port device element. + * @return parallel port device instance. + */ + public static Parallel newInstance( LibvirtXmlNode xmlNode ) + { + return new Parallel( xmlNode ); + } + + /** + * Type of parallel port device. + * + * @author Manuel Bentele + * @version 1.0 + */ + public enum Type + { + // @formatter:off + DEV ( "dev" ), + FILE ( "file" ), + PIPE ( "pipe" ), + UNIX ( "unix" ), + TCP ( "tcp" ), + UDP ( "udp" ), + NULL ( "null" ), + STDIO ( "stdio" ), + VC ( "vc" ), + PTY ( "pty" ), + SPICEVMC ( "spicevmc" ), + SPICEPORT( "spiceport" ), + NMDM ( "nmdm" ); + // @formatter:on + + /** + * Name of the parallel port device type. + */ + private String type; + + /** + * Creates parallel port device type. + * + * @param type valid name of the parallel port device type in a Libvirt domain XML document. + */ + Type( String type ) + { + this.type = type; + } + + @Override + public String toString() + { + return this.type; + } + + /** + * Creates parallel port device type from its name with error check. + * + * @param type name of the parallel port device type in a Libvirt domain XML document. + * @return valid parallel port device type. + */ + public static Type fromString( String type ) + { + for ( Type t : Type.values() ) { + if ( t.type.equalsIgnoreCase( type ) ) { + return t; + } + } + + return null; + } + } +} diff --git a/src/main/java/org/openslx/libvirt/domain/device/Serial.java b/src/main/java/org/openslx/libvirt/domain/device/Serial.java new file mode 100644 index 0000000..54be26e --- /dev/null +++ b/src/main/java/org/openslx/libvirt/domain/device/Serial.java @@ -0,0 +1,156 @@ +package org.openslx.libvirt.domain.device; + +import org.openslx.libvirt.xml.LibvirtXmlNode; + +/** + * A serial port device node in a Libvirt domain XML document. + * + * @author Manuel Bentele + * @version 1.0 + */ +public class Serial extends Device +{ + /** + * Creates an empty serial port device. + */ + public Serial() + { + super(); + } + + /** + * Creates a serial port device representing an existing Libvirt XML serial port device element. + * + * @param xmlNode existing Libvirt XML serial port device element. + */ + public Serial( LibvirtXmlNode xmlNode ) + { + super( xmlNode ); + } + + /** + * Returns the type of the serial port device. + * + * @return type of the serial port device. + */ + public Type getType() + { + final String type = this.getXmlElementAttributeValue( "type" ); + return Type.fromString( type ); + } + + /** + * Sets the type for the serial port device. + * + * @param type type for the serial port device. + */ + public void setType( Type type ) + { + this.setXmlElementAttributeValue( "type", type.toString() ); + } + + /** + * Returns the source of the serial port device. + * + * @return source of the serial port device. + */ + public String getSource() + { + return this.getXmlElementAttributeValue( "source", "path" ); + } + + /** + * Sets the source for the serial port device. + * + * @param source source for the serial port device. + */ + public void setSource( String source ) + { + this.setXmlElementAttributeValue( "source", "path", source ); + } + + /** + * Creates a non-existent serial port device as Libvirt XML serial port device element. + * + * @param xmlNode Libvirt XML node of the Libvirt XML serial port device that is created. + * @return created serial port device instance. + */ + public static Serial createInstance( LibvirtXmlNode xmlNode ) + { + return Serial.newInstance( xmlNode ); + } + + /** + * Creates a serial port device representing an existing Libvirt XML serial port device element. + * + * @param xmlNode existing Libvirt XML serial port device element. + * @return serial port device instance. + */ + public static Serial newInstance( LibvirtXmlNode xmlNode ) + { + return new Serial( xmlNode ); + } + + /** + * Type of serial port device. + * + * @author Manuel Bentele + * @version 1.0 + */ + public enum Type + { + // @formatter:off + DEV ( "dev" ), + FILE ( "file" ), + PIPE ( "pipe" ), + UNIX ( "unix" ), + TCP ( "tcp" ), + UDP ( "udp" ), + NULL ( "null" ), + STDIO ( "stdio" ), + VC ( "vc" ), + PTY ( "pty" ), + SPICEVMC ( "spicevmc" ), + SPICEPORT( "spiceport" ), + NMDM ( "nmdm" ); + // @formatter:on + + /** + * Name of the serial port device type. + */ + private String type; + + /** + * Creates serial port device type. + * + * @param type valid name of the serial port device type in a Libvirt domain XML document. + */ + Type( String type ) + { + this.type = type; + } + + @Override + public String toString() + { + return this.type; + } + + /** + * Creates serial port device type from its name with error check. + * + * @param type name of the serial port device type in a Libvirt domain XML document. + * @return valid serial port device type. + */ + public static Type fromString( String type ) + { + for ( Type t : Type.values() ) { + if ( t.type.equalsIgnoreCase( type ) ) { + return t; + } + } + + return null; + } + } +} diff --git a/src/main/java/org/openslx/libvirt/domain/device/Sound.java b/src/main/java/org/openslx/libvirt/domain/device/Sound.java index e424ed4..dfeeffd 100644 --- a/src/main/java/org/openslx/libvirt/domain/device/Sound.java +++ b/src/main/java/org/openslx/libvirt/domain/device/Sound.java @@ -111,7 +111,7 @@ public class Sound extends Device /** * Creates sound device model from its name with error check. * - * @param type name of the sound device model in a Libvirt domain XML document. + * @param model name of the sound device model in a Libvirt domain XML document. * @return valid sound device model. */ public static Model fromString( String model ) diff --git a/src/main/java/org/openslx/libvirt/domain/device/Video.java b/src/main/java/org/openslx/libvirt/domain/device/Video.java index e901b85..0f8861f 100644 --- a/src/main/java/org/openslx/libvirt/domain/device/Video.java +++ b/src/main/java/org/openslx/libvirt/domain/device/Video.java @@ -171,7 +171,7 @@ public class Video extends Device /** * Creates video device model from its name with error check. * - * @param type name of the video device model in a Libvirt domain XML document. + * @param model name of the video device model in a Libvirt domain XML document. * @return valid video device model. */ public static Model fromString( String model ) diff --git a/src/main/java/org/openslx/libvirt/libosinfo/LibOsInfo.java b/src/main/java/org/openslx/libvirt/libosinfo/LibOsInfo.java new file mode 100644 index 0000000..f506d74 --- /dev/null +++ b/src/main/java/org/openslx/libvirt/libosinfo/LibOsInfo.java @@ -0,0 +1,158 @@ +package org.openslx.libvirt.libosinfo; + +import java.io.File; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.function.Predicate; + +import org.openslx.libvirt.libosinfo.os.Os; +import org.openslx.libvirt.xml.LibvirtXmlDocument; +import org.openslx.libvirt.xml.LibvirtXmlDocumentException; +import org.openslx.libvirt.xml.LibvirtXmlNode; +import org.openslx.libvirt.xml.LibvirtXmlResources; +import org.openslx.libvirt.xml.LibvirtXmlSerializationException; +import org.openslx.libvirt.xml.LibvirtXmlValidationException; +import org.openslx.virtualization.Version; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; + +/** + * Implementation of a libosinfo XML document. + * + * The libosinfo XML document is used to describe existing operating systems, devices and their + * configuration possibilities. + * + * @author Manuel Bentele + * @version 1.0 + */ +public class LibOsInfo extends LibvirtXmlDocument +{ + /** + * Creates a libosinfo XML document from a {@link String} providing libosinfo XML content. + * + * @param xml {@link String} with libosinfo XML content. + * + * @throws LibvirtXmlDocumentException creation of XML context failed. + * @throws LibvirtXmlSerializationException serialization of the libosinfo XML content failed. + * @throws LibvirtXmlValidationException XML content is not a valid libosinfo XML document. + */ + public LibOsInfo( String xml ) + throws LibvirtXmlDocumentException, LibvirtXmlSerializationException, LibvirtXmlValidationException + { + super( xml, LibvirtXmlResources.getLibOsInfoRng( "osinfo.rng" ) ); + } + + /** + * Creates a libosinfo XML document from a {@link File} containing libosinfo XML content. + * + * @param xml existing {@link File} containing libosinfo XML content. + * + * @throws LibvirtXmlDocumentException creation of XML context failed. + * @throws LibvirtXmlSerializationException serialization of the libosinfo XML content failed. + * @throws LibvirtXmlValidationException XML content is not a valid libosinfo XML document. + */ + public LibOsInfo( File xml ) + throws LibvirtXmlDocumentException, LibvirtXmlSerializationException, LibvirtXmlValidationException + { + super( xml, LibvirtXmlResources.getLibOsInfoRng( "osinfo.rng" ) ); + } + + /** + * Creates a libosinfo XML document from an {@link InputStream} providing libosinfo XML content. + * + * @param xml {@link InputStream} providing libosinfo XML content. + * + * @throws LibvirtXmlDocumentException creation of XML context failed. + * @throws LibvirtXmlSerializationException serialization of the libosinfo XML content failed. + * @throws LibvirtXmlValidationException XML content is not a valid libosinfo XML document. + */ + public LibOsInfo( InputStream xml ) + throws LibvirtXmlDocumentException, LibvirtXmlSerializationException, LibvirtXmlValidationException + { + super( xml, LibvirtXmlResources.getLibOsInfoRng( "osinfo.rng" ) ); + } + + /** + * Creates libosinfo XML document from {@link InputSource} providing libosinfo XML content. + * + * @param xml {@link InputSource} providing libosinfo XML content. + * + * @throws LibvirtXmlDocumentException creation of XML context failed. + * @throws LibvirtXmlSerializationException serialization of the libosinfo XML content failed. + * @throws LibvirtXmlValidationException XML content is not a valid libosinfo XML document. + */ + public LibOsInfo( InputSource xml ) + throws LibvirtXmlDocumentException, LibvirtXmlSerializationException, LibvirtXmlValidationException + { + super( xml, LibvirtXmlResources.getLibOsInfoRng( "osinfo.rng" ) ); + } + + /** + * Returns the version of the libosinfo database. + * + * @return version of the libosinfo database. + */ + public Version getVersion() + { + final String version = this.getRootXmlNode().getXmlElementAttributeValue( "version" ); + return Version.valueOf( version ); + } + + /** + * Returns a list of all defined operating systems. + * + * @return list of all defined operating systems. + */ + public ArrayList<Os> getOses() + { + final ArrayList<Os> oses = new ArrayList<Os>(); + final NodeList osNodes = this.getRootXmlNode().getXmlNodes( "os" ); + + if ( osNodes != null ) { + for ( int i = 0; i < osNodes.getLength(); i++ ) { + final Node childNode = osNodes.item( i ); + if ( childNode.getNodeType() == Node.ELEMENT_NODE ) { + final LibvirtXmlNode osNode = new LibvirtXmlNode( this.getRootXmlNode().getXmlDocument(), childNode ); + final Os os = Os.newInstance( osNode ); + + if ( os != null ) { + oses.add( os ); + } + } + } + } + + return oses; + } + + /** + * Lookups an operating system in the libosinfo database specified by the operating system + * identifier. + * + * @param osId identifier of the operating system to lookup in the libosinfo database. + * @return found operating system from the libosinfo database. + */ + public static Os lookupOs( String osId ) + { + Os os = null; + + if ( osId != null && !osId.isEmpty() ) { + ArrayList<Os> oses = null; + + try { + final LibOsInfo osInfo = new LibOsInfo( LibvirtXmlResources.getLibOsInfoXml( "osinfo.xml" ) ); + oses = osInfo.getOses(); + } catch ( LibvirtXmlDocumentException | LibvirtXmlSerializationException | LibvirtXmlValidationException e ) { + oses = null; + } + + if ( oses != null ) { + final Predicate<Os> byOsId = osCandidate -> osId.equals( osCandidate.getId() ); + os = oses.stream().filter( byOsId ).findFirst().orElse( null ); + } + } + + return os; + } +} diff --git a/src/main/java/org/openslx/libvirt/libosinfo/os/Os.java b/src/main/java/org/openslx/libvirt/libosinfo/os/Os.java new file mode 100644 index 0000000..37a0a2e --- /dev/null +++ b/src/main/java/org/openslx/libvirt/libosinfo/os/Os.java @@ -0,0 +1,93 @@ +package org.openslx.libvirt.libosinfo.os; + +import org.openslx.libvirt.xml.LibvirtXmlNode; +import org.openslx.virtualization.Version; + +/** + * A operating system node in a libosinfo XML document. + * + * @author Manuel Bentele + * @version 1.0 + */ +public class Os extends LibvirtXmlNode +{ + /** + * Creates an empty operating system. + */ + public Os() + { + super(); + } + + /** + * Creates a operating system representing an existing libosinfo XML operating system element. + * + * @param xmlNode existing libosinfo XML operating system element. + */ + public Os( LibvirtXmlNode xmlNode ) + { + super( xmlNode ); + } + + /** + * Returns the identifier of the operating system. + * + * @return identifier of the operating system. + */ + public String getId() + { + return this.getXmlElementAttributeValue( "id" ); + } + + /** + * Returns the name of the operating system. + * + * @return name of the operating system. + */ + public String getName() + { + return this.getXmlElementValue( "name" ); + } + + /** + * Returns the version of the operating system. + * + * @return version of the operating system. + */ + public Version getVersion() + { + final String version = this.getXmlElementValue( "version" ); + return Version.valueOf( version ); + } + + /** + * Returns the system family of the operating system. + * + * @return system family of the operating system. + */ + public String getFamily() + { + return this.getXmlElementValue( "family" ); + } + + /** + * Returns the distribution name of the operating system. + * + * @return distribution name of the operating system. + */ + public String getDistro() + { + return this.getXmlElementValue( "distro" ); + } + + /** + * Creates a operating system representing an existing libosinfo XML operating system element. + * + * @param xmlNode existing libosinfo XML operating system element. + * @return libosinfo XML operating system instance. + */ + public static Os newInstance( LibvirtXmlNode node ) + { + return new Os( node ); + } +} diff --git a/src/main/java/org/openslx/libvirt/xml/LibvirtXmlDocument.java b/src/main/java/org/openslx/libvirt/xml/LibvirtXmlDocument.java index 9382ced..f24ba4f 100644 --- a/src/main/java/org/openslx/libvirt/xml/LibvirtXmlDocument.java +++ b/src/main/java/org/openslx/libvirt/xml/LibvirtXmlDocument.java @@ -4,6 +4,7 @@ import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; +import java.io.StringReader; import java.io.StringWriter; import javax.xml.parsers.DocumentBuilder; @@ -252,16 +253,7 @@ public abstract class LibvirtXmlDocument implements LibvirtXmlSerializable, Libv @Override public void fromXml( String xml ) throws LibvirtXmlSerializationException { - try { - this.xmlDocument = this.domBuilder.parse( xml ); - this.xmlDocument.getDocumentElement().normalize(); - } catch ( SAXException e ) { - e.printStackTrace(); - } catch ( IOException e ) { - e.printStackTrace(); - } - - this.rootXmlNode = new LibvirtXmlNode( this.xmlDocument, this.xmlDocument.getDocumentElement() ); + this.fromXml( new InputSource( new StringReader( xml ) ) ); } @Override diff --git a/src/main/java/org/openslx/libvirt/xml/LibvirtXmlEditable.java b/src/main/java/org/openslx/libvirt/xml/LibvirtXmlEditable.java index 1ddddce..40d7b86 100644 --- a/src/main/java/org/openslx/libvirt/xml/LibvirtXmlEditable.java +++ b/src/main/java/org/openslx/libvirt/xml/LibvirtXmlEditable.java @@ -4,7 +4,7 @@ import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** - * Editability of XML nodes based on {@link XPath} expressions. + * Editability of XML nodes based on XPath expressions. * * @author Manuel Bentele * @version 1.0 @@ -12,17 +12,17 @@ import org.w3c.dom.NodeList; public interface LibvirtXmlEditable { /** - * Returns XML node selected by a {@link XPath} expression + * Returns XML node selected by a XPath expression * - * @param expression {@link XPath} expression to select XML node. + * @param expression XPath expression to select XML node. * @return selected XML node. */ public Node getXmlNode( String expression ); /** - * Returns XML nodes selected by a {@link XPath} expression + * Returns XML nodes selected by a XPath expression * - * @param expression {@link XPath} expression to select XML nodes. + * @param expression XPath expression to select XML nodes. * @return selected XML nodes. */ public NodeList getXmlNodes( String expression ); @@ -38,20 +38,20 @@ public interface LibvirtXmlEditable } /** - * Returns XML element from selection by a {@link XPath} expression. + * Returns XML element from selection by a XPath expression. * - * @param expression {@link XPath} expression to select XML element. + * @param expression XPath expression to select XML element. * @return selected XML element. */ public Node getXmlElement( String expression ); /** - * Sets an XML element selected by a {@link XPath} expression. + * Sets an XML element selected by a XPath expression. * - * If the XML element selected by the given {@link XPath} expression does not exists, the XML + * If the XML element selected by the given XPath expression does not exists, the XML * element will be created. * - * @param expression {@link XPath} expression to select XML element. + * @param expression XPath expression to select XML element. */ public default void setXmlElement( String expression ) { @@ -59,43 +59,43 @@ public interface LibvirtXmlEditable } /** - * Sets a XML element selected by a {@link XPath} expression and appends child XML node. + * Sets a XML element selected by a XPath expression and appends child XML node. * - * If the XML element selected by the given {@link XPath} expression does not exists, the XML + * If the XML element selected by the given XPath expression does not exists, the XML * element will be created and the given XML child node is appended. * - * @param expression {@link XPath} expression to select XML element. + * @param expression XPath expression to select XML element. * @param child XML node that will be appended to the selected XML element. */ public void setXmlElement( String expression, Node child ); /** - * Returns the text value of a XML element selected by a {@link XPath} expression. + * Returns the text value of a XML element selected by a XPath expression. * - * @param expression {@link XPath} expression to select XML element. + * @param expression XPath expression to select XML element. * @return Text value of the selected XML element. */ public String getXmlElementValue( String expression ); /** - * Sets the text value of a XML element selected by a {@link XPath} expression. + * Sets the text value of a XML element selected by a XPath expression. * - * @param expression {@link XPath} expression to select XML element. + * @param expression XPath expression to select XML element. * @param value text value to set selected XML element's text. */ public void setXmlElementValue( String expression, String value ); /** - * Removes a XML element and all its childs selected by a {@link XPath} expression. + * Removes a XML element and all its childs selected by a XPath expression. * - * @param expression {@link XPath} expression to select XML element. + * @param expression XPath expression to select XML element. */ public void removeXmlElement( String expression ); /** - * Removes all child elements of a XML element selected by a {@link XPath} expression. + * Removes all child elements of a XML element selected by a XPath expression. * - * @param expression {@link XPath} expression to select XML element. + * @param expression XPath expression to select XML element. */ public void removeXmlElementChilds( String expression ); @@ -128,14 +128,14 @@ public interface LibvirtXmlEditable } /** - * Returns the binary choice of a XML attribute from a XML element selected by a - * {@link XPath}expression. + * Returns the binary choice of a XML attribute from a XML element selected by a XPath + * expression. * * If the text value of the XML attribute equals to <i>yes</i>, the returned {@link boolean} * value is set to <i>true</i>. Otherwise, if the text value of the XML attribute equals to * <i>no</i>, the returned {@link boolean} value is set to <i>false</i>. * - * @param expression {@link XPath} expression to select XML element. + * @param expression XPath expression to select XML element. * @param attributeName name to select XML attribute of the current XML root element. * @return attribute value of the XML attribute from the current XML root element as * {@link boolean}. @@ -146,10 +146,9 @@ public interface LibvirtXmlEditable } /** - * Returns the text value of a XML attribute from a XML element selected by a - * {@link XPath}expression. + * Returns the text value of a XML attribute from a XML element selected by a XPath expression. * - * @param expression {@link XPath} expression to select XML element. + * @param expression XPath expression to select XML element. * @param attributeName name to select XML attribute of the selected XML element. * @return attribute text of the XML attribute from the selected XML element. */ @@ -185,15 +184,15 @@ public interface LibvirtXmlEditable } /** - * Sets the binary choice value of a XML attribute from a XML element selected by a - * {@link XPath} expression. + * Sets the binary choice value of a XML attribute from a XML element selected by a XPath + * expression. * * If the binary choice value for the XML attribute equals to <i>true</i>, the text value of the * selected XML attribute is set to <i>yes</i>. Otherwise, if the binary choice value for the * selected XML attribute equals to <i>false</i>, the text value of the selected XML attribute is * set to <i>no</i>. * - * @param expression {@link XPath} expression to select XML element. + * @param expression XPath expression to select XML element. * @param attributeName name to select XML attribute of the selected XML element. * @param value binary choice value for the selected XML attribute from the selected XML element. */ @@ -204,10 +203,9 @@ public interface LibvirtXmlEditable } /** - * Sets the text value of a XML attribute from a XML element selected by a - * {@link XPath} expression. + * Sets the text value of a XML attribute from a XML element selected by a XPath expression. * - * @param expression {@link XPath} expression to select XML element. + * @param expression XPath expression to select XML element. * @param attributeName name to select XML attribute of the selected XML element. * @param value XML attribute value for the selected XML attribute from the selected XML element. */ @@ -224,17 +222,17 @@ public interface LibvirtXmlEditable } /** - * Removes an XML attribute from a XML element selected by a {@link XPath} expression. + * Removes an XML attribute from a XML element selected by a XPath expression. * - * @param expression {@link XPath} expression to select XML element. + * @param expression XPath expression to select XML element. * @param attributeName name of the attribute which should be deleted. */ public void removeXmlElementAttribute( String expression, String attributeName ); /** - * Removes all XML attributes from a XML element selected by a {@link XPath} expression. + * Removes all XML attributes from a XML element selected by a XPath expression. * - * @param expression {@link XPath} expression to select XML element. + * @param expression XPath expression to select XML element. */ public void removeXmlElementAttributes( String expression ); diff --git a/src/main/java/org/openslx/libvirt/xml/LibvirtXmlNode.java b/src/main/java/org/openslx/libvirt/xml/LibvirtXmlNode.java index 93e28de..6d00271 100644 --- a/src/main/java/org/openslx/libvirt/xml/LibvirtXmlNode.java +++ b/src/main/java/org/openslx/libvirt/xml/LibvirtXmlNode.java @@ -12,7 +12,7 @@ import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** - * A representation of a XML node as part of a {@link LibvirtXMLDocument}. + * A representation of a XML node as part of a {@link LibvirtXmlDocument}. * * @author Manuel Bentele * @version 1.0 @@ -20,17 +20,17 @@ import org.w3c.dom.NodeList; public class LibvirtXmlNode implements LibvirtXmlCreatable, LibvirtXmlEditable { /** - * Separation character for internal {@link XPath} expressions. + * Separation character for internal XPath expressions. */ private static final String XPATH_EXPRESSION_SEPARATOR = "/"; /** - * Current XML node selection character for internal {@link XPath} expressions. + * Current XML node selection character for internal XPath expressions. */ private static final String XPATH_EXPRESSION_CURRENT_NODE = "."; /** - * Factory to create {@link XPath} objects. + * Factory to create XPath objects. */ private XPathFactory xPathFactory = null; @@ -40,13 +40,12 @@ public class LibvirtXmlNode implements LibvirtXmlCreatable, LibvirtXmlEditable private Document xmlDocument = null; /** - * Current XML base node as XML root anchor for relative internal {@link XPath} expressions. + * Current XML base node as XML root anchor for relative internal XPath expressions. */ private Node xmlBaseNode = null; /** - * Create and initialize {@link XPath} context to define and compile custom {@link XPath} - * expressions. + * Create and initialize XPath context to define and compile custom XPath expressions. */ private void createXPathContext() { @@ -139,8 +138,7 @@ public class LibvirtXmlNode implements LibvirtXmlCreatable, LibvirtXmlEditable /** * Returns current XML base node. * - * @return current XML base node as XML root anchor of relative internal {@link XPath} - * expressions. + * @return current XML base node as XML root anchor of relative internal XPath expressions. */ public Node getXmlBaseNode() { @@ -150,8 +148,8 @@ public class LibvirtXmlNode implements LibvirtXmlCreatable, LibvirtXmlEditable /** * Sets existing XML base node for Libvirt XML node. * - * @param xmlBaseNode existing XML base node as XML root anchor for relative internal - * {@link XPath} expressions. + * @param xmlBaseNode existing XML base node as XML root anchor for relative internal XPath + * expressions. */ public void setXmlBaseNode( Node xmlBaseNode ) { @@ -317,7 +315,7 @@ public class LibvirtXmlNode implements LibvirtXmlCreatable, LibvirtXmlEditable attribute.setNodeValue( value ); } } - + @Override public void removeXmlElementAttribute( String expression, String attributeName ) { diff --git a/src/main/java/org/openslx/libvirt/xml/LibvirtXmlResources.java b/src/main/java/org/openslx/libvirt/xml/LibvirtXmlResources.java index 38c818b..a6b3e39 100644 --- a/src/main/java/org/openslx/libvirt/xml/LibvirtXmlResources.java +++ b/src/main/java/org/openslx/libvirt/xml/LibvirtXmlResources.java @@ -17,6 +17,11 @@ public final class LibvirtXmlResources private static final String LIBVIRT_PREFIX_PATH = File.separator + "libvirt"; /** + * File path prefix of the absolute path to the libosinfo resource folder in a *.jar file. + */ + private static final String LIBOSINFO_PREFIX_PATH = File.separator + "libvirt" + File.separator + "libosinfo"; + + /** * File path prefix of the absolute path to the libvirt XSL resource folder in a *.jar file. */ private static final String LIBVIRT_PREFIX_PATH_XSL = LIBVIRT_PREFIX_PATH + File.separator + "xsl"; @@ -27,6 +32,29 @@ public final class LibvirtXmlResources private static final String LIBVIRT_PREFIX_PATH_RNG = LIBVIRT_PREFIX_PATH + File.separator + "rng"; /** + * File path prefix of the absolute path to the libosinfo RNG resource folder in a *.jar file. + */ + private static final String LIBOSINFO_PREFIX_PATH_RNG = LIBOSINFO_PREFIX_PATH + File.separator + "rng"; + + /** + * File path prefix of the absolute path to the libosinfo XML resource folder in a *.jar file. + */ + private static final String LIBOSINFO_PREFIX_PATH_XML = LIBOSINFO_PREFIX_PATH + File.separator + "xml"; + + /** + * Returns a Libvirt resource as stream. + * + * @param prefix file path of the Libvirt resource in the resources *.jar folder. + * @param fileName file name of the Libvirt resource in the resources *.jar folder. + * @return Libvirt resource as stream. + */ + private static InputStream getLibvirtResource( String prefix, String fileName ) + { + final String path = prefix + File.separator + fileName; + return LibvirtXmlResources.class.getResourceAsStream( path ); + } + + /** * Returns a Libvirt XSL resource as stream. * * @param libvirtXslFileName file name of the XSL resource in the resources *.jar folder. @@ -34,8 +62,7 @@ public final class LibvirtXmlResources */ public static InputStream getLibvirtXsl( String libvirtXslFileName ) { - String libvirtXslPath = LibvirtXmlResources.LIBVIRT_PREFIX_PATH_XSL + File.separator + libvirtXslFileName; - return LibvirtXmlResources.class.getResourceAsStream( libvirtXslPath ); + return LibvirtXmlResources.getLibvirtResource( LibvirtXmlResources.LIBVIRT_PREFIX_PATH_XSL, libvirtXslFileName ); } /** @@ -46,7 +73,31 @@ public final class LibvirtXmlResources */ public static InputStream getLibvirtRng( String libvirtRngFileName ) { - String libvirtRngPath = LibvirtXmlResources.LIBVIRT_PREFIX_PATH_RNG + File.separator + libvirtRngFileName; - return LibvirtXmlResources.class.getResourceAsStream( libvirtRngPath ); + return LibvirtXmlResources.getLibvirtResource( LibvirtXmlResources.LIBVIRT_PREFIX_PATH_RNG, libvirtRngFileName ); + } + + /** + * Returns a libosinfo RNG schema resource as stream. + * + * @param libosInfoRngFileName file name of the RNG schema resource in the resources *.jar + * folder. + * @return libosinfo RNG schema resource as stream. + */ + public static InputStream getLibOsInfoRng( String libosInfoRngFileName ) + { + return LibvirtXmlResources.getLibvirtResource( LibvirtXmlResources.LIBOSINFO_PREFIX_PATH_RNG, + libosInfoRngFileName ); + } + + /** + * Returns a libosinfo XML resource as stream. + * + * @param libosInfoXmlFileName file name of the XML resource in the resources *.jar folder. + * @return libosinfo XML resource as stream. + */ + public static InputStream getLibOsInfoXml( String libosInfoXmlFileName ) + { + return LibvirtXmlResources.getLibvirtResource( LibvirtXmlResources.LIBOSINFO_PREFIX_PATH_XML, + libosInfoXmlFileName ); } } diff --git a/src/main/java/org/openslx/libvirt/xml/LibvirtXmlSchemaValidator.java b/src/main/java/org/openslx/libvirt/xml/LibvirtXmlSchemaValidator.java index e074948..bc8f90f 100644 --- a/src/main/java/org/openslx/libvirt/xml/LibvirtXmlSchemaValidator.java +++ b/src/main/java/org/openslx/libvirt/xml/LibvirtXmlSchemaValidator.java @@ -196,8 +196,9 @@ public class LibvirtXmlSchemaValidator /** * Creates a validator for validation of Libvirt XML documents with RelaxNG schemas. * - * @param rngSchema - * @throws SAXException + * @param rngSchema RelaxNG schema used for validation with {@link #validate(Document)}. + * + * @throws SAXException creation of a Libvirt XML validator failed. */ public LibvirtXmlSchemaValidator( InputStream rngSchema ) throws SAXException { diff --git a/src/main/java/org/openslx/libvirt/xml/LibvirtXmlSerializable.java b/src/main/java/org/openslx/libvirt/xml/LibvirtXmlSerializable.java index 6f11ce5..4cd0a32 100644 --- a/src/main/java/org/openslx/libvirt/xml/LibvirtXmlSerializable.java +++ b/src/main/java/org/openslx/libvirt/xml/LibvirtXmlSerializable.java @@ -17,6 +17,8 @@ public abstract interface LibvirtXmlSerializable * Serialize Libvirt XML document from {@link String}. * * @param xml {@link String} containing XML content. + * + * @throws LibvirtXmlSerializationException serialization of Libvirt XML document failed. */ public void fromXml( String xml ) throws LibvirtXmlSerializationException; @@ -24,6 +26,8 @@ public abstract interface LibvirtXmlSerializable * Serialize Libvirt XML document from {@link File}. * * @param xml {@link File} containing XML content. + * + * @throws LibvirtXmlSerializationException serialization of Libvirt XML document failed. */ public void fromXml( File xml ) throws LibvirtXmlSerializationException; @@ -31,6 +35,8 @@ public abstract interface LibvirtXmlSerializable * Serialize Libvirt XML document from {@link InputStream}. * * @param xml {@link InputStream} providing XML content. + * + * @throws LibvirtXmlSerializationException serialization of Libvirt XML document failed. */ void fromXml( InputStream xml ) throws LibvirtXmlSerializationException; @@ -38,6 +44,8 @@ public abstract interface LibvirtXmlSerializable * Serialize Libvirt XML document from {@link InputSource}. * * @param xml {@link InputSource} providing XML content. + * + * @throws LibvirtXmlSerializationException serialization of Libvirt XML document failed. */ public void fromXml( InputSource xml ) throws LibvirtXmlSerializationException; @@ -45,6 +53,8 @@ public abstract interface LibvirtXmlSerializable * Serialize Libvirt XML document to {@link String}. * * @return XML {@link String} containing Libvirt XML document content. + * + * @throws LibvirtXmlSerializationException serialization of Libvirt XML document failed. */ public String toXml() throws LibvirtXmlSerializationException; @@ -52,6 +62,8 @@ public abstract interface LibvirtXmlSerializable * Serialize Libvirt XML document to {@link File}. * * @param xml XML {@link File} containing Libvirt XML document content. + * + * @throws LibvirtXmlSerializationException serialization of Libvirt XML document failed. */ public void toXml( File xml ) throws LibvirtXmlSerializationException; } diff --git a/src/main/java/org/openslx/util/LevenshteinDistance.java b/src/main/java/org/openslx/util/LevenshteinDistance.java new file mode 100644 index 0000000..0f33167 --- /dev/null +++ b/src/main/java/org/openslx/util/LevenshteinDistance.java @@ -0,0 +1,85 @@ +package org.openslx.util; + +public final class LevenshteinDistance +{ + private final int insertionCost; + private final int deletionCost; + private final int substitutionCost; + + public LevenshteinDistance() + { + this( 1, 1, 1 ); + } + + public LevenshteinDistance( int insertionCost, int deletionCost, int substitutionCost ) + { + this.validateCostArgument( insertionCost >= 0, "Insertion cost must be greater than or equal to 0" ); + this.validateCostArgument( deletionCost >= 0, "Deletion cost must be greater than or equal to 0" ); + this.validateCostArgument( substitutionCost >= 0, "Substitution cost must be greater than or equal to 0" ); + + this.insertionCost = insertionCost; + this.deletionCost = deletionCost; + this.substitutionCost = substitutionCost; + } + + private void validateCostArgument( boolean condition, String errorMsg ) + { + if ( !condition ) { + throw new IllegalArgumentException( errorMsg ); + } + } + + public int calculateDistance( CharSequence source, CharSequence target ) + { + if ( source == null || target == null ) { + throw new IllegalArgumentException( "Source or target cannot be null" ); + } + + int sourceLength = source.length(); + int targetLength = target.length(); + + int[][] matrix = new int[ sourceLength + 1 ][ targetLength + 1 ]; + matrix[0][0] = 0; + + for ( int row = 1; row <= sourceLength; ++row ) { + matrix[row][0] = row; + } + + for ( int col = 1; col <= targetLength; ++col ) { + matrix[0][col] = col; + } + + for ( int row = 1; row <= sourceLength; ++row ) { + for ( int col = 1; col <= targetLength; ++col ) { + matrix[row][col] = calcMinCost( source, target, matrix, row, col ); + } + } + + return matrix[sourceLength][targetLength]; + } + + private int calcMinCost( CharSequence source, CharSequence target, int[][] matrix, int row, int col ) + { + return Math.min( calcSubstitutionCost( source, target, matrix, row, col ), + Math.min( calcDeletionCost( matrix, row, col ), calcInsertionCost( matrix, row, col ) ) ); + } + + private int calcInsertionCost( int[][] matrix, int row, int col ) + { + return matrix[row][col - 1] + insertionCost; + } + + private int calcDeletionCost( int[][] matrix, int row, int col ) + { + return matrix[row - 1][col] + deletionCost; + } + + private int calcSubstitutionCost( CharSequence source, CharSequence target, int[][] matrix, int row, int col ) + { + int cost = 0; + if ( source.charAt( row - 1 ) != target.charAt( col - 1 ) ) { + cost = substitutionCost; + } + return matrix[row - 1][col - 1] + cost; + } +} diff --git a/src/main/java/org/openslx/util/ThriftUtil.java b/src/main/java/org/openslx/util/ThriftUtil.java index 3c2c9ea..a9035c1 100644 --- a/src/main/java/org/openslx/util/ThriftUtil.java +++ b/src/main/java/org/openslx/util/ThriftUtil.java @@ -7,7 +7,7 @@ import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; -import org.openslx.vm.VmwareConfig; +import org.openslx.virtualization.configuration.VirtualizationConfigurationVmwareFileFormat; public class ThriftUtil { @@ -41,7 +41,7 @@ public class ThriftUtil { BufferedReader reader; StringBuffer content = new StringBuffer(""); try { - reader = VmwareConfig.getVmxReader(bytes, bytes.length); + reader = VirtualizationConfigurationVmwareFileFormat.getVmxReader(bytes, bytes.length); String line=""; while ((line=reader.readLine()) != null) { content.append(line + "\n"); diff --git a/src/main/java/org/openslx/util/XmlHelper.java b/src/main/java/org/openslx/util/XmlHelper.java index 70c5be8..4e814a0 100644 --- a/src/main/java/org/openslx/util/XmlHelper.java +++ b/src/main/java/org/openslx/util/XmlHelper.java @@ -3,6 +3,8 @@ package org.openslx.util; import java.io.IOException; import java.io.InputStream; import java.io.StringWriter; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -14,6 +16,7 @@ import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; @@ -28,10 +31,11 @@ public class XmlHelper private final static Logger LOGGER = Logger.getLogger( XmlHelper.class ); // TODO check thread-safety - public static final XPath XPath = XPathFactory.newInstance().newXPath(); + private static final XPath XPath = XPathFactory.newInstance().newXPath(); private static DocumentBuilder dBuilder; static { DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); + dbFactory.setNamespaceAware( true ); dbFactory.setIgnoringComments( true ); try { dBuilder = dbFactory.newDocumentBuilder(); @@ -40,6 +44,48 @@ public class XmlHelper } } + public static String globalXPathToLocalXPath( String xPath ) + { + final StringBuilder exprBuilder = new StringBuilder(); + final String[] elements = xPath.split( "/" ); + + for ( final String element : elements ) { + if ( !element.isEmpty() ) { + final Pattern arraySpecifierRegex = Pattern.compile( "^(.*)\\[(.*)\\]$" ); + final Matcher arraySpecifierMatcher = arraySpecifierRegex.matcher( element ); + final String elementName; + final String elementSpecifier; + + if ( arraySpecifierMatcher.find() ) { + elementName = arraySpecifierMatcher.group( 1 ); + elementSpecifier = arraySpecifierMatcher.group( 2 ); + } else { + elementName = element; + elementSpecifier = null; + } + + if ( !elementName.startsWith( "@" ) && !elementName.equals( "*" ) ) { + exprBuilder.append( "/*[local-name()='" + elementName + "']" ); + + } else { + exprBuilder.append( "/" + elementName ); + } + + if ( elementSpecifier != null && !elementSpecifier.isEmpty() ) { + exprBuilder.append( "[" + elementSpecifier + "]" ); + } + } + } + + return exprBuilder.toString(); + } + + public static XPathExpression compileXPath( String xPath ) throws XPathExpressionException + { + final String localXPath = XmlHelper.globalXPathToLocalXPath( xPath ); + return XPath.compile( localXPath ); + } + public static Document parseDocumentFromStream( InputStream is ) { Document doc = null; diff --git a/src/main/java/org/openslx/virtualization/Version.java b/src/main/java/org/openslx/virtualization/Version.java new file mode 100644 index 0000000..51dc98b --- /dev/null +++ b/src/main/java/org/openslx/virtualization/Version.java @@ -0,0 +1,320 @@ +package org.openslx.virtualization; + +import java.util.List; +import java.util.function.Predicate; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Represents a version information. + * + * The version information is used in the field of virtualization (for virtualizers, disk images, + * virtualization configuration files, ...). + * + * @author Manuel Bentele + * @version 1.0 + */ +public class Version implements Comparable<Version> +{ + /** + * Regular expression to parse a version from a {@link String}. + * <p> + * The regular expression matches a version if its textual version information is well-formed + * according to the following examples: + * + * <pre> + * 52 + * 4.31 + * 5.10.13 + * </pre> + */ + private static final String VERSION_NUMBER_REGEX = "^(\\d+)(?:\\.(\\d+)(?:\\.(\\d+))?)?$"; + + /** + * Major number of the version. + */ + private final short major; + + /** + * Minor number of the version. + */ + private final short minor; + + /** + * Name or description of the version. + */ + private final String name; + + /** + * Creates a new version. + * + * The version consists of a major version, whereas the minor version is set to the value + * <code>0</code> and the version name is undefined. + * + * @param major major version. + */ + public Version( short major ) + { + this( major, Short.valueOf( "0" ), null ); + } + + /** + * Creates a new version. + * + * The version consists of a major version labeled with a version name, whereas the minor version + * is set to the value <code>0</code>. + * + * @param major major version. + * @param name version name. + */ + public Version( short major, String name ) + { + this( major, Short.valueOf( "0" ), name ); + } + + /** + * Creates a new version. + * + * The version consists of a major and a minor version, whereas the version name is undefined. + * + * @param major major version. + * @param minor minor version. + */ + public Version( short major, short minor ) + { + this( major, minor, null ); + } + + /** + * Creates a new version. + * + * The version consists of a major and a minor version labeled with a version name. + * + * @param major major version. + * @param minor minor version. + * @param name version name. + */ + public Version( short major, short minor, String name ) + { + this.major = major; + this.minor = minor; + this.name = name; + } + + /** + * Returns the major version. + * + * @return major version. + */ + public short getMajor() + { + return this.major; + } + + /** + * Returns the minor version. + * + * @return minor version. + */ + public short getMinor() + { + return this.minor; + } + + /** + * Returns the full version as {@link Integer}. + * + * The full version consists of the major and minor version where both are combined in one + * {@link Integer} value. The upper 16-bits of the value represent the major number, whereas + * the lower 16-bits represent the minor number. + * + * @return full version as {@link Integer}. + */ + public int getVersion() + { + final int major = this.major; + final int minor = this.minor; + + return ( major << Short.SIZE ) | minor; + } + + /** + * Returns the name of the version. + * + * @return name of the version. + */ + public String getName() + { + return this.name; + } + + /** + * Checks if version is supported by a version from a list of supported versions. + * + * @param supportedVersions list of supported versions. + * @return state whether version is supported by a version from the list of versions or not. + */ + public boolean isSupported( List<Version> supportedVersions ) + { + return supportedVersions.contains( this ); + } + + /** + * Returns a version from a list of supported versions filtered by its given filter predicate. + * + * @param byFilter filter predicate. + * @param supportedVersions list of supported versions. + * @return version from a list of supported versions filtered by its given filter predicate. + */ + private static Version getInstanceByPredicateFromVersions( Predicate<Version> byFilter, + List<Version> supportedVersions ) + { + return supportedVersions.stream().filter( byFilter ).findFirst().orElse( null ); + } + + /** + * Returns a version from a list of supported versions by its given major version. + * + * @param major version. + * @param supportedVersions list of supported versions. + * @return version from a list of supported versions by its given major version. + */ + public static Version getInstanceByMajorFromVersions( short major, List<Version> supportedVersions ) + { + final Predicate<Version> byMajor = version -> major == version.getMajor(); + return Version.getInstanceByPredicateFromVersions( byMajor, supportedVersions ); + } + + /** + * Returns a version from a list of supported versions by its given major and minor version. + * + * @param major version. + * @param minor version. + * @param supportedVersions list of supported versions. + * @return version from a list of supported versions by its given major and minor version. + */ + public static Version getInstanceByMajorMinorFromVersions( short major, short minor, + List<Version> supportedVersions ) + { + final Predicate<Version> byMajorMinor = version -> major == version.getMajor() && minor == version.getMinor(); + return supportedVersions.stream().filter( byMajorMinor ).findFirst().orElse( null ); + } + + /** + * Checks if this version is smaller than a specified {@code version}. + * + * @param version for comparison. + * @return state whether this version is smaller than the specified {@code version} or not. + */ + public boolean isSmallerThan( Version version ) + { + return ( this.compareTo( version ) < 0 ) ? true : false; + } + + /** + * Checks if this version is greater than a specified {@code version}. + * + * @param version for comparison. + * @return state whether this version is greater than the specified {@code version} or not. + */ + public boolean isGreaterThan( Version version ) + { + return ( this.compareTo( version ) > 0 ) ? true : false; + } + + /** + * Creates a new version parsed from a {@link String}. + * + * The version consists of a major and a minor version parsed from the specified {@link String}. + * + * @param version textual information containing a version as {@link String}. The textual + * version should be well-formed according to the defined regular expression + * {@link #VERSION_NUMBER_REGEX}. + * @return version instance. + */ + public static Version valueOf( String version ) + { + final Version parsedVersion; + + if ( version == null || version.isEmpty() ) { + parsedVersion = null; + } else { + final Pattern versionPattern = Pattern.compile( Version.VERSION_NUMBER_REGEX ); + final Matcher versionMatcher = versionPattern.matcher( version ); + + if ( versionMatcher.find() ) { + final String majorStr = versionMatcher.group( 1 ); + final String minorStr = versionMatcher.group( 2 ); + + final short major = ( majorStr != null ) ? Short.valueOf( majorStr ) : 0; + final short minor = ( minorStr != null ) ? Short.valueOf( minorStr ) : 0; + + parsedVersion = new Version( major, minor ); + + } else { + parsedVersion = null; + } + } + + return parsedVersion; + } + + @Override + public String toString() + { + if ( this.getName() == null || this.getName().isEmpty() ) { + return String.format( "%d.%d", this.getMajor(), this.getMinor() ); + } else { + return String.format( "%d.%d %s", this.getMajor(), this.getMinor(), this.getName() ); + } + } + + @Override + public boolean equals( Object obj ) + { + if ( obj == null ) { + return false; + } else if ( this.getClass() != obj.getClass() ) { + return false; + } else if ( this.compareTo( Version.class.cast( obj ) ) == 0 ) { + return true; + } else { + return false; + } + } + + @Override + public int compareTo( Version v ) + { + // compare the current version to the specified version + if ( this.getMajor() < v.getMajor() ) { + // current major version is smaller than the given major version + return -1; + } else if ( this.getMajor() > v.getMajor() ) { + // current major version is larger than the given major version + return 1; + } else { + // current major version is equal to the given major version + // so compare the current minor version to the specified minor version + if ( this.getMinor() < v.getMinor() ) { + // current minor version is smaller than the given minor version + // so the entire version is smaller than the given version + return -1; + } else if ( this.getMinor() > v.getMinor() ) { + // current minor version is larger than the given minor version + // so the entire version is larger than the given version + return 1; + } else { + // current minor version is equal to the given minor version + // so the entire version is equal to the given version + return 0; + } + } + } + + @Override + public int hashCode() + { + return ( Short.valueOf( this.getMajor() ).hashCode() ) ^ ( Short.valueOf( this.getMinor() ).hashCode() ); + } +} diff --git a/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfiguration.java b/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfiguration.java new file mode 100644 index 0000000..cd8af1e --- /dev/null +++ b/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfiguration.java @@ -0,0 +1,421 @@ +package org.openslx.virtualization.configuration; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; +import org.openslx.bwlp.thrift.iface.OperatingSystem; +import org.openslx.virtualization.Version; +import org.openslx.virtualization.virtualizer.Virtualizer; + +/** + * Describes a configured virtual machine. This class is parsed from a machine + * description, like a *.vmx for VMware machines. + */ +public abstract class VirtualizationConfiguration<T, U, W, X> +{ + private static final Logger LOGGER = Logger.getLogger( VirtualizationConfiguration.class ); + + /* + * Helper types + */ + protected Map<SoundCardType, T> soundCards = new HashMap<>(); + protected Map<DDAcceleration, U> ddacc = new HashMap<>(); + protected Map<EthernetDevType, W> networkCards = new HashMap<>(); + protected Map<UsbSpeed, X> usbSpeeds = new HashMap<>(); + + private final Virtualizer virtualizer; + + /** + * Virtual sound cards types + */ + public static enum SoundCardType + { + NONE( "None" ), DEFAULT( "(default)" ), SOUND_BLASTER( "Sound Blaster 16" ), ES( "ES 1371" ), HD_AUDIO( + "Intel Integrated HD Audio" ), AC( "Intel ICH Audio Codec 97" ); + + public final String displayName; + + private SoundCardType( String dName ) + { + this.displayName = dName; + } + } + + /** + * 3D acceleration types + */ + public static enum DDAcceleration + { + OFF( "Off" ), ON( "On" ); + + public final String displayName; + + private DDAcceleration( String dName ) + { + this.displayName = dName; + } + } + + /** + * Virtual network cards + */ + public static enum EthernetDevType + { + AUTO( "(default)" ), PCNET32( "AMD PCnet32" ), E1000( "Intel E1000 (PCI)" ), E1000E( + "Intel E1000e (PCI-Express)" ), VMXNET( "VMXnet" ), VMXNET3( "VMXnet 3" ), PCNETPCI2( + "PCnet-PCI II" ), PCNETFAST3( "PCnet-FAST III" ), PRO1000MTD( + "Intel PRO/1000 MT Desktop" ), PRO1000TS( + "Intel PRO/1000 T Server" ), PRO1000MTS( "Intel PRO/1000 MT Server" ), PARAVIRT( + "Paravirtualized Network" ), NONE( "No Network Card" ); + + public final String displayName; + + private EthernetDevType( String dName ) + { + this.displayName = dName; + } + } + + public static enum UsbSpeed + { + NONE( "None" ), USB1_1( "USB 1.1" ), USB2_0( "USB 2.0" ), USB3_0( "USB 3.0" ); + + public final String displayName; + + private UsbSpeed( String dName ) + { + this.displayName = dName; + } + } + + public static enum DriveBusType + { + SCSI, IDE, SATA, NVME; + } + + public static class HardDisk + { + public final String chipsetDriver; + public final DriveBusType bus; + public final String diskImage; + + public HardDisk( String chipsetDriver, DriveBusType bus, String diskImage ) + { + this.chipsetDriver = chipsetDriver; + this.bus = bus; + this.diskImage = diskImage; + } + } + + public static enum EtherType + { + NAT, BRIDGED, HOST_ONLY; + } + /* + * Members + */ + + protected final List<HardDisk> hdds = new ArrayList<HardDisk>(); + + protected final List<OperatingSystem> osList; + + private OperatingSystem os = null; + + protected String displayName = null; + + protected boolean isMachineSnapshot; + + /* + * Getters for virtual hardware + */ + public List<SoundCardType> getSupportedSoundCards() + { + ArrayList<SoundCardType> availables = new ArrayList<SoundCardType>( soundCards.keySet() ); + Collections.sort( availables ); + return availables; + } + + public List<DDAcceleration> getSupportedDDAccs() + { + ArrayList<DDAcceleration> availables = new ArrayList<DDAcceleration>( ddacc.keySet() ); + Collections.sort( availables ); + return availables; + } + + public List<Version> getSupportedHWVersions() + { + final List<Version> availables = this.getVirtualizer().getSupportedVersions(); + Collections.sort( availables ); + return Collections.unmodifiableList( availables ); + } + + public List<EthernetDevType> getSupportedEthernetDevices() + { + ArrayList<EthernetDevType> availables = new ArrayList<EthernetDevType>( networkCards.keySet() ); + Collections.sort( availables ); + return availables; + } + + public List<UsbSpeed> getSupportedUsbSpeeds() + { + ArrayList<UsbSpeed> availables = new ArrayList<>( usbSpeeds.keySet() ); + Collections.sort( availables ); + return availables; + } + + /** + * Get operating system of this VM. + * + * @return operating system of the VM. + */ + public OperatingSystem getOs() + { + return os; + } + + /** + * Sets the operating system for the virtualization configuration. + * + * @param os operating system for the virtualization configuration. + */ + public void setOs( OperatingSystem os ) + { + this.os = os; + } + + /** + * Get all hard disks of this VM. + * + * @return list of hard disks of the VM. + */ + public List<HardDisk> getHdds() + { + return Collections.unmodifiableList( hdds ); + } + + /** + * Get display name of VM. + * + * @return display name of the VM. + */ + public String getDisplayName() + { + return displayName; + } + + /* + * Getter for isMachineSnapshot + */ + public boolean isMachineSnapshot() + { + return isMachineSnapshot; + } + + /* + * Methods + */ + + public VirtualizationConfiguration( Virtualizer virtualizer, List<OperatingSystem> osList ) + { + this.virtualizer = virtualizer; + + if ( osList == null ) { + // create empty operating system list if none is specified + this.osList = new ArrayList<OperatingSystem>(); + } else { + this.osList = osList; + } + + // register virtual hardware models for graphical editing of virtual devices (GPU, sound, USB, ...) + this.registerVirtualHW(); + } + + /** + * Returns a VmMetaData instance of the given machine description given as file + * + * @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 failed to read machine description from specified file. + */ + public static VirtualizationConfiguration<?, ?, ?, ?> getInstance( List<OperatingSystem> osList, File file ) + throws IOException + { + try { + return new VirtualizationConfigurationVmware( osList, file ); + } catch ( VirtualizationConfigurationException e ) { + LOGGER.debug( "Not a VMware file", e ); + } + try { + return new VirtualizationConfigurationVirtualBox( osList, file ); + } catch ( VirtualizationConfigurationException e ) { + LOGGER.debug( "Not a VirtualBox file", e ); + } + try { + return new VirtualizationConfigurationQemu( osList, file ); + } catch ( VirtualizationConfigurationException e ) { + LOGGER.debug( "Not a Libvirt file", e ); + } + try { + return new VirtualizationConfigurationDocker( osList, file ); + } catch ( VirtualizationConfigurationException e ) { + LOGGER.debug( "Not a tar.gz file, for docker container", e ); + } + + LOGGER.error( "Could not detect any known virtualizer format" ); + return null; + } + + /** + * Returns a VmMetaData instance of the given machine description given as a byte array + * + * @param osList List of supported operating systems + * @param vmContent VM's machine description as byte array (e.g. stored in DB) + * @param length length of the byte array given as vmContent + * @return VmMetaData object representing the relevant parts of the given machine description + * @throws IOException failed to read machine description from specified byte stream. + */ + public static VirtualizationConfiguration<?, ?, ?, ?> getInstance( List<OperatingSystem> osList, byte[] vmContent, + int length ) + throws IOException + { + try { + return new VirtualizationConfigurationVmware( osList, vmContent, length ); + } catch ( VirtualizationConfigurationException e ) { + LOGGER.debug( "Not a VMware file", e ); + } + try { + return new VirtualizationConfigurationVirtualBox( osList, vmContent, length ); + } catch ( VirtualizationConfigurationException e ) { + LOGGER.debug( "Not a VirtualBox file", e ); + } + try { + return new VirtualizationConfigurationQemu( osList, vmContent, length ); + } catch ( VirtualizationConfigurationException e ) { + LOGGER.debug( "Not a Libvirt file", e ); + } + try { + return new VirtualizationConfigurationDocker( osList, vmContent, length ); + } catch ( VirtualizationConfigurationException e ) { + LOGGER.debug( "Not a tar.gz file, for docker container", e ); + } + + LOGGER.error( "Could not detect any known virtualizer format" ); + return null; + } + + /** + * Returns the file name extension for the virtualization configuration file. + * + * @return file name extension for the virtualization configuration file. + */ + public abstract String getFileNameExtension(); + + public abstract boolean addEmptyHddTemplate(); + + public abstract boolean addHddTemplate( File diskImage, String hddMode, String redoDir ); + + public abstract boolean addHddTemplate( String diskImagePath, String hddMode, String redoDir ); + + public abstract boolean addDefaultNat(); + + public abstract void setOs( String vendorOsId ); + + public abstract boolean addDisplayName( String name ); + + public abstract boolean addRam( int mem ); + + public abstract void addFloppy( int index, String image, boolean readOnly ); + + public abstract boolean addCdrom( String image ); + + public abstract boolean addCpuCoreCount( int nrOfCores ); + + public abstract void setSoundCard( SoundCardType type ); + + public abstract SoundCardType getSoundCard(); + + public abstract void setDDAcceleration( DDAcceleration type ); + + public abstract DDAcceleration getDDAcceleration(); + + public abstract void setVirtualizerVersion( Version type ); + + public abstract Version getVirtualizerVersion(); + + public abstract void setEthernetDevType( int cardIndex, EthernetDevType type ); + + public abstract EthernetDevType getEthernetDevType( int cardIndex ); + + public abstract void setMaxUsbSpeed( UsbSpeed speed ); + + public abstract UsbSpeed getMaxUsbSpeed(); + + public abstract byte[] getConfigurationAsByteArray(); + + public String getConfigurationAsString() + { + return new String( this.getConfigurationAsByteArray(), StandardCharsets.UTF_8 ); + } + + @Override + public String toString() + { + return this.getConfigurationAsString(); + } + + public abstract boolean addEthernet( EtherType type ); + + public Virtualizer getVirtualizer() + { + return this.virtualizer; + } + + /** + * Validates the virtualization configuration and reports errors if its content is not a valid + * virtualization configuration. + * + * @throws VirtualizationConfigurationException validation of the virtualization configuration + * failed. + */ + public abstract void validate() throws VirtualizationConfigurationException; + + /** + * Transforms the virtualization configuration in terms of a privacy filter to filter out + * sensitive information like name of users in absolute paths. + * + * @throws VirtualizationConfigurationException transformation of the virtualization + * configuration failed. + */ + public abstract void transformPrivacy() throws VirtualizationConfigurationException; + + /** + * Transforms the virtualization configuration applying options that are desired when locally + * editing a virtualized system (e.g. disables automatic DPI scaling). + * + * @throws VirtualizationConfigurationException transformation of the virtualization + * configuration failed. + */ + public abstract void transformEditable() throws VirtualizationConfigurationException; + + /** + * Transforms the virtualization configuration applying options that are desired when running a + * virtualized system in a stateless manner. + * + * @throws VirtualizationConfigurationException transformation of the virtualization + * configuration failed. + */ + public abstract void transformNonPersistent() throws VirtualizationConfigurationException; + + /** + * Function used to register virtual devices. + */ + public abstract void registerVirtualHW(); +} diff --git a/src/main/java/org/openslx/vm/DockerMetaDataDummy.java b/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationDocker.java index 7381361..d5e9abb 100644 --- a/src/main/java/org/openslx/vm/DockerMetaDataDummy.java +++ b/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationDocker.java @@ -1,18 +1,14 @@ -package org.openslx.vm; +package org.openslx.virtualization.configuration; 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.vm.disk.DiskImage; -import org.openslx.vm.disk.DiskImage.ImageFormat; +import org.openslx.virtualization.Version; +import org.openslx.virtualization.virtualizer.VirtualizerDocker; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; -import java.util.Arrays; -import java.util.Collections; import java.util.List; class DockerSoundCardMeta @@ -23,10 +19,6 @@ class DockerDDAccelMeta { } -class DockerHWVersionMeta -{ -} - class DockerEthernetDevTypeMeta { } @@ -35,17 +27,14 @@ class DockerUsbSpeedMeta { } -public class DockerMetaDataDummy extends VmMetaData<DockerSoundCardMeta, DockerDDAccelMeta, DockerHWVersionMeta, DockerEthernetDevTypeMeta, DockerUsbSpeedMeta> { +public class VirtualizationConfigurationDocker extends VirtualizationConfiguration<DockerSoundCardMeta, DockerDDAccelMeta, DockerEthernetDevTypeMeta, DockerUsbSpeedMeta> { /** - * List of supported image formats by the Docker hypervisor. + * File name extension for Docker virtualization configuration files. */ - private static final List<DiskImage.ImageFormat> SUPPORTED_IMAGE_FORMATS = Collections.unmodifiableList( - Arrays.asList( ImageFormat.NONE ) ); - - private static final Logger LOGGER = Logger.getLogger( DockerMetaDataDummy.class); + private static final String FILE_NAME_EXTENSION = null; - private final Virtualizer virtualizer = new Virtualizer(TConst.VIRT_DOCKER, "Docker"); + private static final Logger LOGGER = Logger.getLogger( VirtualizationConfigurationDocker.class); /** * containerDefinition is a serialized tar.gz archive and represents a @@ -59,8 +48,8 @@ public class DockerMetaDataDummy extends VmMetaData<DockerSoundCardMeta, DockerD */ private byte[] containerDefinition; - public DockerMetaDataDummy(List<OperatingSystem> osList, File file) throws UnsupportedVirtualizerFormatException { - super(osList); + public VirtualizationConfigurationDocker(List<OperatingSystem> osList, File file) throws VirtualizationConfigurationException { + super(new VirtualizerDocker(), osList); BufferedInputStream bis = null; @@ -70,7 +59,7 @@ public class DockerMetaDataDummy extends VmMetaData<DockerSoundCardMeta, DockerD bis.read(containerDefinition); checkIsTarGz(); - } catch (IOException | UnsupportedVirtualizerFormatException e) { + } catch (IOException | VirtualizationConfigurationException e) { LOGGER.error("Couldn't read dockerfile", e); } finally { try { @@ -81,9 +70,9 @@ public class DockerMetaDataDummy extends VmMetaData<DockerSoundCardMeta, DockerD } } - public DockerMetaDataDummy(List<OperatingSystem> osList, byte[] vmContent, int length) - throws UnsupportedVirtualizerFormatException { - super(osList); + public VirtualizationConfigurationDocker(List<OperatingSystem> osList, byte[] vmContent, int length) + throws VirtualizationConfigurationException { + super(new VirtualizerDocker(), osList); containerDefinition = vmContent; @@ -97,28 +86,27 @@ public class DockerMetaDataDummy extends VmMetaData<DockerSoundCardMeta, DockerD * Checks if the first two bytes of the content identifies a tar.gz archive. * The first byte is 31 == 0x1f, the second byte has to be -117 == 0x8b. * - * @throws UnsupportedVirtualizerFormatException + * @throws VirtualizationConfigurationException */ - private void checkIsTarGz() throws UnsupportedVirtualizerFormatException { + private void checkIsTarGz() throws VirtualizationConfigurationException { if (!((31 == containerDefinition[0]) && (-117 == containerDefinition[1]))) { LOGGER.warn("Not Supported Content."); - throw new UnsupportedVirtualizerFormatException( + throw new VirtualizationConfigurationException( "DockerMetaDataDummy: Not tar.gz encoded content!"); } } - @Override public byte[] getFilteredDefinitionArray() { - return containerDefinition; + @Override public void transformEditable() throws VirtualizationConfigurationException { + } @Override - public List<DiskImage.ImageFormat> getSupportedImageFormats() - { - return DockerMetaDataDummy.SUPPORTED_IMAGE_FORMATS; + public void transformPrivacy() throws VirtualizationConfigurationException { } - @Override public void applySettingsForLocalEdit() { - + @Override + public boolean addEmptyHddTemplate() { + return false; } @Override public boolean addHddTemplate(File diskImage, String hddMode, String redoDir) { @@ -173,12 +161,12 @@ public class DockerMetaDataDummy extends VmMetaData<DockerSoundCardMeta, DockerD return DDAcceleration.OFF; } - @Override public void setHWVersion(HWVersion type) { + @Override public void setVirtualizerVersion(Version type) { } - @Override public HWVersion getHWVersion() { - return HWVersion.DEFAULT; + @Override public Version getVirtualizerVersion() { + return null; } @Override public void setEthernetDevType(int cardIndex, EthernetDevType type) { @@ -197,23 +185,29 @@ public class DockerMetaDataDummy extends VmMetaData<DockerSoundCardMeta, DockerD return UsbSpeed.NONE; } - @Override public byte[] getDefinitionArray() { - return new byte[0]; + @Override public byte[] getConfigurationAsByteArray() { + return this.containerDefinition; } @Override public boolean addEthernet(EtherType type) { return false; } - @Override public Virtualizer getVirtualizer() { - return virtualizer; - } - - @Override public boolean tweakForNonPersistent() { - return false; + @Override public void transformNonPersistent() throws VirtualizationConfigurationException { + } @Override public void registerVirtualHW() { } + + @Override + public String getFileNameExtension() { + return VirtualizationConfigurationDocker.FILE_NAME_EXTENSION; + } + + @Override + public void validate() throws VirtualizationConfigurationException + { + } } diff --git a/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationException.java b/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationException.java new file mode 100644 index 0000000..2d401b1 --- /dev/null +++ b/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationException.java @@ -0,0 +1,13 @@ +package org.openslx.virtualization.configuration; + +public class VirtualizationConfigurationException extends Exception +{ + /** + * Version for serialization. + */ + private static final long serialVersionUID = 5794121065945636839L; + + public VirtualizationConfigurationException(String message) { + super(message); + } +}
\ No newline at end of file diff --git a/src/main/java/org/openslx/vm/QemuMetaData.java b/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationQemu.java index c780429..b4bc0ba 100644 --- a/src/main/java/org/openslx/vm/QemuMetaData.java +++ b/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationQemu.java @@ -1,20 +1,20 @@ -package org.openslx.vm; +package org.openslx.virtualization.configuration; import java.io.File; import java.math.BigInteger; import java.nio.charset.StandardCharsets; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.Map.Entry; import org.openslx.bwlp.thrift.iface.OperatingSystem; -import org.openslx.bwlp.thrift.iface.Virtualizer; import org.openslx.libvirt.domain.Domain; +import org.openslx.libvirt.domain.DomainUtils; import org.openslx.libvirt.domain.device.ControllerUsb; import org.openslx.libvirt.domain.device.Disk.BusType; import org.openslx.libvirt.domain.device.Disk.StorageType; +import org.openslx.libvirt.libosinfo.LibOsInfo; +import org.openslx.libvirt.libosinfo.os.Os; import org.openslx.libvirt.domain.device.DiskCdrom; import org.openslx.libvirt.domain.device.DiskFloppy; import org.openslx.libvirt.domain.device.DiskStorage; @@ -26,9 +26,9 @@ import org.openslx.libvirt.domain.device.Video; import org.openslx.libvirt.xml.LibvirtXmlDocumentException; import org.openslx.libvirt.xml.LibvirtXmlSerializationException; import org.openslx.libvirt.xml.LibvirtXmlValidationException; -import org.openslx.thrifthelper.TConst; -import org.openslx.vm.disk.DiskImage; -import org.openslx.vm.disk.DiskImage.ImageFormat; +import org.openslx.util.LevenshteinDistance; +import org.openslx.virtualization.Version; +import org.openslx.virtualization.virtualizer.VirtualizerQemu; /** * Metadata to describe the hardware type of a QEMU sound card. @@ -99,40 +99,6 @@ class QemuDDAccelMeta } /** - * Metadata to describe the version of a QEMU virtual machine configuration. - * - * @author Manuel Bentele - * @version 1.0 - */ -class QemuHWVersionMeta -{ - /** - * Stores the version of a QEMU virtual machine configuration. - */ - private final int version; - - /** - * Creates metadata to describe the version of a QEMU virtual machine configuration. - * - * @param version version of the QEMU virtual machine configuration. - */ - public QemuHWVersionMeta( int version ) - { - this.version = version; - } - - /** - * Returns version of the QEMU virtual machine configuration. - * - * @return version of the QEMU virtual machine configuration. - */ - public int getVersion() - { - return this.version; - } -} - -/** * Metadata to describe the hardware type of a QEMU ethernet device. * * @author Manuel Bentele @@ -223,23 +189,23 @@ class QemuUsbSpeedMeta * @author Manuel Bentele * @version 1.0 */ -public class QemuMetaData extends - VmMetaData<QemuSoundCardMeta, QemuDDAccelMeta, QemuHWVersionMeta, QemuEthernetDevTypeMeta, QemuUsbSpeedMeta> +public class VirtualizationConfigurationQemu extends + VirtualizationConfiguration<QemuSoundCardMeta, QemuDDAccelMeta, QemuEthernetDevTypeMeta, QemuUsbSpeedMeta> { /** - * Default bridge name of the network bridge connected to the LAN. + * Name of the network bridge for the LAN. */ - public static final String NETWORK_DEFAULT_BRIDGE = "brBwLehrpool"; + public static final String NETWORK_BRIDGE_LAN_DEFAULT = "br0"; /** - * Default network name of the isolated host network (host only). + * Name of the network bridge for the default NAT network. */ - public static final String NETWORK_DEFAULT_HOST_ONLY = "host"; + public static final String NETWORK_BRIDGE_NAT_DEFAULT = "nat1"; /** - * Default network name of the NAT network. + * Name of the network for the isolated host network (host only). */ - public static final String NETWORK_DEFAULT_NAT = "nat"; + public static final String NETWORK_BRIDGE_HOST_ONLY_DEFAULT = "vsw2"; /** * Default physical CDROM drive of the hypervisor host. @@ -247,15 +213,9 @@ public class QemuMetaData extends public static final String CDROM_DEFAULT_PHYSICAL_DRIVE = "/dev/sr0"; /** - * List of supported image formats by the QEMU hypervisor. + * File name extension for QEMU (Libvirt) virtualization configuration files. */ - private static final List<DiskImage.ImageFormat> SUPPORTED_IMAGE_FORMATS = Collections.unmodifiableList( - Arrays.asList( ImageFormat.QCOW2, ImageFormat.VMDK, ImageFormat.VDI ) ); - - /** - * Representation of a QEMU hypervisor (managed by Libvirt). - */ - private static final Virtualizer VIRTUALIZER = new Virtualizer( TConst.VIRT_QEMU, "QEMU" ); + public static final String FILE_NAME_EXTENSION = "xml"; /** * Libvirt XML configuration file to modify configuration of virtual machine for QEMU. @@ -263,45 +223,59 @@ public class QemuMetaData extends private Domain vmConfig = null; /** - * Stores current index of added HDD device to the Libvirt XML configuration file. + * Creates new virtual machine configuration (managed by Libvirt) for the QEMU hypervisor. + * + * @param osList list of operating systems. + * @param file image file for the QEMU hypervisor. + * + * @throws VirtualizationConfigurationException Libvirt XML configuration cannot be processed. */ - private int vmDeviceIndexHddAdd = 0; + public VirtualizationConfigurationQemu( List<OperatingSystem> osList, File file ) + throws VirtualizationConfigurationException + { + super( new VirtualizerQemu(), osList ); - /** - * Stores current index of added CDROM device to the Libvirt XML configuration file. - */ - private int vmDeviceIndexCdromAdd = 0; + try { + // read and parse Libvirt domain XML configuration document + this.vmConfig = new Domain( file ); + } catch ( LibvirtXmlDocumentException | LibvirtXmlSerializationException | LibvirtXmlValidationException e ) { + throw new VirtualizationConfigurationException( e.getLocalizedMessage() ); + } - /** - * Stores current index of added ethernet device to the Libvirt XML configuration file. - */ - private int vmDeviceIndexEthernetAdd = 0; + // parse VM config and initialize fields of QemuMetaData class + this.parseVmConfig(); + } /** * Creates new virtual machine configuration (managed by Libvirt) for the QEMU hypervisor. * * @param osList list of operating systems. - * @param file image file for the QEMU hypervisor. - * @throws UnsupportedVirtualizerFormatException Libvirt XML configuration cannot be processed. + * @param vmContent file content for the QEMU hypervisor. + * @param length number of bytes of the file content. + * + * @throws VirtualizationConfigurationException Libvirt XML configuration cannot be processed. */ - public QemuMetaData( List<OperatingSystem> osList, File file ) throws UnsupportedVirtualizerFormatException + public VirtualizationConfigurationQemu( List<OperatingSystem> osList, byte[] vmContent, int length ) + throws VirtualizationConfigurationException { - super( osList ); + super( new VirtualizerQemu(), osList ); try { // read and parse Libvirt domain XML configuration document - this.vmConfig = new Domain( file ); - } catch ( LibvirtXmlDocumentException e ) { - throw new UnsupportedVirtualizerFormatException( e.getLocalizedMessage() ); - } catch ( LibvirtXmlSerializationException e ) { - throw new UnsupportedVirtualizerFormatException( e.getLocalizedMessage() ); - } catch ( LibvirtXmlValidationException e ) { - throw new UnsupportedVirtualizerFormatException( e.getLocalizedMessage() ); + this.vmConfig = new Domain( new String( vmContent ) ); + } catch ( LibvirtXmlDocumentException | LibvirtXmlSerializationException | LibvirtXmlValidationException e ) { + throw new VirtualizationConfigurationException( e.getLocalizedMessage() ); } - // register virtual hardware models for graphical editing of virtual devices (GPU, sound, USB, ...) - this.registerVirtualHW(); + // parse VM config and initialize fields of QemuMetaData class + this.parseVmConfig(); + } + /** + * Parses Libvirt domain XML configuration to initialize QEMU metadata. + */ + private void parseVmConfig() + { // set display name of VM this.displayName = vmConfig.getName(); @@ -313,6 +287,9 @@ public class QemuMetaData extends for ( DiskStorage storageDiskDevice : this.vmConfig.getDiskStorageDevices() ) { this.addHddMetaData( storageDiskDevice ); } + + // detect the operating system from the optional embedded libosinfo metadata + this.setOs( this.vmConfig.getLibOsInfoOsId() ); } /** @@ -324,42 +301,71 @@ public class QemuMetaData extends private void addHddMetaData( DiskStorage storageDiskDevice ) { String hddChipsetModel = null; - DriveBusType hddChipsetBus = QemuMetaDataUtils.convertBusType( storageDiskDevice.getBusType() ); + DriveBusType hddChipsetBus = VirtualizationConfigurationQemuUtils + .convertBusType( storageDiskDevice.getBusType() ); String hddImagePath = storageDiskDevice.getStorageSource(); this.hdds.add( new HardDisk( hddChipsetModel, hddChipsetBus, hddImagePath ) ); } - @Override - public byte[] getFilteredDefinitionArray() + /** + * Detects the operating system by the specified libosinfo operating system identifier. + * + * @param osId libosinfo operating system identifier. + */ + private OperatingSystem detectOperatingSystem( String osId ) { - // remove UUID in Libvirt domain XML configuration - this.vmConfig.removeUuid(); + OperatingSystem os = null; - // removes all specified boot order entries - this.vmConfig.removeBootOrder(); + if ( osId != null && !osId.isEmpty() ) { + // lookup operating system identifier in the libosinfo database + final Os osLookup = LibOsInfo.lookupOs( osId ); - // removes all referenced storage files of all specified CDROMs, Floppy drives and HDDs - this.vmConfig.removeDiskDevicesStorage(); + // check if entry in the database was found + if ( osLookup != null ) { + // operating system entry was found + // so determine OpenSLX OS name with the smallest distance to the libosinfo OS name + final LevenshteinDistance distance = new LevenshteinDistance( 2, 1, 1 ); + int smallestDistance = Integer.MAX_VALUE; - // removes all source networks of all specified network interfaces - this.vmConfig.removeInterfaceDevicesSource(); + // get name of the OS and combine it with the optional available architecture + String osLookupOsName = osLookup.getName(); + final int osArchSize = VirtualizationConfigurationQemuUtils.getOsArchSize( this.vmConfig.getOsArch() ); - // output filtered Libvirt domain XML configuration - String configuration = this.vmConfig.toString(); - return configuration.getBytes( StandardCharsets.UTF_8 ); + if ( osArchSize > 0 ) { + // append architecture size in bit if information is available from the specified architecture + osLookupOsName += " (" + osArchSize + " Bit)"; + } + + for ( final OperatingSystem osCandidate : this.osList ) { + final int currentDistance = distance.calculateDistance( osLookupOsName, osCandidate.getOsName() ); + + if ( currentDistance < smallestDistance ) { + // if the distance is smaller save the current distance and operating system as best candidate + smallestDistance = currentDistance; + os = osCandidate; + } + } + } + } + + return os; } @Override - public List<DiskImage.ImageFormat> getSupportedImageFormats() + public void transformEditable() throws VirtualizationConfigurationException { - return QemuMetaData.SUPPORTED_IMAGE_FORMATS; + // removes all specified boot order entries + this.vmConfig.removeBootOrder(); + + // removes all source networks of all specified network interfaces + this.vmConfig.removeInterfaceDevicesSource(); } @Override - public void applySettingsForLocalEdit() + public boolean addEmptyHddTemplate() { - // NOT implemented yet + return this.addHddTemplate( new String(), null, null ); } @Override @@ -371,7 +377,9 @@ public class QemuMetaData extends @Override public boolean addHddTemplate( String diskImagePath, String hddMode, String redoDir ) { - return this.addHddTemplate( this.vmDeviceIndexHddAdd++, diskImagePath, hddMode, redoDir ); + int index = this.vmConfig.getDiskStorageDevices().size() - 1; + index = ( index > 0 ) ? index : 0; + return this.addHddTemplate( index, diskImagePath, hddMode, redoDir ); } /** @@ -387,25 +395,34 @@ public class QemuMetaData extends public boolean addHddTemplate( int index, String diskImagePath, String hddMode, String redoDir ) { ArrayList<DiskStorage> storageDiskDevices = this.vmConfig.getDiskStorageDevices(); - DiskStorage storageDiskDevice = QemuMetaDataUtils.getArrayIndex( storageDiskDevices, index ); + DiskStorage storageDiskDevice = VirtualizationConfigurationQemuUtils.getArrayIndex( storageDiskDevices, index ); if ( storageDiskDevice == null ) { // HDD does not exist, so create new storage (HDD) device storageDiskDevice = this.vmConfig.addDiskStorageDevice(); storageDiskDevice.setReadOnly( false ); storageDiskDevice.setBusType( BusType.VIRTIO ); - String targetDevName = QemuMetaDataUtils.createAlphabeticalDeviceName( "vd", index ); + String targetDevName = VirtualizationConfigurationQemuUtils.createAlphabeticalDeviceName( "vd", index ); storageDiskDevice.setTargetDevice( targetDevName ); - storageDiskDevice.setStorage( StorageType.FILE, diskImagePath ); + + if ( diskImagePath == null || diskImagePath.isEmpty() ) { + storageDiskDevice.removeStorage(); + } else { + storageDiskDevice.setStorage( StorageType.FILE, diskImagePath ); + } // add new created HDD to the metadata of the QemuMetaData object, too this.addHddMetaData( storageDiskDevice ); } else { // HDD exists, so update existing storage (HDD) device - storageDiskDevice.setStorage( StorageType.FILE, diskImagePath ); + if ( diskImagePath == null || diskImagePath.isEmpty() ) { + storageDiskDevice.removeStorage(); + } else { + storageDiskDevice.setStorage( StorageType.FILE, diskImagePath ); + } } - return false; + return true; } @Override @@ -417,7 +434,8 @@ public class QemuMetaData extends @Override public void setOs( String vendorOsId ) { - this.setOs( vendorOsId ); + final OperatingSystem os = this.detectOperatingSystem( vendorOsId ); + this.setOs( os ); } @Override @@ -433,13 +451,14 @@ public class QemuMetaData extends @Override public boolean addRam( int mem ) { - BigInteger memory = BigInteger.valueOf( mem ); + // convert given memory in MiB to memory in bytes for Libvirt XML Domain API functions + final BigInteger memory = DomainUtils.decodeMemory( Integer.toString( mem ), "MiB" ); this.vmConfig.setMemory( memory ); this.vmConfig.setCurrentMemory( memory ); - final boolean isMemorySet = this.vmConfig.getMemory().toString().equals( memory.toString() ); - final boolean isCurrentMemorySet = this.vmConfig.getCurrentMemory().toString().equals( memory.toString() ); + final boolean isMemorySet = this.vmConfig.getMemory().equals( memory ); + final boolean isCurrentMemorySet = this.vmConfig.getCurrentMemory().equals( memory ); return isMemorySet && isCurrentMemorySet; } @@ -448,27 +467,39 @@ public class QemuMetaData extends public void addFloppy( int index, String image, boolean readOnly ) { ArrayList<DiskFloppy> floppyDiskDevices = this.vmConfig.getDiskFloppyDevices(); - DiskFloppy floppyDiskDevice = QemuMetaDataUtils.getArrayIndex( floppyDiskDevices, index ); + DiskFloppy floppyDiskDevice = VirtualizationConfigurationQemuUtils.getArrayIndex( floppyDiskDevices, index ); if ( floppyDiskDevice == null ) { // floppy device does not exist, so create new floppy device floppyDiskDevice = this.vmConfig.addDiskFloppyDevice(); floppyDiskDevice.setBusType( BusType.FDC ); - String targetDevName = QemuMetaDataUtils.createAlphabeticalDeviceName( "fd", index ); + String targetDevName = VirtualizationConfigurationQemuUtils.createAlphabeticalDeviceName( "fd", index ); floppyDiskDevice.setTargetDevice( targetDevName ); floppyDiskDevice.setReadOnly( readOnly ); - floppyDiskDevice.setStorage( StorageType.FILE, image ); + + if ( image == null || image.isEmpty() ) { + floppyDiskDevice.removeStorage(); + } else { + floppyDiskDevice.setStorage( StorageType.FILE, image ); + } } else { // floppy device exists, so update existing floppy device floppyDiskDevice.setReadOnly( readOnly ); - floppyDiskDevice.setStorage( StorageType.FILE, image ); + + if ( image == null || image.isEmpty() ) { + floppyDiskDevice.removeStorage(); + } else { + floppyDiskDevice.setStorage( StorageType.FILE, image ); + } } } @Override public boolean addCdrom( String image ) { - return this.addCdrom( this.vmDeviceIndexCdromAdd++, image ); + int index = this.vmConfig.getDiskCdromDevices().size() - 1; + index = ( index > 0 ) ? index : 0; + return this.addCdrom( index, image ); } /** @@ -481,20 +512,24 @@ public class QemuMetaData extends public boolean addCdrom( int index, String image ) { ArrayList<DiskCdrom> cdromDiskDevices = this.vmConfig.getDiskCdromDevices(); - DiskCdrom cdromDiskDevice = QemuMetaDataUtils.getArrayIndex( cdromDiskDevices, index ); + DiskCdrom cdromDiskDevice = VirtualizationConfigurationQemuUtils.getArrayIndex( cdromDiskDevices, index ); if ( cdromDiskDevice == null ) { // CDROM device does not exist, so create new CDROM device cdromDiskDevice = this.vmConfig.addDiskCdromDevice(); cdromDiskDevice.setBusType( BusType.SATA ); - String targetDevName = QemuMetaDataUtils.createAlphabeticalDeviceName( "sd", index ); + String targetDevName = VirtualizationConfigurationQemuUtils.createAlphabeticalDeviceName( "sd", index ); cdromDiskDevice.setTargetDevice( targetDevName ); cdromDiskDevice.setReadOnly( true ); if ( image == null ) { cdromDiskDevice.setStorage( StorageType.BLOCK, CDROM_DEFAULT_PHYSICAL_DRIVE ); } else { - cdromDiskDevice.setStorage( StorageType.FILE, image ); + if ( image.isEmpty() ) { + cdromDiskDevice.removeStorage(); + } else { + cdromDiskDevice.setStorage( StorageType.FILE, image ); + } } } else { // CDROM device exists, so update existing CDROM device @@ -503,11 +538,15 @@ public class QemuMetaData extends if ( image == null ) { cdromDiskDevice.setStorage( StorageType.BLOCK, CDROM_DEFAULT_PHYSICAL_DRIVE ); } else { - cdromDiskDevice.setStorage( StorageType.FILE, image ); + if ( image.isEmpty() ) { + cdromDiskDevice.removeStorage(); + } else { + cdromDiskDevice.setStorage( StorageType.FILE, image ); + } } } - return false; + return true; } @Override @@ -551,7 +590,7 @@ public class QemuMetaData extends } else { // the VM configuration at least one sound card device, so return the type of the first one Sound.Model soundDeviceModel = soundDevices.get( 0 ).getModel(); - soundDeviceType = QemuMetaDataUtils.convertSoundDeviceModel( soundDeviceModel ); + soundDeviceType = VirtualizationConfigurationQemuUtils.convertSoundDeviceModel( soundDeviceModel ); } return soundDeviceType; @@ -645,16 +684,36 @@ public class QemuMetaData extends } @Override - public void setHWVersion( HWVersion type ) + public void setVirtualizerVersion( Version type ) { - // NOT supported by the QEMU hypervisor + if ( type != null ) { + final String osMachine = this.vmConfig.getOsMachine(); + final String osMachineName = VirtualizationConfigurationQemuUtils.getOsMachineName( osMachine ); + + if ( osMachineName != null && !osMachineName.isEmpty() ) { + final String modifiedOsMachineVersion = VirtualizationConfigurationQemuUtils.getOsMachineVersion( type ); + final String modifiedOsMachine = VirtualizationConfigurationQemuUtils.getOsMachine( osMachineName, + modifiedOsMachineVersion ); + this.vmConfig.setOsMachine( modifiedOsMachine ); + } + } } @Override - public HWVersion getHWVersion() + public Version getVirtualizerVersion() { - // NOT supported by the QEMU hypervisor - return null; + final String osMachine = this.vmConfig.getOsMachine(); + final Version uncheckedVersion = VirtualizationConfigurationQemuUtils.getOsMachineVersion( osMachine ); + final Version checkedVersion; + + if ( uncheckedVersion == null ) { + checkedVersion = null; + } else { + checkedVersion = Version.getInstanceByMajorMinorFromVersions( uncheckedVersion.getMajor(), + uncheckedVersion.getMinor(), this.getVirtualizer().getSupportedVersions() ); + } + + return checkedVersion; } @Override @@ -662,7 +721,7 @@ public class QemuMetaData extends { QemuEthernetDevTypeMeta networkDeviceConfig = this.networkCards.get( type ); ArrayList<Interface> networkDevices = this.vmConfig.getInterfaceDevices(); - Interface networkDevice = QemuMetaDataUtils.getArrayIndex( networkDevices, cardIndex ); + Interface networkDevice = VirtualizationConfigurationQemuUtils.getArrayIndex( networkDevices, cardIndex ); Interface.Model networkDeviceModel = networkDeviceConfig.getModel(); if ( networkDevice != null ) { @@ -674,7 +733,7 @@ public class QemuMetaData extends public EthernetDevType getEthernetDevType( int cardIndex ) { ArrayList<Interface> networkDevices = this.vmConfig.getInterfaceDevices(); - Interface networkDevice = QemuMetaDataUtils.getArrayIndex( networkDevices, cardIndex ); + Interface networkDevice = VirtualizationConfigurationQemuUtils.getArrayIndex( networkDevices, cardIndex ); EthernetDevType networkDeviceType = EthernetDevType.NONE; if ( networkDevice == null ) { @@ -683,7 +742,7 @@ public class QemuMetaData extends } else { // get model of existing network interface device Interface.Model networkDeviceModel = networkDevice.getModel(); - networkDeviceType = QemuMetaDataUtils.convertNetworkDeviceModel( networkDeviceModel ); + networkDeviceType = VirtualizationConfigurationQemuUtils.convertNetworkDeviceModel( networkDeviceModel ); } return networkDeviceType; @@ -712,7 +771,7 @@ public class QemuMetaData extends public UsbSpeed getMaxUsbSpeed() { ArrayList<ControllerUsb> usbControllerDevices = this.vmConfig.getUsbControllerDevices(); - UsbSpeed maxUsbSpeed = VmMetaData.UsbSpeed.NONE; + UsbSpeed maxUsbSpeed = VirtualizationConfiguration.UsbSpeed.NONE; int maxUsbSpeedNumeric = 0; for ( ControllerUsb usbControllerDevice : usbControllerDevices ) { @@ -731,7 +790,7 @@ public class QemuMetaData extends } @Override - public byte[] getDefinitionArray() + public byte[] getConfigurationAsByteArray() { String configuration = this.vmConfig.toString(); @@ -747,7 +806,9 @@ public class QemuMetaData extends @Override public boolean addEthernet( EtherType type ) { - return this.addEthernet( this.vmDeviceIndexEthernetAdd++, type ); + int index = this.vmConfig.getInterfaceDevices().size() - 1; + index = ( index > 0 ) ? index : 0; + return this.addEthernet( index, type ); } /** @@ -762,7 +823,7 @@ public class QemuMetaData extends { QemuEthernetDevTypeMeta defaultNetworkDeviceConfig = this.networkCards.get( EthernetDevType.AUTO ); ArrayList<Interface> interfaceDevices = this.vmConfig.getInterfaceDevices(); - Interface interfaceDevice = QemuMetaDataUtils.getArrayIndex( interfaceDevices, index ); + Interface interfaceDevice = VirtualizationConfigurationQemuUtils.getArrayIndex( interfaceDevices, index ); final Interface.Model defaultNetworkDeviceModel = defaultNetworkDeviceConfig.getModel(); @@ -773,19 +834,19 @@ public class QemuMetaData extends // add network bridge interface device interfaceDevice = this.vmConfig.addInterfaceBridgeDevice(); interfaceDevice.setModel( defaultNetworkDeviceModel ); - interfaceDevice.setSource( QemuMetaData.NETWORK_DEFAULT_BRIDGE ); + interfaceDevice.setSource( VirtualizationConfigurationQemu.NETWORK_BRIDGE_LAN_DEFAULT ); break; case HOST_ONLY: // add network interface device with link to the isolated host network - interfaceDevice = this.vmConfig.addInterfaceNetworkDevice(); + interfaceDevice = this.vmConfig.addInterfaceBridgeDevice(); interfaceDevice.setModel( defaultNetworkDeviceModel ); - interfaceDevice.setSource( QemuMetaData.NETWORK_DEFAULT_HOST_ONLY ); + interfaceDevice.setSource( VirtualizationConfigurationQemu.NETWORK_BRIDGE_HOST_ONLY_DEFAULT ); break; case NAT: // add network interface device with link to the NAT network - interfaceDevice = this.vmConfig.addInterfaceNetworkDevice(); + interfaceDevice = this.vmConfig.addInterfaceBridgeDevice(); interfaceDevice.setModel( defaultNetworkDeviceModel ); - interfaceDevice.setSource( QemuMetaData.NETWORK_DEFAULT_NAT ); + interfaceDevice.setSource( VirtualizationConfigurationQemu.NETWORK_BRIDGE_NAT_DEFAULT ); break; } } else { @@ -793,63 +854,77 @@ public class QemuMetaData extends switch ( type ) { case BRIDGED: interfaceDevice.setType( Interface.Type.BRIDGE ); - interfaceDevice.setSource( QemuMetaData.NETWORK_DEFAULT_BRIDGE ); + interfaceDevice.setSource( VirtualizationConfigurationQemu.NETWORK_BRIDGE_LAN_DEFAULT ); break; case HOST_ONLY: - interfaceDevice.setType( Interface.Type.NETWORK ); - interfaceDevice.setSource( QemuMetaData.NETWORK_DEFAULT_HOST_ONLY ); + interfaceDevice.setType( Interface.Type.BRIDGE ); + interfaceDevice.setSource( VirtualizationConfigurationQemu.NETWORK_BRIDGE_HOST_ONLY_DEFAULT ); break; case NAT: - interfaceDevice.setType( Interface.Type.NETWORK ); - interfaceDevice.setSource( QemuMetaData.NETWORK_DEFAULT_NAT ); + interfaceDevice.setType( Interface.Type.BRIDGE ); + interfaceDevice.setSource( VirtualizationConfigurationQemu.NETWORK_BRIDGE_NAT_DEFAULT ); break; } } - return false; + return true; } @Override - public Virtualizer getVirtualizer() + public void transformNonPersistent() throws VirtualizationConfigurationException { - return QemuMetaData.VIRTUALIZER; + // NOT implemented yet } @Override - public boolean tweakForNonPersistent() + public void transformPrivacy() throws VirtualizationConfigurationException { - // NOT implemented yet - return false; + // removes all referenced storage files of all specified CDROMs, Floppy drives and HDDs + this.vmConfig.removeDiskDevicesStorage(); } @Override public void registerVirtualHW() { // @formatter:off - soundCards.put( VmMetaData.SoundCardType.NONE, new QemuSoundCardMeta( null ) ); - soundCards.put( VmMetaData.SoundCardType.DEFAULT, new QemuSoundCardMeta( Sound.Model.ICH9 ) ); - soundCards.put( VmMetaData.SoundCardType.SOUND_BLASTER, new QemuSoundCardMeta( Sound.Model.SB16 ) ); - soundCards.put( VmMetaData.SoundCardType.ES, new QemuSoundCardMeta( Sound.Model.ES1370 ) ); - soundCards.put( VmMetaData.SoundCardType.AC, new QemuSoundCardMeta( Sound.Model.AC97 ) ); - soundCards.put( VmMetaData.SoundCardType.HD_AUDIO, new QemuSoundCardMeta( Sound.Model.ICH9 ) ); - - ddacc.put( VmMetaData.DDAcceleration.OFF, new QemuDDAccelMeta( false ) ); - ddacc.put( VmMetaData.DDAcceleration.ON, new QemuDDAccelMeta( true ) ); - - hwversion.put( VmMetaData.HWVersion.DEFAULT, new QemuHWVersionMeta( 0 ) ); - - networkCards.put( VmMetaData.EthernetDevType.NONE, new QemuEthernetDevTypeMeta( null ) ); - networkCards.put( VmMetaData.EthernetDevType.AUTO, new QemuEthernetDevTypeMeta( Interface.Model.VIRTIO_NET_PCI ) ); - networkCards.put( VmMetaData.EthernetDevType.PCNETPCI2, new QemuEthernetDevTypeMeta( Interface.Model.PCNET ) ); - networkCards.put( VmMetaData.EthernetDevType.E1000, new QemuEthernetDevTypeMeta( Interface.Model.E1000 ) ); - networkCards.put( VmMetaData.EthernetDevType.E1000E, new QemuEthernetDevTypeMeta( Interface.Model.E1000E ) ); - networkCards.put( VmMetaData.EthernetDevType.VMXNET3, new QemuEthernetDevTypeMeta( Interface.Model.VMXNET3 ) ); - networkCards.put( VmMetaData.EthernetDevType.PARAVIRT, new QemuEthernetDevTypeMeta( Interface.Model.VIRTIO_NET_PCI ) ); - - usbSpeeds.put( VmMetaData.UsbSpeed.NONE, new QemuUsbSpeedMeta( 0, ControllerUsb.Model.NONE ) ); - usbSpeeds.put( VmMetaData.UsbSpeed.USB1_1, new QemuUsbSpeedMeta( 1, ControllerUsb.Model.ICH9_UHCI1 ) ); - usbSpeeds.put( VmMetaData.UsbSpeed.USB2_0, new QemuUsbSpeedMeta( 2, ControllerUsb.Model.ICH9_EHCI1 ) ); - usbSpeeds.put( VmMetaData.UsbSpeed.USB3_0, new QemuUsbSpeedMeta( 3, ControllerUsb.Model.QEMU_XHCI ) ); + soundCards.put( VirtualizationConfiguration.SoundCardType.NONE, new QemuSoundCardMeta( null ) ); + soundCards.put( VirtualizationConfiguration.SoundCardType.DEFAULT, new QemuSoundCardMeta( Sound.Model.ICH9 ) ); + soundCards.put( VirtualizationConfiguration.SoundCardType.SOUND_BLASTER, new QemuSoundCardMeta( Sound.Model.SB16 ) ); + soundCards.put( VirtualizationConfiguration.SoundCardType.ES, new QemuSoundCardMeta( Sound.Model.ES1370 ) ); + soundCards.put( VirtualizationConfiguration.SoundCardType.AC, new QemuSoundCardMeta( Sound.Model.AC97 ) ); + soundCards.put( VirtualizationConfiguration.SoundCardType.HD_AUDIO, new QemuSoundCardMeta( Sound.Model.ICH9 ) ); + + ddacc.put( VirtualizationConfiguration.DDAcceleration.OFF, new QemuDDAccelMeta( false ) ); + ddacc.put( VirtualizationConfiguration.DDAcceleration.ON, new QemuDDAccelMeta( true ) ); + + networkCards.put( VirtualizationConfiguration.EthernetDevType.NONE, new QemuEthernetDevTypeMeta( null ) ); + networkCards.put( VirtualizationConfiguration.EthernetDevType.AUTO, new QemuEthernetDevTypeMeta( Interface.Model.VIRTIO_NET_PCI ) ); + networkCards.put( VirtualizationConfiguration.EthernetDevType.PCNETPCI2, new QemuEthernetDevTypeMeta( Interface.Model.PCNET ) ); + networkCards.put( VirtualizationConfiguration.EthernetDevType.E1000, new QemuEthernetDevTypeMeta( Interface.Model.E1000 ) ); + networkCards.put( VirtualizationConfiguration.EthernetDevType.E1000E, new QemuEthernetDevTypeMeta( Interface.Model.E1000E ) ); + networkCards.put( VirtualizationConfiguration.EthernetDevType.VMXNET3, new QemuEthernetDevTypeMeta( Interface.Model.VMXNET3 ) ); + networkCards.put( VirtualizationConfiguration.EthernetDevType.PARAVIRT, new QemuEthernetDevTypeMeta( Interface.Model.VIRTIO_NET_PCI ) ); + + usbSpeeds.put( VirtualizationConfiguration.UsbSpeed.NONE, new QemuUsbSpeedMeta( 0, ControllerUsb.Model.NONE ) ); + usbSpeeds.put( VirtualizationConfiguration.UsbSpeed.USB1_1, new QemuUsbSpeedMeta( 1, ControllerUsb.Model.ICH9_UHCI1 ) ); + usbSpeeds.put( VirtualizationConfiguration.UsbSpeed.USB2_0, new QemuUsbSpeedMeta( 2, ControllerUsb.Model.ICH9_EHCI1 ) ); + usbSpeeds.put( VirtualizationConfiguration.UsbSpeed.USB3_0, new QemuUsbSpeedMeta( 3, ControllerUsb.Model.QEMU_XHCI ) ); // @formatter:on } + + @Override + public String getFileNameExtension() + { + return VirtualizationConfigurationQemu.FILE_NAME_EXTENSION; + } + + @Override + public void validate() throws VirtualizationConfigurationException + { + try { + this.vmConfig.validateXml(); + } catch ( LibvirtXmlValidationException e ) { + throw new VirtualizationConfigurationException( e.getLocalizedMessage() ); + } + } } diff --git a/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationQemuUtils.java b/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationQemuUtils.java new file mode 100644 index 0000000..5d74d0d --- /dev/null +++ b/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationQemuUtils.java @@ -0,0 +1,441 @@ +package org.openslx.virtualization.configuration; + +import java.util.ArrayList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.openslx.libvirt.domain.device.Disk; +import org.openslx.libvirt.domain.device.Interface; +import org.openslx.libvirt.domain.device.Disk.BusType; +import org.openslx.virtualization.Version; +import org.openslx.virtualization.configuration.VirtualizationConfiguration.DriveBusType; +import org.openslx.virtualization.configuration.VirtualizationConfiguration.EthernetDevType; +import org.openslx.virtualization.configuration.VirtualizationConfiguration.SoundCardType; +import org.openslx.libvirt.domain.device.Sound; + +/** + * Collection of utils to convert data types from bwLehrpool to Libvirt and vice versa. + * + * @author Manuel Bentele + * @version 1.0 + */ +public class VirtualizationConfigurationQemuUtils +{ + /** + * Separator symbol between Libvirt/QEMU machine name and machine version. + */ + private static final String OS_MACHINE_NAME_VERSION_SEPARATOR = "-"; + + /** + * Converts a Libvirt disk device bus type to a VM metadata driver bus type. + * + * @param busType Libvirt disk device bus type. + * @return VM metadata bus type of the disk drive. + */ + public static DriveBusType convertBusType( Disk.BusType busType ) + { + DriveBusType type = null; + + switch ( busType ) { + case IDE: + type = DriveBusType.IDE; + break; + case SATA: + type = DriveBusType.SATA; + break; + case SCSI: + type = DriveBusType.SCSI; + break; + default: + type = null; + break; + } + + return type; + } + + /** + * Converts a VM metadata driver bus type to a Libvirt disk device bus type. + * + * @param busType VM metadata bus type of the disk drive. + * @return Libvirt disk device bus type. + */ + public static Disk.BusType convertBusType( DriveBusType busType ) + { + Disk.BusType type = null; + + switch ( busType ) { + case IDE: + type = BusType.IDE; + break; + case NVME: + type = null; + break; + case SATA: + type = BusType.SATA; + break; + case SCSI: + type = BusType.SCSI; + break; + } + + return type; + } + + /** + * Converts a Libvirt sound device model to a VM metadata sound card type. + * + * @param soundDeviceModel Libvirt sound device model. + * @return VM metadata sound card type. + */ + public static SoundCardType convertSoundDeviceModel( Sound.Model soundDeviceModel ) + { + SoundCardType type = SoundCardType.NONE; + + switch ( soundDeviceModel ) { + case AC97: + type = SoundCardType.AC; + break; + case ES1370: + type = SoundCardType.ES; + break; + case ICH6: + type = SoundCardType.HD_AUDIO; + break; + case ICH9: + type = SoundCardType.HD_AUDIO; + break; + case SB16: + type = SoundCardType.SOUND_BLASTER; + break; + } + + return type; + } + + /** + * Converts a Libvirt network device model to a VM metadata ethernet device type. + * + * @param networkDeviceModel Libvirt network device model. + * @return VM metadata ethernet device type. + */ + public static EthernetDevType convertNetworkDeviceModel( Interface.Model networkDeviceModel ) + { + EthernetDevType type = EthernetDevType.NONE; + + switch ( networkDeviceModel ) { + case E1000: + type = EthernetDevType.E1000; + break; + case E1000E: + type = EthernetDevType.E1000E; + break; + case PCNET: + type = EthernetDevType.PCNETPCI2; + break; + case VIRTIO: + type = EthernetDevType.PARAVIRT; + break; + case VIRTIO_NET_PCI: + type = EthernetDevType.PARAVIRT; + break; + case VIRTIO_NET_PCI_NON_TRANSITIONAL: + type = EthernetDevType.PARAVIRT; + break; + case VIRTIO_NET_PCI_TRANSITIONAL: + type = EthernetDevType.PARAVIRT; + break; + case VMXNET3: + type = EthernetDevType.VMXNET3; + break; + default: + type = EthernetDevType.AUTO; + break; + } + + return type; + } + + /** + * Returns an item from a given {@link ArrayList}. + * + * The item is selected by a given index. If the item is not available within the + * {@link ArrayList}, <code>null</code> is returned. + * + * @param <T> type of the {@link ArrayList}. + * @param array {@link ArrayList} of type <code>T</code>. + * @param index selects the item from the {@link ArrayList}. + * @return selected item of the {@link ArrayList}. + */ + public static <T> T getArrayIndex( ArrayList<T> array, int index ) + { + T ret; + + try { + ret = array.get( index ); + } catch ( IndexOutOfBoundsException e ) { + ret = null; + } + + return ret; + } + + /** + * Creates an alphabetical device name constructed from a device prefix and a device number. + * + * @param devicePrefix prefix of the constructed device name. + * @param deviceNumber number of the device. + * @return alphabetical device name. + */ + public static String createAlphabeticalDeviceName( String devicePrefix, int deviceNumber ) + { + if ( deviceNumber < 0 || deviceNumber >= ( 'z' - 'a' ) ) { + String errorMsg = new String( "Device number is out of range to be able to create a valid device name." ); + throw new IllegalArgumentException( errorMsg ); + } + + return devicePrefix + Character.valueOf( (char) ( 'a' + deviceNumber ) ).toString(); + } + + /** + * Data container to store a Libvirt/QEMU machine name with version information. + * + * @author Manuel Bentele + * @version 1.0 + */ + static class OsMachineNameAndVersion + { + /** + * Stores the machine name. + */ + final private String osMachineName; + + /** + * Stores the machine version. + */ + final private Version osMachineVersion; + + /** + * Creates a data container for a machine name with version information. + * + * @param osMachineName name of the machine. + * @param osMachineVersion version of the machine. + */ + public OsMachineNameAndVersion( String osMachineName, Version osMachineVersion ) + { + this.osMachineName = osMachineName; + this.osMachineVersion = osMachineVersion; + } + + /** + * Returns the machine name. + * + * @return machine name. + */ + public String getOsMachineName() + { + return this.osMachineName; + } + + /** + * Returns the version information. + * + * @return version information. + */ + public Version getOsMachineVersion() + { + return this.osMachineVersion; + } + } + + /** + * Parses a machine name with version information from a Libvirt/QEMU machine description. + * + * @param osMachine Libvirt/QEMU machine description as {@link String}. + * @return data container containing the parsed machine name with version information. + */ + private static OsMachineNameAndVersion parseOsMachineNameAndVersion( String osMachine ) + { + final String osMachineName; + final Version osMachineVersion; + + if ( osMachine == null || osMachine.isEmpty() ) { + // there is no machine description given, so we can not parse anything + osMachineName = null; + osMachineVersion = null; + } else { + // create regular expression based matcher to extract machine name and version number + final Pattern osMachineNameAndVersionPattern = Pattern.compile( "^([a-z0-9\\-]+)" + + VirtualizationConfigurationQemuUtils.OS_MACHINE_NAME_VERSION_SEPARATOR + "([0-9]+).([0-9]+)$" ); + final Matcher osMachineNameAndVersionMatcher = osMachineNameAndVersionPattern.matcher( osMachine ); + + final boolean matches = osMachineNameAndVersionMatcher.find(); + + if ( matches ) { + // get results of regular expression based matcher + osMachineName = osMachineNameAndVersionMatcher.group( 1 ); + final String osMachineMajorString = osMachineNameAndVersionMatcher.group( 2 ); + final String osMachineMinorString = osMachineNameAndVersionMatcher.group( 3 ); + + // create version representation + final short osMachineMajor = Short.valueOf( osMachineMajorString ); + final short osMachineMinor = Short.valueOf( osMachineMinorString ); + osMachineVersion = new Version( osMachineMajor, osMachineMinor ); + } else { + osMachineName = null; + osMachineVersion = null; + } + } + + return new OsMachineNameAndVersion( osMachineName, osMachineVersion ); + } + + /** + * Parses a machine name from a Libvirt/QEMU machine description. + * + * @param osMachine Libvirt/QEMU machine description as {@link String}. + * @return parsed machine name. + */ + public static String getOsMachineName( String osMachine ) + { + final OsMachineNameAndVersion machineNameAndVersion = VirtualizationConfigurationQemuUtils + .parseOsMachineNameAndVersion( osMachine ); + return machineNameAndVersion.getOsMachineName(); + } + + /** + * Parses a machine version from a Libvirt/QEMU machine description. + * + * @param osMachine Libvirt/QEMU machine description as {@link String}. + * @return parsed machine version. + */ + public static Version getOsMachineVersion( String osMachine ) + { + final OsMachineNameAndVersion machineNameAndVersion = VirtualizationConfigurationQemuUtils + .parseOsMachineNameAndVersion( osMachine ); + return machineNameAndVersion.getOsMachineVersion(); + } + + /** + * Combines a machine name with a machine version and returns a Libvirt/QEMU machine description. + * + * @param osMachineName name of the machine. + * @param osMachineVersion version of the machine. + * @return Libvirt/QEMU machine description. + */ + public static String getOsMachine( String osMachineName, String osMachineVersion ) + { + return osMachineName + VirtualizationConfigurationQemuUtils.OS_MACHINE_NAME_VERSION_SEPARATOR + osMachineVersion; + } + + /** + * Converts a {@link Version} to a Libvirt/QEMU machine version. + * + * @param version Libvirt/QEMU machine version as {@link Version}. + * @return Libvirt/QEMU machine version. + */ + public static String getOsMachineVersion( Version version ) + { + return String.format( "%d.%d", version.getMajor(), version.getMinor() ); + } + + /** + * Returns the size of a given architecture {@link String}. + * + * @param osArch Libvirt/QEMU machine architecture as {@link String}. + * @return Size of the Libvirt/QEMU machine architecture. + */ + public static int getOsArchSize( String osArch ) + { + final int archSize; + + if ( osArch == null || osArch.isEmpty() ) { + archSize = 0; + } else { + switch ( osArch ) { + case "alpha": + archSize = 64; + break; + case "armv6l": + archSize = 32; + break; + case "armv7l": + archSize = 32; + break; + case "aarch64": + archSize = 64; + break; + case "cris": + archSize = 32; + break; + case "i686": + archSize = 32; + break; + case "m68k": + archSize = 32; + break; + case "microblaze": + archSize = 32; + break; + case "microblazeel": + archSize = 32; + break; + case "mips": + archSize = 32; + break; + case "mipsel": + archSize = 32; + break; + case "mips64": + archSize = 64; + break; + case "mips64el": + archSize = 64; + break; + case "ppc": + archSize = 32; + break; + case "ppc64": + archSize = 64; + break; + case "ppc64le": + archSize = 64; + break; + case "riscv32": + archSize = 32; + break; + case "riscv64": + archSize = 64; + break; + case "s390x": + archSize = 64; + break; + case "sh4": + archSize = 32; + break; + case "sh4eb": + archSize = 64; + break; + case "sparc": + archSize = 32; + break; + case "sparc64": + archSize = 64; + break; + case "x86_64": + archSize = 64; + break; + case "xtensa": + archSize = 32; + break; + case "xtensaeb": + archSize = 32; + break; + default: + archSize = 0; + } + } + + return archSize; + } +} diff --git a/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationUtils.java b/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationUtils.java new file mode 100644 index 0000000..2427001 --- /dev/null +++ b/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationUtils.java @@ -0,0 +1,52 @@ +package org.openslx.virtualization.configuration; + +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.openslx.bwlp.thrift.iface.OperatingSystem; + +/** + * Utilities to set up and edit virtualization configurations. + * + * @author Manuel Bentele + * @version 1.0 + */ +public final class VirtualizationConfigurationUtils +{ + /** + * Returns an operating system from a given list of operating systems determined by the + * virtualizer specific operating system parameters. + * + * @param osList list of available operating systems. + * @param virtId virtualizer identifier, e.g. <code>vmware</code> for VMware + * @param virtOsId operating system identifier used by the virtualizer, eg. + * <code>windows7-64</code> for 64bit Windows 7 on VMware. + */ + public static OperatingSystem getOsOfVirtualizerFromList( List<OperatingSystem> osList, String virtId, + String virtOsId ) + { + OperatingSystem os = null; + + for ( final OperatingSystem osCandidate : osList ) { + final Map<String, String> osVirtualizerMapping = osCandidate.getVirtualizerOsId(); + if ( osVirtualizerMapping != null ) { + for ( final Entry<String, String> entry : osVirtualizerMapping.entrySet() ) { + // check if suitable OS has been found + if ( entry.getKey().equals( virtId ) && entry.getValue().equals( virtOsId ) ) { + // save OS and exit inner loop since OS has been found + os = osCandidate; + break; + } + } + + // exit outer loop if OS has been found + if ( os != null ) { + break; + } + } + } + + return os; + } +} diff --git a/src/main/java/org/openslx/vm/VboxMetaData.java b/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationVirtualBox.java index a6ac14d..6922c8c 100644 --- a/src/main/java/org/openslx/vm/VboxMetaData.java +++ b/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationVirtualBox.java @@ -1,4 +1,4 @@ -package org.openslx.vm; +package org.openslx.virtualization.configuration; import java.io.File; import java.io.IOException; @@ -6,18 +6,16 @@ import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.Map.Entry; import java.util.UUID; 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.vm.VboxConfig.PlaceHolder; -import org.openslx.vm.disk.DiskImage; -import org.openslx.vm.disk.DiskImage.ImageFormat; +import org.openslx.virtualization.Version; +import org.openslx.virtualization.configuration.VirtualizationConfigurationVirtualboxFileFormat.PlaceHolder; +import org.openslx.virtualization.virtualizer.VirtualizerVirtualBox; import org.w3c.dom.Attr; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -45,16 +43,6 @@ class VBoxDDAccelMeta } } -class VBoxHWVersionMeta -{ - public final int version; - - public VBoxHWVersionMeta( int vers ) - { - version = vers; - } -} - class VBoxEthernetDevTypeMeta { public final String value; @@ -71,6 +59,7 @@ class VBoxUsbSpeedMeta { public final String value; public final int speed; + public VBoxUsbSpeedMeta( String value, int speed ) { this.value = value; @@ -78,19 +67,17 @@ class VBoxUsbSpeedMeta } } -public class VboxMetaData extends VmMetaData<VBoxSoundCardMeta, VBoxDDAccelMeta, VBoxHWVersionMeta, VBoxEthernetDevTypeMeta, VBoxUsbSpeedMeta> +public class VirtualizationConfigurationVirtualBox + extends VirtualizationConfiguration<VBoxSoundCardMeta, VBoxDDAccelMeta, VBoxEthernetDevTypeMeta, VBoxUsbSpeedMeta> { /** - * List of supported image formats by the VirtualBox hypervisor. + * File name extension for VirtualBox virtualization configuration files.. */ - private static final List<DiskImage.ImageFormat> SUPPORTED_IMAGE_FORMATS = Collections.unmodifiableList( - Arrays.asList( ImageFormat.VDI ) ); - - private static final Logger LOGGER = Logger.getLogger( VboxMetaData.class ); + public static final String FILE_NAME_EXTENSION = "vbox"; - private static final Virtualizer virtualizer = new Virtualizer( TConst.VIRT_VIRTUALBOX, "VirtualBox" ); + private static final Logger LOGGER = Logger.getLogger( VirtualizationConfigurationVirtualBox.class ); - private final VboxConfig config; + private final VirtualizationConfigurationVirtualboxFileFormat config; public static enum EthernetType { @@ -104,23 +91,24 @@ public class VboxMetaData extends VmMetaData<VBoxSoundCardMeta, VBoxDDAccelMeta, } } - public VboxMetaData( List<OperatingSystem> osList, File file ) throws IOException, UnsupportedVirtualizerFormatException + public VirtualizationConfigurationVirtualBox( List<OperatingSystem> osList, File file ) + throws IOException, VirtualizationConfigurationException { - super( osList ); - this.config = new VboxConfig( file ); + super( new VirtualizerVirtualBox(), osList ); + this.config = new VirtualizationConfigurationVirtualboxFileFormat( file ); init(); } - public VboxMetaData( List<OperatingSystem> osList, byte[] vmContent, int length ) throws IOException, UnsupportedVirtualizerFormatException + public VirtualizationConfigurationVirtualBox( List<OperatingSystem> osList, byte[] vmContent, int length ) + throws IOException, VirtualizationConfigurationException { - super( osList ); - this.config = new VboxConfig( vmContent, length ); + super( new VirtualizerVirtualBox(), osList ); + this.config = new VirtualizationConfigurationVirtualboxFileFormat( vmContent, length ); init(); } private void init() { - registerVirtualHW(); displayName = config.getDisplayName(); setOs( config.getOsName() ); this.isMachineSnapshot = config.isMachineSnapshot(); @@ -130,39 +118,34 @@ public class VboxMetaData extends VmMetaData<VBoxSoundCardMeta, VBoxDDAccelMeta, } @Override - public Virtualizer getVirtualizer() + public void transformEditable() throws VirtualizationConfigurationException { - return virtualizer; - } - - @Override - public List<DiskImage.ImageFormat> getSupportedImageFormats() - { - return VboxMetaData.SUPPORTED_IMAGE_FORMATS; + // TODO Auto-generated method stub } @Override - public void applySettingsForLocalEdit() + public void transformPrivacy() throws VirtualizationConfigurationException { - // TODO Auto-generated method stub + } @Override - public byte[] getDefinitionArray() + public byte[] getConfigurationAsByteArray() { - return config.toString( false ).getBytes( StandardCharsets.UTF_8 ); + return config.toString( true ).getBytes( StandardCharsets.UTF_8 ); } @Override - public byte[] getFilteredDefinitionArray() + public boolean addEmptyHddTemplate() { - return config.toString( false ).getBytes( StandardCharsets.UTF_8 ); + return this.addHddTemplate( "%VM_DISK_PATH%", "%VM_DISK_MODE%", "%VM_DISK_REDOLOGDIR%" ); } @Override public boolean addHddTemplate( String diskImage, String hddMode, String redoDir ) { - config.changeAttribute( "/VirtualBox/Machine/MediaRegistry/HardDisks/HardDisk[@location='" + PlaceHolder.HDDLOCATION.toString() + "']", "location", diskImage ); + config.changeAttribute( "/VirtualBox/Machine/MediaRegistry/HardDisks/HardDisk[@location='" + + PlaceHolder.HDDLOCATION.toString() + "']", "location", diskImage ); config.changeAttribute( "/VirtualBox/Machine", "snapshotFolder", redoDir ); return true; } @@ -178,7 +161,8 @@ public class VboxMetaData extends VmMetaData<VBoxSoundCardMeta, VBoxDDAccelMeta, // patching the new uuid in the vbox config file here String vboxUUid = "{" + newhdduuid.toString() + "}"; config.changeAttribute( "/VirtualBox/Machine/MediaRegistry/HardDisks/HardDisk", "uuid", vboxUUid ); - config.changeAttribute( "/VirtualBox/Machine/StorageControllers/StorageController/AttachedDevice/Image", "uuid", vboxUUid ); + config.changeAttribute( "/VirtualBox/Machine/StorageControllers/StorageController/AttachedDevice/Image", "uuid", + vboxUUid ); // the order of the UUID is BIG_ENDIAN but we need to change the order of the first 8 Bytes // to be able to write them to the vdi file... the PROBLEM here is that the first 8 @@ -228,7 +212,10 @@ public class VboxMetaData extends VmMetaData<VBoxSoundCardMeta, VBoxDDAccelMeta, public void setOs( String vendorOsId ) { config.changeAttribute( "/VirtualBox/Machine", "OSType", vendorOsId ); - setOs( TConst.VIRT_VIRTUALBOX, vendorOsId ); + + final OperatingSystem os = VirtualizationConfigurationUtils.getOsOfVirtualizerFromList( this.osList, + TConst.VIRT_VIRTUALBOX, vendorOsId ); + this.setOs( os ); } @Override @@ -247,7 +234,8 @@ public class VboxMetaData extends VmMetaData<VBoxSoundCardMeta, VBoxDDAccelMeta, public void addFloppy( int index, String image, boolean readOnly ) { Element floppyController = null; - NodeList matches = (NodeList)config.findNodes( "/VirtualBox/Machine/StorageControllers/StorageController[@name='Floppy']" ); + NodeList matches = (NodeList)config + .findNodes( "/VirtualBox/Machine/StorageControllers/StorageController[@name='Floppy']" ); if ( matches == null || matches.getLength() == 0 ) { floppyController = (Element)config.addNewNode( "/VirtualBox/Machine/StorageControllers", "StorageController" ); if ( floppyController == null ) { @@ -287,20 +275,24 @@ public class VboxMetaData extends VmMetaData<VBoxSoundCardMeta, VBoxDDAccelMeta, LOGGER.error( "Failed to add <Image> to floppy device." ); return; } - floppyImage.setAttribute( "uuid", VboxConfig.PlaceHolder.FLOPPYUUID.toString() ); + floppyImage.setAttribute( "uuid", + VirtualizationConfigurationVirtualboxFileFormat.PlaceHolder.FLOPPYUUID.toString() ); // register the image in the media registry Element floppyImages = (Element)config.addNewNode( "/VirtualBox/Machine/MediaRegistry", "FloppyImages" ); if ( floppyImages == null ) { LOGGER.error( "Failed to add <FloppyImages> to media registry." ); return; } - Element floppyImageReg = (Element)config.addNewNode( "/VirtualBox/Machine/MediaRegistry/FloppyImages", "Image" ); + Element floppyImageReg = (Element)config.addNewNode( "/VirtualBox/Machine/MediaRegistry/FloppyImages", + "Image" ); if ( floppyImageReg == null ) { LOGGER.error( "Failed to add <Image> to floppy images in the media registry." ); return; } - floppyImageReg.setAttribute( "uuid", VboxConfig.PlaceHolder.FLOPPYUUID.toString() ); - floppyImageReg.setAttribute( "location", VboxConfig.PlaceHolder.FLOPPYLOCATION.toString() ); + floppyImageReg.setAttribute( "uuid", + VirtualizationConfigurationVirtualboxFileFormat.PlaceHolder.FLOPPYUUID.toString() ); + floppyImageReg.setAttribute( "location", + VirtualizationConfigurationVirtualboxFileFormat.PlaceHolder.FLOPPYLOCATION.toString() ); } } @@ -318,29 +310,32 @@ public class VboxMetaData extends VmMetaData<VBoxSoundCardMeta, VBoxDDAccelMeta, } @Override - public void setSoundCard( org.openslx.vm.VmMetaData.SoundCardType type ) + public void setSoundCard( org.openslx.virtualization.configuration.VirtualizationConfiguration.SoundCardType type ) { VBoxSoundCardMeta sound = soundCards.get( type ); - config.changeAttribute( "/VirtualBox/Machine/Hardware/AudioAdapter", "enabled", Boolean.toString( sound.isPresent ) ); + config.changeAttribute( "/VirtualBox/Machine/Hardware/AudioAdapter", "enabled", + Boolean.toString( sound.isPresent ) ); config.changeAttribute( "/VirtualBox/Machine/Hardware/AudioAdapter", "controller", sound.value ); } @Override - public VmMetaData.SoundCardType getSoundCard() + public VirtualizationConfiguration.SoundCardType getSoundCard() { // initialize here to type None to avoid all null pointer exceptions thrown for unknown user written sound cards - VmMetaData.SoundCardType returnsct = VmMetaData.SoundCardType.NONE; + VirtualizationConfiguration.SoundCardType returnsct = VirtualizationConfiguration.SoundCardType.NONE; Element x = (Element)config.findNodes( "/VirtualBox/Machine/Hardware/AudioAdapter" ).item( 0 ); - if ( !x.hasAttribute( "enabled" ) || ( x.hasAttribute( "enabled" ) && x.getAttribute( "enabled" ).equals( "false" ) ) ) { + if ( !x.hasAttribute( "enabled" ) + || ( x.hasAttribute( "enabled" ) && x.getAttribute( "enabled" ).equals( "false" ) ) ) { return returnsct; } else { // extra separate case for the non-existing argument} if ( !x.hasAttribute( "controller" ) ) { - returnsct = VmMetaData.SoundCardType.AC; + returnsct = VirtualizationConfiguration.SoundCardType.AC; } else { String controller = x.getAttribute( "controller" ); VBoxSoundCardMeta soundMeta = null; - for ( VmMetaData.SoundCardType type : VmMetaData.SoundCardType.values() ) { + for ( VirtualizationConfiguration.SoundCardType type : VirtualizationConfiguration.SoundCardType + .values() ) { soundMeta = soundCards.get( type ); if ( soundMeta != null ) { if ( controller.equals( soundMeta.value ) ) { @@ -354,25 +349,26 @@ public class VboxMetaData extends VmMetaData<VBoxSoundCardMeta, VBoxDDAccelMeta, } @Override - public void setDDAcceleration( VmMetaData.DDAcceleration type ) + public void setDDAcceleration( VirtualizationConfiguration.DDAcceleration type ) { VBoxDDAccelMeta accel = ddacc.get( type ); - config.changeAttribute( "/VirtualBox/Machine/Hardware/Display", "accelerate3D", Boolean.toString( accel.isPresent ) ); + config.changeAttribute( "/VirtualBox/Machine/Hardware/Display", "accelerate3D", + Boolean.toString( accel.isPresent ) ); } @Override - public VmMetaData.DDAcceleration getDDAcceleration() + public VirtualizationConfiguration.DDAcceleration getDDAcceleration() { - VmMetaData.DDAcceleration returndda = null; + VirtualizationConfiguration.DDAcceleration returndda = null; Element x = (Element)config.findNodes( "/VirtualBox/Machine/Hardware/Display" ).item( 0 ); if ( x.hasAttribute( "accelerate3D" ) ) { if ( x.getAttribute( "accelerate3D" ).equals( "true" ) ) { - returndda = VmMetaData.DDAcceleration.ON; + returndda = VirtualizationConfiguration.DDAcceleration.ON; } else { - returndda = VmMetaData.DDAcceleration.OFF; + returndda = VirtualizationConfiguration.DDAcceleration.OFF; } } else { - returndda = VmMetaData.DDAcceleration.OFF; + returndda = VirtualizationConfiguration.DDAcceleration.OFF; } return returndda; } @@ -382,15 +378,20 @@ public class VboxMetaData extends VmMetaData<VBoxSoundCardMeta, VBoxDDAccelMeta, * Virtual Box accepts per default only one hardware version and is hidden from the user */ @Override - public void setHWVersion( HWVersion type ) + public void setVirtualizerVersion( Version type ) { } + public Version getConfigurationVersion() + { + return this.config.getVersion(); + } + @Override - public VmMetaData.HWVersion getHWVersion() + public Version getVirtualizerVersion() { // Virtual Box uses only one virtual hardware version and can't be changed - return VmMetaData.HWVersion.DEFAULT; + return null; } @Override @@ -399,25 +400,29 @@ public class VboxMetaData extends VmMetaData<VBoxSoundCardMeta, VBoxDDAccelMeta, String index = "0"; VBoxEthernetDevTypeMeta nic = networkCards.get( type ); // cardIndex is not used yet...maybe later needed for different network cards - config.changeAttribute( "/VirtualBox/Machine/Hardware/Network/Adapter[@slot='" + index + "']", "enabled", Boolean.toString( nic.isPresent ) ); - config.changeAttribute( "/VirtualBox/Machine/Hardware/Network/Adapter[@slot='" + index + "']", "type", nic.value ); + config.changeAttribute( "/VirtualBox/Machine/Hardware/Network/Adapter[@slot='" + index + "']", "enabled", + Boolean.toString( nic.isPresent ) ); + config.changeAttribute( "/VirtualBox/Machine/Hardware/Network/Adapter[@slot='" + index + "']", "type", + nic.value ); } @Override - public VmMetaData.EthernetDevType getEthernetDevType( int cardIndex ) + public VirtualizationConfiguration.EthernetDevType getEthernetDevType( int cardIndex ) { - VmMetaData.EthernetDevType returnedt = VmMetaData.EthernetDevType.NONE; + VirtualizationConfiguration.EthernetDevType returnedt = VirtualizationConfiguration.EthernetDevType.NONE; Element x = (Element)config.findNodes( "/VirtualBox/Machine/Hardware/Network/Adapter" ).item( 0 ); - if ( !x.hasAttribute( "enabled" ) || ( x.hasAttribute( "enabled" ) && x.getAttribute( "enabled" ).equals( "false" ) ) ) { + if ( !x.hasAttribute( "enabled" ) + || ( x.hasAttribute( "enabled" ) && x.getAttribute( "enabled" ).equals( "false" ) ) ) { return returnedt; } else { // extra separate case for the non-existing argument} if ( !x.hasAttribute( "type" ) ) { - returnedt = VmMetaData.EthernetDevType.PCNETFAST3; + returnedt = VirtualizationConfiguration.EthernetDevType.PCNETFAST3; } else { String temp = x.getAttribute( "type" ); VBoxEthernetDevTypeMeta etherMeta = null; - for ( VmMetaData.EthernetDevType type : VmMetaData.EthernetDevType.values() ) { + for ( VirtualizationConfiguration.EthernetDevType type : VirtualizationConfiguration.EthernetDevType + .values() ) { etherMeta = networkCards.get( type ); if ( etherMeta != null ) { if ( temp.equals( etherMeta.value ) ) { @@ -434,35 +439,41 @@ public class VboxMetaData extends VmMetaData<VBoxSoundCardMeta, VBoxDDAccelMeta, { // none type needs to have a valid value; it takes the value of AC97; if value is left null or empty vm will not start because value is not valid // TODO: Maybe just remove the entire section from the XML? Same for ethernet... - soundCards.put( VmMetaData.SoundCardType.NONE, new VBoxSoundCardMeta( false, "AC97" ) ); - soundCards.put( VmMetaData.SoundCardType.SOUND_BLASTER, new VBoxSoundCardMeta( true, "SB16" ) ); - soundCards.put( VmMetaData.SoundCardType.HD_AUDIO, new VBoxSoundCardMeta( true, "HDA" ) ); - soundCards.put( VmMetaData.SoundCardType.AC, new VBoxSoundCardMeta( true, "AC97" ) ); - - ddacc.put( VmMetaData.DDAcceleration.OFF, new VBoxDDAccelMeta( false ) ); - ddacc.put( VmMetaData.DDAcceleration.ON, new VBoxDDAccelMeta( true ) ); + soundCards.put( VirtualizationConfiguration.SoundCardType.NONE, new VBoxSoundCardMeta( false, "AC97" ) ); + soundCards.put( VirtualizationConfiguration.SoundCardType.SOUND_BLASTER, new VBoxSoundCardMeta( true, "SB16" ) ); + soundCards.put( VirtualizationConfiguration.SoundCardType.HD_AUDIO, new VBoxSoundCardMeta( true, "HDA" ) ); + soundCards.put( VirtualizationConfiguration.SoundCardType.AC, new VBoxSoundCardMeta( true, "AC97" ) ); - hwversion.put( VmMetaData.HWVersion.DEFAULT, new VBoxHWVersionMeta( 0 ) ); + ddacc.put( VirtualizationConfiguration.DDAcceleration.OFF, new VBoxDDAccelMeta( false ) ); + ddacc.put( VirtualizationConfiguration.DDAcceleration.ON, new VBoxDDAccelMeta( true ) ); // none type needs to have a valid value; it takes the value of pcnetcpi2; if value is left null or empty vm will not start because value is not valid - networkCards.put( VmMetaData.EthernetDevType.NONE, new VBoxEthernetDevTypeMeta( false, "Am79C970A" ) ); - networkCards.put( VmMetaData.EthernetDevType.PCNETPCI2, new VBoxEthernetDevTypeMeta( true, "Am79C970A" ) ); - networkCards.put( VmMetaData.EthernetDevType.PCNETFAST3, new VBoxEthernetDevTypeMeta( true, "Am79C973" ) ); - networkCards.put( VmMetaData.EthernetDevType.PRO1000MTD, new VBoxEthernetDevTypeMeta( true, "82540EM" ) ); - networkCards.put( VmMetaData.EthernetDevType.PRO1000TS, new VBoxEthernetDevTypeMeta( true, "82543GC" ) ); - networkCards.put( VmMetaData.EthernetDevType.PRO1000MTS, new VBoxEthernetDevTypeMeta( true, "82545EM" ) ); - networkCards.put( VmMetaData.EthernetDevType.PARAVIRT, new VBoxEthernetDevTypeMeta( true, "virtio" ) ); - - usbSpeeds.put( VmMetaData.UsbSpeed.NONE, new VBoxUsbSpeedMeta( null, 0 ) ); - usbSpeeds.put( VmMetaData.UsbSpeed.USB1_1, new VBoxUsbSpeedMeta( "OHCI", 1 ) ); - usbSpeeds.put( VmMetaData.UsbSpeed.USB2_0, new VBoxUsbSpeedMeta( "EHCI", 2 ) ); - usbSpeeds.put( VmMetaData.UsbSpeed.USB3_0, new VBoxUsbSpeedMeta( "XHCI", 3 ) ); + networkCards.put( VirtualizationConfiguration.EthernetDevType.NONE, + new VBoxEthernetDevTypeMeta( false, "Am79C970A" ) ); + networkCards.put( VirtualizationConfiguration.EthernetDevType.PCNETPCI2, + new VBoxEthernetDevTypeMeta( true, "Am79C970A" ) ); + networkCards.put( VirtualizationConfiguration.EthernetDevType.PCNETFAST3, + new VBoxEthernetDevTypeMeta( true, "Am79C973" ) ); + networkCards.put( VirtualizationConfiguration.EthernetDevType.PRO1000MTD, + new VBoxEthernetDevTypeMeta( true, "82540EM" ) ); + networkCards.put( VirtualizationConfiguration.EthernetDevType.PRO1000TS, + new VBoxEthernetDevTypeMeta( true, "82543GC" ) ); + networkCards.put( VirtualizationConfiguration.EthernetDevType.PRO1000MTS, + new VBoxEthernetDevTypeMeta( true, "82545EM" ) ); + networkCards.put( VirtualizationConfiguration.EthernetDevType.PARAVIRT, + new VBoxEthernetDevTypeMeta( true, "virtio" ) ); + + usbSpeeds.put( VirtualizationConfiguration.UsbSpeed.NONE, new VBoxUsbSpeedMeta( null, 0 ) ); + usbSpeeds.put( VirtualizationConfiguration.UsbSpeed.USB1_1, new VBoxUsbSpeedMeta( "OHCI", 1 ) ); + usbSpeeds.put( VirtualizationConfiguration.UsbSpeed.USB2_0, new VBoxUsbSpeedMeta( "EHCI", 2 ) ); + usbSpeeds.put( VirtualizationConfiguration.UsbSpeed.USB3_0, new VBoxUsbSpeedMeta( "XHCI", 3 ) ); } @Override - public boolean addEthernet( VmMetaData.EtherType type ) + public boolean addEthernet( VirtualizationConfiguration.EtherType type ) { - Node hostOnlyInterfaceNode = config.addNewNode( "/VirtualBox/Machine/Hardware/Network/Adapter[@slot='0']", "HostOnlyInterface" ); + Node hostOnlyInterfaceNode = config.addNewNode( "/VirtualBox/Machine/Hardware/Network/Adapter[@slot='0']", + "HostOnlyInterface" ); if ( hostOnlyInterfaceNode == null ) { LOGGER.error( "Failed to create node for HostOnlyInterface." ); return false; @@ -471,7 +482,7 @@ public class VboxMetaData extends VmMetaData<VBoxSoundCardMeta, VBoxDDAccelMeta, } @Override - public boolean tweakForNonPersistent() + public void transformNonPersistent() throws VirtualizationConfigurationException { // Cannot disable suspend // https://forums.virtualbox.org/viewtopic.php?f=6&t=77169 @@ -485,15 +496,14 @@ public class VboxMetaData extends VmMetaData<VBoxSoundCardMeta, VBoxDDAccelMeta, config.setExtraData( "GUI/PreventSnapshotOperations", "true" ); config.setExtraData( "GUI/PreventApplicationUpdate", "true" ); config.setExtraData( "GUI/RestrictedCloseActions", "SaveState,PowerOffRestoringSnapshot,Detach" ); - return true; } @Override - public void setMaxUsbSpeed( VmMetaData.UsbSpeed speed ) + public void setMaxUsbSpeed( VirtualizationConfiguration.UsbSpeed speed ) { // Wipe existing ones config.removeNodes( "/VirtualBox/Machine/Hardware", "USB" ); - if ( speed == null || speed == VmMetaData.UsbSpeed.NONE ) { + if ( speed == null || speed == VirtualizationConfiguration.UsbSpeed.NONE ) { // Add marker so we know it's not an old config and we really want no USB Element node = config.createNodeRecursive( "/VirtualBox/OpenSLX/USB" ); if ( node != null ) { @@ -513,18 +523,18 @@ public class VboxMetaData extends VmMetaData<VBoxSoundCardMeta, VBoxDDAccelMeta, } @Override - public VmMetaData.UsbSpeed getMaxUsbSpeed() + public VirtualizationConfiguration.UsbSpeed getMaxUsbSpeed() { NodeList nodes = config.findNodes( "/VirtualBox/Machine/Hardware/USB/Controllers/Controller/@type" ); int maxSpeed = 0; - VmMetaData.UsbSpeed maxItem = VmMetaData.UsbSpeed.NONE; + VirtualizationConfiguration.UsbSpeed maxItem = VirtualizationConfiguration.UsbSpeed.NONE; for ( int i = 0; i < nodes.getLength(); ++i ) { if ( nodes.item( i ).getNodeType() != Node.ATTRIBUTE_NODE ) { LOGGER.info( "Not ATTRIBUTE type" ); continue; } - String type = ((Attr)nodes.item( i )).getValue(); - for ( Entry<VmMetaData.UsbSpeed, VBoxUsbSpeedMeta> s : usbSpeeds.entrySet() ) { + String type = ( (Attr)nodes.item( i ) ).getValue(); + for ( Entry<VirtualizationConfiguration.UsbSpeed, VBoxUsbSpeedMeta> s : usbSpeeds.entrySet() ) { if ( s.getValue().speed > maxSpeed && type.equals( s.getValue().value ) ) { maxSpeed = s.getValue().speed; maxItem = s.getKey(); @@ -533,4 +543,16 @@ public class VboxMetaData extends VmMetaData<VBoxSoundCardMeta, VBoxDDAccelMeta, } return maxItem; } + + @Override + public String getFileNameExtension() + { + return VirtualizationConfigurationVirtualBox.FILE_NAME_EXTENSION; + } + + @Override + public void validate() throws VirtualizationConfigurationException + { + this.config.validate(); + } } diff --git a/src/main/java/org/openslx/vm/VboxConfig.java b/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationVirtualboxFileFormat.java index 9724b6a..b1c940a 100644 --- a/src/main/java/org/openslx/vm/VboxConfig.java +++ b/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationVirtualboxFileFormat.java @@ -1,4 +1,4 @@ -package org.openslx.vm; +package org.openslx.virtualization.configuration; import java.io.ByteArrayInputStream; import java.io.File; @@ -6,9 +6,13 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import javax.xml.XMLConstants; +import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; @@ -20,8 +24,9 @@ import javax.xml.xpath.XPathExpressionException; import org.apache.log4j.Logger; import org.openslx.util.Util; import org.openslx.util.XmlHelper; -import org.openslx.vm.VmMetaData.DriveBusType; -import org.openslx.vm.VmMetaData.HardDisk; +import org.openslx.virtualization.Version; +import org.openslx.virtualization.configuration.VirtualizationConfiguration.DriveBusType; +import org.openslx.virtualization.configuration.VirtualizationConfiguration.HardDisk; import org.w3c.dom.DOMException; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -32,9 +37,9 @@ import org.xml.sax.SAXException; /** * Class handling the parsing of a .vbox machine description file */ -public class VboxConfig +public class VirtualizationConfigurationVirtualboxFileFormat { - private static final Logger LOGGER = Logger.getLogger( VboxConfig.class ); + private static final Logger LOGGER = Logger.getLogger( VirtualizationConfigurationVirtualboxFileFormat.class ); // key information set during initial parsing of the XML file private String osName = new String(); @@ -43,6 +48,31 @@ public class VboxConfig // XPath and DOM parsing related members private Document doc = null; + /** + * Version of the configuration file format. + */ + private Version version = null; + + /** + * File names of XML schema files for different file format versions. + */ + private final static HashMap<Version, String> FILE_FORMAT_SCHEMA_VERSIONS = new HashMap<Version, String>() { + + private static final long serialVersionUID = -3163681758191475625L; + + { + put( Version.valueOf( "1.15" ), "VirtualBox-settings_v1-15.xsd" ); + put( Version.valueOf( "1.16" ), "VirtualBox-settings_v1-16.xsd" ); + put( Version.valueOf( "1.17" ), "VirtualBox-settings_v1-17.xsd" ); + put( Version.valueOf( "1.18" ), "VirtualBox-settings_v1-18.xsd" ); + } + }; + + /** + * Path to the VirtualBox file format schemas within the *.jar file. + */ + private final static String FILE_FORMAT_SCHEMA_PREFIX_PATH = File.separator + "virtualbox" + File.separator + "xsd"; + // list of nodes to automatically remove when reading the vbox file private static String[] blacklist = { "/VirtualBox/Machine/Hardware/GuestProperties", @@ -53,6 +83,7 @@ public class VboxConfig "/VirtualBox/Machine/Hardware/Network/Adapter[@enabled='true']/*", "/VirtualBox/Machine/ExtraData", "/VirtualBox/Machine/StorageControllers/StorageController/AttachedDevice[not(@type='HardDisk')]", + "/VirtualBox/Machine/Hardware/StorageControllers/StorageController/AttachedDevice[not(@type='HardDisk')]", "/VirtualBox/Machine/MediaRegistry/FloppyImages", "/VirtualBox/Machine/MediaRegistry/DVDImages" }; @@ -83,31 +114,18 @@ public class VboxConfig * * @param file the VirtualBox machine configuration file * @throws IOException if an error occurs while reading the file - * @throws UnsupportedVirtualizerFormatException if the given file is not a valid VirtualBox + * @throws VirtualizationConfigurationException if the given file is not a valid VirtualBox * configuration file. */ - public VboxConfig( File file ) throws IOException, UnsupportedVirtualizerFormatException + public VirtualizationConfigurationVirtualboxFileFormat( File file ) throws IOException, VirtualizationConfigurationException { - // first validate xml - try { - SchemaFactory factory = SchemaFactory.newInstance( XMLConstants.W3C_XML_SCHEMA_NS_URI ); - InputStream xsdStream = VboxConfig.class.getResourceAsStream( "/master-sync-shared/xml/VirtualBox-settings.xsd" ); - if ( xsdStream == null ) { - LOGGER.warn( "Cannot validate Vbox XML: No XSD found in JAR" ); - } else { - Schema schema = factory.newSchema( new StreamSource( xsdStream ) ); - Validator validator = schema.newValidator(); - validator.validate( new StreamSource( file ) ); - } - } catch ( SAXException e ) { - LOGGER.error( "Selected vbox file was not validated against the XSD schema: " + e.getMessage() ); - } - // 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(); + throw new VirtualizationConfigurationException( "Could not parse given VirtualBox machine configuration file!" ); + + this.parseConfigurationVersion(); + this.init(); } /** @@ -116,27 +134,86 @@ public class VboxConfig * * @param machineDescription content of the XML file saved as a byte array. * @param length of the machine description byte array. - * @throws IOException if an + * @throws VirtualizationConfigurationException creation of VirtualBox configuration file representation failed. */ - public VboxConfig( byte[] machineDescription, int length ) throws UnsupportedVirtualizerFormatException + public VirtualizationConfigurationVirtualboxFileFormat( byte[] machineDescription, int length ) throws VirtualizationConfigurationException { ByteArrayInputStream is = new ByteArrayInputStream( machineDescription ); + doc = XmlHelper.parseDocumentFromStream( is ); if ( doc == null ) { - 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." ); + final String errorMsg = "Could not parse given VirtualBox machine description from byte array!"; + LOGGER.debug( errorMsg ); + throw new VirtualizationConfigurationException( errorMsg ); } - init(); + + this.parseConfigurationVersion(); + this.init(); + } + + public void validate() throws VirtualizationConfigurationException + { + this.validateFileFormatVersion( this.getVersion() ); + } + + public void validateFileFormatVersion( Version version ) throws VirtualizationConfigurationException + { + if ( this.getVersion() != null && this.doc != null ) { + // check if specified version is supported + final String fileName = FILE_FORMAT_SCHEMA_VERSIONS.get( version ); + + if ( fileName == null ) { + final String errorMsg = "File format version " + version.toString() + " is not supported!"; + LOGGER.debug( errorMsg ); + throw new VirtualizationConfigurationException( errorMsg ); + } else { + // specified version is supported, so validate document with corresponding schema file + final InputStream schemaResource = VirtualizationConfigurationVirtualboxFileFormat + .getSchemaResource( fileName ); + + if ( schemaResource != null ) { + try { + final SchemaFactory factory = SchemaFactory.newInstance( XMLConstants.W3C_XML_SCHEMA_NS_URI ); + final Schema schema = factory.newSchema( new StreamSource( schemaResource ) ); + final Validator validator = schema.newValidator(); + validator.validate( new DOMSource( this.doc ) ); + } catch ( SAXException | IOException e ) { + final String errorMsg = "XML configuration is not a valid VirtualBox v" + version.toString() + + " configuration: " + e.getLocalizedMessage(); + LOGGER.debug( errorMsg ); + throw new VirtualizationConfigurationException( errorMsg ); + } + } + } + } + } + + private static InputStream getSchemaResource( String fileName ) + { + final String schemaFilePath = FILE_FORMAT_SCHEMA_PREFIX_PATH + File.separator + fileName; + return VirtualizationConfigurationVirtualboxFileFormat.class.getResourceAsStream( schemaFilePath ); } /** * Main initialization functions parsing the document created during the constructor. - * @throws UnsupportedVirtualizerFormatException + * @throws VirtualizationConfigurationException */ - private void init() throws UnsupportedVirtualizerFormatException + private void init() throws VirtualizationConfigurationException { + try { + this.validate(); + } catch ( VirtualizationConfigurationException e ) { + // do not print output of failed validation if placeholders are available + // since thoses placeholder values violate the defined UUID pattern + if ( !this.checkForPlaceholders() ) { + final String errorMsg = "XML configuration is not a valid VirtualBox v" + version.toString() + + " configuration: " + e.getLocalizedMessage(); + LOGGER.debug( errorMsg ); + } + } + if ( Util.isEmptyString( getDisplayName() ) ) { - throw new UnsupportedVirtualizerFormatException( "Machine doesn't have a name" ); + throw new VirtualizationConfigurationException( "Machine doesn't have a name" ); } try { ensureHardwareUuid(); @@ -154,6 +231,33 @@ public class VboxConfig } } + private void parseConfigurationVersion() throws VirtualizationConfigurationException + { + String versionText; + try { + versionText = XmlHelper.compileXPath( "/VirtualBox/@version" ).evaluate( this.doc ); + } catch ( XPathExpressionException e ) { + throw new VirtualizationConfigurationException( + "Failed to parse the version number of the configuration file" ); + } + + if ( versionText == null || versionText.isEmpty() ) { + throw new VirtualizationConfigurationException( "Configuration file does not contain any version number!" ); + } else { + // parse version information from textual description + final Pattern versionPattern = Pattern.compile( "^(\\d+\\.\\d+).*$" ); + final Matcher versionMatcher = versionPattern.matcher( versionText ); + + if ( versionMatcher.find() ) { + this.version = Version.valueOf( versionMatcher.group( 1 ) ); + } + + if ( this.version == null ) { + throw new VirtualizationConfigurationException( "Configuration file version number is not valid!" ); + } + } + } + private void fixUsb() { NodeList list = findNodes( "/VirtualBox/Machine/Hardware/USB/Controllers/Controller" ); @@ -186,21 +290,21 @@ public class VboxConfig * believing in a hardware change. * * @throws XPathExpressionException - * @throws UnsupportedVirtualizerFormatException + * @throws VirtualizationConfigurationException */ - private void ensureHardwareUuid() throws XPathExpressionException, UnsupportedVirtualizerFormatException + private void ensureHardwareUuid() throws XPathExpressionException, VirtualizationConfigurationException { // we will need the machine uuid, so get it - String machineUuid = XmlHelper.XPath.compile( "/VirtualBox/Machine/@uuid" ).evaluate( this.doc ); + String machineUuid = XmlHelper.compileXPath( "/VirtualBox/Machine/@uuid" ).evaluate( this.doc ); if ( machineUuid.isEmpty() ) { LOGGER.error( "Machine UUID empty, should never happen!" ); - throw new UnsupportedVirtualizerFormatException( "XML doesn't contain a machine uuid" ); + throw new VirtualizationConfigurationException( "XML doesn't contain a machine uuid" ); } NodeList hwNodes = findNodes( "/VirtualBox/Machine/Hardware" ); int count = hwNodes.getLength(); if ( count != 1 ) { - throw new UnsupportedVirtualizerFormatException( "Zero or more '/VirtualBox/Machine/Hardware' node were found, should never happen!" ); + throw new VirtualizationConfigurationException( "Zero or more '/VirtualBox/Machine/Hardware' node were found, should never happen!" ); } Element hw = (Element)hwNodes.item( 0 ); String hwUuid = hw.getAttribute( "uuid" ); @@ -216,6 +320,11 @@ public class VboxConfig } } + public Version getVersion() + { + return this.version; + } + /** * Self-explanatory. */ @@ -243,7 +352,14 @@ public class VboxConfig continue; String hddUuid = hdd.getAttribute( "uuid" ); hdd.setAttribute( "uuid", PlaceHolder.HDDUUID.toString() + i + "%" ); - NodeList images = findNodes( "/VirtualBox/Machine/StorageControllers/StorageController/AttachedDevice/Image" ); + final NodeList images; + if ( this.getVersion().isSmallerThan( Version.valueOf( "1.17" ) ) ) { + images = findNodes( "/VirtualBox/Machine/StorageControllers/StorageController/AttachedDevice/Image" ); + } else { + images = findNodes( + "/VirtualBox/Machine/Hardware/StorageControllers/StorageController/AttachedDevice/Image" ); + } + for ( int j = 0; j < images.getLength(); j++ ) { Element image = (Element)images.item( j ); if ( image == null ) @@ -286,7 +402,7 @@ public class VboxConfig { // iterate over the blackList for ( String blackedTag : blacklist ) { - XPathExpression blackedExpr = XmlHelper.XPath.compile( blackedTag ); + XPathExpression blackedExpr = XmlHelper.compileXPath( blackedTag ); NodeList blackedNodes = (NodeList)blackedExpr.evaluate( this.doc, XPathConstants.NODESET ); for ( int i = 0; i < blackedNodes.getLength(); i++ ) { // go through the child nodes of the blacklisted ones -> why? @@ -304,7 +420,7 @@ public class VboxConfig public String getDisplayName() { try { - return XmlHelper.XPath.compile( "/VirtualBox/Machine/@name" ).evaluate( this.doc ); + return XmlHelper.compileXPath( "/VirtualBox/Machine/@name" ).evaluate( this.doc ); } catch ( XPathExpressionException e ) { return ""; } @@ -313,11 +429,11 @@ public class VboxConfig /** * Function finds and saves the name of the guest OS * - * @throws XPathExpressionException + * @throws XPathExpressionException failed to find and retrieve name of the guest OS. */ public void setOsType() throws XPathExpressionException { - String os = XmlHelper.XPath.compile( "/VirtualBox/Machine/@OSType" ).evaluate( this.doc ); + String os = XmlHelper.compileXPath( "/VirtualBox/Machine/@OSType" ).evaluate( this.doc ); if ( os != null && !os.isEmpty() ) { osName = os; } @@ -336,11 +452,19 @@ public class VboxConfig /** * Search for attached hard drives and determine their controller and their path. * - * @throws XPathExpressionException + * @throws XPathExpressionException failed to find attached hard drives and their controllers. */ public void setHdds() throws XPathExpressionException { - XPathExpression hddsExpr = XmlHelper.XPath.compile( "/VirtualBox/Machine/StorageControllers/StorageController/AttachedDevice[@type='HardDisk']/Image" ); + final XPathExpression hddsExpr; + if ( this.getVersion().isSmallerThan( Version.valueOf( "1.17" ) ) ) { + hddsExpr = XmlHelper.compileXPath( + "/VirtualBox/Machine/StorageControllers/StorageController/AttachedDevice[@type='HardDisk']/Image" ); + } else { + hddsExpr = XmlHelper.compileXPath( + "/VirtualBox/Machine/Hardware/StorageControllers/StorageController/AttachedDevice[@type='HardDisk']/Image" ); + } + NodeList nodes = (NodeList)hddsExpr.evaluate( this.doc, XPathConstants.NODESET ); if ( nodes == null ) { LOGGER.error( "Failed to find attached hard drives." ); @@ -354,7 +478,7 @@ public class VboxConfig if ( uuid.isEmpty() ) continue; // got uuid, check if it was registered - XPathExpression hddsRegistered = XmlHelper.XPath.compile( "/VirtualBox/Machine/MediaRegistry/HardDisks/HardDisk[@uuid='" + uuid + "']" ); + XPathExpression hddsRegistered = XmlHelper.compileXPath( "/VirtualBox/Machine/MediaRegistry/HardDisks/HardDisk[@uuid='" + uuid + "']" ); NodeList hddsRegisteredNodes = (NodeList)hddsRegistered.evaluate( this.doc, XPathConstants.NODESET ); if ( hddsRegisteredNodes == null || hddsRegisteredNodes.getLength() != 1 ) { LOGGER.error( "Found hard disk with uuid '" + uuid + "' which does not appear (unique) in the Media Registry. Skipping." ); @@ -433,7 +557,7 @@ public class VboxConfig { NodeList nodes = null; try { - XPathExpression expr = XmlHelper.XPath.compile( xpath ); + XPathExpression expr = XmlHelper.compileXPath( xpath ); Object nodesObject = expr.evaluate( this.doc, XPathConstants.NODESET ); nodes = (NodeList)nodesObject; } catch ( XPathExpressionException e ) { @@ -452,6 +576,7 @@ public class VboxConfig * @param elementXPath given as an xpath expression * @param attribute attribute to change * @param value to set the attribute to + * @return state of the change operation whether the attribute was changed successful or not. */ public boolean changeAttribute( String elementXPath, String attribute, String value ) { @@ -491,7 +616,7 @@ public class VboxConfig * Adds a new node named nameOfNewNode to the given parent found by parentXPath. * * @param parentXPath XPath expression to the parent - * @param nameOfnewNode name of the node to be added + * @param childName name of the node to be added * @return the newly added Node */ public Node addNewNode( String parentXPath, String childName ) @@ -539,13 +664,19 @@ public class VboxConfig public void setExtraData( String key, String value ) { - NodeList nl = findNodes( "/VirtualBox/Machine/ExtraData/ExtraDataItem[@name='" + key + "']" ); + NodeList nl = findNodes( "/VirtualBox/Machine/ExtraData/ExtraDataItem" ); Element e = null; - for ( int i = 0; i < nl.getLength(); ++i ) { - Node n = nl.item( i ); - if ( n.getNodeType() == Node.ELEMENT_NODE ) { - e = (Element)n; - break; + if ( nl != null ) { + for ( int i = 0; i < nl.getLength(); ++i ) { + Node n = nl.item( i ); + if ( n.getNodeType() == Node.ELEMENT_NODE ) { + final Element ne = (Element)n; + final String keyValue = ne.getAttribute( "name" ); + if ( keyValue != null && keyValue.equals( key ) ) { + e = ne; + break; + } + } } } if ( e == null ) { diff --git a/src/main/java/org/openslx/vm/VmwareMetaData.java b/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationVmware.java index 9bbe581..39aaae5 100644 --- a/src/main/java/org/openslx/vm/VmwareMetaData.java +++ b/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationVmware.java @@ -1,10 +1,8 @@ -package org.openslx.vm; +package org.openslx.virtualization.configuration; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -14,12 +12,11 @@ import java.util.regex.Pattern; 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.Util; -import org.openslx.vm.VmwareConfig.ConfigEntry; -import org.openslx.vm.disk.DiskImage; -import org.openslx.vm.disk.DiskImage.ImageFormat; +import org.openslx.virtualization.Version; +import org.openslx.virtualization.configuration.VirtualizationConfigurationVmwareFileFormat.ConfigEntry; +import org.openslx.virtualization.virtualizer.VirtualizerVmware; class VmWareSoundCardMeta { @@ -43,16 +40,6 @@ class VmWareDDAccelMeta } } -class VmWareHWVersionMeta -{ - public final int version; - - public VmWareHWVersionMeta( int vers ) - { - version = vers; - } -} - class VmWareEthernetDevTypeMeta { public final String value; @@ -67,7 +54,7 @@ class VmwareUsbSpeed { public final String keyName; public final int speedNumeric; - + public VmwareUsbSpeed( int speed, String key ) { this.keyName = key == null ? null : ( key + ".present" ); @@ -75,30 +62,32 @@ class VmwareUsbSpeed } } -public class VmwareMetaData extends VmMetaData<VmWareSoundCardMeta, VmWareDDAccelMeta, VmWareHWVersionMeta, VmWareEthernetDevTypeMeta, VmwareUsbSpeed> +public class VirtualizationConfigurationVmware extends + VirtualizationConfiguration<VmWareSoundCardMeta, VmWareDDAccelMeta, VmWareEthernetDevTypeMeta, VmwareUsbSpeed> { /** - * List of supported image formats by the VMware hypervisor. + * File name extension for VMware virtualization configuration files. */ - private static final List<DiskImage.ImageFormat> SUPPORTED_IMAGE_FORMATS = Collections.unmodifiableList( - Arrays.asList( ImageFormat.VMDK ) ); - - private static final Logger LOGGER = Logger.getLogger( VmwareMetaData.class ); + public static final String FILE_NAME_EXTENSION = "vmx"; - private static final Virtualizer virtualizer = new Virtualizer( TConst.VIRT_VMWARE, "VMware" ); + private static final Logger LOGGER = Logger.getLogger( VirtualizationConfigurationVmware.class ); - private static final Pattern hddKey = Pattern.compile( "^(ide\\d|scsi\\d|sata\\d|nvme\\d):?(\\d)?\\.(.*)", Pattern.CASE_INSENSITIVE ); + private static final Pattern hddKey = Pattern.compile( "^(ide\\d|scsi\\d|sata\\d|nvme\\d):?(\\d)?\\.(.*)", + Pattern.CASE_INSENSITIVE ); // Lowercase list of allowed settings for upload (as regex) private static final Pattern[] whitelist; - private final VmwareConfig config; + private final VirtualizationConfigurationVmwareFileFormat config; // Init static members static { - String[] list = { "^guestos", "^uuid\\.bios", "^config\\.version", "^ehci[.:]", "^mks\\.enable3d", "^virtualhw\\.", - "^sound[.:]", "\\.pcislotnumber$", "^pcibridge", "\\.virtualdev$", "^tools\\.syncTime$", "^time\\.synchronize", - "^bios\\.bootDelay", "^rtc\\.", "^xhci[.:]", "^usb_xhci[.:]", "\\.deviceType$", "\\.port$", "\\.parent$", "^usb[.:]", + String[] list = { "^guestos", "^uuid\\.bios", "^config\\.version", "^ehci[.:]", "^mks\\.enable3d", + "^virtualhw\\.", + "^sound[.:]", "\\.pcislotnumber$", "^pcibridge", "\\.virtualdev$", "^tools\\.syncTime$", + "^time\\.synchronize", + "^bios\\.bootDelay", "^rtc\\.", "^xhci[.:]", "^usb_xhci[.:]", "\\.deviceType$", "\\.port$", "\\.parent$", + "^usb[.:]", "^firmware", "^hpet", "^vm\\.genid" }; whitelist = new Pattern[ list.length ]; for ( int i = 0; i < list.length; ++i ) { @@ -120,24 +109,24 @@ public class VmwareMetaData extends VmMetaData<VmWareSoundCardMeta, VmWareDDAcce private final Map<String, Controller> disks = new HashMap<>(); - public VmwareMetaData( List<OperatingSystem> osList, File file ) throws IOException, UnsupportedVirtualizerFormatException + public VirtualizationConfigurationVmware( List<OperatingSystem> osList, File file ) + throws IOException, VirtualizationConfigurationException { - super( osList ); - this.config = new VmwareConfig( file ); + super( new VirtualizerVmware(), osList ); + this.config = new VirtualizationConfigurationVmwareFileFormat( file ); init(); } - public VmwareMetaData( List<OperatingSystem> osList, byte[] vmxContent, int length ) throws UnsupportedVirtualizerFormatException + public VirtualizationConfigurationVmware( List<OperatingSystem> osList, byte[] vmxContent, int length ) + throws VirtualizationConfigurationException { - super( osList ); - this.config = new VmwareConfig( vmxContent, length ); // still unfiltered + super( new VirtualizerVmware(), osList ); + this.config = new VirtualizationConfigurationVmwareFileFormat( vmxContent, length ); // still unfiltered init(); // now filtered } private void init() { - registerVirtualHW(); - for ( Entry<String, ConfigEntry> entry : config.entrySet() ) { handleLoadEntry( entry ); } @@ -257,11 +246,11 @@ public class VmwareMetaData extends VmMetaData<VmWareSoundCardMeta, VmWareDDAcce } @Override - public List<DiskImage.ImageFormat> getSupportedImageFormats() + public boolean addEmptyHddTemplate() { - return VmwareMetaData.SUPPORTED_IMAGE_FORMATS; + return this.addHddTemplate( "%VM_DISK_PATH%", "%VM_DISK_MODE%", "%VM_DISK_REDOLOGDIR%" ); } - + @Override public boolean addHddTemplate( File diskImage, String hddMode, String redoDir ) { @@ -275,6 +264,7 @@ public class VmwareMetaData extends VmMetaData<VmWareSoundCardMeta, VmWareDDAcce LOGGER.error( "Empty disk image path given!" ); return false; } + DriveBusType bus; try { bus = DriveBusType.valueOf( config.get( "#SLX_HDD_BUS" ) ); @@ -324,7 +314,7 @@ public class VmwareMetaData extends VmMetaData<VmWareSoundCardMeta, VmWareDDAcce return true; } - public boolean addEthernet( VmMetaData.EtherType type ) + public boolean addEthernet( VirtualizationConfiguration.EtherType type ) { boolean ret = false; int index = 0; @@ -414,10 +404,9 @@ public class VmwareMetaData extends VmMetaData<VmWareSoundCardMeta, VmWareDDAcce } @Override - public boolean tweakForNonPersistent() + public void transformNonPersistent() throws VirtualizationConfigurationException { addFiltered( "suspend.disabled", "TRUE" ); - return true; } @Override @@ -437,24 +426,15 @@ public class VmwareMetaData extends VmMetaData<VmWareSoundCardMeta, VmWareDDAcce public void setOs( String vendorOsId ) { addFiltered( "guestOS", vendorOsId ); - setOs( TConst.VIRT_VMWARE, vendorOsId ); - } - - @Override - public byte[] getFilteredDefinitionArray() - { - return config.toString( true, false ).getBytes( StandardCharsets.UTF_8 ); - } - public byte[] getDefinitionArray() - { - return config.toString( false, false ).getBytes( StandardCharsets.UTF_8 ); + final OperatingSystem os = VirtualizationConfigurationUtils.getOsOfVirtualizerFromList( this.osList, + TConst.VIRT_VMWARE, vendorOsId ); + this.setOs( os ); } - @Override - public Virtualizer getVirtualizer() + public byte[] getConfigurationAsByteArray() { - return virtualizer; + return config.toString( true, false ).getBytes( StandardCharsets.UTF_8 ); } private static class Device @@ -484,7 +464,7 @@ public class VmwareMetaData extends VmMetaData<VmWareSoundCardMeta, VmWareDDAcce } @Override - public void applySettingsForLocalEdit() + public void transformEditable() throws VirtualizationConfigurationException { addFiltered( "gui.applyHostDisplayScalingToGuest", "FALSE" ); } @@ -494,7 +474,7 @@ public class VmwareMetaData extends VmMetaData<VmWareSoundCardMeta, VmWareDDAcce return config.get( key ); } - public void setSoundCard( VmMetaData.SoundCardType type ) + public void setSoundCard( VirtualizationConfiguration.SoundCardType type ) { VmWareSoundCardMeta soundCardMeta = soundCards.get( type ); addFiltered( "sound.present", vmBoolean( soundCardMeta.isPresent ) ); @@ -505,15 +485,15 @@ public class VmwareMetaData extends VmMetaData<VmWareSoundCardMeta, VmWareDDAcce } } - public VmMetaData.SoundCardType getSoundCard() + public VirtualizationConfiguration.SoundCardType getSoundCard() { if ( !isSetAndTrue( "sound.present" ) || !isSetAndTrue( "sound.autodetect" ) ) { - return VmMetaData.SoundCardType.NONE; + return VirtualizationConfiguration.SoundCardType.NONE; } String current = config.get( "sound.virtualDev" ); if ( current != null ) { VmWareSoundCardMeta soundCardMeta = null; - for ( VmMetaData.SoundCardType type : VmMetaData.SoundCardType.values() ) { + for ( VirtualizationConfiguration.SoundCardType type : VirtualizationConfiguration.SoundCardType.values() ) { soundCardMeta = soundCards.get( type ); if ( soundCardMeta != null ) { if ( current.equals( soundCardMeta.value ) ) { @@ -522,47 +502,36 @@ public class VmwareMetaData extends VmMetaData<VmWareSoundCardMeta, VmWareDDAcce } } } - return VmMetaData.SoundCardType.DEFAULT; + return VirtualizationConfiguration.SoundCardType.DEFAULT; } - public void setDDAcceleration( VmMetaData.DDAcceleration type ) + public void setDDAcceleration( VirtualizationConfiguration.DDAcceleration type ) { VmWareDDAccelMeta ddaMeta = ddacc.get( type ); addFiltered( "mks.enable3d", vmBoolean( ddaMeta.isPresent ) ); } - public VmMetaData.DDAcceleration getDDAcceleration() + public VirtualizationConfiguration.DDAcceleration getDDAcceleration() { if ( isSetAndTrue( "mks.enable3d" ) ) { - return VmMetaData.DDAcceleration.ON; + return VirtualizationConfiguration.DDAcceleration.ON; } else { - return VmMetaData.DDAcceleration.OFF; + return VirtualizationConfiguration.DDAcceleration.OFF; } } - public void setHWVersion( VmMetaData.HWVersion type ) + public void setVirtualizerVersion( Version type ) { - VmWareHWVersionMeta hwVersionMeta = hwversion.get( type ); - addFiltered( "virtualHW.version", vmInteger( hwVersionMeta.version ) ); + addFiltered( "virtualHW.version", vmInteger( type.getMajor() ) ); } - public VmMetaData.HWVersion getHWVersion() + public Version getVirtualizerVersion() { - int currentValue = Util.parseInt( config.get( "virtualHW.version" ), -1 ); - VmWareHWVersionMeta hwVersionMeta = null; - for ( VmMetaData.HWVersion ver : VmMetaData.HWVersion.values() ) { - hwVersionMeta = hwversion.get( ver ); - if ( hwVersionMeta == null ) { - continue; - } - if ( currentValue == hwVersionMeta.version ) { - return ver; - } - } - return HWVersion.NONE; + final short major = Integer.valueOf( Util.parseInt( config.get( "virtualHW.version" ), -1 ) ).shortValue(); + return Version.getInstanceByMajorFromVersions( major, this.getVirtualizer().getSupportedVersions() ); } - public void setEthernetDevType( int cardIndex, VmMetaData.EthernetDevType type ) + public void setEthernetDevType( int cardIndex, VirtualizationConfiguration.EthernetDevType type ) { VmWareEthernetDevTypeMeta ethernetDevTypeMeta = networkCards.get( type ); if ( ethernetDevTypeMeta.value != null ) { @@ -572,12 +541,13 @@ public class VmwareMetaData extends VmMetaData<VmWareSoundCardMeta, VmWareDDAcce } } - public VmMetaData.EthernetDevType getEthernetDevType( int cardIndex ) + public VirtualizationConfiguration.EthernetDevType getEthernetDevType( int cardIndex ) { String temp = config.get( "ethernet" + cardIndex + ".virtualDev" ); if ( temp != null ) { VmWareEthernetDevTypeMeta ethernetDevTypeMeta = null; - for ( VmMetaData.EthernetDevType type : VmMetaData.EthernetDevType.values() ) { + for ( VirtualizationConfiguration.EthernetDevType type : VirtualizationConfiguration.EthernetDevType + .values() ) { ethernetDevTypeMeta = networkCards.get( type ); if ( ethernetDevTypeMeta == null ) { continue; @@ -587,14 +557,14 @@ public class VmwareMetaData extends VmMetaData<VmWareSoundCardMeta, VmWareDDAcce } } } - return VmMetaData.EthernetDevType.AUTO; + return VirtualizationConfiguration.EthernetDevType.AUTO; } @Override - public void setMaxUsbSpeed( VmMetaData.UsbSpeed newSpeed ) + public void setMaxUsbSpeed( VirtualizationConfiguration.UsbSpeed newSpeed ) { if ( newSpeed == null ) { - newSpeed = VmMetaData.UsbSpeed.NONE; + newSpeed = VirtualizationConfiguration.UsbSpeed.NONE; } VmwareUsbSpeed newSpeedMeta = usbSpeeds.get( newSpeed ); if ( newSpeedMeta == null ) { @@ -620,11 +590,11 @@ public class VmwareMetaData extends VmMetaData<VmWareSoundCardMeta, VmWareDDAcce } @Override - public VmMetaData.UsbSpeed getMaxUsbSpeed() + public VirtualizationConfiguration.UsbSpeed getMaxUsbSpeed() { int max = 0; - VmMetaData.UsbSpeed maxEnum = VmMetaData.UsbSpeed.NONE; - for ( Entry<VmMetaData.UsbSpeed, VmwareUsbSpeed> entry : usbSpeeds.entrySet() ) { + VirtualizationConfiguration.UsbSpeed maxEnum = VirtualizationConfiguration.UsbSpeed.NONE; + for ( Entry<VirtualizationConfiguration.UsbSpeed, VmwareUsbSpeed> entry : usbSpeeds.entrySet() ) { VmwareUsbSpeed v = entry.getValue(); if ( v.speedNumeric > max && isSetAndTrue( v.keyName ) ) { max = v.speedNumeric; @@ -638,47 +608,49 @@ public class VmwareMetaData extends VmMetaData<VmWareSoundCardMeta, VmWareDDAcce public boolean addCpuCoreCount( int numCores ) { // TODO actually add the cpu core count to the machine description - return false; + return true; + } + + @Override + public void transformPrivacy() throws VirtualizationConfigurationException + { } public void registerVirtualHW() { - soundCards.put( VmMetaData.SoundCardType.NONE, new VmWareSoundCardMeta( false, null ) ); - soundCards.put( VmMetaData.SoundCardType.DEFAULT, new VmWareSoundCardMeta( true, null ) ); - soundCards.put( VmMetaData.SoundCardType.SOUND_BLASTER, new VmWareSoundCardMeta( true, "sb16" ) ); - soundCards.put( VmMetaData.SoundCardType.ES, new VmWareSoundCardMeta( true, "es1371" ) ); - soundCards.put( VmMetaData.SoundCardType.HD_AUDIO, new VmWareSoundCardMeta( true, "hdaudio" ) ); - - ddacc.put( VmMetaData.DDAcceleration.OFF, new VmWareDDAccelMeta( false ) ); - ddacc.put( VmMetaData.DDAcceleration.ON, new VmWareDDAccelMeta( true ) ); - - hwversion.put( VmMetaData.HWVersion.NONE, new VmWareHWVersionMeta( 0 ) ); - hwversion.put( VmMetaData.HWVersion.THREE, new VmWareHWVersionMeta( 3 ) ); - hwversion.put( VmMetaData.HWVersion.FOUR, new VmWareHWVersionMeta( 4 ) ); - hwversion.put( VmMetaData.HWVersion.SIX, new VmWareHWVersionMeta( 6 ) ); - hwversion.put( VmMetaData.HWVersion.SEVEN, new VmWareHWVersionMeta( 7 ) ); - hwversion.put( VmMetaData.HWVersion.EIGHT, new VmWareHWVersionMeta( 8 ) ); - hwversion.put( VmMetaData.HWVersion.NINE, new VmWareHWVersionMeta( 9 ) ); - hwversion.put( VmMetaData.HWVersion.TEN, new VmWareHWVersionMeta( 10 ) ); - hwversion.put( VmMetaData.HWVersion.ELEVEN, new VmWareHWVersionMeta( 11 ) ); - hwversion.put( VmMetaData.HWVersion.TWELVE, new VmWareHWVersionMeta( 12 ) ); - hwversion.put( VmMetaData.HWVersion.FOURTEEN, new VmWareHWVersionMeta( 14 ) ); - hwversion.put( VmMetaData.HWVersion.FIFTEEN, new VmWareHWVersionMeta( 15 ) ); - hwversion.put( VmMetaData.HWVersion.FIFTEEN_ONE, new VmWareHWVersionMeta( 16 ) ); - hwversion.put( VmMetaData.HWVersion.SIXTEEN, new VmWareHWVersionMeta( 17 ) ); - hwversion.put( VmMetaData.HWVersion.SIXTEEN_ONE, new VmWareHWVersionMeta( 18 ) ); - - networkCards.put( VmMetaData.EthernetDevType.AUTO, new VmWareEthernetDevTypeMeta( null ) ); - networkCards.put( VmMetaData.EthernetDevType.PCNET32, new VmWareEthernetDevTypeMeta( "vlance" ) ); - networkCards.put( VmMetaData.EthernetDevType.E1000, new VmWareEthernetDevTypeMeta( "e1000" ) ); - networkCards.put( VmMetaData.EthernetDevType.E1000E, new VmWareEthernetDevTypeMeta( "e1000e" ) ); - networkCards.put( VmMetaData.EthernetDevType.VMXNET, new VmWareEthernetDevTypeMeta( "vmxnet" ) ); - networkCards.put( VmMetaData.EthernetDevType.VMXNET3, new VmWareEthernetDevTypeMeta( "vmxnet3" ) ); - - usbSpeeds.put( VmMetaData.UsbSpeed.NONE, new VmwareUsbSpeed( 0, null )); - usbSpeeds.put( VmMetaData.UsbSpeed.USB1_1, new VmwareUsbSpeed( 1, "usb" ) ); - usbSpeeds.put( VmMetaData.UsbSpeed.USB2_0, new VmwareUsbSpeed( 2, "ehci" ) ); - usbSpeeds.put( VmMetaData.UsbSpeed.USB3_0, new VmwareUsbSpeed( 3, "usb_xhci" ) ); + soundCards.put( VirtualizationConfiguration.SoundCardType.NONE, new VmWareSoundCardMeta( false, null ) ); + soundCards.put( VirtualizationConfiguration.SoundCardType.DEFAULT, new VmWareSoundCardMeta( true, null ) ); + soundCards.put( VirtualizationConfiguration.SoundCardType.SOUND_BLASTER, + new VmWareSoundCardMeta( true, "sb16" ) ); + soundCards.put( VirtualizationConfiguration.SoundCardType.ES, new VmWareSoundCardMeta( true, "es1371" ) ); + soundCards.put( VirtualizationConfiguration.SoundCardType.HD_AUDIO, new VmWareSoundCardMeta( true, "hdaudio" ) ); + + ddacc.put( VirtualizationConfiguration.DDAcceleration.OFF, new VmWareDDAccelMeta( false ) ); + ddacc.put( VirtualizationConfiguration.DDAcceleration.ON, new VmWareDDAccelMeta( true ) ); + + networkCards.put( VirtualizationConfiguration.EthernetDevType.AUTO, new VmWareEthernetDevTypeMeta( null ) ); + networkCards.put( VirtualizationConfiguration.EthernetDevType.PCNET32, + new VmWareEthernetDevTypeMeta( "vlance" ) ); + networkCards.put( VirtualizationConfiguration.EthernetDevType.E1000, new VmWareEthernetDevTypeMeta( "e1000" ) ); + networkCards.put( VirtualizationConfiguration.EthernetDevType.E1000E, new VmWareEthernetDevTypeMeta( "e1000e" ) ); + networkCards.put( VirtualizationConfiguration.EthernetDevType.VMXNET, new VmWareEthernetDevTypeMeta( "vmxnet" ) ); + networkCards.put( VirtualizationConfiguration.EthernetDevType.VMXNET3, + new VmWareEthernetDevTypeMeta( "vmxnet3" ) ); + + usbSpeeds.put( VirtualizationConfiguration.UsbSpeed.NONE, new VmwareUsbSpeed( 0, null ) ); + usbSpeeds.put( VirtualizationConfiguration.UsbSpeed.USB1_1, new VmwareUsbSpeed( 1, "usb" ) ); + usbSpeeds.put( VirtualizationConfiguration.UsbSpeed.USB2_0, new VmwareUsbSpeed( 2, "ehci" ) ); + usbSpeeds.put( VirtualizationConfiguration.UsbSpeed.USB3_0, new VmwareUsbSpeed( 3, "usb_xhci" ) ); + } + + @Override + public String getFileNameExtension() + { + return VirtualizationConfigurationVmware.FILE_NAME_EXTENSION; } + @Override + public void validate() throws VirtualizationConfigurationException + { + } } diff --git a/src/main/java/org/openslx/vm/VmwareConfig.java b/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationVmwareFileFormat.java index d98a1d4..24df02f 100644 --- a/src/main/java/org/openslx/vm/VmwareConfig.java +++ b/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationVmwareFileFormat.java @@ -1,4 +1,4 @@ -package org.openslx.vm; +package org.openslx.virtualization.configuration; import java.io.BufferedReader; import java.io.ByteArrayInputStream; @@ -19,19 +19,31 @@ import java.util.regex.Pattern; import org.apache.log4j.Logger; import org.openslx.util.Util; -public class VmwareConfig +class KeyValuePair { + public final String key; + public final String value; - private static final Logger LOGGER = Logger.getLogger( VmwareConfig.class ); + public KeyValuePair( String key, String value ) + { + this.key = key; + this.value = value; + } +} + +public class VirtualizationConfigurationVmwareFileFormat +{ + + private static final Logger LOGGER = Logger.getLogger( VirtualizationConfigurationVmwareFileFormat.class ); private Map<String, ConfigEntry> entries = new TreeMap<>( String.CASE_INSENSITIVE_ORDER ); - public VmwareConfig() + public VirtualizationConfigurationVmwareFileFormat() { // (void) } - public VmwareConfig( File file ) throws IOException, UnsupportedVirtualizerFormatException + public VirtualizationConfigurationVmwareFileFormat( File file ) throws IOException, VirtualizationConfigurationException { int todo = (int)Math.min( 100000, file.length() ); int offset = 0; @@ -53,7 +65,7 @@ public class VmwareConfig } - public VmwareConfig( InputStream is ) throws IOException, UnsupportedVirtualizerFormatException + public VirtualizationConfigurationVmwareFileFormat( InputStream is ) throws IOException, VirtualizationConfigurationException { int todo = Math.max( 4000, Math.min( 100000, is.available() ) ); int offset = 0; @@ -68,13 +80,13 @@ public class VmwareConfig init( data, offset ); } - public VmwareConfig( byte[] vmxContent, int length ) throws UnsupportedVirtualizerFormatException + public VirtualizationConfigurationVmwareFileFormat( byte[] vmxContent, int length ) throws VirtualizationConfigurationException { init( vmxContent, length ); } // function is used for both .vmx and .vmdk files - private void init( byte[] vmxContent, int length ) throws UnsupportedVirtualizerFormatException + private void init( byte[] vmxContent, int length ) throws VirtualizationConfigurationException { try { boolean isValid = false; @@ -94,7 +106,7 @@ public class VmwareConfig } } if ( !isValid ) { - throw new UnsupportedVirtualizerFormatException( "Not in VMX format." ); + throw new VirtualizationConfigurationException( "Not in VMX format." ); } } catch ( IOException e ) { LOGGER.warn( "Exception when loading vmx from byte array (how!?)", e ); diff --git a/src/main/java/org/openslx/virtualization/configuration/data/ConfigurationDataDozModClientToDozModServer.java b/src/main/java/org/openslx/virtualization/configuration/data/ConfigurationDataDozModClientToDozModServer.java new file mode 100644 index 0000000..8a08d05 --- /dev/null +++ b/src/main/java/org/openslx/virtualization/configuration/data/ConfigurationDataDozModClientToDozModServer.java @@ -0,0 +1,21 @@ +package org.openslx.virtualization.configuration.data; + +/** + * Data container to collect and store input arguments for a + * {@link org.openslx.virtualization.configuration.logic.ConfigurationLogicDozModClientToDozModServer} + * transformation. + * + * @author Manuel Bentele + * @version 1.0 + */ +public class ConfigurationDataDozModClientToDozModServer +{ + /** + * Creates a new data container to collect and store input arguments for a + * {@link org.openslx.virtualization.configuration.logic.ConfigurationLogicDozModClientToDozModServer} + * transformation. + */ + public ConfigurationDataDozModClientToDozModServer() + { + } +} diff --git a/src/main/java/org/openslx/virtualization/configuration/data/ConfigurationDataDozModServerToDozModClient.java b/src/main/java/org/openslx/virtualization/configuration/data/ConfigurationDataDozModServerToDozModClient.java new file mode 100644 index 0000000..4e18d48 --- /dev/null +++ b/src/main/java/org/openslx/virtualization/configuration/data/ConfigurationDataDozModServerToDozModClient.java @@ -0,0 +1,116 @@ +package org.openslx.virtualization.configuration.data; + +import java.io.File; + +import org.openslx.bwlp.thrift.iface.OperatingSystem; + +/** + * Data container to collect and store input arguments for a + * {@link org.openslx.virtualization.configuration.logic.ConfigurationLogicDozModServerToDozModClient} + * transformation. + * + * @author Manuel Bentele + * @version 1.0 + */ +public class ConfigurationDataDozModServerToDozModClient +{ + /** + * Display name for a transformation of a virtualization configuration. + */ + private final String displayName; + + /** + * Disk image file for a transformation of a virtualization configuration. + */ + private final File diskImage; + + /** + * Guest operating system for a transformation of a virtualization configuration. + */ + private final OperatingSystem guestOs; + + /** + * Virtualizer identifier for a transformation of a virtualization configuration. + */ + private final String virtualizerId; + + /** + * Total amount of available memory for a transformation of a virtualization configuration. + */ + private final int totalMemory; + + /** + * Creates a new data container to collect and store input arguments for a + * {@link org.openslx.virtualization.configuration.logic.ConfigurationLogicDozModServerToDozModClient} + * transformation. + * + * @param displayName display name for a transformation of a virtualization configuration. + * @param diskImage disk image file for a transformation of a virtualization configuration. + * @param guestOs guest operating system for a transformation of a virtualization configuration. + * @param virtualizerId virtualizer identifier for a transformation of a virtualization + * configuration. + * @param totalMemory total amount of available memory for a transformation of a virtualization + * configuration. + */ + public ConfigurationDataDozModServerToDozModClient( String displayName, File diskImage, OperatingSystem guestOs, + String virtualizerId, int totalMemory ) + { + this.displayName = displayName; + this.diskImage = diskImage; + this.guestOs = guestOs; + this.virtualizerId = virtualizerId; + this.totalMemory = totalMemory; + } + + /** + * Returns the display name for a transformation of a virtualization configuration. + * + * @return display name for a transformation of a virtualization configuration. + */ + public String getDisplayName() + { + return this.displayName; + } + + /** + * Returns the disk image file for a transformation of a virtualization configuration. + * + * @return disk image file for a transformation of a virtualization configuration. + */ + public File getDiskImage() + { + return this.diskImage; + } + + /** + * Returns the guest operating system for a transformation of a virtualization configuration. + * + * @return guest operating system for a transformation of a virtualization configuration. + */ + public OperatingSystem getGuestOs() + { + return this.guestOs; + } + + /** + * Returns the virtualizer identifier for a transformation of a virtualization configuration. + * + * @return virtualizer identifier for a transformation of a virtualization configuration. + */ + public String getVirtualizerId() + { + return this.virtualizerId; + } + + /** + * Returns the total amount of available memory for a transformation of a virtualization + * configuration. + * + * @return total amount of available memory for a transformation of a virtualization + * configuration. + */ + public int getTotalMemory() + { + return this.totalMemory; + } +} diff --git a/src/main/java/org/openslx/virtualization/configuration/data/ConfigurationDataDozModServerToStatelessClient.java b/src/main/java/org/openslx/virtualization/configuration/data/ConfigurationDataDozModServerToStatelessClient.java new file mode 100644 index 0000000..65cc7ce --- /dev/null +++ b/src/main/java/org/openslx/virtualization/configuration/data/ConfigurationDataDozModServerToStatelessClient.java @@ -0,0 +1,79 @@ +package org.openslx.virtualization.configuration.data; + +/** + * Data container to collect and store input arguments for a + * {@link org.openslx.virtualization.configuration.logic.ConfigurationLogicDozModServerToStatelessClient} + * transformation. + * + * @author Manuel Bentele + * @version 1.0 + */ +public class ConfigurationDataDozModServerToStatelessClient +{ + /** + * Display name for a transformation of a virtualization configuration. + */ + private final String displayName; + + /** + * Operating system identifier for a transformation of a virtualization configuration. + */ + private final String osId; + + /** + * State whether USB access is allowed or not for a transformation of a virtualization + * configuration. + */ + private final boolean hasUsbAccess; + + /** + * Creates a new data container to collect and store input arguments for a + * {@link org.openslx.virtualization.configuration.logic.ConfigurationLogicDozModServerToStatelessClient} + * transformation. + * + * @param displayName display name for a transformation of a virtualization configuration. + * @param osId operating system identifier for a transformation of a virtualization + * configuration. + * @param hasUsbAccess state whether USB access is allowed or not for a transformation of a + * virtualization configuration. + */ + public ConfigurationDataDozModServerToStatelessClient( String displayName, String osId, boolean hasUsbAccess ) + { + this.displayName = displayName; + this.osId = osId; + this.hasUsbAccess = hasUsbAccess; + } + + /** + * Returns the display name for a transformation of a virtualization configuration. + * + * @return display name for a transformation of a virtualization configuration. + */ + public String getDisplayName() + { + return this.displayName; + } + + /** + * Returns the operating system identifier for a transformation of a virtualization + * configuration. + * + * @return operating system identifier for a transformation of a virtualization configuration. + */ + public String getOsId() + { + return this.osId; + } + + /** + * Returns the state whether USB access is allowed or not for a transformation of a + * virtualization configuration. + * + * @return state whether USB access is allowed or not for a transformation of a virtualization + * configuration. + */ + public boolean hasUsbAccess() + { + return this.hasUsbAccess; + } +} diff --git a/src/main/java/org/openslx/virtualization/configuration/logic/ConfigurationLogic.java b/src/main/java/org/openslx/virtualization/configuration/logic/ConfigurationLogic.java new file mode 100644 index 0000000..018d046 --- /dev/null +++ b/src/main/java/org/openslx/virtualization/configuration/logic/ConfigurationLogic.java @@ -0,0 +1,28 @@ +package org.openslx.virtualization.configuration.logic; + +import org.openslx.virtualization.configuration.VirtualizationConfiguration; +import org.openslx.virtualization.configuration.transformation.TransformationGeneric; + +/** + * Generic transformation logic for virtualization configurations. + * <p> + * This transformation logic represents an encapsulated transformation logic to transform + * virtualization configurations as part of server or client implementations. + * + * @author Manuel Bentele + * @version 1.0 + * + * @param <T> type of configuration data used as input arguments for a transformation. + */ +public abstract class ConfigurationLogic<T> extends TransformationGeneric<VirtualizationConfiguration<?, ?, ?, ?>, T> +{ + /** + * Creates a new generic transformation logic for virtualization configurations. + * + * @param name generic transformation logic name. + */ + public ConfigurationLogic( String name ) + { + super( name ); + } +} diff --git a/src/main/java/org/openslx/virtualization/configuration/logic/ConfigurationLogicDozModClientToDozModServer.java b/src/main/java/org/openslx/virtualization/configuration/logic/ConfigurationLogicDozModClientToDozModServer.java new file mode 100644 index 0000000..f375693 --- /dev/null +++ b/src/main/java/org/openslx/virtualization/configuration/logic/ConfigurationLogicDozModClientToDozModServer.java @@ -0,0 +1,76 @@ +package org.openslx.virtualization.configuration.logic; + +import org.openslx.virtualization.configuration.VirtualizationConfiguration; +import org.openslx.virtualization.configuration.VirtualizationConfigurationException; +import org.openslx.virtualization.configuration.data.ConfigurationDataDozModClientToDozModServer; +import org.openslx.virtualization.configuration.transformation.TransformationException; + +/** + * Transformation logic for virtualization configurations between a dozmod-client and a + * dozmod-server. + * <p> + * This transformation logic is applied while uploading a new virtualization configuration from a + * dozmod-client to a dozmod-server. + * + * <pre> + * +------------------------------+ DozModClientToDozModServer +------------------------------+ + * | virtualization configuration | ----------------------------â–¶ | virtualization configuration | + * +---------------+--------------+ transformation logic +---------------+--------------+ + * | dozmod-client | | dozmod-server | + * +---------------+ +---------------+ + * </pre> + * + * @author Manuel Bentele + * @version 1.0 + */ +public class ConfigurationLogicDozModClientToDozModServer + extends ConfigurationLogic<ConfigurationDataDozModClientToDozModServer> +{ + /** + * Name of the transformation logic for virtualization configurations. + */ + private static final String CONFIGURATION_LOGIC_NAME = "Transformation of virtualization configuration during upload from DozMod client to DozMod server"; + + /** + * Creates a new transformation logic for virtualization configurations between a dozmod-client + * and a dozmod-server. + */ + public ConfigurationLogicDozModClientToDozModServer() + { + super( ConfigurationLogicDozModClientToDozModServer.CONFIGURATION_LOGIC_NAME ); + } + + /** + * Validates a virtualization configuration and input arguments for a transformation. + * + * @param config virtualization configuration for the validation. + * @param args input arguments for the validation. + * @throws TransformationException validation has failed. + */ + private void validateInputs( VirtualizationConfiguration<?, ?, ?, ?> config, + ConfigurationDataDozModClientToDozModServer args ) + throws TransformationException + { + if ( config == null || args == null ) { + throw new TransformationException( "Virtualization configuration or input arguments are missing!" ); + } else if ( config.getDisplayName() == null ) { + throw new TransformationException( "Display name is missing in virtualization configuration!" ); + } + } + + @Override + public void transform( VirtualizationConfiguration<?, ?, ?, ?> config, + ConfigurationDataDozModClientToDozModServer args ) + throws TransformationException + { + // check if input parameters for a transformation are valid + this.validateInputs( config, args ); + + // apply the privacy filter on the given virtualization configuration + try { + config.transformPrivacy(); + } catch ( VirtualizationConfigurationException e ) { + throw new TransformationException( e.getLocalizedMessage() ); + } + } +} diff --git a/src/main/java/org/openslx/virtualization/configuration/logic/ConfigurationLogicDozModServerToDozModClient.java b/src/main/java/org/openslx/virtualization/configuration/logic/ConfigurationLogicDozModServerToDozModClient.java new file mode 100644 index 0000000..06c8ad1 --- /dev/null +++ b/src/main/java/org/openslx/virtualization/configuration/logic/ConfigurationLogicDozModServerToDozModClient.java @@ -0,0 +1,203 @@ +package org.openslx.virtualization.configuration.logic; + +import java.util.Map; + +import org.openslx.bwlp.thrift.iface.OperatingSystem; +import org.openslx.virtualization.configuration.VirtualizationConfiguration; +import org.openslx.virtualization.configuration.VirtualizationConfiguration.UsbSpeed; +import org.openslx.virtualization.configuration.VirtualizationConfigurationException; +import org.openslx.virtualization.configuration.data.ConfigurationDataDozModServerToDozModClient; +import org.openslx.virtualization.configuration.transformation.TransformationException; + +/** + * Transformation logic for virtualization configurations between a dozmod-server and a + * dozmod-client. + * <p> + * This transformation logic is applied while downloading an existing virtualization configuration + * from a dozmod-server to a dozmod-client. + * + * <pre> + * +------------------------------+ DozModServerToDozModClient +------------------------------+ + * | virtualization configuration | ----------------------------â–¶ | virtualization configuration | + * +---------------+--------------+ transformation logic +---------------+--------------+ + * | dozmod-server | | dozmod-client | + * +---------------+ +---------------+ + * </pre> + * + * @author Manuel Bentele + * @version 1.0 + */ +public class ConfigurationLogicDozModServerToDozModClient + extends ConfigurationLogic<ConfigurationDataDozModServerToDozModClient> +{ + /** + * Name of the transformation logic for virtualization configurations. + */ + private static final String CONFIGURATION_LOGIC_NAME = "Transformation of virtualization configuration during download from DozMod server to DozMod client"; + + /** + * Default number of CPU cores set by the configuration logic for the virtualization + * configuration's virtualizer. + */ + private static final int CONFIGURATION_LOGIC_NUM_CPU_CORES = 1; + + /** + * Default memory in megabytes set by the configuration logic for the virtualization + * configuration's virtualizer. + */ + private static final int CONFIGURATION_LOGIC_MEMORY_MIN = 1024; + + /** + * Creates a new transformation logic for virtualization configurations between a dozmod-server + * and a dozmod-client. + */ + public ConfigurationLogicDozModServerToDozModClient() + { + super( ConfigurationLogicDozModServerToDozModClient.CONFIGURATION_LOGIC_NAME ); + } + + /** + * Validates a virtualization configuration and input arguments for a transformation. + * + * @param config virtualization configuration for the validation. + * @param args input arguments for the validation. + * @throws TransformationException validation has failed. + */ + private void validateInputs( VirtualizationConfiguration<?, ?, ?, ?> config, + ConfigurationDataDozModServerToDozModClient args ) + throws TransformationException + { + if ( config == null || args == null ) { + throw new TransformationException( "Virtualization configuration or input arguments are missing!" ); + } else if ( args.getDisplayName() == null || args.getDisplayName().isEmpty() ) { + throw new TransformationException( "Valid display name is not specified!" ); + } else if ( args.getDiskImage() == null || !args.getDiskImage().exists() ) { + throw new TransformationException( "Valid disk image file is not specified!" ); + } else if ( ! ( args.getTotalMemory() > 0 ) ) { + throw new TransformationException( "Total memory amount is not specified!" ); + } + } + + /** + * Rounds a given value to the nearest factor. + * + * @param value input value for the rounding. + * @param nearestFactor nearest factor for the rounding. + * @return rounded value as a multiple of the nearest factor. + * + * @apiNote This utility method rounds the given value to an integer value and no to a floating + * point value. + */ + private static int roundToNearest( int value, int nearestFactor ) + { + return ( value / nearestFactor ) * nearestFactor; + } + + /** + * Calculates the amount of memory for the virtualization configuration depending on the + * available resources of the dozmod-client's host system. + * + * @param totalMemory maximum memory available on the dozmod-client's host system. + * @param osMaxMemory maximum memory supported by the defined operating system in the + * virtualization configuration. + * @return amount of memory for the virtualization configuration in megabytes + */ + private static int calculateVirtualizationMemoryOnDozmodClient( int totalMemory, int osMaxMemory ) + { + // calculate the amount of memory + int memory = totalMemory / 2 - 512; + + // increase calculated memory if lower memory limit is undercut + if ( memory < ConfigurationLogicDozModServerToDozModClient.CONFIGURATION_LOGIC_MEMORY_MIN ) { + memory = ConfigurationLogicDozModServerToDozModClient.CONFIGURATION_LOGIC_MEMORY_MIN; + } + + // limit virtualization memory if the available host's system memory amount is smaller + if ( osMaxMemory > 0 && memory > osMaxMemory ) { + memory = osMaxMemory; + } + + // round to nearest factor of 4, otherwise VMware virtualization configuration files are invalid + return ConfigurationLogicDozModServerToDozModClient.roundToNearest( memory, 4 ); + } + + @Override + public void transform( VirtualizationConfiguration<?, ?, ?, ?> config, + ConfigurationDataDozModServerToDozModClient args ) + throws TransformationException + { + // check if input parameters for a transformation are valid + this.validateInputs( config, args ); + + // set display name + if ( !config.addDisplayName( args.getDisplayName() ) ) { + throw new TransformationException( "Can not set display name in virtualization configuration!" ); + } + + // append hard disk drive + if ( !config.addHddTemplate( args.getDiskImage(), null, null ) ) { + throw new TransformationException( "Can not configure hard disk in virtualization configuration!" ); + } + + // append default NAT interface + if ( !config.addDefaultNat() ) { + throw new TransformationException( "Can not configure NAT interface in virtualization configuration!" ); + } + + // set the guest OS if specified + final OperatingSystem guestOs = args.getGuestOs(); + final String virtualizerId = args.getVirtualizerId(); + int osMaxMemory = 0; + + if ( guestOs != null && virtualizerId != null ) { + final Map<String, String> virtOsIdMap = guestOs.getVirtualizerOsId(); + if ( virtOsIdMap != null ) { + // set guest operating system if possible + final String virtOsId = virtOsIdMap.get( virtualizerId ); + if ( virtOsId != null ) { + config.setOs( virtOsId ); + } + + // get maximum memory of editable host for guestOs if possible + final int maxMemMb = guestOs.getMaxMemMb(); + if ( maxMemMb > 0 ) { + osMaxMemory = maxMemMb; + } + } + } + + // set CPU core count + if ( !config.addCpuCoreCount( ConfigurationLogicDozModServerToDozModClient.CONFIGURATION_LOGIC_NUM_CPU_CORES ) ) { + throw new TransformationException( "Can not set CPU core count in virtualization configuration!" ); + } + + // calculate and set memory + final int virtualizationMemory = ConfigurationLogicDozModServerToDozModClient + .calculateVirtualizationMemoryOnDozmodClient( args.getTotalMemory(), osMaxMemory ); + if ( !config.addRam( virtualizationMemory ) ) { + throw new TransformationException( "Can not set memory in virtualization configuration!" ); + } + + // append first empty floppy drive + config.addFloppy( 0, null, true ); + // append second empty floppy drive + config.addFloppy( 1, null, true ); + + // append first empty (ISO-based) CDROM drive + config.addCdrom( "" ); + // append second CDROM drive connected to the host's physical drive + config.addCdrom( null ); + + // set maximum USB speed + if ( config.getMaxUsbSpeed() != UsbSpeed.USB3_0 ) { + config.setMaxUsbSpeed( UsbSpeed.USB2_0 ); + } + + // apply settings to edit virtualized system locally + try { + config.transformEditable(); + } catch ( VirtualizationConfigurationException e ) { + throw new TransformationException( e.getLocalizedMessage() ); + } + } +} diff --git a/src/main/java/org/openslx/virtualization/configuration/logic/ConfigurationLogicDozModServerToStatelessClient.java b/src/main/java/org/openslx/virtualization/configuration/logic/ConfigurationLogicDozModServerToStatelessClient.java new file mode 100644 index 0000000..30d690a --- /dev/null +++ b/src/main/java/org/openslx/virtualization/configuration/logic/ConfigurationLogicDozModServerToStatelessClient.java @@ -0,0 +1,109 @@ +package org.openslx.virtualization.configuration.logic; + +import org.openslx.virtualization.configuration.VirtualizationConfiguration; +import org.openslx.virtualization.configuration.VirtualizationConfiguration.EtherType; +import org.openslx.virtualization.configuration.VirtualizationConfiguration.UsbSpeed; +import org.openslx.virtualization.configuration.VirtualizationConfigurationException; +import org.openslx.virtualization.configuration.data.ConfigurationDataDozModServerToStatelessClient; +import org.openslx.virtualization.configuration.transformation.TransformationException; + +/** + * Transformation logic for virtualization configurations between a dozmod-server and a stateless + * client. + * <p> + * This transformation logic is applied while downloading an existing virtualization configuration + * from a dozmod-server to a stateless client. + * + * <pre> + * +------------------------------+ DozModServerToStatelessClient +------------------------------+ + * | virtualization configuration | -------------------------------â–¶ | virtualization configuration | + * +---------------+--------------+ transformation logic +------------------+-----------+ + * | dozmod-server | | stateless client | + * +---------------+ +------------------+ + * </pre> + * + * @author Manuel Bentele + * @version 1.0 + */ +public class ConfigurationLogicDozModServerToStatelessClient + extends ConfigurationLogic<ConfigurationDataDozModServerToStatelessClient> +{ + /** + * Name of the transformation logic for virtualization configurations. + */ + private static final String CONFIGURATION_LOGIC_NAME = "Transformation of virtualization configuration during download from DozMod server to stateless client"; + + /** + * Default type for an ethernet interface in a virtualization configuration. + */ + private static final EtherType CONFIGURATION_DEFAULT_ETHERNET_TYPE = EtherType.NAT; + + /** + * Creates a new transformation logic for virtualization configurations between a dozmod-server + * and a stateless client. + */ + public ConfigurationLogicDozModServerToStatelessClient() + { + super( ConfigurationLogicDozModServerToStatelessClient.CONFIGURATION_LOGIC_NAME ); + } + + /** + * Validates a virtualization configuration and input arguments for a transformation. + * + * @param config virtualization configuration for the validation. + * @param args input arguments for the validation. + * @throws TransformationException validation has failed. + */ + private void validateInputs( VirtualizationConfiguration<?, ?, ?, ?> config, + ConfigurationDataDozModServerToStatelessClient args ) + throws TransformationException + { + if ( config == null || args == null ) { + throw new TransformationException( "Virtualization configuration or input arguments are missing!" ); + } else if ( args.getDisplayName() == null || args.getDisplayName().isEmpty() ) { + throw new TransformationException( "Valid display name is not specified!" ); + } + } + + @Override + public void transform( VirtualizationConfiguration<?, ?, ?, ?> config, + ConfigurationDataDozModServerToStatelessClient args ) + throws TransformationException + { + // check if input parameters for a transformation are valid + this.validateInputs( config, args ); + + // set display name of lecture + if ( !config.addDisplayName( args.getDisplayName() ) ) { + throw new TransformationException( "Can not set display name in virtualization configuration!" ); + } + + // append hard disk drive (with no referenced image as content) + if ( !config.addEmptyHddTemplate() ) { + throw new TransformationException( "Can not configure hard disk in virtualization configuration!" ); + } + + // append default NAT interface + if ( !config.addEthernet( + ConfigurationLogicDozModServerToStatelessClient.CONFIGURATION_DEFAULT_ETHERNET_TYPE ) ) { + throw new TransformationException( "Can not configure NAT interface in virtualization configuration!" ); + } + + // set the guest OS if specified + if ( args.getOsId() != null ) { + config.setOs( args.getOsId() ); + } + + // disable USB if necessary + if ( !args.hasUsbAccess() ) { + config.setMaxUsbSpeed( UsbSpeed.NONE ); + } + + // apply settings to run virtualized system in a stateless manner + try { + config.transformNonPersistent(); + } catch ( VirtualizationConfigurationException e ) { + throw new TransformationException( e.getLocalizedMessage() ); + } + } +} diff --git a/src/main/java/org/openslx/virtualization/configuration/transformation/Transformation.java b/src/main/java/org/openslx/virtualization/configuration/transformation/Transformation.java new file mode 100644 index 0000000..af0e181 --- /dev/null +++ b/src/main/java/org/openslx/virtualization/configuration/transformation/Transformation.java @@ -0,0 +1,65 @@ +package org.openslx.virtualization.configuration.transformation; + +/** + * Represents a transformation that transforms (alters) a given configuration with specified input + * arguments. + * + * @author Manuel Bentele + * @version 1.0 + * + * @param <T> type of the configuration which will be transformed. + * @param <R> type of input arguments for the transformation. + */ +public abstract class Transformation<T, R> implements TransformationFunction<T, R> +{ + /** + * Name of the transformation. + */ + private final String name; + + /** + * State of the transformation. + */ + private boolean enabled; + + /** + * Creates a transformation. + * + * @param name comprehensible name for the transformation. + */ + public Transformation( String name ) + { + this.name = name; + this.setEnabled( true ); + } + + /** + * Returns the name of the transformation. + * + * @return name of the transformation. + */ + public String getName() + { + return this.name; + } + + /** + * Returns the state of the transformation. + * + * @return state of the transformation. + */ + public boolean isEnabled() + { + return this.enabled; + } + + /** + * Sets the state for the transformation. + * + * @param enabled state for the transformation. + */ + public void setEnabled( boolean enabled ) + { + this.enabled = enabled; + } +} diff --git a/src/main/java/org/openslx/virtualization/configuration/transformation/TransformationException.java b/src/main/java/org/openslx/virtualization/configuration/transformation/TransformationException.java new file mode 100644 index 0000000..72f320d --- /dev/null +++ b/src/main/java/org/openslx/virtualization/configuration/transformation/TransformationException.java @@ -0,0 +1,25 @@ +package org.openslx.virtualization.configuration.transformation; + +/** + * An exception of a transformation error. + * + * @author Manuel Bentele + * @version 1.0 + */ +public class TransformationException extends Exception +{ + /** + * Version for serialization. + */ + private static final long serialVersionUID = 7293420658901349154L; + + /** + * Creates a transformation exception including an error message. + * + * @param errorMsg message to describe the exception. + */ + public TransformationException( String errorMsg ) + { + super( errorMsg ); + } +} diff --git a/src/main/java/org/openslx/virtualization/configuration/transformation/TransformationFunction.java b/src/main/java/org/openslx/virtualization/configuration/transformation/TransformationFunction.java new file mode 100644 index 0000000..b5be7a0 --- /dev/null +++ b/src/main/java/org/openslx/virtualization/configuration/transformation/TransformationFunction.java @@ -0,0 +1,39 @@ +package org.openslx.virtualization.configuration.transformation; + +/** + * Represents a transformation operation that transforms (alters) a given configuration with + * specified input arguments and returns no result. + * + * @author Manuel Bentele + * @version 1.0 + * + * @param <T> type of the configuration which will be transformed. + * @param <R> type of input arguments for the transformation. + */ +@FunctionalInterface +public interface TransformationFunction<T, R> +{ + /** + * Transforms a given configuration with the specified input arguments. + * + * @param config configuration which will be transformed. + * @param args input arguments for the transformation. + * + * @throws TransformationException transformation of the configuration failed. + */ + public void transform( T config, R args ) throws TransformationException; + + /** + * Applies the transformation function {@link #transform(Object, Object)} to the given + * configuration and specified input arguments. + * + * @param config configuration which will be transformed. + * @param args input arguments for the transformation. + * + * @throws TransformationException transformation of the configuration failed. + */ + public default void apply( T config, R args ) throws TransformationException + { + this.transform( config, args ); + } +} diff --git a/src/main/java/org/openslx/virtualization/configuration/transformation/TransformationGeneric.java b/src/main/java/org/openslx/virtualization/configuration/transformation/TransformationGeneric.java new file mode 100644 index 0000000..4ad36c7 --- /dev/null +++ b/src/main/java/org/openslx/virtualization/configuration/transformation/TransformationGeneric.java @@ -0,0 +1,25 @@ +package org.openslx.virtualization.configuration.transformation; + +/** + * Represents a generic transformation that transforms (alters) a given configuration with specified + * input arguments. The generic transformation does not depend on any external states of a + * virtualizer. + * + * @author Manuel Bentele + * @version 1.0 + * + * @param <T> type of the configuration which will be transformed. + * @param <R> type of input arguments for the transformation. + */ +public abstract class TransformationGeneric<T, R> extends Transformation<T, R> +{ + /** + * Create a generic transformation. + * + * @param name comprehensible name for the transformation. + */ + public TransformationGeneric( String name ) + { + super( name ); + } +} diff --git a/src/main/java/org/openslx/virtualization/configuration/transformation/TransformationManager.java b/src/main/java/org/openslx/virtualization/configuration/transformation/TransformationManager.java new file mode 100644 index 0000000..ce0ad96 --- /dev/null +++ b/src/main/java/org/openslx/virtualization/configuration/transformation/TransformationManager.java @@ -0,0 +1,146 @@ +package org.openslx.virtualization.configuration.transformation; + +import java.util.ArrayList; + +/** + * A transformation manager is a class to manage several transformations and their application. + * + * Transformations can be registered at the transformation manager. The transformation manager has + * the ability to apply all registered transformations on a given configuration and specified input + * arguments. + * + * @author Manuel Bentele + * @version 1.0 + * + * @param <T> type of the configuration which will be transformed by all transformations. + * @param <R> type of input arguments for all transformations. + */ +public class TransformationManager<T, R> +{ + /** + * List of registered transformations. + */ + private ArrayList<Transformation<T, R>> transformations; + + /** + * Reference to the configuration that will be transformed (altered). + */ + private T config; + + /** + * Reference to the input arguments for all registered transformations. + */ + private R args; + + /** + * Create a transformation manager. + * + * @param config configuration which will be transformed. + * @param args input arguments for all registered transformations. + */ + public TransformationManager( T config, R args ) + { + this.transformations = new ArrayList<Transformation<T, R>>(); + this.config = config; + this.args = args; + } + + /** + * Registers and enables a transformation. + * + * @param transformation existing transformation that will be registered and enabled. + */ + public void register( Transformation<T, R> transformation ) + { + this.register( transformation, true ); + } + + /** + * Registers a transformation and sets its state. + * + * @param transformation existing transformation that will be registered. + * @param enabled state for the existing transformation that will be set. + */ + public void register( Transformation<T, R> transformation, boolean enabled ) + { + transformation.setEnabled( enabled ); + this.transformations.add( transformation ); + } + + /** + * Registers a transformation function as a new transformation and enables the registered + * transformation. + * + * @param name comprehensible name for the transformation. + * @param function transformation operation for the transformation. + */ + public void register( String name, TransformationFunction<T, R> function ) + { + this.register( name, function, true ); + } + + /** + * Registers a transformation function as a new transformation and sets the state of the + * registered transformation. + * + * @param name comprehensible name for the transformation. + * @param function transformation operation for the transformation. + * @param enabled state for the transformation. + */ + public void register( String name, TransformationFunction<T, R> function, boolean enabled ) + { + this.register( new Transformation<T, R>( name ) { + @Override + public void transform( T document, R args ) throws TransformationException + { + function.apply( document, args ); + } + }, enabled ); + } + + /** + * Applies all registered transformations, whose state is set to <code>enabled</code>, to the + * referenced configuration and input arguments. + * + * @throws TransformationException transformation of the configuration failed. + */ + public void transform() throws TransformationException + { + for ( Transformation<T, R> transformation : this.transformations ) { + try { + transformation.apply( this.config, this.args ); + } catch ( TransformationException e ) { + final String errorMsg = new String( + "Error in configuration filter '" + transformation.getName() + "':" + e.getLocalizedMessage() ); + throw new TransformationException( errorMsg ); + } + } + } + + /** + * Returns a human readable summary of all registered transformations. + * + * @return human readable summary of all registered transformations. + */ + private String showTransformations() + { + String transformationSummary = new String(); + final int maxFilterNumCharacters = ( this.transformations.size() + 1 ) / 10; + + for ( int i = 0; i < this.transformations.size(); i++ ) { + final Transformation<T, R> transformation = this.transformations.get( i ); + final String paddedNumber = String.format( "%-" + maxFilterNumCharacters + "s", i + 1 ); + final String transformationState = transformation.isEnabled() ? "[ active ]" : "[inactive]"; + transformationSummary += paddedNumber + ": " + transformationState + " "; + transformationSummary += transformation.getName() + System.lineSeparator(); + } + + return transformationSummary; + } + + @Override + public String toString() + { + return this.showTransformations(); + } +} diff --git a/src/main/java/org/openslx/virtualization/configuration/transformation/TransformationSpecific.java b/src/main/java/org/openslx/virtualization/configuration/transformation/TransformationSpecific.java new file mode 100644 index 0000000..7038abf --- /dev/null +++ b/src/main/java/org/openslx/virtualization/configuration/transformation/TransformationSpecific.java @@ -0,0 +1,44 @@ +package org.openslx.virtualization.configuration.transformation; + +/** + * Represents a specific transformation that transforms (alters) a given configuration with + * specified input arguments. The specific transformation depends on external states of a + * specified virtualizer. + * + * @author Manuel Bentele + * @version 1.0 + * + * @param <T> type of the configuration which will be transformed. + * @param <R> type of input arguments for the transformation. + * @param <H> type of the external input source. + */ +public abstract class TransformationSpecific<T, R, H> extends Transformation<T, R> +{ + /** + * Reference to virtualizer to query external states. + */ + private final H virtualizer; + + /** + * Create a specific transformation. + * + * @param name comprehensible name for the transformation. + * @param virtualizer initialized virtualizer. + */ + public TransformationSpecific( String name, H virtualizer ) + { + super( name ); + + this.virtualizer = virtualizer; + } + + /** + * Returns the referenced virtualizer of the transformation. + * + * @return referenced virtualizer of the transformation. + */ + public H getVirtualizer() + { + return this.virtualizer; + } +} diff --git a/src/main/java/org/openslx/virtualization/virtualizer/Virtualizer.java b/src/main/java/org/openslx/virtualization/virtualizer/Virtualizer.java new file mode 100644 index 0000000..ac3a4ec --- /dev/null +++ b/src/main/java/org/openslx/virtualization/virtualizer/Virtualizer.java @@ -0,0 +1,68 @@ +package org.openslx.virtualization.virtualizer; + +import java.util.List; + +import org.openslx.virtualization.Version; +import org.openslx.vm.disk.DiskImage.ImageFormat; + +/** + * Representation of a virtualization system. + * + * The virtualization system can be for example a virtual machine hypervisor (like VirtualBox), a + * container for operating systems or applications (like LXC or Docker), or a runtime environment + * (like Wine). + * + * @author Manuel Bentele + * @version 1.0 + */ +public abstract class Virtualizer +{ + /** + * Internal data representation for the virtualizer. + */ + protected final org.openslx.bwlp.thrift.iface.Virtualizer internalVirtualizer; + + /** + * Creates a new virtualizer. + * + * @param internalVirtualizer internal data representation for the new virtualizer. + */ + public Virtualizer( org.openslx.bwlp.thrift.iface.Virtualizer internalVirtualizer ) + { + this.internalVirtualizer = internalVirtualizer; + } + + /** + * Returns the identifier of the virtualizer. + * + * @return identifier of the virtualizer. + */ + public String getId() + { + return this.internalVirtualizer.getVirtId(); + } + + /** + * Returns the name of the virtualizer. + * + * @return name of the virtualizer. + */ + public String getName() + { + return this.internalVirtualizer.getVirtName(); + } + + /** + * Returns a list of supported disk image formats by the virtualizer. + * + * @return list of supported disk image formats by the virtualizer. + */ + public abstract List<ImageFormat> getSupportedImageFormats(); + + /** + * Returns a list of supported versions of the virtualizer. + * + * @return list of supported versions of the virtualizer. + */ + public abstract List<Version> getSupportedVersions(); +} diff --git a/src/main/java/org/openslx/virtualization/virtualizer/VirtualizerDocker.java b/src/main/java/org/openslx/virtualization/virtualizer/VirtualizerDocker.java new file mode 100644 index 0000000..673447b --- /dev/null +++ b/src/main/java/org/openslx/virtualization/virtualizer/VirtualizerDocker.java @@ -0,0 +1,55 @@ +package org.openslx.virtualization.virtualizer; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.openslx.thrifthelper.TConst; +import org.openslx.virtualization.Version; +import org.openslx.vm.disk.DiskImage; +import org.openslx.vm.disk.DiskImage.ImageFormat; + +/** + * Representation of the Docker virtualizer for application containers. + * + * @author Manuel Bentele + * @version 1.0 + */ +public class VirtualizerDocker extends Virtualizer +{ + /** + * Name of the Docker virtualizer. + */ + private static final String VIRTUALIZER_NAME = "Docker"; + + /** + * List of supported image formats by the Docker virtualizer. + */ + private static final List<DiskImage.ImageFormat> VIRTUALIZER_SUPPORTED_IMAGE_FORMATS = Collections + .unmodifiableList( Arrays.asList( ImageFormat.NONE ) ); + + /** + * List of supported versions of the Docker virtualizer. + */ + private static final List<Version> VIRTUALIZER_SUPPORTED_VERSIONS = null; + + /** + * Creates a new Docker virtualizer. + */ + public VirtualizerDocker() + { + super( new org.openslx.bwlp.thrift.iface.Virtualizer( TConst.VIRT_DOCKER, VirtualizerDocker.VIRTUALIZER_NAME ) ); + } + + @Override + public List<ImageFormat> getSupportedImageFormats() + { + return VirtualizerDocker.VIRTUALIZER_SUPPORTED_IMAGE_FORMATS; + } + + @Override + public List<Version> getSupportedVersions() + { + return VirtualizerDocker.VIRTUALIZER_SUPPORTED_VERSIONS; + } +} diff --git a/src/main/java/org/openslx/virtualization/virtualizer/VirtualizerQemu.java b/src/main/java/org/openslx/virtualization/virtualizer/VirtualizerQemu.java new file mode 100644 index 0000000..fcce392 --- /dev/null +++ b/src/main/java/org/openslx/virtualization/virtualizer/VirtualizerQemu.java @@ -0,0 +1,68 @@ +package org.openslx.virtualization.virtualizer; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.openslx.thrifthelper.TConst; +import org.openslx.virtualization.Version; +import org.openslx.vm.disk.DiskImage; +import org.openslx.vm.disk.DiskImage.ImageFormat; + +/** + * Representation of the QEMU virtualizer for virtual machines. + * + * @author Manuel Bentele + * @version 1.0 + */ +public class VirtualizerQemu extends Virtualizer +{ + /** + * Name of the QEMU virtualizer. + */ + private static final String VIRTUALIZER_NAME = "QEMU"; + + /** + * List of supported image formats by the QEMU virtualizer. + */ + private static final List<DiskImage.ImageFormat> VIRTUALIZER_SUPPORTED_IMAGE_FORMATS = Collections + .unmodifiableList( Arrays.asList( ImageFormat.QCOW2, ImageFormat.VMDK, ImageFormat.VDI ) ); + + /** + * List of supported versions of the QEMU virtualizer. + */ + private static final List<Version> VIRTUALIZER_SUPPORTED_VERSIONS = Collections.unmodifiableList( + Arrays.asList( + new Version( Short.valueOf( "2" ), Short.valueOf( "1" ), "QEMU 2.1" ), + new Version( Short.valueOf( "2" ), Short.valueOf( "4" ), "QEMU 2.4" ), + new Version( Short.valueOf( "2" ), Short.valueOf( "5" ), "QEMU 2.5" ), + new Version( Short.valueOf( "2" ), Short.valueOf( "6" ), "QEMU 2.6" ), + new Version( Short.valueOf( "2" ), Short.valueOf( "7" ), "QEMU 2.7" ), + new Version( Short.valueOf( "2" ), Short.valueOf( "8" ), "QEMU 2.8" ), + new Version( Short.valueOf( "2" ), Short.valueOf( "9" ), "QEMU 2.9" ), + new Version( Short.valueOf( "3" ), Short.valueOf( "0" ), "QEMU 3.0" ), + new Version( Short.valueOf( "3" ), Short.valueOf( "1" ), "QEMU 3.1" ), + new Version( Short.valueOf( "4" ), Short.valueOf( "0" ), "QEMU 4.0" ), + new Version( Short.valueOf( "4" ), Short.valueOf( "1" ), "QEMU 4.1" ), + new Version( Short.valueOf( "4" ), Short.valueOf( "2" ), "QEMU 4.2" ) ) ); + + /** + * Creates a new QEMU virtualizer. + */ + public VirtualizerQemu() + { + super( new org.openslx.bwlp.thrift.iface.Virtualizer( TConst.VIRT_QEMU, VirtualizerQemu.VIRTUALIZER_NAME ) ); + } + + @Override + public List<ImageFormat> getSupportedImageFormats() + { + return VirtualizerQemu.VIRTUALIZER_SUPPORTED_IMAGE_FORMATS; + } + + @Override + public List<Version> getSupportedVersions() + { + return VirtualizerQemu.VIRTUALIZER_SUPPORTED_VERSIONS; + } +} diff --git a/src/main/java/org/openslx/virtualization/virtualizer/VirtualizerVirtualBox.java b/src/main/java/org/openslx/virtualization/virtualizer/VirtualizerVirtualBox.java new file mode 100644 index 0000000..6be7cbf --- /dev/null +++ b/src/main/java/org/openslx/virtualization/virtualizer/VirtualizerVirtualBox.java @@ -0,0 +1,56 @@ +package org.openslx.virtualization.virtualizer; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.openslx.thrifthelper.TConst; +import org.openslx.virtualization.Version; +import org.openslx.vm.disk.DiskImage; +import org.openslx.vm.disk.DiskImage.ImageFormat; + +/** + * Representation of the VirtualBox virtualizer for virtual machines. + * + * @author Manuel Bentele + * @version 1.0 + */ +public class VirtualizerVirtualBox extends Virtualizer +{ + /** + * Name of the VirtualBox virtualizer. + */ + private static final String VIRTUALIZER_NAME = "VirtualBox"; + + /** + * List of supported image formats by the VirtualBox virtualizer. + */ + private static final List<DiskImage.ImageFormat> VIRTUALIZER_SUPPORTED_IMAGE_FORMATS = Collections + .unmodifiableList( Arrays.asList( ImageFormat.VDI ) ); + + /** + * List of supported version of the VirtualBox virtualizer. + */ + private static final List<Version> VIRTUALIZER_SUPPORTED_VERSIONS = null; + + /** + * Creates a new VirtualBox virtualizer. + */ + public VirtualizerVirtualBox() + { + super( new org.openslx.bwlp.thrift.iface.Virtualizer( TConst.VIRT_VIRTUALBOX, + VirtualizerVirtualBox.VIRTUALIZER_NAME ) ); + } + + @Override + public List<ImageFormat> getSupportedImageFormats() + { + return VirtualizerVirtualBox.VIRTUALIZER_SUPPORTED_IMAGE_FORMATS; + } + + @Override + public List<Version> getSupportedVersions() + { + return VirtualizerVirtualBox.VIRTUALIZER_SUPPORTED_VERSIONS; + } +} diff --git a/src/main/java/org/openslx/virtualization/virtualizer/VirtualizerVmware.java b/src/main/java/org/openslx/virtualization/virtualizer/VirtualizerVmware.java new file mode 100644 index 0000000..6e676f3 --- /dev/null +++ b/src/main/java/org/openslx/virtualization/virtualizer/VirtualizerVmware.java @@ -0,0 +1,71 @@ +package org.openslx.virtualization.virtualizer; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.openslx.thrifthelper.TConst; +import org.openslx.virtualization.Version; +import org.openslx.vm.disk.DiskImage; +import org.openslx.vm.disk.DiskImage.ImageFormat; + +/** + * Representation of the VMware virtualizer for virtual machines. + * + * @author Manuel Bentele + * @version 1.0 + */ +public class VirtualizerVmware extends Virtualizer +{ + /** + * Name of the VMware virtualizer. + */ + private static final String VIRTUALIZER_NAME = "VMware"; + + /** + * List of supported image formats by the VMware virtualizer. + */ + private static final List<DiskImage.ImageFormat> VIRTUALIZER_SUPPORTED_IMAGE_FORMATS = Collections + .unmodifiableList( Arrays.asList( ImageFormat.VMDK ) ); + + /** + * List of supported versions of the VMware virtualizer. + */ + private static final List<Version> VIRTUALIZER_SUPPORTED_VERSIONS = Collections.unmodifiableList( + Arrays.asList( + new Version( Short.valueOf( "03" ), "Workstation 4/5, Player 1" ), + new Version( Short.valueOf( "04" ), "Workstation 4/5, Player 1/2, Fusion 1" ), + new Version( Short.valueOf( "06" ), "Workstation 6" ), + new Version( Short.valueOf( "07" ), "Workstation 6.5/7, Player 3, Fusion 2/3" ), + new Version( Short.valueOf( "08" ), "Workstation 8, Player/Fusion 4" ), + new Version( Short.valueOf( "09" ), "Workstation 9, Player/Fusion 5" ), + new Version( Short.valueOf( "10" ), "Workstation 10, Player/Fusion 6" ), + new Version( Short.valueOf( "11" ), "Workstation 11, Player/Fusion 7" ), + new Version( Short.valueOf( "12" ), "Workstation/Player 12, Fusion 8" ), + new Version( Short.valueOf( "14" ), "Workstation/Player 14, Fusion 10" ), + new Version( Short.valueOf( "15" ), "Workstation/Player 15, Fusion 11" ), + new Version( Short.valueOf( "16" ), "Workstation/Player 15.1, Fusion 11.1" ), + new Version( Short.valueOf( "17" ), "Workstation/Player 16, Fusion 12" ), + new Version( Short.valueOf( "18" ), "Workstation/Player 16.1, Fusion 12.1" ) ) ); + + /** + * Creates a new VMware virtualizer. + */ + public VirtualizerVmware() + { + super( new org.openslx.bwlp.thrift.iface.Virtualizer( TConst.VIRT_VMWARE, VirtualizerVmware.VIRTUALIZER_NAME ) ); + } + + @Override + public List<ImageFormat> getSupportedImageFormats() + { + return VirtualizerVmware.VIRTUALIZER_SUPPORTED_IMAGE_FORMATS; + } + + @Override + public List<Version> getSupportedVersions() + { + return VirtualizerVmware.VIRTUALIZER_SUPPORTED_VERSIONS; + } + +} diff --git a/src/main/java/org/openslx/vm/KeyValuePair.java b/src/main/java/org/openslx/vm/KeyValuePair.java deleted file mode 100644 index c5650ec..0000000 --- a/src/main/java/org/openslx/vm/KeyValuePair.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.openslx.vm; - -class KeyValuePair -{ - public final String key; - public final String value; - - public KeyValuePair( String key, String value ) - { - this.key = key; - this.value = value; - } -}
\ No newline at end of file diff --git a/src/main/java/org/openslx/vm/QemuMetaDataUtils.java b/src/main/java/org/openslx/vm/QemuMetaDataUtils.java deleted file mode 100644 index a6142ab..0000000 --- a/src/main/java/org/openslx/vm/QemuMetaDataUtils.java +++ /dev/null @@ -1,191 +0,0 @@ -package org.openslx.vm; - -import java.util.ArrayList; - -import org.openslx.libvirt.domain.device.Disk; -import org.openslx.libvirt.domain.device.Interface; -import org.openslx.libvirt.domain.device.Disk.BusType; -import org.openslx.vm.VmMetaData.DriveBusType; -import org.openslx.vm.VmMetaData.EthernetDevType; -import org.openslx.vm.VmMetaData.SoundCardType; -import org.openslx.libvirt.domain.device.Sound; - -/** - * Collection of utils to convert data types from bwLehrpool to Libvirt and vice versa. - * - * @author Manuel Bentele - * @version 1.0 - */ -public class QemuMetaDataUtils -{ - /** - * Converts a Libvirt disk device bus type to a VM metadata driver bus type. - * - * @param busType Libvirt disk device bus type. - * @return VM metadata bus type of the disk drive. - */ - public static DriveBusType convertBusType( Disk.BusType busType ) - { - DriveBusType type = null; - - switch ( busType ) { - case IDE: - type = DriveBusType.IDE; - break; - case SATA: - type = DriveBusType.SATA; - break; - case SCSI: - type = DriveBusType.SCSI; - break; - default: - type = null; - break; - } - - return type; - } - - /** - * Converts a VM metadata driver bus type to a Libvirt disk device bus type. - * - * @param busType VM metadata bus type of the disk drive. - * @return Libvirt disk device bus type. - */ - public static Disk.BusType convertBusType( DriveBusType busType ) - { - Disk.BusType type = null; - - switch ( busType ) { - case IDE: - type = BusType.IDE; - break; - case NVME: - type = null; - break; - case SATA: - type = BusType.SATA; - break; - case SCSI: - type = BusType.SCSI; - break; - } - - return type; - } - - /** - * Converts a Libvirt sound device model to a VM metadata sound card type. - * - * @param soundDeviceModel Libvirt sound device model. - * @return VM metadata sound card type. - */ - public static SoundCardType convertSoundDeviceModel( Sound.Model soundDeviceModel ) - { - SoundCardType type = SoundCardType.NONE; - - switch ( soundDeviceModel ) { - case AC97: - type = SoundCardType.AC; - break; - case ES1370: - type = SoundCardType.ES; - break; - case ICH6: - type = SoundCardType.HD_AUDIO; - break; - case ICH9: - type = SoundCardType.HD_AUDIO; - break; - case SB16: - type = SoundCardType.SOUND_BLASTER; - break; - } - - return type; - } - - /** - * Converts a Libvirt network device model to a VM metadata ethernet device type. - * - * @param soundDeviceModel Libvirt network device model. - * @return VM metadata ethernet device type. - */ - public static EthernetDevType convertNetworkDeviceModel( Interface.Model networkDeviceModel ) - { - EthernetDevType type = EthernetDevType.NONE; - - switch ( networkDeviceModel ) { - case E1000: - type = EthernetDevType.E1000; - break; - case E1000E: - type = EthernetDevType.E1000E; - break; - case PCNET: - type = EthernetDevType.PCNETPCI2; - break; - case VIRTIO: - type = EthernetDevType.PARAVIRT; - break; - case VIRTIO_NET_PCI: - type = EthernetDevType.PARAVIRT; - break; - case VIRTIO_NET_PCI_NON_TRANSITIONAL: - type = EthernetDevType.PARAVIRT; - break; - case VIRTIO_NET_PCI_TRANSITIONAL: - type = EthernetDevType.PARAVIRT; - break; - case VMXNET3: - type = EthernetDevType.VMXNET3; - break; - default: - type = EthernetDevType.AUTO; - break; - } - - return type; - } - - /** - * Returns an item from a given {@link ArrayList}. - * - * The item is selected by a given index. If the item is not available within the - * {@link ArrayList}, <code>null</code> is returned. - * - * @param <T> type of the {@link ArrayList}. - * @param array {@link ArrayList} of type <code>T</code>. - * @param index selects the item from the {@link ArrayList}. - * @return selected item of the {@link ArrayList}. - */ - public static <T> T getArrayIndex( ArrayList<T> array, int index ) - { - T ret; - - try { - ret = array.get( index ); - } catch ( IndexOutOfBoundsException e ) { - ret = null; - } - - return ret; - } - - /** - * Creates an alphabetical device name constructed from a device prefix and a device number. - * - * @param devicePrefix prefix of the constructed device name. - * @param deviceNumber number of the device. - * @return alphabetical device name. - */ - public static String createAlphabeticalDeviceName( String devicePrefix, int deviceNumber ) - { - if ( deviceNumber < 0 || deviceNumber >= ( 'z' - 'a' ) ) { - String errorMsg = new String( "Device number is out of range to be able to create a valid device name." ); - throw new IllegalArgumentException( errorMsg ); - } - - return devicePrefix + ( 'a' + deviceNumber ); - } -} diff --git a/src/main/java/org/openslx/vm/UnsupportedVirtualizerFormatException.java b/src/main/java/org/openslx/vm/UnsupportedVirtualizerFormatException.java deleted file mode 100644 index a6f3197..0000000 --- a/src/main/java/org/openslx/vm/UnsupportedVirtualizerFormatException.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.openslx.vm; - -public class UnsupportedVirtualizerFormatException extends Exception -{ - /** - * Version for serialization. - */ - private static final long serialVersionUID = 5794121065945636839L; - - public UnsupportedVirtualizerFormatException(String message) { - super(message); - } -}
\ No newline at end of file diff --git a/src/main/java/org/openslx/vm/VmMetaData.java b/src/main/java/org/openslx/vm/VmMetaData.java deleted file mode 100644 index 0be07e4..0000000 --- a/src/main/java/org/openslx/vm/VmMetaData.java +++ /dev/null @@ -1,419 +0,0 @@ -package org.openslx.vm; - -import java.io.File; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import org.apache.log4j.Logger; -import org.openslx.bwlp.thrift.iface.OperatingSystem; -import org.openslx.bwlp.thrift.iface.Virtualizer; -import org.openslx.vm.disk.DiskImage; - -/** - * Describes a configured virtual machine. This class is parsed from a machine - * description, like a *.vmx for VMware machines. - */ -public abstract class VmMetaData<T, U, V, W, X> -{ - private static final Logger LOGGER = Logger.getLogger( VmMetaData.class ); - - /* - * Helper types - */ - protected Map<SoundCardType, T> soundCards = new HashMap<>(); - protected Map<DDAcceleration, U> ddacc = new HashMap<>(); - protected Map<HWVersion, V> hwversion = new HashMap<>(); - protected Map<EthernetDevType, W> networkCards = new HashMap<>(); - protected Map<UsbSpeed, X> usbSpeeds = new HashMap<>(); - - /** - * Virtual sound cards types - */ - public static enum SoundCardType - { - NONE( "None" ), DEFAULT( "(default)" ), SOUND_BLASTER( "Sound Blaster 16" ), ES( "ES 1371" ), HD_AUDIO( "Intel Integrated HD Audio" ), AC( "Intel ICH Audio Codec 97" ); - - public final String displayName; - - private SoundCardType( String dName ) - { - this.displayName = dName; - } - } - - /** - * 3D acceleration types - */ - public static enum DDAcceleration - { - OFF( "Off" ), ON( "On" ); - - public final String displayName; - - private DDAcceleration( String dName ) - { - this.displayName = dName; - } - } - - /** - * Virtual hardware version - currently only in use for VMPlayer - */ - public static enum HWVersion - { - NONE( "(invalid)" ), - THREE( " 3 (Workstation 4/5, Player 1)" ), - FOUR( " 4 (Workstation 4/5, Player 1/2, Fusion 1)" ), - SIX( " 6 (Workstation 6)" ), - SEVEN( " 7 (Workstation 6.5/7, Player 3, Fusion 2/3)" ), - EIGHT( " 8 (Workstation 8, Player/Fusion 4)" ), - NINE( " 9 (Workstation 9, Player/Fusion 5)" ), - TEN( "10 (Workstation 10, Player/Fusion 6)" ), - ELEVEN( "11 (Workstation 11, Player/Fusion 7)" ), - TWELVE( "12 (Workstation/Player 12, Fusion 8)" ), - FOURTEEN( "14 (Workstation/Player 14, Fusion 10)"), - FIFTEEN( "15 (Workstation/Player 15, Fusion 11)"), - FIFTEEN_ONE( "16 (Workstation/Player 15.1, Fusion 11.1)"), - SIXTEEN( "17 (Workstation/Player 16, Fusion 12)"), - SIXTEEN_ONE( "18 (Workstation/Player 16.1, Fusion 12.1)"), - DEFAULT( "default" ); - - public final String displayName; - - private HWVersion( String dName ) - { - this.displayName = dName; - } - } - - /** - * Virtual network cards - */ - public static enum EthernetDevType - { - AUTO( "(default)" ), PCNET32( "AMD PCnet32" ), E1000( "Intel E1000 (PCI)" ), E1000E( "Intel E1000e (PCI-Express)" ), VMXNET( "VMXnet" ), VMXNET3( "VMXnet 3" ), PCNETPCI2( - "PCnet-PCI II" ), PCNETFAST3( "PCnet-FAST III" ), PRO1000MTD( "Intel PRO/1000 MT Desktop" ), PRO1000TS( - "Intel PRO/1000 T Server" ), PRO1000MTS( "Intel PRO/1000 MT Server" ), PARAVIRT( "Paravirtualized Network" ), NONE( "No Network Card" ); - - public final String displayName; - - private EthernetDevType( String dName ) - { - this.displayName = dName; - } - } - - public static enum UsbSpeed - { - NONE( "None" ), - USB1_1( "USB 1.1" ), - USB2_0( "USB 2.0" ), - USB3_0( "USB 3.0" ); - - public final String displayName; - - private UsbSpeed( String dName ) - { - this.displayName = dName; - } - } - - public static enum DriveBusType - { - SCSI, IDE, SATA, NVME; - } - - public static class HardDisk - { - public final String chipsetDriver; - public final DriveBusType bus; - public final String diskImage; - - public HardDisk( String chipsetDriver, DriveBusType bus, String diskImage ) - { - this.chipsetDriver = chipsetDriver; - this.bus = bus; - this.diskImage = diskImage; - } - } - - public static enum EtherType - { - NAT, BRIDGED, HOST_ONLY; - } - /* - * Members - */ - - protected final List<HardDisk> hdds = new ArrayList<>(); - - private final List<OperatingSystem> osList; - - private OperatingSystem os = null; - - protected String displayName = null; - - protected boolean isMachineSnapshot; - - /* - * Getters for virtual hardware - */ - public List<SoundCardType> getSupportedSoundCards() - { - ArrayList<SoundCardType> availables = new ArrayList<SoundCardType>( soundCards.keySet() ); - Collections.sort( availables ); - return availables; - } - - public List<DDAcceleration> getSupportedDDAccs() - { - ArrayList<DDAcceleration> availables = new ArrayList<DDAcceleration>( ddacc.keySet() ); - Collections.sort( availables ); - return availables; - } - - public List<HWVersion> getSupportedHWVersions() - { - ArrayList<HWVersion> availables = new ArrayList<HWVersion>( hwversion.keySet() ); - Collections.sort( availables ); - return availables; - } - - public List<EthernetDevType> getSupportedEthernetDevices() - { - ArrayList<EthernetDevType> availables = new ArrayList<EthernetDevType>( networkCards.keySet() ); - Collections.sort( availables ); - return availables; - } - - public List<UsbSpeed> getSupportedUsbSpeeds() - { - ArrayList<UsbSpeed> availables = new ArrayList<>( usbSpeeds.keySet() ); - Collections.sort( availables ); - return availables; - } - - /** - * Get operating system of this VM. - */ - public OperatingSystem getOs() - { - return os; - } - - /** - * Get all hard disks of this VM. - */ - public List<HardDisk> getHdds() - { - return Collections.unmodifiableList( hdds ); - } - - /** - * Get display name of VM. - */ - public String getDisplayName() - { - return displayName; - } - - /* - * Getter for isMachineSnapshot - */ - public boolean isMachineSnapshot() - { - return isMachineSnapshot; - } - - /** - * This method should return a minimal representation of the input meta data. - * The representation is platform dependent, and should be stripped of all - * non-essential configuration, such as CD/DVD/FLoppy drives, serial or parallel - * ports, shared folders, or anything else that could be considered sensible - * information (absolute paths containing the local user's name). - */ - public abstract byte[] getFilteredDefinitionArray(); - - public final ByteBuffer getFilteredDefinition() - { - return ByteBuffer.wrap( getFilteredDefinitionArray() ); - } - - /* - * Methods - */ - - public VmMetaData( List<OperatingSystem> osList ) - { - this.osList = osList; - } - - /** - * Called from subclass to set the OS. If the OS cannot be determined from the - * given parameters, it will not be set. - * - * @param virtId - * virtualizer, eg "vmware" for VMware - * @param virtOsId - * the os identifier used by the virtualizer, eg. windows7-64 for - * 64bit Windows 7 on VMware - */ - protected final void setOs( String virtId, String virtOsId ) - { - OperatingSystem lazyMatch = null; - for ( OperatingSystem os : osList ) { - if ( os.getVirtualizerOsId() == null ) - continue; - for ( Entry<String, String> entry : os.getVirtualizerOsId().entrySet() ) { - if ( !entry.getValue().equals( virtOsId ) ) - continue; - if ( entry.getKey().equals( virtId ) ) { - this.os = os; - return; - } else { - lazyMatch = os; - } - } - } - this.os = lazyMatch; - } - - /** - * Returns list of image formats supported by the VM's hypervisor. - * - * @return list of image formats. - */ - public abstract List<DiskImage.ImageFormat> getSupportedImageFormats(); - - /** - * Apply config options that are desired when locally editing a VM. for vmware, - * this disables automatic DPI scaling of the guest. - */ - public abstract void applySettingsForLocalEdit(); - - /** - * Returns a VmMetaData instance of the given machine description given as file - * - * @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 - */ - public static VmMetaData<?, ?, ?, ?, ?> getInstance( List<OperatingSystem> osList, File file ) - throws IOException - { - try { - return new VmwareMetaData( osList, file ); - } catch ( UnsupportedVirtualizerFormatException e ) { - LOGGER.info( "Not a VMware file", e ); - } - try { - return new VboxMetaData( osList, file ); - } catch ( UnsupportedVirtualizerFormatException e ) { - LOGGER.info( "Not a VirtualBox file", e ); - } - try { - return new QemuMetaData( osList, file ); - } catch ( Exception e ) { - LOGGER.info( "Not a Qemu file", e ); - } - try { - return new DockerMetaDataDummy(osList, file); - } catch ( Exception e ) { - LOGGER.info( "Not a tar.gz file, for docker container", e ); - } - LOGGER.error( "Could not detect any known virtualizer format" ); - return null; - } - - /** - * Returns a VmMetaData instance of the given machine description given as a byte array - * - * @param osList List of supported operating systems - * @param vmContent VM's machine description as byte array (e.g. stored in DB) - * @param length length of the byte array given as vmContent - * @return VmMetaData object representing the relevant parts of the given machine description - * @throws IOException - */ - public static VmMetaData<?, ?, ?, ?, ?> getInstance( List<OperatingSystem> osList, byte[] vmContent, int length ) throws IOException - { - Map<String, Exception> exceptions = new HashMap<>(); - try { - return new VmwareMetaData( osList, vmContent, length ); - } catch ( UnsupportedVirtualizerFormatException e ) { - exceptions.put( "Not a VMware file", e ); - } - try { - return new VboxMetaData( osList, vmContent, length ); - } catch ( UnsupportedVirtualizerFormatException e ) { - exceptions.put( "Not a VirtualBox file", e ); - } - try { - return new DockerMetaDataDummy(osList, vmContent, length); - } catch (UnsupportedVirtualizerFormatException e) { - exceptions.put( "Not tar.gz file for DockerMetaDataDummy ", 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" ); - for ( Entry<String, Exception> e : exceptions.entrySet() ) { - LOGGER.error( e.getKey(), e.getValue() ); - } - return null; - } - - public abstract boolean addHddTemplate( File diskImage, String hddMode, String redoDir ); - - public abstract boolean addHddTemplate( String diskImagePath, String hddMode, String redoDir ); - - public abstract boolean addDefaultNat(); - - public abstract void setOs( String vendorOsId ); - - public abstract boolean addDisplayName( String name ); - - public abstract boolean addRam( int mem ); - - public abstract void addFloppy( int index, String image, boolean readOnly ); - - public abstract boolean addCdrom( String image ); - - public abstract boolean addCpuCoreCount( int nrOfCores ); - - public abstract void setSoundCard( SoundCardType type ); - - public abstract SoundCardType getSoundCard(); - - public abstract void setDDAcceleration( DDAcceleration type ); - - public abstract DDAcceleration getDDAcceleration(); - - public abstract void setHWVersion( HWVersion type ); - - public abstract HWVersion getHWVersion(); - - public abstract void setEthernetDevType( int cardIndex, EthernetDevType type ); - - public abstract EthernetDevType getEthernetDevType( int cardIndex ); - - public abstract void setMaxUsbSpeed( UsbSpeed speed ); - - public abstract UsbSpeed getMaxUsbSpeed(); - - public abstract byte[] getDefinitionArray(); - - public abstract boolean addEthernet( EtherType type ); - - public abstract Virtualizer getVirtualizer(); - - public abstract boolean tweakForNonPersistent(); - - /** - * Function used to register virtual devices - */ - public abstract void registerVirtualHW(); -} diff --git a/src/main/java/org/openslx/vm/disk/DiskImage.java b/src/main/java/org/openslx/vm/disk/DiskImage.java index 5706db3..cf7df83 100644 --- a/src/main/java/org/openslx/vm/disk/DiskImage.java +++ b/src/main/java/org/openslx/vm/disk/DiskImage.java @@ -11,6 +11,7 @@ import java.util.function.Predicate; import org.openslx.bwlp.thrift.iface.Virtualizer; import org.openslx.thrifthelper.TConst; import org.openslx.util.Util; +import org.openslx.virtualization.Version; /** * Disk image for virtual machines. @@ -87,7 +88,7 @@ public abstract class DiskImage implements Closeable * * @throws DiskImageException unable to obtain version of the disk image format. */ - public abstract int getVersion() throws DiskImageException; + public abstract Version getVersion() throws DiskImageException; /** * Returns the disk image description. @@ -115,7 +116,8 @@ public abstract class DiskImage implements Closeable * @throws IOException cannot access the content of the disk image file. * @throws DiskImageException disk image file has an invalid and unknown disk image format. */ - public static DiskImage newInstance( File diskImagePath ) throws FileNotFoundException, IOException, DiskImageException + public static DiskImage newInstance( File diskImagePath ) + throws FileNotFoundException, IOException, DiskImageException { // Make sure this doesn't escape the scope, in case instantiation fails - we can't know when the GC // would come along and close this file, which is problematic on Windows (blocking rename/delete) @@ -193,7 +195,7 @@ public abstract class DiskImage implements Closeable /** * Checks if the disk image format is supported by a virtualizer. * - * @param supportedImageTypes list of supported disk image formats of a virtualizer. + * @param supportedImageFormats list of supported disk image formats of a virtualizer. * @return <code>true</code> if image type is supported by the virtualizer; otherwise * <code>false</code>. */ diff --git a/src/main/java/org/openslx/vm/disk/DiskImageQcow2.java b/src/main/java/org/openslx/vm/disk/DiskImageQcow2.java index a9826e4..e569708 100644 --- a/src/main/java/org/openslx/vm/disk/DiskImageQcow2.java +++ b/src/main/java/org/openslx/vm/disk/DiskImageQcow2.java @@ -2,6 +2,8 @@ package org.openslx.vm.disk; import java.io.RandomAccessFile; +import org.openslx.virtualization.Version; + /** * QCOW2 disk image for virtual machines. * @@ -48,9 +50,9 @@ public class DiskImageQcow2 extends DiskImage * * @param diskImage file to a QCOW2 disk storing the image content. */ - DiskImageQcow2( RandomAccessFile disk ) + DiskImageQcow2( RandomAccessFile diskImage ) { - super( disk ); + super( diskImage ); } /** @@ -104,7 +106,7 @@ public class DiskImageQcow2 extends DiskImage // check if QCOW2 image uses extended L2 tables // extended L2 tables are only possible in QCOW2 version 3 header format - if ( this.getVersion() >= 3 ) { + if ( this.getVersion().getMajor() >= Short.valueOf( "3" ) ) { // read incompatible feature bits final long qcowIncompatibleFeatures = DiskImageUtils.readLong( diskFile, 72 ); @@ -200,7 +202,7 @@ public class DiskImageQcow2 extends DiskImage } @Override - public int getVersion() throws DiskImageException + public Version getVersion() throws DiskImageException { final RandomAccessFile diskFile = this.getDiskImage(); final int qcowVersion = DiskImageUtils.readInt( diskFile, 4 ); @@ -212,7 +214,7 @@ public class DiskImageQcow2 extends DiskImage throw new DiskImageException( errorMsg ); } - return DiskImageUtils.versionFromMajor( Integer.valueOf( qcowVersion ).shortValue() ); + return new Version( Integer.valueOf( qcowVersion ).shortValue() ); } @Override diff --git a/src/main/java/org/openslx/vm/disk/DiskImageUtils.java b/src/main/java/org/openslx/vm/disk/DiskImageUtils.java index fbed6f9..ccb053f 100644 --- a/src/main/java/org/openslx/vm/disk/DiskImageUtils.java +++ b/src/main/java/org/openslx/vm/disk/DiskImageUtils.java @@ -114,12 +114,12 @@ public class DiskImageUtils } /** - * Reads two bytes ({@link Short}) at a given <code>offset</code> from the specified disk image - * file. + * Reads a variable number of bytes (<code>numBytes</code>) at a given <code>offset</code> from the specified disk image file. * * @param diskImage file to a disk storing the image content. - * @param offset offset in bytes for reading the two bytes. - * @return value of the two bytes from the disk image file as {@link Short}. + * @param offset offset in bytes for reading <code>numBytes</code> bytes. + * @param numBytes number of bytes to read at <code>offset</code>. + * @return read bytes from the disk image file as {@link String}. * * @throws DiskImageException unable to read two bytes from the disk image file. */ @@ -141,14 +141,4 @@ public class DiskImageUtils return new String( values ); } - - public static int versionFromMajorMinor( final short major, final short minor ) - { - return ( ( Integer.valueOf( major ) << 16 ) | minor ); - } - - public static int versionFromMajor( final short major ) - { - return DiskImageUtils.versionFromMajorMinor( major, Short.valueOf( "0" ) ); - } } diff --git a/src/main/java/org/openslx/vm/disk/DiskImageVdi.java b/src/main/java/org/openslx/vm/disk/DiskImageVdi.java index 9be49d8..37e45c1 100644 --- a/src/main/java/org/openslx/vm/disk/DiskImageVdi.java +++ b/src/main/java/org/openslx/vm/disk/DiskImageVdi.java @@ -2,6 +2,8 @@ package org.openslx.vm.disk; import java.io.RandomAccessFile; +import org.openslx.virtualization.Version; + /** * VDI disk image for virtual machines. * @@ -78,14 +80,14 @@ public class DiskImageVdi extends DiskImage } @Override - public int getVersion() throws DiskImageException + public Version getVersion() throws DiskImageException { final RandomAccessFile diskFile = this.getDiskImage(); final short vdiVersionMajor = Short.reverseBytes( DiskImageUtils.readShort( diskFile, 68 ) ); final short vdiVersionMinor = Short.reverseBytes( DiskImageUtils.readShort( diskFile, 70 ) ); - return DiskImageUtils.versionFromMajorMinor( vdiVersionMajor, vdiVersionMinor ); + return new Version( vdiVersionMajor, vdiVersionMinor ); } @Override diff --git a/src/main/java/org/openslx/vm/disk/DiskImageVmdk.java b/src/main/java/org/openslx/vm/disk/DiskImageVmdk.java index 58314fc..75a2bac 100644 --- a/src/main/java/org/openslx/vm/disk/DiskImageVmdk.java +++ b/src/main/java/org/openslx/vm/disk/DiskImageVmdk.java @@ -3,8 +3,9 @@ package org.openslx.vm.disk; import java.io.RandomAccessFile; import org.openslx.util.Util; -import org.openslx.vm.UnsupportedVirtualizerFormatException; -import org.openslx.vm.VmwareConfig; +import org.openslx.virtualization.configuration.VirtualizationConfigurationVmwareFileFormat; +import org.openslx.virtualization.Version; +import org.openslx.virtualization.configuration.VirtualizationConfigurationException; /** * VMDK (sparse extent) disk image for virtual machines. @@ -32,7 +33,7 @@ public class DiskImageVmdk extends DiskImage /** * Stores disk configuration if VMDK disk image contains an embedded descriptor file. */ - private final VmwareConfig vmdkConfig; + private final VirtualizationConfigurationVmwareFileFormat vmdkConfig; /** * Creates a new VMDK disk image from an existing VMDK image file. @@ -80,7 +81,7 @@ public class DiskImageVmdk extends DiskImage */ private String getCreationType() { - final VmwareConfig vmdkConfig = this.getVmdkConfig(); + final VirtualizationConfigurationVmwareFileFormat vmdkConfig = this.getVmdkConfig(); final String vmdkCreationType; if ( vmdkConfig == null ) { @@ -103,10 +104,10 @@ public class DiskImageVmdk extends DiskImage * * @throws DiskImageException parsing of the VMDK's embedded descriptor file failed. */ - protected VmwareConfig parseVmdkConfig() throws DiskImageException + protected VirtualizationConfigurationVmwareFileFormat parseVmdkConfig() throws DiskImageException { final RandomAccessFile diskFile = this.getDiskImage(); - final VmwareConfig vmdkConfig; + final VirtualizationConfigurationVmwareFileFormat vmdkConfig; // get offset and size of descriptor file embedded into the VMDK disk image final long vmdkDescriptorSectorOffset = Long.reverseBytes( DiskImageUtils.readLong( diskFile, 28 ) ); @@ -133,8 +134,8 @@ public class DiskImageVmdk extends DiskImage // create configuration instance from content of the descriptor file try { - vmdkConfig = new VmwareConfig( configStr.getBytes(), vmdkDescriptorSize ); - } catch ( UnsupportedVirtualizerFormatException e ) { + vmdkConfig = new VirtualizationConfigurationVmwareFileFormat( configStr.getBytes(), vmdkDescriptorSize ); + } catch ( VirtualizationConfigurationException e ) { throw new DiskImageException( e.getLocalizedMessage() ); } } else { @@ -150,7 +151,7 @@ public class DiskImageVmdk extends DiskImage * * @return parsed configuration of the VMDK's embedded descriptor file. */ - protected VmwareConfig getVmdkConfig() + protected VirtualizationConfigurationVmwareFileFormat getVmdkConfig() { return this.vmdkConfig; } @@ -163,12 +164,13 @@ public class DiskImageVmdk extends DiskImage * * @return hardware version from the VMDK's embedded descriptor file. * - * @throws DiskImageException + * @throws DiskImageException unable to obtain the VMDK's hardware version of the disk image + * format. */ - public int getHwVersion() throws DiskImageException + public Version getHwVersion() throws DiskImageException { - final VmwareConfig vmdkConfig = this.getVmdkConfig(); - final int hwVersion; + final VirtualizationConfigurationVmwareFileFormat vmdkConfig = this.getVmdkConfig(); + final Version hwVersion; if ( vmdkConfig != null ) { // VMDK image contains a hardware version, so return parsed hardware version @@ -176,11 +178,11 @@ public class DiskImageVmdk extends DiskImage final String hwVersionStr = vmdkConfig.get( "ddb.virtualHWVersion" ); final int hwVersionMajor = Util.parseInt( hwVersionStr, DiskImageVmdk.VMDK_DEFAULT_HW_VERSION ); - hwVersion = DiskImageUtils.versionFromMajor( Integer.valueOf( hwVersionMajor ).shortValue() ); + hwVersion = new Version( Integer.valueOf( hwVersionMajor ).shortValue() ); } else { // VMDK image does not contain any hardware version, so return default hardware version final int hwVersionMajor = DiskImageVmdk.VMDK_DEFAULT_HW_VERSION; - hwVersion = DiskImageUtils.versionFromMajor( Integer.valueOf( hwVersionMajor ).shortValue() ); + hwVersion = new Version( Integer.valueOf( hwVersionMajor ).shortValue() ); } return hwVersion; @@ -233,7 +235,7 @@ public class DiskImageVmdk extends DiskImage @Override public boolean isSnapshot() throws DiskImageException { - final VmwareConfig vmdkConfig = this.getVmdkConfig(); + final VirtualizationConfigurationVmwareFileFormat vmdkConfig = this.getVmdkConfig(); final boolean vmdkSnapshot; if ( vmdkConfig == null ) { @@ -257,12 +259,12 @@ public class DiskImageVmdk extends DiskImage } @Override - public int getVersion() throws DiskImageException + public Version getVersion() throws DiskImageException { final RandomAccessFile diskFile = this.getDiskImage(); final int vmdkVersion = Integer.reverseBytes( DiskImageUtils.readInt( diskFile, 4 ) ); - return DiskImageUtils.versionFromMajor( Integer.valueOf( vmdkVersion ).shortValue() ); + return new Version( Integer.valueOf( vmdkVersion ).shortValue() ); } @Override |