summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManuel Bentele2021-05-05 09:37:45 +0200
committerManuel Bentele2021-05-05 09:37:45 +0200
commit07e2d0fdde3c85ea6d126e8986694a091f1803ff (patch)
treecd49d98653377d3003f24a95c0757bf1480bce14
parentAdd libosinfo database and validation schema files for Libvirt (diff)
downloadmaster-sync-shared-07e2d0fdde3c85ea6d126e8986694a091f1803ff.tar.gz
master-sync-shared-07e2d0fdde3c85ea6d126e8986694a091f1803ff.tar.xz
master-sync-shared-07e2d0fdde3c85ea6d126e8986694a091f1803ff.zip
Add OS detection for Libvirt/QEMU virtualization configurations
-rw-r--r--pom.xml2
-rw-r--r--src/main/java/org/openslx/libvirt/domain/Domain.java11
-rw-r--r--src/main/java/org/openslx/libvirt/libosinfo/LibOsInfo.java158
-rw-r--r--src/main/java/org/openslx/libvirt/libosinfo/os/Os.java93
-rw-r--r--src/main/java/org/openslx/libvirt/xml/LibvirtXmlResources.java59
-rw-r--r--src/main/java/org/openslx/util/LevenshteinDistance.java85
-rw-r--r--src/main/java/org/openslx/virtualization/Version.java64
-rw-r--r--src/main/java/org/openslx/virtualization/configuration/VirtualizationConfiguration.java51
-rw-r--r--src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationQemu.java47
-rw-r--r--src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationUtils.java52
-rw-r--r--src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationVirtualBox.java98
-rw-r--r--src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationVmware.java35
-rw-r--r--src/test/java/org/openslx/libvirt/domain/DomainTest.java8
-rw-r--r--src/test/java/org/openslx/libvirt/libosinfo/LibOsInfoTest.java28
-rw-r--r--src/test/java/org/openslx/virtualization/VersionTest.java17
-rw-r--r--src/test/java/org/openslx/virtualization/configuration/VirtualizationConfigurationQemuTest.java40
-rw-r--r--src/test/java/org/openslx/virtualization/configuration/logic/ConfigurationLogicTestUtils.java2
-rw-r--r--src/test/resources/libvirt/xml/qemu-kvm_default-ubuntu-20-04-vm_i686.xml164
18 files changed, 929 insertions, 85 deletions
diff --git a/pom.xml b/pom.xml
index b48bb26..ff2d062 100644
--- a/pom.xml
+++ b/pom.xml
@@ -87,6 +87,8 @@
<resource>
<directory>${basedir}/src/main/resources</directory>
<includes>
+ <include>libvirt/libosinfo/rng/*</include>
+ <include>libvirt/libosinfo/xml/*</include>
<include>libvirt/rng/*</include>
<include>libvirt/xsl/*</include>
</includes>
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;
diff --git a/src/test/java/org/openslx/libvirt/domain/DomainTest.java b/src/test/java/org/openslx/libvirt/domain/DomainTest.java
index aa556f9..e1fb73b 100644
--- a/src/test/java/org/openslx/libvirt/domain/DomainTest.java
+++ b/src/test/java/org/openslx/libvirt/domain/DomainTest.java
@@ -111,6 +111,14 @@ public class DomainTest
}
@Test
+ @DisplayName( "Get VM libosinfo operating system identifier in libvirt XML file" )
+ public void testGetLibOsInfoOsId()
+ {
+ Domain vm = this.newDomainInstance( "qemu-kvm_default-ubuntu-20-04-vm.xml" );
+ assertEquals( "http://ubuntu.com/ubuntu/20.04", vm.getLibOsInfoOsId() );
+ }
+
+ @Test
@DisplayName( "Get VM UUID from libvirt XML file" )
public void testGetUuid()
{
diff --git a/src/test/java/org/openslx/libvirt/libosinfo/LibOsInfoTest.java b/src/test/java/org/openslx/libvirt/libosinfo/LibOsInfoTest.java
new file mode 100644
index 0000000..af1c611
--- /dev/null
+++ b/src/test/java/org/openslx/libvirt/libosinfo/LibOsInfoTest.java
@@ -0,0 +1,28 @@
+package org.openslx.libvirt.libosinfo;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.openslx.libvirt.libosinfo.os.Os;
+import org.openslx.virtualization.Version;
+
+public class LibOsInfoTest
+{
+ @Test
+ @DisplayName( "Test the lookup of an operating system" )
+ public void testOsLookup()
+ {
+ final String osId = "http://ubuntu.com/ubuntu/20.04";
+ final Os os = LibOsInfo.lookupOs( osId );
+
+ assertNotNull( os );
+
+ assertEquals( osId, os.getId() );
+ assertEquals( "Ubuntu 20.04", os.getName() );
+ assertEquals( "linux", os.getFamily() );
+ assertEquals( "ubuntu", os.getDistro() );
+ assertEquals( new Version( Short.valueOf( "20" ), Short.valueOf( "04" ) ), os.getVersion() );
+ }
+}
diff --git a/src/test/java/org/openslx/virtualization/VersionTest.java b/src/test/java/org/openslx/virtualization/VersionTest.java
index c1ad21b..988437a 100644
--- a/src/test/java/org/openslx/virtualization/VersionTest.java
+++ b/src/test/java/org/openslx/virtualization/VersionTest.java
@@ -2,6 +2,7 @@ package org.openslx.virtualization;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.Arrays;
@@ -42,6 +43,22 @@ public class VersionTest
}
@Test
+ @DisplayName( "Test that new version from String is valid" )
+ public void testVersionValueOfValid()
+ {
+ assertEquals( new Version( Short.valueOf( "52" ) ), Version.valueOf( "52" ) );
+ assertEquals( new Version( Short.valueOf( "1" ), Short.valueOf( "34" ) ), Version.valueOf( "1.34" ) );
+ }
+
+ @Test
+ @DisplayName( "Test that new version from String is invalid" )
+ public void testVersionValueOfInvalid()
+ {
+ assertNull( Version.valueOf( "52." ) );
+ assertNull( Version.valueOf( "1.34-release" ) );
+ }
+
+ @Test
@DisplayName( "Test that versions are equal" )
public void testVersionEquals()
{
diff --git a/src/test/java/org/openslx/virtualization/configuration/VirtualizationConfigurationQemuTest.java b/src/test/java/org/openslx/virtualization/configuration/VirtualizationConfigurationQemuTest.java
index b59a86d..1cc7841 100644
--- a/src/test/java/org/openslx/virtualization/configuration/VirtualizationConfigurationQemuTest.java
+++ b/src/test/java/org/openslx/virtualization/configuration/VirtualizationConfigurationQemuTest.java
@@ -25,6 +25,7 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;
+import org.openslx.bwlp.thrift.iface.OperatingSystem;
import org.openslx.libvirt.domain.Domain;
import org.openslx.libvirt.domain.device.ControllerUsb;
import org.openslx.libvirt.domain.device.DiskCdrom;
@@ -38,12 +39,15 @@ import org.openslx.virtualization.configuration.VirtualizationConfiguration.Ethe
import org.openslx.virtualization.configuration.VirtualizationConfiguration.EthernetDevType;
import org.openslx.virtualization.configuration.VirtualizationConfiguration.SoundCardType;
import org.openslx.virtualization.configuration.VirtualizationConfiguration.UsbSpeed;
+import org.openslx.virtualization.configuration.logic.ConfigurationLogicTestUtils;
import org.openslx.vm.disk.DiskImage;
import org.openslx.vm.disk.DiskImageTestResources;
import org.openslx.vm.disk.DiskImage.ImageFormat;
public class VirtualizationConfigurationQemuTest
{
+ public static final List<OperatingSystem> STUB_OS_LIST = ConfigurationLogicTestUtils.STUB_OS_LIST;
+
private static Domain getPrivateDomainFromQemuMetaData( VirtualizationConfigurationQemu qemuMetadata )
throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException
{
@@ -111,6 +115,42 @@ public class VirtualizationConfigurationQemuTest
}
@Test
+ @DisplayName( "Test output of detected 32-bit OS from VM configuration" )
+ public void testQemuMetaDataGetOs32Bit()
+ throws VirtualizationConfigurationException, IOException, NoSuchFieldException, SecurityException,
+ IllegalArgumentException, IllegalAccessException
+ {
+ final File file = LibvirtXmlTestResources.getLibvirtXmlFile( "qemu-kvm_default-ubuntu-20-04-vm_i686.xml" );
+ final VirtualizationConfigurationQemu vmConfig = new VirtualizationConfigurationQemu(
+ VirtualizationConfigurationQemuTest.STUB_OS_LIST, file );
+
+ final OperatingSystem os = vmConfig.getOs();
+
+ assertNotNull( os );
+ assertEquals( VirtualizationConfigurationQemuTest.STUB_OS_LIST.get( 3 ), os );
+
+ assertDoesNotThrow( () -> vmConfig.validate() );
+ }
+
+ @Test
+ @DisplayName( "Test output of detected 64-bit OS from VM configuration" )
+ public void testQemuMetaDataGetOs64Bit()
+ throws VirtualizationConfigurationException, IOException, NoSuchFieldException, SecurityException,
+ IllegalArgumentException, IllegalAccessException
+ {
+ final File file = LibvirtXmlTestResources.getLibvirtXmlFile( "qemu-kvm_default-ubuntu-20-04-vm.xml" );
+ final VirtualizationConfigurationQemu vmConfig = new VirtualizationConfigurationQemu(
+ VirtualizationConfigurationQemuTest.STUB_OS_LIST, file );
+
+ final OperatingSystem os = vmConfig.getOs();
+
+ assertNotNull( os );
+ assertEquals( VirtualizationConfigurationQemuTest.STUB_OS_LIST.get( 4 ), os );
+
+ assertDoesNotThrow( () -> vmConfig.validate() );
+ }
+
+ @Test
@DisplayName( "Test output of HDDs from VM configuration" )
public void testQemuMetaDataGetHdds()
throws VirtualizationConfigurationException, IOException, NoSuchFieldException, SecurityException,
diff --git a/src/test/java/org/openslx/virtualization/configuration/logic/ConfigurationLogicTestUtils.java b/src/test/java/org/openslx/virtualization/configuration/logic/ConfigurationLogicTestUtils.java
index 4f85719..07046b5 100644
--- a/src/test/java/org/openslx/virtualization/configuration/logic/ConfigurationLogicTestUtils.java
+++ b/src/test/java/org/openslx/virtualization/configuration/logic/ConfigurationLogicTestUtils.java
@@ -21,7 +21,7 @@ import org.openslx.virtualization.configuration.VirtualizationConfiguration;
public class ConfigurationLogicTestUtils
{
// @formatter:off
- private static final List<OperatingSystem> STUB_OS_LIST = Collections.unmodifiableList( Arrays.asList(
+ public static final List<OperatingSystem> STUB_OS_LIST = Collections.unmodifiableList( Arrays.asList(
new OperatingSystem( 1, "Windows 7 (64 Bit)", null, "AMD64", 196608, 256 ),
new OperatingSystem( 2, "Windows 8 (32 Bit)", null, "x86", 4096, 32 ),
new OperatingSystem( 3, "Windows 8 (64 Bit)", null, "AMD64", 131072, 256 ),
diff --git a/src/test/resources/libvirt/xml/qemu-kvm_default-ubuntu-20-04-vm_i686.xml b/src/test/resources/libvirt/xml/qemu-kvm_default-ubuntu-20-04-vm_i686.xml
new file mode 100644
index 0000000..91e86e6
--- /dev/null
+++ b/src/test/resources/libvirt/xml/qemu-kvm_default-ubuntu-20-04-vm_i686.xml
@@ -0,0 +1,164 @@
+<domain type='kvm'>
+ <name>ubuntu-20-04</name>
+ <uuid>8dc5433c-0228-49e4-b019-fa2b606aa544</uuid>
+ <title>Ubuntu 20.04</title>
+ <description>Ubuntu 20.04 desktop installation</description>
+ <metadata>
+ <libosinfo:libosinfo xmlns:libosinfo="http://libosinfo.org/xmlns/libvirt/domain/1.0">
+ <libosinfo:os id="http://ubuntu.com/ubuntu/20.04"/>
+ </libosinfo:libosinfo>
+ </metadata>
+ <memory unit='KiB'>4194304</memory>
+ <currentMemory unit='KiB'>4194304</currentMemory>
+ <vcpu placement='static'>2</vcpu>
+ <os>
+ <type arch='i686' machine='pc-q35-5.1'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <features>
+ <acpi/>
+ <apic/>
+ <vmport state='off'/>
+ </features>
+ <cpu mode='host-model' check='partial'/>
+ <clock offset='utc'>
+ <timer name='rtc' tickpolicy='catchup'/>
+ <timer name='pit' tickpolicy='delay'/>
+ <timer name='hpet' present='no'/>
+ </clock>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <pm>
+ <suspend-to-mem enabled='no'/>
+ <suspend-to-disk enabled='no'/>
+ </pm>
+ <devices>
+ <emulator>/usr/bin/qemu-system-x86_64</emulator>
+ <disk type='block' device='disk'>
+ <driver name='qemu' type='raw' cache='none' io='native'/>
+ <source dev='/dev/data/ubuntu-20-04.img'/>
+ <target dev='vda' bus='virtio'/>
+ <address type='pci' domain='0x0000' bus='0x03' slot='0x00' function='0x0'/>
+ </disk>
+ <disk type='file' device='cdrom'>
+ <driver name='qemu' type='raw'/>
+ <target dev='sda' bus='sata'/>
+ <readonly/>
+ <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+ </disk>
+ <disk type='file' device='floppy'>
+ <driver name='qemu' type='raw'/>
+ <target dev='fda' bus='fdc'/>
+ <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+ </disk>
+ <controller type='usb' index='0' model='ich9-ehci1'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x1d' function='0x7'/>
+ </controller>
+ <controller type='usb' index='0' model='ich9-uhci1'>
+ <master startport='0'/>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x1d' function='0x0' multifunction='on'/>
+ </controller>
+ <controller type='usb' index='0' model='ich9-uhci2'>
+ <master startport='2'/>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x1d' function='0x1'/>
+ </controller>
+ <controller type='usb' index='0' model='ich9-uhci3'>
+ <master startport='4'/>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x1d' function='0x2'/>
+ </controller>
+ <controller type='sata' index='0'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/>
+ </controller>
+ <controller type='pci' index='0' model='pcie-root'/>
+ <controller type='pci' index='1' model='pcie-root-port'>
+ <model name='pcie-root-port'/>
+ <target chassis='1' port='0x10'/>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0' multifunction='on'/>
+ </controller>
+ <controller type='pci' index='2' model='pcie-root-port'>
+ <model name='pcie-root-port'/>
+ <target chassis='2' port='0x11'/>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x1'/>
+ </controller>
+ <controller type='pci' index='3' model='pcie-root-port'>
+ <model name='pcie-root-port'/>
+ <target chassis='3' port='0x12'/>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x2'/>
+ </controller>
+ <controller type='pci' index='4' model='pcie-root-port'>
+ <model name='pcie-root-port'/>
+ <target chassis='4' port='0x13'/>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x3'/>
+ </controller>
+ <controller type='pci' index='5' model='pcie-root-port'>
+ <model name='pcie-root-port'/>
+ <target chassis='5' port='0x14'/>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x4'/>
+ </controller>
+ <controller type='pci' index='6' model='pcie-root-port'>
+ <model name='pcie-root-port'/>
+ <target chassis='6' port='0x15'/>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x5'/>
+ </controller>
+ <controller type='virtio-serial' index='0'>
+ <address type='pci' domain='0x0000' bus='0x02' slot='0x00' function='0x0'/>
+ </controller>
+ <controller type='scsi' index='0' model='virtio-scsi'>
+ <address type='pci' domain='0x0000' bus='0x06' slot='0x00' function='0x0'/>
+ </controller>
+ <controller type='fdc' index='0'/>
+ <interface type='network'>
+ <mac address='52:54:00:0d:90:0c'/>
+ <source network='default'/>
+ <model type='virtio'/>
+ <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>
+ </interface>
+ <serial type='pty'>
+ <target type='isa-serial' port='0'>
+ <model name='isa-serial'/>
+ </target>
+ </serial>
+ <console type='pty'>
+ <target type='serial' port='0'/>
+ </console>
+ <channel type='unix'>
+ <target type='virtio' name='org.qemu.guest_agent.0'/>
+ <address type='virtio-serial' controller='0' bus='0' port='1'/>
+ </channel>
+ <channel type='spicevmc'>
+ <target type='virtio' name='com.redhat.spice.0'/>
+ <address type='virtio-serial' controller='0' bus='0' port='2'/>
+ </channel>
+ <input type='tablet' bus='usb'>
+ <address type='usb' bus='0' port='1'/>
+ </input>
+ <input type='mouse' bus='ps2'/>
+ <input type='keyboard' bus='ps2'/>
+ <graphics type='spice' autoport='yes'>
+ <listen type='address'/>
+ <image compression='off'/>
+ </graphics>
+ <sound model='ich9'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x1b' function='0x0'/>
+ </sound>
+ <video>
+ <model type='qxl' ram='65536' vram='65536' vgamem='16384' heads='1' primary='yes'/>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/>
+ </video>
+ <redirdev bus='usb' type='spicevmc'>
+ <address type='usb' bus='0' port='2'/>
+ </redirdev>
+ <redirdev bus='usb' type='spicevmc'>
+ <address type='usb' bus='0' port='3'/>
+ </redirdev>
+ <memballoon model='virtio'>
+ <address type='pci' domain='0x0000' bus='0x04' slot='0x00' function='0x0'/>
+ </memballoon>
+ <rng model='virtio'>
+ <backend model='random'>/dev/urandom</backend>
+ <address type='pci' domain='0x0000' bus='0x05' slot='0x00' function='0x0'/>
+ </rng>
+ </devices>
+</domain>
+