From 07661b83665c2db556d26dcc11c9ad380878b0ff Mon Sep 17 00:00:00 2001 From: Manuel Bentele Date: Thu, 15 Apr 2021 15:05:15 +0200 Subject: Move VmMetaData classes to new virtualization config directories --- src/main/java/org/openslx/util/ThriftUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/org/openslx/util') diff --git a/src/main/java/org/openslx/util/ThriftUtil.java b/src/main/java/org/openslx/util/ThriftUtil.java index 3c2c9ea..2cfc770 100644 --- a/src/main/java/org/openslx/util/ThriftUtil.java +++ b/src/main/java/org/openslx/util/ThriftUtil.java @@ -7,7 +7,7 @@ import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; -import org.openslx.vm.VmwareConfig; +import org.openslx.virtualization.configuration.machine.VmwareConfig; public class ThriftUtil { -- cgit v1.2.3-55-g7522 From 2d91c4b1094e25b4c4c94335364f5d3c31729521 Mon Sep 17 00:00:00 2001 From: Manuel Bentele Date: Fri, 16 Apr 2021 10:24:39 +0200 Subject: Rename VmMetaData classes --- src/main/java/org/openslx/util/ThriftUtil.java | 4 +- .../UnsupportedVirtualizerFormatException.java | 13 - .../configuration/VirtualizationConfiguration.java | 425 ++++++++++ .../VirtualizationConfigurationDocker.java | 219 +++++ .../VirtualizationConfigurationException.java | 13 + .../VirtualizationConfigurationQemu.java | 881 ++++++++++++++++++++ .../VirtualizationConfigurationQemuUtils.java | 191 +++++ .../VirtualizationConfigurationVirtualBox.java | 535 +++++++++++++ ...alizationConfigurationVirtualboxFileFormat.java | 631 +++++++++++++++ .../VirtualizationConfigurationVmware.java | 682 ++++++++++++++++ ...irtualizationConfigurationVmwareFileFormat.java | 288 +++++++ .../virtualization/configuration/VmMetaData.java | 429 ---------- .../container/DockerMetaDataDummy.java | 221 ------ .../configuration/machine/KeyValuePair.java | 13 - .../configuration/machine/QemuMetaData.java | 883 --------------------- .../configuration/machine/QemuMetaDataUtils.java | 191 ----- .../configuration/machine/VboxConfig.java | 632 --------------- .../configuration/machine/VboxMetaData.java | 537 ------------- .../configuration/machine/VmwareConfig.java | 277 ------- .../configuration/machine/VmwareMetaData.java | 684 ---------------- .../java/org/openslx/vm/disk/DiskImageVmdk.java | 22 +- .../VirtualizationConfigurationQemuTest.java | 550 +++++++++++++ .../configuration/machine/QemuMetaDataTest.java | 533 ------------- 23 files changed, 4428 insertions(+), 4426 deletions(-) delete mode 100644 src/main/java/org/openslx/virtualization/configuration/UnsupportedVirtualizerFormatException.java create mode 100644 src/main/java/org/openslx/virtualization/configuration/VirtualizationConfiguration.java create mode 100644 src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationDocker.java create mode 100644 src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationException.java create mode 100644 src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationQemu.java create mode 100644 src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationQemuUtils.java create mode 100644 src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationVirtualBox.java create mode 100644 src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationVirtualboxFileFormat.java create mode 100644 src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationVmware.java create mode 100644 src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationVmwareFileFormat.java delete mode 100644 src/main/java/org/openslx/virtualization/configuration/VmMetaData.java delete mode 100644 src/main/java/org/openslx/virtualization/configuration/container/DockerMetaDataDummy.java delete mode 100644 src/main/java/org/openslx/virtualization/configuration/machine/KeyValuePair.java delete mode 100644 src/main/java/org/openslx/virtualization/configuration/machine/QemuMetaData.java delete mode 100644 src/main/java/org/openslx/virtualization/configuration/machine/QemuMetaDataUtils.java delete mode 100644 src/main/java/org/openslx/virtualization/configuration/machine/VboxConfig.java delete mode 100644 src/main/java/org/openslx/virtualization/configuration/machine/VboxMetaData.java delete mode 100644 src/main/java/org/openslx/virtualization/configuration/machine/VmwareConfig.java delete mode 100644 src/main/java/org/openslx/virtualization/configuration/machine/VmwareMetaData.java create mode 100644 src/test/java/org/openslx/virtualization/configuration/VirtualizationConfigurationQemuTest.java delete mode 100644 src/test/java/org/openslx/virtualization/configuration/machine/QemuMetaDataTest.java (limited to 'src/main/java/org/openslx/util') diff --git a/src/main/java/org/openslx/util/ThriftUtil.java b/src/main/java/org/openslx/util/ThriftUtil.java index 2cfc770..a9035c1 100644 --- a/src/main/java/org/openslx/util/ThriftUtil.java +++ b/src/main/java/org/openslx/util/ThriftUtil.java @@ -7,7 +7,7 @@ import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; -import org.openslx.virtualization.configuration.machine.VmwareConfig; +import org.openslx.virtualization.configuration.VirtualizationConfigurationVmwareFileFormat; public class ThriftUtil { @@ -41,7 +41,7 @@ public class ThriftUtil { BufferedReader reader; StringBuffer content = new StringBuffer(""); try { - reader = VmwareConfig.getVmxReader(bytes, bytes.length); + reader = VirtualizationConfigurationVmwareFileFormat.getVmxReader(bytes, bytes.length); String line=""; while ((line=reader.readLine()) != null) { content.append(line + "\n"); diff --git a/src/main/java/org/openslx/virtualization/configuration/UnsupportedVirtualizerFormatException.java b/src/main/java/org/openslx/virtualization/configuration/UnsupportedVirtualizerFormatException.java deleted file mode 100644 index 3040669..0000000 --- a/src/main/java/org/openslx/virtualization/configuration/UnsupportedVirtualizerFormatException.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.openslx.virtualization.configuration; - -public class UnsupportedVirtualizerFormatException extends Exception -{ - /** - * Version for serialization. - */ - private static final long serialVersionUID = 5794121065945636839L; - - public UnsupportedVirtualizerFormatException(String message) { - super(message); - } -} \ No newline at end of file diff --git a/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfiguration.java b/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfiguration.java new file mode 100644 index 0000000..4f00b92 --- /dev/null +++ b/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfiguration.java @@ -0,0 +1,425 @@ +package org.openslx.virtualization.configuration; + +import java.io.File; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.log4j.Logger; +import org.openslx.bwlp.thrift.iface.OperatingSystem; +import org.openslx.bwlp.thrift.iface.Virtualizer; +import org.openslx.vm.disk.DiskImage; + +/** + * Describes a configured virtual machine. This class is parsed from a machine + * description, like a *.vmx for VMware machines. + */ +public abstract class VirtualizationConfiguration +{ + private static final Logger LOGGER = Logger.getLogger( VirtualizationConfiguration.class ); + + /* + * Helper types + */ + protected Map soundCards = new HashMap<>(); + protected Map ddacc = new HashMap<>(); + protected Map hwversion = new HashMap<>(); + protected Map networkCards = new HashMap<>(); + protected Map usbSpeeds = new HashMap<>(); + + /** + * Virtual sound cards types + */ + public static enum SoundCardType + { + NONE( "None" ), DEFAULT( "(default)" ), SOUND_BLASTER( "Sound Blaster 16" ), ES( "ES 1371" ), HD_AUDIO( "Intel Integrated HD Audio" ), AC( "Intel ICH Audio Codec 97" ); + + public final String displayName; + + private SoundCardType( String dName ) + { + this.displayName = dName; + } + } + + /** + * 3D acceleration types + */ + public static enum DDAcceleration + { + OFF( "Off" ), ON( "On" ); + + public final String displayName; + + private DDAcceleration( String dName ) + { + this.displayName = dName; + } + } + + /** + * Virtual hardware version - currently only in use for VMPlayer + */ + public static enum HWVersion + { + NONE( "(invalid)" ), + THREE( " 3 (Workstation 4/5, Player 1)" ), + FOUR( " 4 (Workstation 4/5, Player 1/2, Fusion 1)" ), + SIX( " 6 (Workstation 6)" ), + SEVEN( " 7 (Workstation 6.5/7, Player 3, Fusion 2/3)" ), + EIGHT( " 8 (Workstation 8, Player/Fusion 4)" ), + NINE( " 9 (Workstation 9, Player/Fusion 5)" ), + TEN( "10 (Workstation 10, Player/Fusion 6)" ), + ELEVEN( "11 (Workstation 11, Player/Fusion 7)" ), + TWELVE( "12 (Workstation/Player 12, Fusion 8)" ), + FOURTEEN( "14 (Workstation/Player 14, Fusion 10)"), + FIFTEEN( "15 (Workstation/Player 15, Fusion 11)"), + FIFTEEN_ONE( "16 (Workstation/Player 15.1, Fusion 11.1)"), + SIXTEEN( "17 (Workstation/Player 16, Fusion 12)"), + SIXTEEN_ONE( "18 (Workstation/Player 16.1, Fusion 12.1)"), + DEFAULT( "default" ); + + public final String displayName; + + private HWVersion( String dName ) + { + this.displayName = dName; + } + } + + /** + * Virtual network cards + */ + public static enum EthernetDevType + { + AUTO( "(default)" ), PCNET32( "AMD PCnet32" ), E1000( "Intel E1000 (PCI)" ), E1000E( "Intel E1000e (PCI-Express)" ), VMXNET( "VMXnet" ), VMXNET3( "VMXnet 3" ), PCNETPCI2( + "PCnet-PCI II" ), PCNETFAST3( "PCnet-FAST III" ), PRO1000MTD( "Intel PRO/1000 MT Desktop" ), PRO1000TS( + "Intel PRO/1000 T Server" ), PRO1000MTS( "Intel PRO/1000 MT Server" ), PARAVIRT( "Paravirtualized Network" ), NONE( "No Network Card" ); + + public final String displayName; + + private EthernetDevType( String dName ) + { + this.displayName = dName; + } + } + + public static enum UsbSpeed + { + NONE( "None" ), + USB1_1( "USB 1.1" ), + USB2_0( "USB 2.0" ), + USB3_0( "USB 3.0" ); + + public final String displayName; + + private UsbSpeed( String dName ) + { + this.displayName = dName; + } + } + + public static enum DriveBusType + { + SCSI, IDE, SATA, NVME; + } + + public static class HardDisk + { + public final String chipsetDriver; + public final DriveBusType bus; + public final String diskImage; + + public HardDisk( String chipsetDriver, DriveBusType bus, String diskImage ) + { + this.chipsetDriver = chipsetDriver; + this.bus = bus; + this.diskImage = diskImage; + } + } + + public static enum EtherType + { + NAT, BRIDGED, HOST_ONLY; + } + /* + * Members + */ + + protected final List hdds = new ArrayList(); + + private final List osList; + + private OperatingSystem os = null; + + protected String displayName = null; + + protected boolean isMachineSnapshot; + + /* + * Getters for virtual hardware + */ + public List getSupportedSoundCards() + { + ArrayList availables = new ArrayList( soundCards.keySet() ); + Collections.sort( availables ); + return availables; + } + + public List getSupportedDDAccs() + { + ArrayList availables = new ArrayList( ddacc.keySet() ); + Collections.sort( availables ); + return availables; + } + + public List getSupportedHWVersions() + { + ArrayList availables = new ArrayList( hwversion.keySet() ); + Collections.sort( availables ); + return availables; + } + + public List getSupportedEthernetDevices() + { + ArrayList availables = new ArrayList( networkCards.keySet() ); + Collections.sort( availables ); + return availables; + } + + public List getSupportedUsbSpeeds() + { + ArrayList availables = new ArrayList<>( usbSpeeds.keySet() ); + Collections.sort( availables ); + return availables; + } + + /** + * Get operating system of this VM. + */ + public OperatingSystem getOs() + { + return os; + } + + /** + * Get all hard disks of this VM. + */ + public List getHdds() + { + return Collections.unmodifiableList( hdds ); + } + + /** + * Get display name of VM. + */ + public String getDisplayName() + { + return displayName; + } + + /* + * Getter for isMachineSnapshot + */ + public boolean isMachineSnapshot() + { + return isMachineSnapshot; + } + + /** + * This method should return a minimal representation of the input meta data. + * The representation is platform dependent, and should be stripped of all + * non-essential configuration, such as CD/DVD/FLoppy drives, serial or parallel + * ports, shared folders, or anything else that could be considered sensible + * information (absolute paths containing the local user's name). + */ + public abstract byte[] getFilteredDefinitionArray(); + + public final ByteBuffer getFilteredDefinition() + { + return ByteBuffer.wrap( getFilteredDefinitionArray() ); + } + + /* + * Methods + */ + + public VirtualizationConfiguration( List osList ) + { + 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 entry : os.getVirtualizerOsId().entrySet() ) { + if ( !entry.getValue().equals( virtOsId ) ) + continue; + if ( entry.getKey().equals( virtId ) ) { + this.os = os; + return; + } else { + lazyMatch = os; + } + } + } + this.os = lazyMatch; + } + + /** + * Returns list of image formats supported by the VM's hypervisor. + * + * @return list of image formats. + */ + public abstract List getSupportedImageFormats(); + + /** + * Apply config options that are desired when locally editing a VM. for vmware, + * this disables automatic DPI scaling of the guest. + */ + public abstract void applySettingsForLocalEdit(); + + /** + * Returns a VmMetaData instance of the given machine description given as file + * + * @param osList List of supported operating systems + * @param file VM's machine description file to get the metadata instance from + * @return VmMetaData object representing the relevant parts of the given machine description + */ + public static VirtualizationConfiguration getInstance( List osList, File file ) + throws IOException + { + try { + return new VirtualizationConfigurationVmware( osList, file ); + } catch ( VirtualizationConfigurationException e ) { + LOGGER.info( "Not a VMware file", e ); + } + try { + return new VirtualizationConfigurationVirtualBox( osList, file ); + } catch ( VirtualizationConfigurationException e ) { + LOGGER.info( "Not a VirtualBox file", e ); + } + try { + return new VirtualizationConfigurationQemu( osList, file ); + } catch ( VirtualizationConfigurationException e ) { + LOGGER.info( "Not a Libvirt file", e ); + } + try { + return new VirtualizationConfigurationDocker(osList, file); + } catch ( Exception e ) { + LOGGER.info( "Not a tar.gz file, for docker container", e ); + } + + LOGGER.error( "Could not detect any known virtualizer format" ); + return null; + } + + /** + * Returns a VmMetaData instance of the given machine description given as a byte array + * + * @param osList List of supported operating systems + * @param vmContent VM's machine description as byte array (e.g. stored in DB) + * @param length length of the byte array given as vmContent + * @return VmMetaData object representing the relevant parts of the given machine description + * @throws IOException + */ + public static VirtualizationConfiguration getInstance( List osList, byte[] vmContent, int length ) + throws IOException + { + try { + return new VirtualizationConfigurationVmware( osList, vmContent, length ); + } catch ( VirtualizationConfigurationException e ) { + LOGGER.info( "Not a VMware file", e ); + } + try { + return new VirtualizationConfigurationVirtualBox( osList, vmContent, length ); + } catch ( VirtualizationConfigurationException e ) { + LOGGER.info( "Not a VirtualBox file", e ); + } + try { + return new VirtualizationConfigurationQemu( osList, vmContent, length ); + } catch ( VirtualizationConfigurationException e ) { + LOGGER.info( "Not a Libvirt file", e ); + } + try { + return new VirtualizationConfigurationDocker( osList, vmContent, length ); + } catch ( VirtualizationConfigurationException e ) { + LOGGER.info( "Not a tar.gz file, for docker container", e ); + } + + LOGGER.error( "Could not detect any known virtualizer format" ); + return null; + } + + public abstract boolean addHddTemplate( File diskImage, String hddMode, String redoDir ); + + public abstract boolean addHddTemplate( String diskImagePath, String hddMode, String redoDir ); + + public abstract boolean addDefaultNat(); + + public abstract void setOs( String vendorOsId ); + + public abstract boolean addDisplayName( String name ); + + public abstract boolean addRam( int mem ); + + public abstract void addFloppy( int index, String image, boolean readOnly ); + + public abstract boolean addCdrom( String image ); + + public abstract boolean addCpuCoreCount( int nrOfCores ); + + public abstract void setSoundCard( SoundCardType type ); + + public abstract SoundCardType getSoundCard(); + + public abstract void setDDAcceleration( DDAcceleration type ); + + public abstract DDAcceleration getDDAcceleration(); + + public abstract void setHWVersion( HWVersion type ); + + public abstract HWVersion getHWVersion(); + + public abstract void setEthernetDevType( int cardIndex, EthernetDevType type ); + + public abstract EthernetDevType getEthernetDevType( int cardIndex ); + + public abstract void setMaxUsbSpeed( UsbSpeed speed ); + + public abstract UsbSpeed getMaxUsbSpeed(); + + public abstract byte[] getDefinitionArray(); + + public abstract boolean addEthernet( EtherType type ); + + public abstract Virtualizer getVirtualizer(); + + public abstract boolean tweakForNonPersistent(); + + /** + * Function used to register virtual devices + */ + public abstract void registerVirtualHW(); +} diff --git a/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationDocker.java b/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationDocker.java new file mode 100644 index 0000000..b6f237b --- /dev/null +++ b/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationDocker.java @@ -0,0 +1,219 @@ +package org.openslx.virtualization.configuration; + +import org.apache.log4j.Logger; +import org.openslx.bwlp.thrift.iface.OperatingSystem; +import org.openslx.bwlp.thrift.iface.Virtualizer; +import org.openslx.thrifthelper.TConst; +import org.openslx.vm.disk.DiskImage; +import org.openslx.vm.disk.DiskImage.ImageFormat; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +class DockerSoundCardMeta +{ +} + +class DockerDDAccelMeta +{ +} + +class DockerHWVersionMeta +{ +} + +class DockerEthernetDevTypeMeta +{ +} + +class DockerUsbSpeedMeta +{ +} + +public class VirtualizationConfigurationDocker extends VirtualizationConfiguration { + + /** + * List of supported image formats by the Docker hypervisor. + */ + private static final List SUPPORTED_IMAGE_FORMATS = Collections.unmodifiableList( + Arrays.asList( ImageFormat.NONE ) ); + + private static final Logger LOGGER = Logger.getLogger( VirtualizationConfigurationDocker.class); + + private final Virtualizer virtualizer = new Virtualizer(TConst.VIRT_DOCKER, "Docker"); + + /** + * containerDefinition is a serialized tar.gz archive and represents a + * ContainerDefinition. This archive contains a serialized Container Recipe (e.g. Dockerfile) + * and a ContainerMeta witch is serialized as a json file. + *

+ * See ContainerDefintion in tutor-module (bwsuite). + *

+ * This field is in vm context the machine description e.g. vmware = vmx. + * This field will be stored in table imageversion.virtualizerconfig + */ + private byte[] containerDefinition; + + public VirtualizationConfigurationDocker(List osList, File file) throws VirtualizationConfigurationException { + super(osList); + + BufferedInputStream bis = null; + + try { + bis = new BufferedInputStream(new FileInputStream(file)); + containerDefinition = new byte[(int) file.length()]; + bis.read(containerDefinition); + + checkIsTarGz(); + } catch (IOException | VirtualizationConfigurationException e) { + LOGGER.error("Couldn't read dockerfile", e); + } finally { + try { + bis.close(); + } catch ( IOException e ) { + LOGGER.warn( "Could not close the input stream!" ); + } + } + } + + public VirtualizationConfigurationDocker(List osList, byte[] vmContent, int length) + throws VirtualizationConfigurationException { + super(osList); + + containerDefinition = vmContent; + + checkIsTarGz(); + } + + /* + TODO This is just a simple check to prevent the workflow from considering any content as acceptable. + */ + /** + * Checks if the first two bytes of the content identifies a tar.gz archive. + * The first byte is 31 == 0x1f, the second byte has to be -117 == 0x8b. + * + * @throws VirtualizationConfigurationException + */ + private void checkIsTarGz() throws VirtualizationConfigurationException { + if (!((31 == containerDefinition[0]) && (-117 == containerDefinition[1]))) { + LOGGER.warn("Not Supported Content."); + throw new VirtualizationConfigurationException( + "DockerMetaDataDummy: Not tar.gz encoded content!"); + } + } + + @Override public byte[] getFilteredDefinitionArray() { + return containerDefinition; + } + + @Override + public List getSupportedImageFormats() + { + return VirtualizationConfigurationDocker.SUPPORTED_IMAGE_FORMATS; + } + + @Override public void applySettingsForLocalEdit() { + + } + + @Override public boolean addHddTemplate(File diskImage, String hddMode, String redoDir) { + return false; + } + + @Override public boolean addHddTemplate(String diskImagePath, String hddMode, String redoDir) { + return false; + } + + @Override public boolean addDefaultNat() { + return false; + } + + @Override public void setOs(String vendorOsId) { + + } + + @Override public boolean addDisplayName(String name) { + return false; + } + + @Override public boolean addRam(int mem) { + return false; + } + + @Override public void addFloppy(int index, String image, boolean readOnly) { + + } + + @Override public boolean addCdrom(String image) { + return false; + } + + @Override public boolean addCpuCoreCount(int nrOfCores) { + return false; + } + + @Override public void setSoundCard(SoundCardType type) { + + } + + @Override public SoundCardType getSoundCard() { + return SoundCardType.NONE; + } + + @Override public void setDDAcceleration(DDAcceleration type) { + + } + + @Override public DDAcceleration getDDAcceleration() { + return DDAcceleration.OFF; + } + + @Override public void setHWVersion(HWVersion type) { + + } + + @Override public HWVersion getHWVersion() { + return HWVersion.DEFAULT; + } + + @Override public void setEthernetDevType(int cardIndex, EthernetDevType type) { + + } + + @Override public EthernetDevType getEthernetDevType(int cardIndex) { + return EthernetDevType.NONE; + } + + @Override public void setMaxUsbSpeed(UsbSpeed speed) { + + } + + @Override public UsbSpeed getMaxUsbSpeed() { + return UsbSpeed.NONE; + } + + @Override public byte[] getDefinitionArray() { + return new byte[0]; + } + + @Override public boolean addEthernet(EtherType type) { + return false; + } + + @Override public Virtualizer getVirtualizer() { + return virtualizer; + } + + @Override public boolean tweakForNonPersistent() { + return false; + } + + @Override public void registerVirtualHW() { + + } +} diff --git a/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationException.java b/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationException.java new file mode 100644 index 0000000..2d401b1 --- /dev/null +++ b/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationException.java @@ -0,0 +1,13 @@ +package org.openslx.virtualization.configuration; + +public class VirtualizationConfigurationException extends Exception +{ + /** + * Version for serialization. + */ + private static final long serialVersionUID = 5794121065945636839L; + + public VirtualizationConfigurationException(String message) { + super(message); + } +} \ No newline at end of file diff --git a/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationQemu.java b/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationQemu.java new file mode 100644 index 0000000..91bb9ae --- /dev/null +++ b/src/main/java/org/openslx/virtualization/configuration/VirtualizationConfigurationQemu.java @@ -0,0 +1,881 @@ +package org.openslx.virtualization.configuration; + +import java.io.File; +import java.math.BigInteger; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map.Entry; + +import org.openslx.bwlp.thrift.iface.OperatingSystem; +import org.openslx.bwlp.thrift.iface.Virtualizer; +import org.openslx.libvirt.domain.Domain; +import org.openslx.libvirt.domain.device.ControllerUsb; +import org.openslx.libvirt.domain.device.Disk.BusType; +import org.openslx.libvirt.domain.device.Disk.StorageType; +import org.openslx.libvirt.domain.device.DiskCdrom; +import org.openslx.libvirt.domain.device.DiskFloppy; +import org.openslx.libvirt.domain.device.DiskStorage; +import org.openslx.libvirt.domain.device.Graphics; +import org.openslx.libvirt.domain.device.GraphicsSpice; +import org.openslx.libvirt.domain.device.Interface; +import org.openslx.libvirt.domain.device.Sound; +import org.openslx.libvirt.domain.device.Video; +import org.openslx.libvirt.xml.LibvirtXmlDocumentException; +import org.openslx.libvirt.xml.LibvirtXmlSerializationException; +import org.openslx.libvirt.xml.LibvirtXmlValidationException; +import org.openslx.thrifthelper.TConst; +import org.openslx.vm.disk.DiskImage; +import org.openslx.vm.disk.DiskImage.ImageFormat; + +/** + * Metadata to describe the hardware type of a QEMU sound card. + * + * @author Manuel Bentele + * @version 1.0 + */ +class QemuSoundCardMeta +{ + /** + * Stores the hardware model of the QEMU sound card. + */ + private final Sound.Model model; + + /** + * Creates metadata to describe the hardware model of a QEMU sound card. + * + * @param model hardware model of the QEMU sound card. + */ + public QemuSoundCardMeta( Sound.Model model ) + { + this.model = model; + } + + /** + * Returns hardware model of the QEMU sound card. + * + * @return hardware model of the QEMU sound card. + */ + public Sound.Model getModel() + { + return this.model; + } +} + +/** + * Metadata to describe the hardware acceleration state of QEMU virtual graphics. + * + * @author Manuel Bentele + * @version 1.0 + */ +class QemuDDAccelMeta +{ + /** + * Stores state of the hardware acceleration for QEMU virtual graphics. + */ + private final boolean enabled; + + /** + * Creates metadata to describe the hardware acceleration state of QEMU virtual graphics. + * + * @param enabled state of the hardware acceleration for QEMU virtual graphics. + */ + public QemuDDAccelMeta( boolean enabled ) + { + this.enabled = enabled; + } + + /** + * Returns state of the hardware acceleration of QEMU virtual graphics. + * + * @return state of the hardware acceleration for QEMU virtual graphics. + */ + public boolean isEnabled() + { + return this.enabled; + } +} + +/** + * Metadata to describe the version of a QEMU virtual machine configuration. + * + * @author Manuel Bentele + * @version 1.0 + */ +class QemuHWVersionMeta +{ + /** + * Stores the version of a QEMU virtual machine configuration. + */ + private final int version; + + /** + * Creates metadata to describe the version of a QEMU virtual machine configuration. + * + * @param version version of the QEMU virtual machine configuration. + */ + public QemuHWVersionMeta( int version ) + { + this.version = version; + } + + /** + * Returns version of the QEMU virtual machine configuration. + * + * @return version of the QEMU virtual machine configuration. + */ + public int getVersion() + { + return this.version; + } +} + +/** + * Metadata to describe the hardware type of a QEMU ethernet device. + * + * @author Manuel Bentele + * @version 1.0 + */ +class QemuEthernetDevTypeMeta +{ + /** + * Stores the hardware model of the QEMU ethernet device. + */ + private final Interface.Model model; + + /** + * Creates metadata to describe the hardware type of a QEMU ethernet device. + * + * @param model hardware type of the QEMU ethernet device. + */ + public QemuEthernetDevTypeMeta( Interface.Model model ) + { + this.model = model; + } + + /** + * Returns the hardware type of a QEMU ethernet device. + * + * @return hardware type of the QEMU ethernet device. + */ + public Interface.Model getModel() + { + return this.model; + } +} + +/** + * Metadata to describe a QEMU USB controller. + * + * @author Manuel Bentele + * @version 1.0 + */ +class QemuUsbSpeedMeta +{ + /** + * Stores the USB speed of the QEMU USB controller. + */ + private final int speed; + + /** + * Stores the QEMU hardware model of the USB controller. + */ + private final ControllerUsb.Model model; + + /** + * Creates metadata to describe a QEMU USB controller. + * + * @param speed USB speed of the QEMU USB controller. + * @param model QEMU hardware model of the USB controller. + */ + public QemuUsbSpeedMeta( int speed, ControllerUsb.Model model ) + { + this.speed = speed; + this.model = model; + } + + /** + * Returns the speed of the QEMU USB controller. + * + * @return speed of the QEMU USB controller. + */ + public int getSpeed() + { + return this.speed; + } + + /** + * Returns QEMU hardware model of the USB controller. + * + * @return hardware model of the QEMU USB controller. + */ + public ControllerUsb.Model getModel() + { + return this.model; + } +} + +/** + * Virtual machine configuration (managed by Libvirt) for the QEMU hypervisor. + * + * @author Manuel Bentele + * @version 1.0 + */ +public class VirtualizationConfigurationQemu extends + VirtualizationConfiguration +{ + /** + * Name of the network bridge for the LAN. + */ + public static final String NETWORK_BRIDGE_LAN_DEFAULT = "br0"; + + /** + * Name of the network bridge for the default NAT network. + */ + public static final String NETWORK_BRIDGE_NAT_DEFAULT = "nat1"; + + /** + * Name of the network for the isolated host network (host only). + */ + public static final String NETWORK_BRIDGE_HOST_ONLY_DEFAULT = "vsw2"; + + /** + * Default physical CDROM drive of the hypervisor host. + */ + public static final String CDROM_DEFAULT_PHYSICAL_DRIVE = "/dev/sr0"; + + /** + * List of supported image formats by the QEMU hypervisor. + */ + private static final List SUPPORTED_IMAGE_FORMATS = Collections.unmodifiableList( + Arrays.asList( ImageFormat.QCOW2, ImageFormat.VMDK, ImageFormat.VDI ) ); + + /** + * Representation of a QEMU hypervisor (managed by Libvirt). + */ + private static final Virtualizer VIRTUALIZER = new Virtualizer( TConst.VIRT_QEMU, "QEMU" ); + + /** + * Libvirt XML configuration file to modify configuration of virtual machine for QEMU. + */ + private Domain vmConfig = null; + + /** + * Stores current index of added HDD device to the Libvirt XML configuration file. + */ + private int vmDeviceIndexHddAdd = 0; + + /** + * Stores current index of added CDROM device to the Libvirt XML configuration file. + */ + private int vmDeviceIndexCdromAdd = 0; + + /** + * Stores current index of added ethernet device to the Libvirt XML configuration file. + */ + private int vmDeviceIndexEthernetAdd = 0; + + /** + * Creates new virtual machine configuration (managed by Libvirt) for the QEMU hypervisor. + * + * @param osList list of operating systems. + * @param file image file for the QEMU hypervisor. + * + * @throws VirtualizationConfigurationException Libvirt XML configuration cannot be processed. + */ + public VirtualizationConfigurationQemu( List osList, File file ) throws VirtualizationConfigurationException + { + super( osList ); + + try { + // read and parse Libvirt domain XML configuration document + this.vmConfig = new Domain( file ); + } catch ( LibvirtXmlDocumentException | LibvirtXmlSerializationException | LibvirtXmlValidationException e ) { + throw new VirtualizationConfigurationException( e.getLocalizedMessage() ); + } + + // parse VM config and initialize fields of QemuMetaData class + this.parseVmConfig(); + } + + /** + * Creates new virtual machine configuration (managed by Libvirt) for the QEMU hypervisor. + * + * @param osList list of operating systems. + * @param vmContent file content for the QEMU hypervisor. + * @param length number of bytes of the file content. + * + * @throws VirtualizationConfigurationException Libvirt XML configuration cannot be processed. + */ + public VirtualizationConfigurationQemu( List osList, byte[] vmContent, int length ) + throws VirtualizationConfigurationException + { + super( osList ); + + try { + // read and parse Libvirt domain XML configuration document + this.vmConfig = new Domain( new String( vmContent ) ); + } catch ( LibvirtXmlDocumentException | LibvirtXmlSerializationException | LibvirtXmlValidationException e ) { + throw new VirtualizationConfigurationException( e.getLocalizedMessage() ); + } + + // parse VM config and initialize fields of QemuMetaData class + this.parseVmConfig(); + } + + /** + * Parses Libvirt domain XML configuration to initialize QEMU metadata. + */ + private void parseVmConfig() + { + // set display name of VM + this.displayName = vmConfig.getName(); + + // this property cannot be checked with the Libvirt domain XML configuration + // to check if machine is in a paused/suspended state, look in the QEMU qcow2 image for snapshots and machine states + this.isMachineSnapshot = false; + + // add HDDs, SSDs to QEMU metadata + for ( DiskStorage storageDiskDevice : this.vmConfig.getDiskStorageDevices() ) { + this.addHddMetaData( storageDiskDevice ); + } + + // start of privacy filters to filter out sensitive information like name of users in absolute paths, ... + // removes all referenced storage files of all specified CDROMs, Floppy drives and HDDs + this.vmConfig.removeDiskDevicesStorage(); + } + + /** + * Adds an existing and observed storage disk device to the HDD metadata. + * + * @param storageDiskDevice existing and observed storage disk that should be added to the + * metadata. + */ + private void addHddMetaData( DiskStorage storageDiskDevice ) + { + String hddChipsetModel = null; + DriveBusType hddChipsetBus = VirtualizationConfigurationQemuUtils.convertBusType( storageDiskDevice.getBusType() ); + String hddImagePath = storageDiskDevice.getStorageSource(); + + this.hdds.add( new HardDisk( hddChipsetModel, hddChipsetBus, hddImagePath ) ); + } + + @Override + public byte[] getFilteredDefinitionArray() + { + // removes all specified boot order entries + this.vmConfig.removeBootOrder(); + + // removes all source networks of all specified network interfaces + this.vmConfig.removeInterfaceDevicesSource(); + + // output filtered Libvirt domain XML configuration + String configuration = this.vmConfig.toString(); + return configuration.getBytes( StandardCharsets.UTF_8 ); + } + + @Override + public List getSupportedImageFormats() + { + return VirtualizationConfigurationQemu.SUPPORTED_IMAGE_FORMATS; + } + + @Override + public void applySettingsForLocalEdit() + { + // NOT implemented yet + } + + @Override + public boolean addHddTemplate( File diskImage, String hddMode, String redoDir ) + { + return this.addHddTemplate( diskImage.getAbsolutePath(), hddMode, redoDir ); + } + + @Override + public boolean addHddTemplate( String diskImagePath, String hddMode, String redoDir ) + { + return this.addHddTemplate( this.vmDeviceIndexHddAdd++, diskImagePath, hddMode, redoDir ); + } + + /** + * Adds hard disk drive (HDD) to the QEMU virtual machine configuration. + * + * @param index current index of HDD to be added to the virtual machine configuration. + * @param diskImagePath path to the virtual disk image for the HDD. + * @param hddMode operation mode of the HDD. + * @param redoDir directory for the redo log if an independent non-persistent + * hddMode is set. + * @return result state of adding the HDD. + */ + public boolean addHddTemplate( int index, String diskImagePath, String hddMode, String redoDir ) + { + ArrayList storageDiskDevices = this.vmConfig.getDiskStorageDevices(); + DiskStorage storageDiskDevice = VirtualizationConfigurationQemuUtils.getArrayIndex( storageDiskDevices, index ); + + if ( storageDiskDevice == null ) { + // HDD does not exist, so create new storage (HDD) device + storageDiskDevice = this.vmConfig.addDiskStorageDevice(); + storageDiskDevice.setReadOnly( false ); + storageDiskDevice.setBusType( BusType.VIRTIO ); + String targetDevName = VirtualizationConfigurationQemuUtils.createAlphabeticalDeviceName( "vd", index ); + storageDiskDevice.setTargetDevice( targetDevName ); + storageDiskDevice.setStorage( StorageType.FILE, diskImagePath ); + + // add new created HDD to the metadata of the QemuMetaData object, too + this.addHddMetaData( storageDiskDevice ); + } else { + // HDD exists, so update existing storage (HDD) device + storageDiskDevice.setStorage( StorageType.FILE, diskImagePath ); + } + + return false; + } + + @Override + public boolean addDefaultNat() + { + return this.addEthernet( EtherType.NAT ); + } + + @Override + public void setOs( String vendorOsId ) + { + this.setOs( vendorOsId ); + } + + @Override + public boolean addDisplayName( String name ) + { + this.vmConfig.setName( name ); + + final boolean statusName = this.vmConfig.getName().equals( name ); + + return statusName; + } + + @Override + public boolean addRam( int mem ) + { + BigInteger memory = BigInteger.valueOf( mem ); + + this.vmConfig.setMemory( memory ); + this.vmConfig.setCurrentMemory( memory ); + + final boolean isMemorySet = this.vmConfig.getMemory().toString().equals( memory.toString() ); + final boolean isCurrentMemorySet = this.vmConfig.getCurrentMemory().toString().equals( memory.toString() ); + + return isMemorySet && isCurrentMemorySet; + } + + @Override + public void addFloppy( int index, String image, boolean readOnly ) + { + ArrayList floppyDiskDevices = this.vmConfig.getDiskFloppyDevices(); + DiskFloppy floppyDiskDevice = VirtualizationConfigurationQemuUtils.getArrayIndex( floppyDiskDevices, index ); + + if ( floppyDiskDevice == null ) { + // floppy device does not exist, so create new floppy device + floppyDiskDevice = this.vmConfig.addDiskFloppyDevice(); + floppyDiskDevice.setBusType( BusType.FDC ); + String targetDevName = VirtualizationConfigurationQemuUtils.createAlphabeticalDeviceName( "fd", index ); + floppyDiskDevice.setTargetDevice( targetDevName ); + floppyDiskDevice.setReadOnly( readOnly ); + floppyDiskDevice.setStorage( StorageType.FILE, image ); + } else { + // floppy device exists, so update existing floppy device + floppyDiskDevice.setReadOnly( readOnly ); + floppyDiskDevice.setStorage( StorageType.FILE, image ); + } + } + + @Override + public boolean addCdrom( String image ) + { + return this.addCdrom( this.vmDeviceIndexCdromAdd++, image ); + } + + /** + * Adds CDROM drive to the QEMU virtual machine configuration. + * + * @param index current index of CDROM drive to be added to the virtual machine configuration. + * @param image path to a virtual image that will be inserted as CDROM into the drive. + * @return result state of adding the CDROM drive. + */ + public boolean addCdrom( int index, String image ) + { + ArrayList cdromDiskDevices = this.vmConfig.getDiskCdromDevices(); + DiskCdrom cdromDiskDevice = VirtualizationConfigurationQemuUtils.getArrayIndex( cdromDiskDevices, index ); + + if ( cdromDiskDevice == null ) { + // CDROM device does not exist, so create new CDROM device + cdromDiskDevice = this.vmConfig.addDiskCdromDevice(); + cdromDiskDevice.setBusType( BusType.SATA ); + String targetDevName = VirtualizationConfigurationQemuUtils.createAlphabeticalDeviceName( "sd", index ); + cdromDiskDevice.setTargetDevice( targetDevName ); + cdromDiskDevice.setReadOnly( true ); + + if ( image == null ) { + cdromDiskDevice.setStorage( StorageType.BLOCK, CDROM_DEFAULT_PHYSICAL_DRIVE ); + } else { + cdromDiskDevice.setStorage( StorageType.FILE, image ); + } + } else { + // CDROM device exists, so update existing CDROM device + cdromDiskDevice.setReadOnly( true ); + + if ( image == null ) { + cdromDiskDevice.setStorage( StorageType.BLOCK, CDROM_DEFAULT_PHYSICAL_DRIVE ); + } else { + cdromDiskDevice.setStorage( StorageType.FILE, image ); + } + } + + return false; + } + + @Override + public boolean addCpuCoreCount( int nrOfCores ) + { + this.vmConfig.setVCpu( nrOfCores ); + + boolean isVCpuSet = this.vmConfig.getVCpu() == nrOfCores; + + return isVCpuSet; + } + + @Override + public void setSoundCard( SoundCardType type ) + { + QemuSoundCardMeta soundDeviceConfig = this.soundCards.get( type ); + ArrayList soundDevices = this.vmConfig.getSoundDevices(); + Sound.Model soundDeviceModel = soundDeviceConfig.getModel(); + + if ( soundDevices.isEmpty() ) { + // create new sound device with 'soundDeviceModel' hardware + Sound soundDevice = this.vmConfig.addSoundDevice(); + soundDevice.setModel( soundDeviceModel ); + } else { + // update sound device model type of existing sound devices + for ( Sound soundDevice : soundDevices ) { + soundDevice.setModel( soundDeviceModel ); + } + } + } + + @Override + public SoundCardType getSoundCard() + { + ArrayList soundDevices = this.vmConfig.getSoundDevices(); + SoundCardType soundDeviceType = SoundCardType.DEFAULT; + + if ( soundDevices.isEmpty() ) { + // the VM configuration does not contain a sound card device + soundDeviceType = SoundCardType.NONE; + } else { + // the VM configuration at least one sound card device, so return the type of the first one + Sound.Model soundDeviceModel = soundDevices.get( 0 ).getModel(); + soundDeviceType = VirtualizationConfigurationQemuUtils.convertSoundDeviceModel( soundDeviceModel ); + } + + return soundDeviceType; + } + + @Override + public void setDDAcceleration( DDAcceleration type ) + { + QemuDDAccelMeta accelerationConfig = this.ddacc.get( type ); + ArrayList graphicDevices = this.vmConfig.getGraphicDevices(); + ArrayList

- * See ContainerDefintion in tutor-module (bwsuite). - *

- * This field is in vm context the machine description e.g. vmware = vmx. - * This field will be stored in table imageversion.virtualizerconfig - */ - private byte[] containerDefinition; - - public DockerMetaDataDummy(List osList, File file) throws UnsupportedVirtualizerFormatException { - super(osList); - - BufferedInputStream bis = null; - - try { - bis = new BufferedInputStream(new FileInputStream(file)); - containerDefinition = new byte[(int) file.length()]; - bis.read(containerDefinition); - - checkIsTarGz(); - } catch (IOException | UnsupportedVirtualizerFormatException e) { - LOGGER.error("Couldn't read dockerfile", e); - } finally { - try { - bis.close(); - } catch ( IOException e ) { - LOGGER.warn( "Could not close the input stream!" ); - } - } - } - - public DockerMetaDataDummy(List osList, byte[] vmContent, int length) - throws UnsupportedVirtualizerFormatException { - super(osList); - - containerDefinition = vmContent; - - checkIsTarGz(); - } - - /* - TODO This is just a simple check to prevent the workflow from considering any content as acceptable. - */ - /** - * Checks if the first two bytes of the content identifies a tar.gz archive. - * The first byte is 31 == 0x1f, the second byte has to be -117 == 0x8b. - * - * @throws UnsupportedVirtualizerFormatException - */ - private void checkIsTarGz() throws UnsupportedVirtualizerFormatException { - if (!((31 == containerDefinition[0]) && (-117 == containerDefinition[1]))) { - LOGGER.warn("Not Supported Content."); - throw new UnsupportedVirtualizerFormatException( - "DockerMetaDataDummy: Not tar.gz encoded content!"); - } - } - - @Override public byte[] getFilteredDefinitionArray() { - return containerDefinition; - } - - @Override - public List getSupportedImageFormats() - { - return DockerMetaDataDummy.SUPPORTED_IMAGE_FORMATS; - } - - @Override public void applySettingsForLocalEdit() { - - } - - @Override public boolean addHddTemplate(File diskImage, String hddMode, String redoDir) { - return false; - } - - @Override public boolean addHddTemplate(String diskImagePath, String hddMode, String redoDir) { - return false; - } - - @Override public boolean addDefaultNat() { - return false; - } - - @Override public void setOs(String vendorOsId) { - - } - - @Override public boolean addDisplayName(String name) { - return false; - } - - @Override public boolean addRam(int mem) { - return false; - } - - @Override public void addFloppy(int index, String image, boolean readOnly) { - - } - - @Override public boolean addCdrom(String image) { - return false; - } - - @Override public boolean addCpuCoreCount(int nrOfCores) { - return false; - } - - @Override public void setSoundCard(SoundCardType type) { - - } - - @Override public SoundCardType getSoundCard() { - return SoundCardType.NONE; - } - - @Override public void setDDAcceleration(DDAcceleration type) { - - } - - @Override public DDAcceleration getDDAcceleration() { - return DDAcceleration.OFF; - } - - @Override public void setHWVersion(HWVersion type) { - - } - - @Override public HWVersion getHWVersion() { - return HWVersion.DEFAULT; - } - - @Override public void setEthernetDevType(int cardIndex, EthernetDevType type) { - - } - - @Override public EthernetDevType getEthernetDevType(int cardIndex) { - return EthernetDevType.NONE; - } - - @Override public void setMaxUsbSpeed(UsbSpeed speed) { - - } - - @Override public UsbSpeed getMaxUsbSpeed() { - return UsbSpeed.NONE; - } - - @Override public byte[] getDefinitionArray() { - return new byte[0]; - } - - @Override public boolean addEthernet(EtherType type) { - return false; - } - - @Override public Virtualizer getVirtualizer() { - return virtualizer; - } - - @Override public boolean tweakForNonPersistent() { - return false; - } - - @Override public void registerVirtualHW() { - - } -} diff --git a/src/main/java/org/openslx/virtualization/configuration/machine/KeyValuePair.java b/src/main/java/org/openslx/virtualization/configuration/machine/KeyValuePair.java deleted file mode 100644 index ecd4f2a..0000000 --- a/src/main/java/org/openslx/virtualization/configuration/machine/KeyValuePair.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.openslx.virtualization.configuration.machine; - -class KeyValuePair -{ - public final String key; - public final String value; - - public KeyValuePair( String key, String value ) - { - this.key = key; - this.value = value; - } -} \ No newline at end of file diff --git a/src/main/java/org/openslx/virtualization/configuration/machine/QemuMetaData.java b/src/main/java/org/openslx/virtualization/configuration/machine/QemuMetaData.java deleted file mode 100644 index 5dd86be..0000000 --- a/src/main/java/org/openslx/virtualization/configuration/machine/QemuMetaData.java +++ /dev/null @@ -1,883 +0,0 @@ -package org.openslx.virtualization.configuration.machine; - -import java.io.File; -import java.math.BigInteger; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map.Entry; - -import org.openslx.bwlp.thrift.iface.OperatingSystem; -import org.openslx.bwlp.thrift.iface.Virtualizer; -import org.openslx.libvirt.domain.Domain; -import org.openslx.libvirt.domain.device.ControllerUsb; -import org.openslx.libvirt.domain.device.Disk.BusType; -import org.openslx.libvirt.domain.device.Disk.StorageType; -import org.openslx.libvirt.domain.device.DiskCdrom; -import org.openslx.libvirt.domain.device.DiskFloppy; -import org.openslx.libvirt.domain.device.DiskStorage; -import org.openslx.libvirt.domain.device.Graphics; -import org.openslx.libvirt.domain.device.GraphicsSpice; -import org.openslx.libvirt.domain.device.Interface; -import org.openslx.libvirt.domain.device.Sound; -import org.openslx.libvirt.domain.device.Video; -import org.openslx.libvirt.xml.LibvirtXmlDocumentException; -import org.openslx.libvirt.xml.LibvirtXmlSerializationException; -import org.openslx.libvirt.xml.LibvirtXmlValidationException; -import org.openslx.thrifthelper.TConst; -import org.openslx.virtualization.configuration.UnsupportedVirtualizerFormatException; -import org.openslx.virtualization.configuration.VmMetaData; -import org.openslx.vm.disk.DiskImage; -import org.openslx.vm.disk.DiskImage.ImageFormat; - -/** - * Metadata to describe the hardware type of a QEMU sound card. - * - * @author Manuel Bentele - * @version 1.0 - */ -class QemuSoundCardMeta -{ - /** - * Stores the hardware model of the QEMU sound card. - */ - private final Sound.Model model; - - /** - * Creates metadata to describe the hardware model of a QEMU sound card. - * - * @param model hardware model of the QEMU sound card. - */ - public QemuSoundCardMeta( Sound.Model model ) - { - this.model = model; - } - - /** - * Returns hardware model of the QEMU sound card. - * - * @return hardware model of the QEMU sound card. - */ - public Sound.Model getModel() - { - return this.model; - } -} - -/** - * Metadata to describe the hardware acceleration state of QEMU virtual graphics. - * - * @author Manuel Bentele - * @version 1.0 - */ -class QemuDDAccelMeta -{ - /** - * Stores state of the hardware acceleration for QEMU virtual graphics. - */ - private final boolean enabled; - - /** - * Creates metadata to describe the hardware acceleration state of QEMU virtual graphics. - * - * @param enabled state of the hardware acceleration for QEMU virtual graphics. - */ - public QemuDDAccelMeta( boolean enabled ) - { - this.enabled = enabled; - } - - /** - * Returns state of the hardware acceleration of QEMU virtual graphics. - * - * @return state of the hardware acceleration for QEMU virtual graphics. - */ - public boolean isEnabled() - { - return this.enabled; - } -} - -/** - * Metadata to describe the version of a QEMU virtual machine configuration. - * - * @author Manuel Bentele - * @version 1.0 - */ -class QemuHWVersionMeta -{ - /** - * Stores the version of a QEMU virtual machine configuration. - */ - private final int version; - - /** - * Creates metadata to describe the version of a QEMU virtual machine configuration. - * - * @param version version of the QEMU virtual machine configuration. - */ - public QemuHWVersionMeta( int version ) - { - this.version = version; - } - - /** - * Returns version of the QEMU virtual machine configuration. - * - * @return version of the QEMU virtual machine configuration. - */ - public int getVersion() - { - return this.version; - } -} - -/** - * Metadata to describe the hardware type of a QEMU ethernet device. - * - * @author Manuel Bentele - * @version 1.0 - */ -class QemuEthernetDevTypeMeta -{ - /** - * Stores the hardware model of the QEMU ethernet device. - */ - private final Interface.Model model; - - /** - * Creates metadata to describe the hardware type of a QEMU ethernet device. - * - * @param model hardware type of the QEMU ethernet device. - */ - public QemuEthernetDevTypeMeta( Interface.Model model ) - { - this.model = model; - } - - /** - * Returns the hardware type of a QEMU ethernet device. - * - * @return hardware type of the QEMU ethernet device. - */ - public Interface.Model getModel() - { - return this.model; - } -} - -/** - * Metadata to describe a QEMU USB controller. - * - * @author Manuel Bentele - * @version 1.0 - */ -class QemuUsbSpeedMeta -{ - /** - * Stores the USB speed of the QEMU USB controller. - */ - private final int speed; - - /** - * Stores the QEMU hardware model of the USB controller. - */ - private final ControllerUsb.Model model; - - /** - * Creates metadata to describe a QEMU USB controller. - * - * @param speed USB speed of the QEMU USB controller. - * @param model QEMU hardware model of the USB controller. - */ - public QemuUsbSpeedMeta( int speed, ControllerUsb.Model model ) - { - this.speed = speed; - this.model = model; - } - - /** - * Returns the speed of the QEMU USB controller. - * - * @return speed of the QEMU USB controller. - */ - public int getSpeed() - { - return this.speed; - } - - /** - * Returns QEMU hardware model of the USB controller. - * - * @return hardware model of the QEMU USB controller. - */ - public ControllerUsb.Model getModel() - { - return this.model; - } -} - -/** - * Virtual machine configuration (managed by Libvirt) for the QEMU hypervisor. - * - * @author Manuel Bentele - * @version 1.0 - */ -public class QemuMetaData extends - VmMetaData -{ - /** - * Name of the network bridge for the LAN. - */ - public static final String NETWORK_BRIDGE_LAN_DEFAULT = "br0"; - - /** - * Name of the network bridge for the default NAT network. - */ - public static final String NETWORK_BRIDGE_NAT_DEFAULT = "nat1"; - - /** - * Name of the network for the isolated host network (host only). - */ - public static final String NETWORK_BRIDGE_HOST_ONLY_DEFAULT = "vsw2"; - - /** - * Default physical CDROM drive of the hypervisor host. - */ - public static final String CDROM_DEFAULT_PHYSICAL_DRIVE = "/dev/sr0"; - - /** - * List of supported image formats by the QEMU hypervisor. - */ - private static final List SUPPORTED_IMAGE_FORMATS = Collections.unmodifiableList( - Arrays.asList( ImageFormat.QCOW2, ImageFormat.VMDK, ImageFormat.VDI ) ); - - /** - * Representation of a QEMU hypervisor (managed by Libvirt). - */ - private static final Virtualizer VIRTUALIZER = new Virtualizer( TConst.VIRT_QEMU, "QEMU" ); - - /** - * Libvirt XML configuration file to modify configuration of virtual machine for QEMU. - */ - private Domain vmConfig = null; - - /** - * Stores current index of added HDD device to the Libvirt XML configuration file. - */ - private int vmDeviceIndexHddAdd = 0; - - /** - * Stores current index of added CDROM device to the Libvirt XML configuration file. - */ - private int vmDeviceIndexCdromAdd = 0; - - /** - * Stores current index of added ethernet device to the Libvirt XML configuration file. - */ - private int vmDeviceIndexEthernetAdd = 0; - - /** - * Creates new virtual machine configuration (managed by Libvirt) for the QEMU hypervisor. - * - * @param osList list of operating systems. - * @param file image file for the QEMU hypervisor. - * - * @throws UnsupportedVirtualizerFormatException Libvirt XML configuration cannot be processed. - */ - public QemuMetaData( List osList, File file ) throws UnsupportedVirtualizerFormatException - { - super( osList ); - - try { - // read and parse Libvirt domain XML configuration document - this.vmConfig = new Domain( file ); - } catch ( LibvirtXmlDocumentException | LibvirtXmlSerializationException | LibvirtXmlValidationException e ) { - throw new UnsupportedVirtualizerFormatException( e.getLocalizedMessage() ); - } - - // parse VM config and initialize fields of QemuMetaData class - this.parseVmConfig(); - } - - /** - * Creates new virtual machine configuration (managed by Libvirt) for the QEMU hypervisor. - * - * @param osList list of operating systems. - * @param vmContent file content for the QEMU hypervisor. - * @param length number of bytes of the file content. - * - * @throws UnsupportedVirtualizerFormatException Libvirt XML configuration cannot be processed. - */ - public QemuMetaData( List osList, byte[] vmContent, int length ) - throws UnsupportedVirtualizerFormatException - { - super( osList ); - - try { - // read and parse Libvirt domain XML configuration document - this.vmConfig = new Domain( new String( vmContent ) ); - } catch ( LibvirtXmlDocumentException | LibvirtXmlSerializationException | LibvirtXmlValidationException e ) { - throw new UnsupportedVirtualizerFormatException( e.getLocalizedMessage() ); - } - - // parse VM config and initialize fields of QemuMetaData class - this.parseVmConfig(); - } - - /** - * Parses Libvirt domain XML configuration to initialize QEMU metadata. - */ - private void parseVmConfig() - { - // set display name of VM - this.displayName = vmConfig.getName(); - - // this property cannot be checked with the Libvirt domain XML configuration - // to check if machine is in a paused/suspended state, look in the QEMU qcow2 image for snapshots and machine states - this.isMachineSnapshot = false; - - // add HDDs, SSDs to QEMU metadata - for ( DiskStorage storageDiskDevice : this.vmConfig.getDiskStorageDevices() ) { - this.addHddMetaData( storageDiskDevice ); - } - - // start of privacy filters to filter out sensitive information like name of users in absolute paths, ... - // removes all referenced storage files of all specified CDROMs, Floppy drives and HDDs - this.vmConfig.removeDiskDevicesStorage(); - } - - /** - * Adds an existing and observed storage disk device to the HDD metadata. - * - * @param storageDiskDevice existing and observed storage disk that should be added to the - * metadata. - */ - private void addHddMetaData( DiskStorage storageDiskDevice ) - { - String hddChipsetModel = null; - DriveBusType hddChipsetBus = QemuMetaDataUtils.convertBusType( storageDiskDevice.getBusType() ); - String hddImagePath = storageDiskDevice.getStorageSource(); - - this.hdds.add( new HardDisk( hddChipsetModel, hddChipsetBus, hddImagePath ) ); - } - - @Override - public byte[] getFilteredDefinitionArray() - { - // removes all specified boot order entries - this.vmConfig.removeBootOrder(); - - // removes all source networks of all specified network interfaces - this.vmConfig.removeInterfaceDevicesSource(); - - // output filtered Libvirt domain XML configuration - String configuration = this.vmConfig.toString(); - return configuration.getBytes( StandardCharsets.UTF_8 ); - } - - @Override - public List getSupportedImageFormats() - { - return QemuMetaData.SUPPORTED_IMAGE_FORMATS; - } - - @Override - public void applySettingsForLocalEdit() - { - // NOT implemented yet - } - - @Override - public boolean addHddTemplate( File diskImage, String hddMode, String redoDir ) - { - return this.addHddTemplate( diskImage.getAbsolutePath(), hddMode, redoDir ); - } - - @Override - public boolean addHddTemplate( String diskImagePath, String hddMode, String redoDir ) - { - return this.addHddTemplate( this.vmDeviceIndexHddAdd++, diskImagePath, hddMode, redoDir ); - } - - /** - * Adds hard disk drive (HDD) to the QEMU virtual machine configuration. - * - * @param index current index of HDD to be added to the virtual machine configuration. - * @param diskImagePath path to the virtual disk image for the HDD. - * @param hddMode operation mode of the HDD. - * @param redoDir directory for the redo log if an independent non-persistent - * hddMode is set. - * @return result state of adding the HDD. - */ - public boolean addHddTemplate( int index, String diskImagePath, String hddMode, String redoDir ) - { - ArrayList storageDiskDevices = this.vmConfig.getDiskStorageDevices(); - DiskStorage storageDiskDevice = QemuMetaDataUtils.getArrayIndex( storageDiskDevices, index ); - - if ( storageDiskDevice == null ) { - // HDD does not exist, so create new storage (HDD) device - storageDiskDevice = this.vmConfig.addDiskStorageDevice(); - storageDiskDevice.setReadOnly( false ); - storageDiskDevice.setBusType( BusType.VIRTIO ); - String targetDevName = QemuMetaDataUtils.createAlphabeticalDeviceName( "vd", index ); - storageDiskDevice.setTargetDevice( targetDevName ); - storageDiskDevice.setStorage( StorageType.FILE, diskImagePath ); - - // add new created HDD to the metadata of the QemuMetaData object, too - this.addHddMetaData( storageDiskDevice ); - } else { - // HDD exists, so update existing storage (HDD) device - storageDiskDevice.setStorage( StorageType.FILE, diskImagePath ); - } - - return false; - } - - @Override - public boolean addDefaultNat() - { - return this.addEthernet( EtherType.NAT ); - } - - @Override - public void setOs( String vendorOsId ) - { - this.setOs( vendorOsId ); - } - - @Override - public boolean addDisplayName( String name ) - { - this.vmConfig.setName( name ); - - final boolean statusName = this.vmConfig.getName().equals( name ); - - return statusName; - } - - @Override - public boolean addRam( int mem ) - { - BigInteger memory = BigInteger.valueOf( mem ); - - this.vmConfig.setMemory( memory ); - this.vmConfig.setCurrentMemory( memory ); - - final boolean isMemorySet = this.vmConfig.getMemory().toString().equals( memory.toString() ); - final boolean isCurrentMemorySet = this.vmConfig.getCurrentMemory().toString().equals( memory.toString() ); - - return isMemorySet && isCurrentMemorySet; - } - - @Override - public void addFloppy( int index, String image, boolean readOnly ) - { - ArrayList floppyDiskDevices = this.vmConfig.getDiskFloppyDevices(); - DiskFloppy floppyDiskDevice = QemuMetaDataUtils.getArrayIndex( floppyDiskDevices, index ); - - if ( floppyDiskDevice == null ) { - // floppy device does not exist, so create new floppy device - floppyDiskDevice = this.vmConfig.addDiskFloppyDevice(); - floppyDiskDevice.setBusType( BusType.FDC ); - String targetDevName = QemuMetaDataUtils.createAlphabeticalDeviceName( "fd", index ); - floppyDiskDevice.setTargetDevice( targetDevName ); - floppyDiskDevice.setReadOnly( readOnly ); - floppyDiskDevice.setStorage( StorageType.FILE, image ); - } else { - // floppy device exists, so update existing floppy device - floppyDiskDevice.setReadOnly( readOnly ); - floppyDiskDevice.setStorage( StorageType.FILE, image ); - } - } - - @Override - public boolean addCdrom( String image ) - { - return this.addCdrom( this.vmDeviceIndexCdromAdd++, image ); - } - - /** - * Adds CDROM drive to the QEMU virtual machine configuration. - * - * @param index current index of CDROM drive to be added to the virtual machine configuration. - * @param image path to a virtual image that will be inserted as CDROM into the drive. - * @return result state of adding the CDROM drive. - */ - public boolean addCdrom( int index, String image ) - { - ArrayList cdromDiskDevices = this.vmConfig.getDiskCdromDevices(); - DiskCdrom cdromDiskDevice = QemuMetaDataUtils.getArrayIndex( cdromDiskDevices, index ); - - if ( cdromDiskDevice == null ) { - // CDROM device does not exist, so create new CDROM device - cdromDiskDevice = this.vmConfig.addDiskCdromDevice(); - cdromDiskDevice.setBusType( BusType.SATA ); - String targetDevName = QemuMetaDataUtils.createAlphabeticalDeviceName( "sd", index ); - cdromDiskDevice.setTargetDevice( targetDevName ); - cdromDiskDevice.setReadOnly( true ); - - if ( image == null ) { - cdromDiskDevice.setStorage( StorageType.BLOCK, CDROM_DEFAULT_PHYSICAL_DRIVE ); - } else { - cdromDiskDevice.setStorage( StorageType.FILE, image ); - } - } else { - // CDROM device exists, so update existing CDROM device - cdromDiskDevice.setReadOnly( true ); - - if ( image == null ) { - cdromDiskDevice.setStorage( StorageType.BLOCK, CDROM_DEFAULT_PHYSICAL_DRIVE ); - } else { - cdromDiskDevice.setStorage( StorageType.FILE, image ); - } - } - - return false; - } - - @Override - public boolean addCpuCoreCount( int nrOfCores ) - { - this.vmConfig.setVCpu( nrOfCores ); - - boolean isVCpuSet = this.vmConfig.getVCpu() == nrOfCores; - - return isVCpuSet; - } - - @Override - public void setSoundCard( SoundCardType type ) - { - QemuSoundCardMeta soundDeviceConfig = this.soundCards.get( type ); - ArrayList soundDevices = this.vmConfig.getSoundDevices(); - Sound.Model soundDeviceModel = soundDeviceConfig.getModel(); - - if ( soundDevices.isEmpty() ) { - // create new sound device with 'soundDeviceModel' hardware - Sound soundDevice = this.vmConfig.addSoundDevice(); - soundDevice.setModel( soundDeviceModel ); - } else { - // update sound device model type of existing sound devices - for ( Sound soundDevice : soundDevices ) { - soundDevice.setModel( soundDeviceModel ); - } - } - } - - @Override - public SoundCardType getSoundCard() - { - ArrayList soundDevices = this.vmConfig.getSoundDevices(); - SoundCardType soundDeviceType = SoundCardType.DEFAULT; - - if ( soundDevices.isEmpty() ) { - // the VM configuration does not contain a sound card device - soundDeviceType = SoundCardType.NONE; - } else { - // the VM configuration at least one sound card device, so return the type of the first one - Sound.Model soundDeviceModel = soundDevices.get( 0 ).getModel(); - soundDeviceType = QemuMetaDataUtils.convertSoundDeviceModel( soundDeviceModel ); - } - - return soundDeviceType; - } - - @Override - public void setDDAcceleration( DDAcceleration type ) - { - QemuDDAccelMeta accelerationConfig = this.ddacc.get( type ); - ArrayList graphicDevices = this.vmConfig.getGraphicDevices(); - ArrayList

+ * The regular expression matches a version if its textual version information is well-formed + * according to the following examples: + * + *

+	 *   52
+	 *   4.31
+	 *   5.10.13
+	 * 
+ */ + 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 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 protected final List hdds = new ArrayList(); - private final List osList; + protected final List osList; private OperatingSystem os = null; @@ -180,6 +179,16 @@ public abstract class VirtualizationConfiguration { 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,42 +225,18 @@ public abstract class VirtualizationConfiguration public VirtualizationConfiguration( Virtualizer virtualizer, List osList ) { this.virtualizer = virtualizer; - this.osList = osList; + + if ( osList == null ) { + // create empty operating system list if none is specified + this.osList = new ArrayList(); + } 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 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 * 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. vmware for VMware + * @param virtOsId operating system identifier used by the virtualizer, eg. + * windows7-64 for 64bit Windows 7 on VMware. + */ + public static OperatingSystem getOsOfVirtualizerFromList( List osList, String virtId, + String virtOsId ) + { + OperatingSystem os = null; + + for ( final OperatingSystem osCandidate : osList ) { + final Map osVirtualizerMapping = osCandidate.getVirtualizerOsId(); + if ( osVirtualizerMapping != null ) { + for ( final Entry 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 +public class VirtualizationConfigurationVirtualBox + extends VirtualizationConfiguration { /** * 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 osList, File file ) throws IOException, VirtualizationConfigurationException + public VirtualizationConfigurationVirtualBox( List osList, File file ) + throws IOException, VirtualizationConfigurationException { super( new VirtualizerVirtualBox(), osList ); this.config = new VirtualizationConfigurationVirtualboxFileFormat( file ); init(); } - public VirtualizationConfigurationVirtualBox( List osList, byte[] vmContent, int length ) throws IOException, VirtualizationConfigurationException + public VirtualizationConfigurationVirtualBox( List 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 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 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 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 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 +public class VirtualizationConfigurationVmware extends + VirtualizationConfiguration { /** * 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 disks = new HashMap<>(); - public VirtualizationConfigurationVmware( List osList, File file ) throws IOException, VirtualizationConfigurationException + public VirtualizationConfigurationVmware( List osList, File file ) + throws IOException, VirtualizationConfigurationException { super( new VirtualizerVmware(), osList ); this.config = new VirtualizationConfigurationVmwareFileFormat( file ); init(); } - public VirtualizationConfigurationVmware( List osList, byte[] vmxContent, int length ) throws VirtualizationConfigurationException + public VirtualizationConfigurationVmware( List 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 @@ -110,6 +110,14 @@ public class DomainTest assertEquals( "Ubuntu 18.04 server installation", vm.getDescription() ); } + @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; @@ -41,6 +42,22 @@ public class VersionTest assertFalse( version.isSupported( versions ) ); } + @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 STUB_OS_LIST = ConfigurationLogicTestUtils.STUB_OS_LIST; + private static Domain getPrivateDomainFromQemuMetaData( VirtualizationConfigurationQemu qemuMetadata ) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { @@ -110,6 +114,42 @@ public class VirtualizationConfigurationQemuTest assertDoesNotThrow( () -> vmConfig.validate() ); } + @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() 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 STUB_OS_LIST = Collections.unmodifiableList( Arrays.asList( + public static final List 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 @@ + + ubuntu-20-04 + 8dc5433c-0228-49e4-b019-fa2b606aa544 + Ubuntu 20.04 + Ubuntu 20.04 desktop installation + + + + + + 4194304 + 4194304 + 2 + + hvm + + + + + + + + + + + + + + destroy + restart + destroy + + + + + + /usr/bin/qemu-system-x86_64 + + + + +
+ + + + + +
+ + + + +
+ + +
+ + + +
+ + + +
+ + + +
+ + +
+ + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + +
+ + +
+ + + + + + +
+ + + + + + + + + + + +
+ + + +
+ + +
+ + + + + + + + +
+ +