diff options
Diffstat (limited to 'src/main/java/org/openslx')
11 files changed, 669 insertions, 84 deletions
diff --git a/src/main/java/org/openslx/libvirt/domain/Domain.java b/src/main/java/org/openslx/libvirt/domain/Domain.java index c8f5303..50d0811 100644 --- a/src/main/java/org/openslx/libvirt/domain/Domain.java +++ b/src/main/java/org/openslx/libvirt/domain/Domain.java @@ -261,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. 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/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/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/virtualization/Version.java b/src/main/java/org/openslx/virtualization/Version.java index 5d99ac1..698e22e 100644 --- a/src/main/java/org/openslx/virtualization/Version.java +++ b/src/main/java/org/openslx/virtualization/Version.java @@ -2,6 +2,8 @@ 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. @@ -14,8 +16,33 @@ import java.util.function.Predicate; */ 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; /** @@ -173,6 +200,43 @@ public class Version implements Comparable<Version> return supportedVersions.stream().filter( byMajorMinor ).findFirst().orElse( null ); } + /** + * 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 boolean equals( Object obj ) { diff --git a/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfiguration.java b/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfiguration.java index 0ecd693..cd8af1e 100644 --- a/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfiguration.java +++ b/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfiguration.java @@ -8,7 +8,6 @@ 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; @@ -125,7 +124,7 @@ public abstract class VirtualizationConfiguration<T, U, W, X> protected final List<HardDisk> hdds = new ArrayList<HardDisk>(); - private final List<OperatingSystem> osList; + protected final List<OperatingSystem> osList; private OperatingSystem os = null; @@ -180,6 +179,16 @@ public abstract class VirtualizationConfiguration<T, U, W, X> { 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. @@ -216,43 +225,19 @@ public abstract class VirtualizationConfiguration<T, U, W, X> public VirtualizationConfiguration( Virtualizer virtualizer, List<OperatingSystem> osList ) { this.virtualizer = virtualizer; - this.osList = osList; + + 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(); } /** - * 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 a VmMetaData instance of the given machine description given as file * * @param osList List of supported operating systems diff --git a/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationQemu.java b/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationQemu.java index 710a42d..e844e4e 100644 --- a/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationQemu.java +++ b/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationQemu.java @@ -13,6 +13,8 @@ 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; @@ -24,6 +26,7 @@ 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.util.LevenshteinDistance; import org.openslx.virtualization.Version; import org.openslx.virtualization.virtualizer.VirtualizerQemu; @@ -284,6 +287,9 @@ public class VirtualizationConfigurationQemu 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() ); } /** @@ -302,6 +308,44 @@ public class VirtualizationConfigurationQemu extends this.hdds.add( new HardDisk( hddChipsetModel, hddChipsetBus, hddImagePath ) ); } + /** + * Detects the operating system by the specified libosinfo operating system identifier. + * + * @param osId libosinfo operating system identifier. + */ + private OperatingSystem detectOperatingSystem( String osId ) + { + OperatingSystem os = null; + + if ( osId != null && !osId.isEmpty() ) { + // lookup operating system identifier in the libosinfo database + final Os osLookup = LibOsInfo.lookupOs( osId ); + + // 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( 1, 1, 1 ); + int smallestDistance = Integer.MAX_VALUE; + + // get name of the OS and combine it with the optional available architecture + final String osLookupOsName = osLookup.getName() + " " + this.vmConfig.getOsArch(); + + 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 void transformEditable() throws VirtualizationConfigurationException { @@ -384,7 +428,8 @@ public class VirtualizationConfigurationQemu extends @Override public void setOs( String vendorOsId ) { - this.setOs( vendorOsId ); + final OperatingSystem os = this.detectOperatingSystem( vendorOsId ); + this.setOs( os ); } @Override 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/virtualization/configuration/VirtualizationConfigurationVirtualBox.java b/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationVirtualBox.java index c53a7e0..8225af1 100644 --- a/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationVirtualBox.java +++ b/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationVirtualBox.java @@ -59,6 +59,7 @@ class VBoxUsbSpeedMeta { public final String value; public final int speed; + public VBoxUsbSpeedMeta( String value, int speed ) { this.value = value; @@ -66,13 +67,14 @@ class VBoxUsbSpeedMeta } } -public class VirtualizationConfigurationVirtualBox extends VirtualizationConfiguration<VBoxSoundCardMeta, VBoxDDAccelMeta, VBoxEthernetDevTypeMeta, VBoxUsbSpeedMeta> +public class VirtualizationConfigurationVirtualBox + extends VirtualizationConfiguration<VBoxSoundCardMeta, VBoxDDAccelMeta, VBoxEthernetDevTypeMeta, VBoxUsbSpeedMeta> { /** * File name extension for VirtualBox virtualization configuration files.. */ public static final String FILE_NAME_EXTENSION = "vbox"; - + private static final Logger LOGGER = Logger.getLogger( VirtualizationConfigurationVirtualBox.class ); private final VirtualizationConfigurationVirtualboxFileFormat config; @@ -89,14 +91,16 @@ public class VirtualizationConfigurationVirtualBox extends VirtualizationConfigu } } - public VirtualizationConfigurationVirtualBox( List<OperatingSystem> osList, File file ) throws IOException, VirtualizationConfigurationException + public VirtualizationConfigurationVirtualBox( List<OperatingSystem> osList, File file ) + throws IOException, VirtualizationConfigurationException { super( new VirtualizerVirtualBox(), osList ); this.config = new VirtualizationConfigurationVirtualboxFileFormat( file ); init(); } - public VirtualizationConfigurationVirtualBox( List<OperatingSystem> osList, byte[] vmContent, int length ) throws IOException, VirtualizationConfigurationException + public VirtualizationConfigurationVirtualBox( List<OperatingSystem> osList, byte[] vmContent, int length ) + throws IOException, VirtualizationConfigurationException { super( new VirtualizerVirtualBox(), osList ); this.config = new VirtualizationConfigurationVirtualboxFileFormat( vmContent, length ); @@ -118,11 +122,11 @@ public class VirtualizationConfigurationVirtualBox extends VirtualizationConfigu { // TODO Auto-generated method stub } - + @Override public void transformPrivacy() throws VirtualizationConfigurationException { - + } @Override @@ -136,11 +140,12 @@ public class VirtualizationConfigurationVirtualBox extends VirtualizationConfigu { 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; } @@ -156,7 +161,8 @@ public class VirtualizationConfigurationVirtualBox extends VirtualizationConfigu // 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 @@ -206,7 +212,10 @@ public class VirtualizationConfigurationVirtualBox extends VirtualizationConfigu 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 @@ -225,7 +234,8 @@ public class VirtualizationConfigurationVirtualBox extends VirtualizationConfigu 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 ) { @@ -265,20 +275,24 @@ public class VirtualizationConfigurationVirtualBox extends VirtualizationConfigu LOGGER.error( "Failed to add <Image> to floppy device." ); return; } - floppyImage.setAttribute( "uuid", VirtualizationConfigurationVirtualboxFileFormat.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", VirtualizationConfigurationVirtualboxFileFormat.PlaceHolder.FLOPPYUUID.toString() ); - floppyImageReg.setAttribute( "location", VirtualizationConfigurationVirtualboxFileFormat.PlaceHolder.FLOPPYLOCATION.toString() ); + floppyImageReg.setAttribute( "uuid", + VirtualizationConfigurationVirtualboxFileFormat.PlaceHolder.FLOPPYUUID.toString() ); + floppyImageReg.setAttribute( "location", + VirtualizationConfigurationVirtualboxFileFormat.PlaceHolder.FLOPPYLOCATION.toString() ); } } @@ -299,7 +313,8 @@ public class VirtualizationConfigurationVirtualBox extends VirtualizationConfigu 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 ); } @@ -309,7 +324,8 @@ public class VirtualizationConfigurationVirtualBox extends VirtualizationConfigu // initialize here to type None to avoid all null pointer exceptions thrown for unknown user written sound cards 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} @@ -318,7 +334,8 @@ public class VirtualizationConfigurationVirtualBox extends VirtualizationConfigu } else { String controller = x.getAttribute( "controller" ); VBoxSoundCardMeta soundMeta = null; - for ( VirtualizationConfiguration.SoundCardType type : VirtualizationConfiguration.SoundCardType.values() ) { + for ( VirtualizationConfiguration.SoundCardType type : VirtualizationConfiguration.SoundCardType + .values() ) { soundMeta = soundCards.get( type ); if ( soundMeta != null ) { if ( controller.equals( soundMeta.value ) ) { @@ -335,7 +352,8 @@ public class VirtualizationConfigurationVirtualBox extends VirtualizationConfigu 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 @@ -377,8 +395,10 @@ public class VirtualizationConfigurationVirtualBox extends VirtualizationConfigu 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 @@ -386,7 +406,8 @@ public class VirtualizationConfigurationVirtualBox extends VirtualizationConfigu { 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} @@ -395,7 +416,8 @@ public class VirtualizationConfigurationVirtualBox extends VirtualizationConfigu } else { String temp = x.getAttribute( "type" ); VBoxEthernetDevTypeMeta etherMeta = null; - for ( VirtualizationConfiguration.EthernetDevType type : VirtualizationConfiguration.EthernetDevType.values() ) { + for ( VirtualizationConfiguration.EthernetDevType type : VirtualizationConfiguration.EthernetDevType + .values() ) { etherMeta = networkCards.get( type ); if ( etherMeta != null ) { if ( temp.equals( etherMeta.value ) ) { @@ -421,14 +443,21 @@ public class VirtualizationConfigurationVirtualBox extends VirtualizationConfigu 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( 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" ) ); - + 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 ) ); @@ -438,7 +467,8 @@ public class VirtualizationConfigurationVirtualBox extends VirtualizationConfigu @Override 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; @@ -498,7 +528,7 @@ public class VirtualizationConfigurationVirtualBox extends VirtualizationConfigu LOGGER.info( "Not ATTRIBUTE type" ); continue; } - String type = ((Attr)nodes.item( i )).getValue(); + 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; @@ -514,7 +544,7 @@ public class VirtualizationConfigurationVirtualBox extends VirtualizationConfigu { return VirtualizationConfigurationVirtualBox.FILE_NAME_EXTENSION; } - + @Override public void validate() throws VirtualizationConfigurationException { diff --git a/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationVmware.java b/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationVmware.java index 3e8d913..39aaae5 100644 --- a/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationVmware.java +++ b/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationVmware.java @@ -54,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" ); @@ -62,16 +62,18 @@ class VmwareUsbSpeed } } -public class VirtualizationConfigurationVmware extends VirtualizationConfiguration<VmWareSoundCardMeta, VmWareDDAccelMeta, VmWareEthernetDevTypeMeta, VmwareUsbSpeed> +public class VirtualizationConfigurationVmware extends + VirtualizationConfiguration<VmWareSoundCardMeta, VmWareDDAccelMeta, VmWareEthernetDevTypeMeta, VmwareUsbSpeed> { /** * File name extension for VMware virtualization configuration files. */ public static final String FILE_NAME_EXTENSION = "vmx"; - + 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; @@ -80,9 +82,12 @@ public class VirtualizationConfigurationVmware extends VirtualizationConfigurati // 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 ) { @@ -104,14 +109,16 @@ public class VirtualizationConfigurationVmware extends VirtualizationConfigurati private final Map<String, Controller> disks = new HashMap<>(); - public VirtualizationConfigurationVmware( List<OperatingSystem> osList, File file ) throws IOException, VirtualizationConfigurationException + public VirtualizationConfigurationVmware( List<OperatingSystem> osList, File file ) + throws IOException, VirtualizationConfigurationException { super( new VirtualizerVmware(), osList ); this.config = new VirtualizationConfigurationVmwareFileFormat( file ); init(); } - public VirtualizationConfigurationVmware( List<OperatingSystem> osList, byte[] vmxContent, int length ) throws VirtualizationConfigurationException + public VirtualizationConfigurationVmware( List<OperatingSystem> osList, byte[] vmxContent, int length ) + throws VirtualizationConfigurationException { super( new VirtualizerVmware(), osList ); this.config = new VirtualizationConfigurationVmwareFileFormat( vmxContent, length ); // still unfiltered @@ -237,7 +244,7 @@ public class VirtualizationConfigurationVmware extends VirtualizationConfigurati device.present = Boolean.parseBoolean( value ); } } - + @Override public boolean addEmptyHddTemplate() { @@ -419,7 +426,10 @@ public class VirtualizationConfigurationVmware extends VirtualizationConfigurati public void setOs( String vendorOsId ) { addFiltered( "guestOS", vendorOsId ); - setOs( TConst.VIRT_VMWARE, vendorOsId ); + + final OperatingSystem os = VirtualizationConfigurationUtils.getOsOfVirtualizerFromList( this.osList, + TConst.VIRT_VMWARE, vendorOsId ); + this.setOs( os ); } public byte[] getConfigurationAsByteArray() @@ -536,7 +546,8 @@ public class VirtualizationConfigurationVmware extends VirtualizationConfigurati String temp = config.get( "ethernet" + cardIndex + ".virtualDev" ); if ( temp != null ) { VmWareEthernetDevTypeMeta ethernetDevTypeMeta = null; - for ( VirtualizationConfiguration.EthernetDevType type : VirtualizationConfiguration.EthernetDevType.values() ) { + for ( VirtualizationConfiguration.EthernetDevType type : VirtualizationConfiguration.EthernetDevType + .values() ) { ethernetDevTypeMeta = networkCards.get( type ); if ( ethernetDevTypeMeta == null ) { continue; |