diff options
Diffstat (limited to 'src/main/java/org/openslx/vm')
-rw-r--r-- | src/main/java/org/openslx/vm/DockerMetaDataDummy.java | 219 | ||||
-rw-r--r-- | src/main/java/org/openslx/vm/KeyValuePair.java | 13 | ||||
-rw-r--r-- | src/main/java/org/openslx/vm/QemuMetaData.java | 855 | ||||
-rw-r--r-- | src/main/java/org/openslx/vm/QemuMetaDataUtils.java | 191 | ||||
-rw-r--r-- | src/main/java/org/openslx/vm/UnsupportedVirtualizerFormatException.java | 13 | ||||
-rw-r--r-- | src/main/java/org/openslx/vm/VboxConfig.java | 631 | ||||
-rw-r--r-- | src/main/java/org/openslx/vm/VboxMetaData.java | 536 | ||||
-rw-r--r-- | src/main/java/org/openslx/vm/VmMetaData.java | 419 | ||||
-rw-r--r-- | src/main/java/org/openslx/vm/VmwareConfig.java | 276 | ||||
-rw-r--r-- | src/main/java/org/openslx/vm/VmwareMetaData.java | 684 | ||||
-rw-r--r-- | src/main/java/org/openslx/vm/disk/DiskImage.java | 8 | ||||
-rw-r--r-- | src/main/java/org/openslx/vm/disk/DiskImageQcow2.java | 12 | ||||
-rw-r--r-- | src/main/java/org/openslx/vm/disk/DiskImageUtils.java | 18 | ||||
-rw-r--r-- | src/main/java/org/openslx/vm/disk/DiskImageVdi.java | 6 | ||||
-rw-r--r-- | src/main/java/org/openslx/vm/disk/DiskImageVmdk.java | 38 |
15 files changed, 40 insertions, 3879 deletions
diff --git a/src/main/java/org/openslx/vm/DockerMetaDataDummy.java b/src/main/java/org/openslx/vm/DockerMetaDataDummy.java deleted file mode 100644 index 7381361..0000000 --- a/src/main/java/org/openslx/vm/DockerMetaDataDummy.java +++ /dev/null @@ -1,219 +0,0 @@ -package org.openslx.vm; - -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 DockerMetaDataDummy extends VmMetaData<DockerSoundCardMeta, DockerDDAccelMeta, DockerHWVersionMeta, DockerEthernetDevTypeMeta, DockerUsbSpeedMeta> { - - /** - * List of supported image formats by the Docker hypervisor. - */ - private static final List<DiskImage.ImageFormat> SUPPORTED_IMAGE_FORMATS = Collections.unmodifiableList( - Arrays.asList( ImageFormat.NONE ) ); - - private static final Logger LOGGER = Logger.getLogger( DockerMetaDataDummy.class); - - private 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. - * <p> - * See ContainerDefintion in tutor-module (bwsuite). - * <p> - * 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<OperatingSystem> 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<OperatingSystem> 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<DiskImage.ImageFormat> 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/vm/KeyValuePair.java b/src/main/java/org/openslx/vm/KeyValuePair.java deleted file mode 100644 index c5650ec..0000000 --- a/src/main/java/org/openslx/vm/KeyValuePair.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.openslx.vm; - -class KeyValuePair -{ - public final String key; - public final String value; - - public KeyValuePair( String key, String value ) - { - this.key = key; - this.value = value; - } -}
\ No newline at end of file diff --git a/src/main/java/org/openslx/vm/QemuMetaData.java b/src/main/java/org/openslx/vm/QemuMetaData.java deleted file mode 100644 index c780429..0000000 --- a/src/main/java/org/openslx/vm/QemuMetaData.java +++ /dev/null @@ -1,855 +0,0 @@ -package org.openslx.vm; - -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 QemuMetaData extends - VmMetaData<QemuSoundCardMeta, QemuDDAccelMeta, QemuHWVersionMeta, QemuEthernetDevTypeMeta, QemuUsbSpeedMeta> -{ - /** - * Default bridge name of the network bridge connected to the LAN. - */ - public static final String NETWORK_DEFAULT_BRIDGE = "brBwLehrpool"; - - /** - * Default network name of the isolated host network (host only). - */ - public static final String NETWORK_DEFAULT_HOST_ONLY = "host"; - - /** - * Default network name of the NAT network. - */ - public static final String NETWORK_DEFAULT_NAT = "nat"; - - /** - * 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<DiskImage.ImageFormat> SUPPORTED_IMAGE_FORMATS = Collections.unmodifiableList( - Arrays.asList( ImageFormat.QCOW2, ImageFormat.VMDK, ImageFormat.VDI ) ); - - /** - * Representation of a QEMU hypervisor (managed by Libvirt). - */ - private static final Virtualizer VIRTUALIZER = new Virtualizer( TConst.VIRT_QEMU, "QEMU" ); - - /** - * 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<OperatingSystem> osList, File file ) throws UnsupportedVirtualizerFormatException - { - super( osList ); - - try { - // read and parse Libvirt domain XML configuration document - this.vmConfig = new Domain( file ); - } catch ( LibvirtXmlDocumentException e ) { - throw new UnsupportedVirtualizerFormatException( e.getLocalizedMessage() ); - } catch ( LibvirtXmlSerializationException e ) { - throw new UnsupportedVirtualizerFormatException( e.getLocalizedMessage() ); - } catch ( LibvirtXmlValidationException e ) { - throw new UnsupportedVirtualizerFormatException( e.getLocalizedMessage() ); - } - - // register virtual hardware models for graphical editing of virtual devices (GPU, sound, USB, ...) - this.registerVirtualHW(); - - // 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 ); - } - } - - /** - * 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() - { - // remove UUID in Libvirt domain XML configuration - this.vmConfig.removeUuid(); - - // removes all specified boot order entries - this.vmConfig.removeBootOrder(); - - // removes all referenced storage files of all specified CDROMs, Floppy drives and HDDs - this.vmConfig.removeDiskDevicesStorage(); - - // 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<DiskImage.ImageFormat> 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 - * <code>hddMode</code> is set. - * @return result state of adding the HDD. - */ - public boolean addHddTemplate( int index, String diskImagePath, String hddMode, String redoDir ) - { - ArrayList<DiskStorage> 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<DiskFloppy> 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<DiskCdrom> 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<Sound> 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<Sound> 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<Graphics> graphicDevices = this.vmConfig.getGraphicDevices(); - ArrayList<Video> videoDevices = this.vmConfig.getVideoDevices(); - final boolean accelerationEnabled = accelerationConfig.isEnabled(); - - boolean acceleratedGraphicsAvailable = false; - - if ( graphicDevices.isEmpty() ) { - // add new graphics device with enabled acceleration to VM configuration - GraphicsSpice graphicSpiceDevice = this.vmConfig.addGraphicsSpiceDevice(); - graphicSpiceDevice.setOpenGl( true ); - acceleratedGraphicsAvailable = true; - } else { - // enable graphic acceleration of existing graphics devices - for ( Graphics graphicDevice : graphicDevices ) { - // set hardware acceleration for SPICE based graphics output - // other graphic devices do not support hardware acceleration - if ( graphicDevice instanceof GraphicsSpice ) { - GraphicsSpice.class.cast( graphicDevice ).setOpenGl( true ); - acceleratedGraphicsAvailable = true; - } - } - } - - // only configure hardware acceleration of video card(s) if graphics with hardware acceleration is available - if ( acceleratedGraphicsAvailable ) { - if ( videoDevices.isEmpty() ) { - // add new video device with enabled acceleration to VM configuration - Video videoDevice = this.vmConfig.addVideoDevice(); - videoDevice.setModel( Video.Model.VIRTIO ); - videoDevice.set2DAcceleration( true ); - videoDevice.set3DAcceleration( true ); - } else { - // enable graphic acceleration of existing graphics and video devices - for ( Video videoDevice : videoDevices ) { - // set hardware acceleration for Virtio GPUs - // other GPUs do not support hardware acceleration - if ( videoDevice.getModel() == Video.Model.VIRTIO ) { - videoDevice.set2DAcceleration( accelerationEnabled ); - videoDevice.set3DAcceleration( accelerationEnabled ); - } - } - } - } - } - - @Override - public DDAcceleration getDDAcceleration() - { - ArrayList<Graphics> graphicsDevices = this.vmConfig.getGraphicDevices(); - ArrayList<Video> videoDevices = this.vmConfig.getVideoDevices(); - DDAcceleration accelerationState = DDAcceleration.OFF; - - boolean acceleratedGraphicsAvailable = false; - boolean acceleratedVideoDevAvailable = false; - - // search for hardware accelerated graphics - for ( Graphics graphicDevice : graphicsDevices ) { - // only SPICE based graphic devices support hardware acceleration - if ( graphicDevice instanceof GraphicsSpice ) { - acceleratedGraphicsAvailable = true; - break; - } - } - - // search for hardware accelerated video devices - for ( Video videoDevice : videoDevices ) { - // only Virtio based video devices support hardware acceleration - if ( videoDevice.getModel() == Video.Model.VIRTIO ) { - acceleratedVideoDevAvailable = true; - break; - } - } - - // hardware acceleration is available if at least one accelerated graphics and video device is available - if ( acceleratedGraphicsAvailable && acceleratedVideoDevAvailable ) { - accelerationState = DDAcceleration.ON; - } else { - accelerationState = DDAcceleration.OFF; - } - - return accelerationState; - } - - @Override - public void setHWVersion( HWVersion type ) - { - // NOT supported by the QEMU hypervisor - } - - @Override - public HWVersion getHWVersion() - { - // NOT supported by the QEMU hypervisor - return null; - } - - @Override - public void setEthernetDevType( int cardIndex, EthernetDevType type ) - { - QemuEthernetDevTypeMeta networkDeviceConfig = this.networkCards.get( type ); - ArrayList<Interface> networkDevices = this.vmConfig.getInterfaceDevices(); - Interface networkDevice = QemuMetaDataUtils.getArrayIndex( networkDevices, cardIndex ); - Interface.Model networkDeviceModel = networkDeviceConfig.getModel(); - - if ( networkDevice != null ) { - networkDevice.setModel( networkDeviceModel ); - } - } - - @Override - public EthernetDevType getEthernetDevType( int cardIndex ) - { - ArrayList<Interface> networkDevices = this.vmConfig.getInterfaceDevices(); - Interface networkDevice = QemuMetaDataUtils.getArrayIndex( networkDevices, cardIndex ); - EthernetDevType networkDeviceType = EthernetDevType.NONE; - - if ( networkDevice == null ) { - // network interface device is not present - networkDeviceType = EthernetDevType.NONE; - } else { - // get model of existing network interface device - Interface.Model networkDeviceModel = networkDevice.getModel(); - networkDeviceType = QemuMetaDataUtils.convertNetworkDeviceModel( networkDeviceModel ); - } - - return networkDeviceType; - } - - @Override - public void setMaxUsbSpeed( UsbSpeed speed ) - { - QemuUsbSpeedMeta usbControllerConfig = this.usbSpeeds.get( speed ); - ArrayList<ControllerUsb> usbControllerDevices = this.vmConfig.getUsbControllerDevices(); - ControllerUsb.Model usbControllerModel = usbControllerConfig.getModel(); - - if ( usbControllerDevices.isEmpty() ) { - // add new USB controller with specified speed 'usbControllerModel' - ControllerUsb usbControllerDevice = this.vmConfig.addControllerUsbDevice(); - usbControllerDevice.setModel( usbControllerModel ); - } else { - // update model of all USB controller devices to support the maximum speed - for ( ControllerUsb usbControllerDevice : usbControllerDevices ) { - usbControllerDevice.setModel( usbControllerModel ); - } - } - } - - @Override - public UsbSpeed getMaxUsbSpeed() - { - ArrayList<ControllerUsb> usbControllerDevices = this.vmConfig.getUsbControllerDevices(); - UsbSpeed maxUsbSpeed = VmMetaData.UsbSpeed.NONE; - int maxUsbSpeedNumeric = 0; - - for ( ControllerUsb usbControllerDevice : usbControllerDevices ) { - ControllerUsb.Model usbControllerModel = usbControllerDevice.getModel(); - - for ( Entry<UsbSpeed, QemuUsbSpeedMeta> usbSpeedEntry : this.usbSpeeds.entrySet() ) { - QemuUsbSpeedMeta usbSpeed = usbSpeedEntry.getValue(); - if ( usbSpeed.getSpeed() > maxUsbSpeedNumeric && usbSpeed.getModel() == usbControllerModel ) { - maxUsbSpeed = usbSpeedEntry.getKey(); - maxUsbSpeedNumeric = usbSpeed.getSpeed(); - } - } - } - - return maxUsbSpeed; - } - - @Override - public byte[] getDefinitionArray() - { - String configuration = this.vmConfig.toString(); - - if ( configuration == null ) { - return null; - } else { - // append newline at the end of the XML content to match the structure of an original Libvirt XML file - configuration += System.lineSeparator(); - return configuration.getBytes( StandardCharsets.UTF_8 ); - } - } - - @Override - public boolean addEthernet( EtherType type ) - { - return this.addEthernet( this.vmDeviceIndexEthernetAdd++, type ); - } - - /** - * Adds an ethernet card to the QEMU virtual machine configuration. - * - * @param index current index of the ethernet card to be added to the virtual machine - * configuration. - * @param type card model of the ethernet card. - * @return result state of adding the ethernet card. - */ - public boolean addEthernet( int index, EtherType type ) - { - QemuEthernetDevTypeMeta defaultNetworkDeviceConfig = this.networkCards.get( EthernetDevType.AUTO ); - ArrayList<Interface> interfaceDevices = this.vmConfig.getInterfaceDevices(); - Interface interfaceDevice = QemuMetaDataUtils.getArrayIndex( interfaceDevices, index ); - - final Interface.Model defaultNetworkDeviceModel = defaultNetworkDeviceConfig.getModel(); - - if ( interfaceDevice == null ) { - // network interface device does not exist, so create new network interface device - switch ( type ) { - case BRIDGED: - // add network bridge interface device - interfaceDevice = this.vmConfig.addInterfaceBridgeDevice(); - interfaceDevice.setModel( defaultNetworkDeviceModel ); - interfaceDevice.setSource( QemuMetaData.NETWORK_DEFAULT_BRIDGE ); - break; - case HOST_ONLY: - // add network interface device with link to the isolated host network - interfaceDevice = this.vmConfig.addInterfaceNetworkDevice(); - interfaceDevice.setModel( defaultNetworkDeviceModel ); - interfaceDevice.setSource( QemuMetaData.NETWORK_DEFAULT_HOST_ONLY ); - break; - case NAT: - // add network interface device with link to the NAT network - interfaceDevice = this.vmConfig.addInterfaceNetworkDevice(); - interfaceDevice.setModel( defaultNetworkDeviceModel ); - interfaceDevice.setSource( QemuMetaData.NETWORK_DEFAULT_NAT ); - break; - } - } else { - // network interface device exists, so update existing network interface device - switch ( type ) { - case BRIDGED: - interfaceDevice.setType( Interface.Type.BRIDGE ); - interfaceDevice.setSource( QemuMetaData.NETWORK_DEFAULT_BRIDGE ); - break; - case HOST_ONLY: - interfaceDevice.setType( Interface.Type.NETWORK ); - interfaceDevice.setSource( QemuMetaData.NETWORK_DEFAULT_HOST_ONLY ); - break; - case NAT: - interfaceDevice.setType( Interface.Type.NETWORK ); - interfaceDevice.setSource( QemuMetaData.NETWORK_DEFAULT_NAT ); - break; - } - } - - return false; - } - - @Override - public Virtualizer getVirtualizer() - { - return QemuMetaData.VIRTUALIZER; - } - - @Override - public boolean tweakForNonPersistent() - { - // NOT implemented yet - return false; - } - - @Override - public void registerVirtualHW() - { - // @formatter:off - soundCards.put( VmMetaData.SoundCardType.NONE, new QemuSoundCardMeta( null ) ); - soundCards.put( VmMetaData.SoundCardType.DEFAULT, new QemuSoundCardMeta( Sound.Model.ICH9 ) ); - soundCards.put( VmMetaData.SoundCardType.SOUND_BLASTER, new QemuSoundCardMeta( Sound.Model.SB16 ) ); - soundCards.put( VmMetaData.SoundCardType.ES, new QemuSoundCardMeta( Sound.Model.ES1370 ) ); - soundCards.put( VmMetaData.SoundCardType.AC, new QemuSoundCardMeta( Sound.Model.AC97 ) ); - soundCards.put( VmMetaData.SoundCardType.HD_AUDIO, new QemuSoundCardMeta( Sound.Model.ICH9 ) ); - - ddacc.put( VmMetaData.DDAcceleration.OFF, new QemuDDAccelMeta( false ) ); - ddacc.put( VmMetaData.DDAcceleration.ON, new QemuDDAccelMeta( true ) ); - - hwversion.put( VmMetaData.HWVersion.DEFAULT, new QemuHWVersionMeta( 0 ) ); - - networkCards.put( VmMetaData.EthernetDevType.NONE, new QemuEthernetDevTypeMeta( null ) ); - networkCards.put( VmMetaData.EthernetDevType.AUTO, new QemuEthernetDevTypeMeta( Interface.Model.VIRTIO_NET_PCI ) ); - networkCards.put( VmMetaData.EthernetDevType.PCNETPCI2, new QemuEthernetDevTypeMeta( Interface.Model.PCNET ) ); - networkCards.put( VmMetaData.EthernetDevType.E1000, new QemuEthernetDevTypeMeta( Interface.Model.E1000 ) ); - networkCards.put( VmMetaData.EthernetDevType.E1000E, new QemuEthernetDevTypeMeta( Interface.Model.E1000E ) ); - networkCards.put( VmMetaData.EthernetDevType.VMXNET3, new QemuEthernetDevTypeMeta( Interface.Model.VMXNET3 ) ); - networkCards.put( VmMetaData.EthernetDevType.PARAVIRT, new QemuEthernetDevTypeMeta( Interface.Model.VIRTIO_NET_PCI ) ); - - usbSpeeds.put( VmMetaData.UsbSpeed.NONE, new QemuUsbSpeedMeta( 0, ControllerUsb.Model.NONE ) ); - usbSpeeds.put( VmMetaData.UsbSpeed.USB1_1, new QemuUsbSpeedMeta( 1, ControllerUsb.Model.ICH9_UHCI1 ) ); - usbSpeeds.put( VmMetaData.UsbSpeed.USB2_0, new QemuUsbSpeedMeta( 2, ControllerUsb.Model.ICH9_EHCI1 ) ); - usbSpeeds.put( VmMetaData.UsbSpeed.USB3_0, new QemuUsbSpeedMeta( 3, ControllerUsb.Model.QEMU_XHCI ) ); - // @formatter:on - } -} diff --git a/src/main/java/org/openslx/vm/QemuMetaDataUtils.java b/src/main/java/org/openslx/vm/QemuMetaDataUtils.java deleted file mode 100644 index a6142ab..0000000 --- a/src/main/java/org/openslx/vm/QemuMetaDataUtils.java +++ /dev/null @@ -1,191 +0,0 @@ -package org.openslx.vm; - -import java.util.ArrayList; - -import org.openslx.libvirt.domain.device.Disk; -import org.openslx.libvirt.domain.device.Interface; -import org.openslx.libvirt.domain.device.Disk.BusType; -import org.openslx.vm.VmMetaData.DriveBusType; -import org.openslx.vm.VmMetaData.EthernetDevType; -import org.openslx.vm.VmMetaData.SoundCardType; -import org.openslx.libvirt.domain.device.Sound; - -/** - * Collection of utils to convert data types from bwLehrpool to Libvirt and vice versa. - * - * @author Manuel Bentele - * @version 1.0 - */ -public class QemuMetaDataUtils -{ - /** - * Converts a Libvirt disk device bus type to a VM metadata driver bus type. - * - * @param busType Libvirt disk device bus type. - * @return VM metadata bus type of the disk drive. - */ - public static DriveBusType convertBusType( Disk.BusType busType ) - { - DriveBusType type = null; - - switch ( busType ) { - case IDE: - type = DriveBusType.IDE; - break; - case SATA: - type = DriveBusType.SATA; - break; - case SCSI: - type = DriveBusType.SCSI; - break; - default: - type = null; - break; - } - - return type; - } - - /** - * Converts a VM metadata driver bus type to a Libvirt disk device bus type. - * - * @param busType VM metadata bus type of the disk drive. - * @return Libvirt disk device bus type. - */ - public static Disk.BusType convertBusType( DriveBusType busType ) - { - Disk.BusType type = null; - - switch ( busType ) { - case IDE: - type = BusType.IDE; - break; - case NVME: - type = null; - break; - case SATA: - type = BusType.SATA; - break; - case SCSI: - type = BusType.SCSI; - break; - } - - return type; - } - - /** - * Converts a Libvirt sound device model to a VM metadata sound card type. - * - * @param soundDeviceModel Libvirt sound device model. - * @return VM metadata sound card type. - */ - public static SoundCardType convertSoundDeviceModel( Sound.Model soundDeviceModel ) - { - SoundCardType type = SoundCardType.NONE; - - switch ( soundDeviceModel ) { - case AC97: - type = SoundCardType.AC; - break; - case ES1370: - type = SoundCardType.ES; - break; - case ICH6: - type = SoundCardType.HD_AUDIO; - break; - case ICH9: - type = SoundCardType.HD_AUDIO; - break; - case SB16: - type = SoundCardType.SOUND_BLASTER; - break; - } - - return type; - } - - /** - * Converts a Libvirt network device model to a VM metadata ethernet device type. - * - * @param soundDeviceModel Libvirt network device model. - * @return VM metadata ethernet device type. - */ - public static EthernetDevType convertNetworkDeviceModel( Interface.Model networkDeviceModel ) - { - EthernetDevType type = EthernetDevType.NONE; - - switch ( networkDeviceModel ) { - case E1000: - type = EthernetDevType.E1000; - break; - case E1000E: - type = EthernetDevType.E1000E; - break; - case PCNET: - type = EthernetDevType.PCNETPCI2; - break; - case VIRTIO: - type = EthernetDevType.PARAVIRT; - break; - case VIRTIO_NET_PCI: - type = EthernetDevType.PARAVIRT; - break; - case VIRTIO_NET_PCI_NON_TRANSITIONAL: - type = EthernetDevType.PARAVIRT; - break; - case VIRTIO_NET_PCI_TRANSITIONAL: - type = EthernetDevType.PARAVIRT; - break; - case VMXNET3: - type = EthernetDevType.VMXNET3; - break; - default: - type = EthernetDevType.AUTO; - break; - } - - return type; - } - - /** - * Returns an item from a given {@link ArrayList}. - * - * The item is selected by a given index. If the item is not available within the - * {@link ArrayList}, <code>null</code> is returned. - * - * @param <T> type of the {@link ArrayList}. - * @param array {@link ArrayList} of type <code>T</code>. - * @param index selects the item from the {@link ArrayList}. - * @return selected item of the {@link ArrayList}. - */ - public static <T> T getArrayIndex( ArrayList<T> array, int index ) - { - T ret; - - try { - ret = array.get( index ); - } catch ( IndexOutOfBoundsException e ) { - ret = null; - } - - return ret; - } - - /** - * Creates an alphabetical device name constructed from a device prefix and a device number. - * - * @param devicePrefix prefix of the constructed device name. - * @param deviceNumber number of the device. - * @return alphabetical device name. - */ - public static String createAlphabeticalDeviceName( String devicePrefix, int deviceNumber ) - { - if ( deviceNumber < 0 || deviceNumber >= ( 'z' - 'a' ) ) { - String errorMsg = new String( "Device number is out of range to be able to create a valid device name." ); - throw new IllegalArgumentException( errorMsg ); - } - - return devicePrefix + ( 'a' + deviceNumber ); - } -} diff --git a/src/main/java/org/openslx/vm/UnsupportedVirtualizerFormatException.java b/src/main/java/org/openslx/vm/UnsupportedVirtualizerFormatException.java deleted file mode 100644 index a6f3197..0000000 --- a/src/main/java/org/openslx/vm/UnsupportedVirtualizerFormatException.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.openslx.vm; - -public class UnsupportedVirtualizerFormatException extends Exception -{ - /** - * Version for serialization. - */ - private static final long serialVersionUID = 5794121065945636839L; - - public UnsupportedVirtualizerFormatException(String message) { - super(message); - } -}
\ No newline at end of file diff --git a/src/main/java/org/openslx/vm/VboxConfig.java b/src/main/java/org/openslx/vm/VboxConfig.java deleted file mode 100644 index 9724b6a..0000000 --- a/src/main/java/org/openslx/vm/VboxConfig.java +++ /dev/null @@ -1,631 +0,0 @@ -package org.openslx.vm; - -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; - -import javax.xml.XMLConstants; -import javax.xml.transform.stream.StreamSource; -import javax.xml.validation.Schema; -import javax.xml.validation.SchemaFactory; -import javax.xml.validation.Validator; -import javax.xml.xpath.XPathConstants; -import javax.xml.xpath.XPathExpression; -import javax.xml.xpath.XPathExpressionException; - -import org.apache.log4j.Logger; -import org.openslx.util.Util; -import org.openslx.util.XmlHelper; -import org.openslx.vm.VmMetaData.DriveBusType; -import org.openslx.vm.VmMetaData.HardDisk; -import org.w3c.dom.DOMException; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.xml.sax.SAXException; - -/** - * Class handling the parsing of a .vbox machine description file - */ -public class VboxConfig -{ - private static final Logger LOGGER = Logger.getLogger( VboxConfig.class ); - - // key information set during initial parsing of the XML file - private String osName = new String(); - private ArrayList<HardDisk> hddsArray = new ArrayList<HardDisk>(); - - // XPath and DOM parsing related members - private Document doc = null; - - // list of nodes to automatically remove when reading the vbox file - private static String[] blacklist = { - "/VirtualBox/Machine/Hardware/GuestProperties", - "/VirtualBox/Machine/Hardware/VideoCapture", - "/VirtualBox/Machine/Hardware/HID", - "/VirtualBox/Machine/Hardware/LPT", - "/VirtualBox/Machine/Hardware/SharedFolders", - "/VirtualBox/Machine/Hardware/Network/Adapter[@enabled='true']/*", - "/VirtualBox/Machine/ExtraData", - "/VirtualBox/Machine/StorageControllers/StorageController/AttachedDevice[not(@type='HardDisk')]", - "/VirtualBox/Machine/MediaRegistry/FloppyImages", - "/VirtualBox/Machine/MediaRegistry/DVDImages" }; - - public static enum PlaceHolder - { - FLOPPYUUID( "%VM_FLOPPY_UUID%" ), FLOPPYLOCATION( "%VM_FLOPPY_LOCATION%" ), CPU( "%VM_CPU_CORES%" ), MEMORY( "%VM_RAM%" ), MACHINEUUID( "%VM_MACHINE_UUID%" ), NETWORKMAC( - "%VM_NIC_MAC%" ), HDDLOCATION( "%VM_HDD_LOCATION%" ), HDDUUID( "%VM_HDD_UUID_" ); - - private final String holderName; - - private PlaceHolder( String name ) - { - this.holderName = name; - } - - @Override - public String toString() - { - return holderName; - } - } - - /** - * Creates a vbox configuration by constructing a DOM from the given VirtualBox machine - * configuration file. - * Will validate the given file against the VirtualBox XSD schema and only proceed if it is - * valid. - * - * @param file the VirtualBox machine configuration file - * @throws IOException if an error occurs while reading the file - * @throws UnsupportedVirtualizerFormatException if the given file is not a valid VirtualBox - * configuration file. - */ - public VboxConfig( File file ) throws IOException, UnsupportedVirtualizerFormatException - { - // first validate xml - try { - SchemaFactory factory = SchemaFactory.newInstance( XMLConstants.W3C_XML_SCHEMA_NS_URI ); - InputStream xsdStream = VboxConfig.class.getResourceAsStream( "/master-sync-shared/xml/VirtualBox-settings.xsd" ); - if ( xsdStream == null ) { - LOGGER.warn( "Cannot validate Vbox XML: No XSD found in JAR" ); - } else { - Schema schema = factory.newSchema( new StreamSource( xsdStream ) ); - Validator validator = schema.newValidator(); - validator.validate( new StreamSource( file ) ); - } - } catch ( SAXException e ) { - LOGGER.error( "Selected vbox file was not validated against the XSD schema: " + e.getMessage() ); - } - // valid xml, try to create the DOM - doc = XmlHelper.parseDocumentFromStream( new FileInputStream( file ) ); - doc = XmlHelper.removeFormattingNodes( doc ); - if ( doc == null ) - throw new UnsupportedVirtualizerFormatException( "Could not create DOM from given VirtualBox machine configuration file!" ); - init(); - } - - /** - * Creates an vbox configuration by constructing a DOM from the XML content given as a byte - * array. - * - * @param machineDescription content of the XML file saved as a byte array. - * @param length of the machine description byte array. - * @throws IOException if an - */ - public VboxConfig( byte[] machineDescription, int length ) throws UnsupportedVirtualizerFormatException - { - ByteArrayInputStream is = new ByteArrayInputStream( machineDescription ); - doc = XmlHelper.parseDocumentFromStream( is ); - if ( doc == null ) { - LOGGER.error( "Failed to create a DOM from given machine description." ); - throw new UnsupportedVirtualizerFormatException( "Could not create DOM from given machine description as. byte array." ); - } - init(); - } - - /** - * Main initialization functions parsing the document created during the constructor. - * @throws UnsupportedVirtualizerFormatException - */ - private void init() throws UnsupportedVirtualizerFormatException - { - if ( Util.isEmptyString( getDisplayName() ) ) { - throw new UnsupportedVirtualizerFormatException( "Machine doesn't have a name" ); - } - try { - ensureHardwareUuid(); - setOsType(); - fixUsb(); // Since we now support selecting specific speed - if ( checkForPlaceholders() ) { - return; - } - setHdds(); - removeBlacklistedElements(); - addPlaceHolders(); - } catch ( XPathExpressionException e ) { - LOGGER.debug( "Could not initialize VBoxConfig", e ); - return; - } - } - - private void fixUsb() - { - NodeList list = findNodes( "/VirtualBox/Machine/Hardware/USB/Controllers/Controller" ); - if ( list != null && list.getLength() != 0 ) { - LOGGER.info( "USB present, not fixing anything" ); - return; - } - // If there's no USB section, this can mean two things: - // 1) Old config that would always default to USB 2.0 for "USB enabled" or nothing for disabled - // 2) New config with USB disabled - list = findNodes( "/VirtualBox/OpenSLX/USB[@disabled]" ); - if ( list != null && list.getLength() != 0 ) { - LOGGER.info( "USB explicitly disabled" ); - return; // Explicitly marked as disabled, do nothing - } - // We assume case 1) and add USB 2.0 - LOGGER.info( "Fixing USB: Adding USB 2.0" ); - Element controller; - Element node = createNodeRecursive( "/VirtualBox/Machine/Hardware/USB/Controllers" ); - controller = addNewNode( node, "Controller" ); - controller.setAttribute( "name", "OHCI" ); - controller.setAttribute( "type", "OHCI" ); - controller = addNewNode( node, "Controller" ); - controller.setAttribute( "name", "EHCI" ); - controller.setAttribute( "type", "EHCI" ); - } - - /** - * Saves the machine's uuid as hardware uuid to prevent VMs from - * believing in a hardware change. - * - * @throws XPathExpressionException - * @throws UnsupportedVirtualizerFormatException - */ - private void ensureHardwareUuid() throws XPathExpressionException, UnsupportedVirtualizerFormatException - { - // we will need the machine uuid, so get it - String machineUuid = XmlHelper.XPath.compile( "/VirtualBox/Machine/@uuid" ).evaluate( this.doc ); - if ( machineUuid.isEmpty() ) { - LOGGER.error( "Machine UUID empty, should never happen!" ); - throw new UnsupportedVirtualizerFormatException( "XML doesn't contain a machine uuid" ); - } - - NodeList hwNodes = findNodes( "/VirtualBox/Machine/Hardware" ); - int count = hwNodes.getLength(); - if ( count != 1 ) { - throw new UnsupportedVirtualizerFormatException( "Zero or more '/VirtualBox/Machine/Hardware' node were found, should never happen!" ); - } - Element hw = (Element)hwNodes.item( 0 ); - String hwUuid = hw.getAttribute( "uuid" ); - if ( !hwUuid.isEmpty() ) { - LOGGER.info( "Found hardware uuid: " + hwUuid ); - return; - } else { - if ( !addAttributeToNode( hw, "uuid", machineUuid ) ) { - LOGGER.error( "Failed to set machine UUID '" + machineUuid + "' as hardware UUID." ); - return; - } - LOGGER.info( "Saved machine UUID as hardware UUID." ); - } - } - - /** - * Self-explanatory. - */ - public void addPlaceHolders() - { - // placeholder for the machine uuid - changeAttribute( "/VirtualBox/Machine", "uuid", PlaceHolder.MACHINEUUID.toString() ); - - // placeholder for the location of the virtual hdd - changeAttribute( "/VirtualBox/Machine/MediaRegistry/HardDisks/HardDisk", "location", PlaceHolder.HDDLOCATION.toString() ); - - // placeholder for the memory - changeAttribute( "/VirtualBox/Machine/Hardware/Memory", "RAMSize", PlaceHolder.MEMORY.toString() ); - - // placeholder for the CPU - changeAttribute( "/VirtualBox/Machine/Hardware/CPU", "count", PlaceHolder.CPU.toString() ); - - // placeholder for the MACAddress - changeAttribute( "/VirtualBox/Machine/Hardware/Network/Adapter", "MACAddress", PlaceHolder.NETWORKMAC.toString() ); - - NodeList hdds = findNodes( "/VirtualBox/Machine/MediaRegistry/HardDisks/HardDisk" ); - for ( int i = 0; i < hdds.getLength(); i++ ) { - Element hdd = (Element)hdds.item( i ); - if ( hdd == null ) - continue; - String hddUuid = hdd.getAttribute( "uuid" ); - hdd.setAttribute( "uuid", PlaceHolder.HDDUUID.toString() + i + "%" ); - NodeList images = findNodes( "/VirtualBox/Machine/StorageControllers/StorageController/AttachedDevice/Image" ); - for ( int j = 0; j < images.getLength(); j++ ) { - Element image = (Element)images.item( j ); - if ( image == null ) - continue; - if ( hddUuid.equals( image.getAttribute( "uuid" ) ) ) { - image.setAttribute( "uuid", PlaceHolder.HDDUUID.toString() + i + "%" ); - break; - } - } - } - } - - /** - * Function checks if the placeholders are present - * - * @return true if the placeholders are present, false otherwise - */ - private boolean checkForPlaceholders() - { - // TODO this should be more robust... - NodeList hdds = findNodes( "/VirtualBox/Machine/MediaRegistry/HardDisks/HardDisk" ); - for ( int i = 0; i < hdds.getLength(); i++ ) { - Element hdd = (Element)hdds.item( i ); - if ( hdd == null ) - continue; - if ( hdd.getAttribute( "location" ).equals( PlaceHolder.HDDLOCATION.toString() ) ) { - return true; - } - } - return false; - } - - /** - * Called during init(), prunes the DOM from the elements blacklisted defined - * in the member blacklist, a list of XPath expressions as String - * - * @throws XPathExpressionException - */ - private void removeBlacklistedElements() throws XPathExpressionException - { - // iterate over the blackList - for ( String blackedTag : blacklist ) { - XPathExpression blackedExpr = XmlHelper.XPath.compile( blackedTag ); - NodeList blackedNodes = (NodeList)blackedExpr.evaluate( this.doc, XPathConstants.NODESET ); - for ( int i = 0; i < blackedNodes.getLength(); i++ ) { - // go through the child nodes of the blacklisted ones -> why? - Element child = (Element)blackedNodes.item( i ); - removeNode( child ); - } - } - } - - /** - * Getter for the display name - * - * @return the display name of this VM - */ - public String getDisplayName() - { - try { - return XmlHelper.XPath.compile( "/VirtualBox/Machine/@name" ).evaluate( this.doc ); - } catch ( XPathExpressionException e ) { - return ""; - } - } - - /** - * Function finds and saves the name of the guest OS - * - * @throws XPathExpressionException - */ - public void setOsType() throws XPathExpressionException - { - String os = XmlHelper.XPath.compile( "/VirtualBox/Machine/@OSType" ).evaluate( this.doc ); - if ( os != null && !os.isEmpty() ) { - osName = os; - } - } - - /** - * Getter for the parsed guest OS name - * - * @return name of the guest OS - */ - public String getOsName() - { - return osName; - } - - /** - * Search for attached hard drives and determine their controller and their path. - * - * @throws XPathExpressionException - */ - public void setHdds() throws XPathExpressionException - { - XPathExpression hddsExpr = XmlHelper.XPath.compile( "/VirtualBox/Machine/StorageControllers/StorageController/AttachedDevice[@type='HardDisk']/Image" ); - NodeList nodes = (NodeList)hddsExpr.evaluate( this.doc, XPathConstants.NODESET ); - if ( nodes == null ) { - LOGGER.error( "Failed to find attached hard drives." ); - return; - } - for ( int i = 0; i < nodes.getLength(); i++ ) { - Element hddElement = (Element)nodes.item( i ); - if ( hddElement == null ) - continue; - String uuid = hddElement.getAttribute( "uuid" ); - if ( uuid.isEmpty() ) - continue; - // got uuid, check if it was registered - XPathExpression hddsRegistered = XmlHelper.XPath.compile( "/VirtualBox/Machine/MediaRegistry/HardDisks/HardDisk[@uuid='" + uuid + "']" ); - NodeList hddsRegisteredNodes = (NodeList)hddsRegistered.evaluate( this.doc, XPathConstants.NODESET ); - if ( hddsRegisteredNodes == null || hddsRegisteredNodes.getLength() != 1 ) { - LOGGER.error( "Found hard disk with uuid '" + uuid + "' which does not appear (unique) in the Media Registry. Skipping." ); - continue; - } - Element hddElementReg = (Element)hddsRegisteredNodes.item( 0 ); - if ( hddElementReg == null ) - continue; - String fileName = hddElementReg.getAttribute( "location" ); - String type = hddElementReg.getAttribute( "type" ); - if ( !type.equals( "Normal" ) && !type.equals( "Writethrough" ) ) { - LOGGER.warn( "Type of the disk file is neither 'Normal' nor 'Writethrough' but: " + type ); - LOGGER.warn( "This makes the image not directly modificable, which might lead to problems when editing it locally." ); - } - // search if it is also attached to a controller - Node hddDevice = hddElement.getParentNode(); - if ( hddDevice == null ) { - LOGGER.error( "HDD node had a null parent, shouldn't happen" ); - continue; - } - Element hddController = (Element)hddDevice.getParentNode(); - if ( hddController == null ) { - LOGGER.error( "HDD node had a null parent, shouldn't happen" ); - continue; - } - String controllerMode = hddController.getAttribute( "type" ); - String controllerType = hddController.getAttribute( "name" ); - DriveBusType busType; - if ( controllerType.equals( "NVMe" ) ) { - busType = DriveBusType.NVME; - } else { - try { - // This assumes the type in the xml matches our enum constants. - busType = DriveBusType.valueOf( controllerType ); - } catch (Exception e) { - LOGGER.warn( "Skipping unknown HDD controller type '" + controllerType + "'" ); - continue; - } - } - LOGGER.info( "Adding hard disk with controller: " + busType + " (" + controllerMode + ") from file '" + fileName + "'." ); - hddsArray.add( new HardDisk( controllerMode, busType, fileName ) ); - } - } - - /** - * Getter for the list of detected hard drives. - * - * @return list of disk drives. - */ - public ArrayList<HardDisk> getHdds() - { - return hddsArray; - } - - /** - * Detect if the vbox file has any machine snapshot by looking at - * the existance of '/VirtualBox/Machine/Snapshot' elements. - * - * @return true if a machine snapshot is present, false otherwise. - */ - public boolean isMachineSnapshot() - { - // check if the vbox configuration file contains some machine snapshots. - // by looking at the existance of /VirtualBox/Machine/Snapshot - NodeList machineSnapshots = findNodes( "/VirtualBox/Machine/Snapshot" ); - return machineSnapshots != null && machineSnapshots.getLength() > 0; - } - - /** - * Searches the DOM for the elements matching the given XPath expression. - * - * @param xpath expression to search the DOM with - * @return nodes found by evaluating given XPath expression - */ - public NodeList findNodes( String xpath ) - { - NodeList nodes = null; - try { - XPathExpression expr = XmlHelper.XPath.compile( xpath ); - Object nodesObject = expr.evaluate( this.doc, XPathConstants.NODESET ); - nodes = (NodeList)nodesObject; - } catch ( XPathExpressionException e ) { - LOGGER.error( "Could not build path", e ); - } - return nodes; - } - - /** - * Function used to change the value of an attribute of given element. - * The given xpath to the element needs to find a single node, or this function will return - * false. If only one element was found, it will return the result of calling addAttributeToNode. - * Note that due to the way setAttribute() works, this function to create the attribute if it - * doesn't exists. - * - * @param elementXPath given as an xpath expression - * @param attribute attribute to change - * @param value to set the attribute to - */ - public boolean changeAttribute( String elementXPath, String attribute, String value ) - { - NodeList nodes = findNodes( elementXPath ); - if ( nodes == null || nodes.getLength() != 1 ) { - LOGGER.error( "No unique node could be found for: " + elementXPath ); - return false; - } - return addAttributeToNode( nodes.item( 0 ), attribute, value ); - } - - /** - * Add given attribute with given value to the given node. - * NOTE: this will overwrite the attribute of the node if it already exists. - * - * @param node to add the attribute to - * @param attribute attribute to add to the node - * @param value of the attribute - * @return true if successful, false otherwise - */ - public boolean addAttributeToNode( Node node, String attribute, String value ) - { - if ( node == null || node.getNodeType() != Node.ELEMENT_NODE ) { - LOGGER.error( "Trying to change attribute of a non element node!" ); - return false; - } - try { - ( (Element)node ).setAttribute( attribute, value ); - } catch ( DOMException e ) { - LOGGER.error( "Failed set '" + attribute + "' to '" + value + "' of xml node '" + node.getNodeName() + "': ", e ); - return false; - } - return true; - } - - /** - * Adds a new node named nameOfNewNode to the given parent found by parentXPath. - * - * @param parentXPath XPath expression to the parent - * @param nameOfnewNode name of the node to be added - * @return the newly added Node - */ - public Node addNewNode( String parentXPath, String childName ) - { - NodeList possibleParents = findNodes( parentXPath ); - if ( possibleParents == null || possibleParents.getLength() != 1 ) { - LOGGER.error( "Could not find unique parent node to add new node to: " + parentXPath ); - return null; - } - return addNewNode( possibleParents.item( 0 ), childName ); - } - - public Element createNodeRecursive( String xPath ) - { - String[] nodeNames = xPath.split( "/" ); - Node parent = this.doc; - Element latest = null; - for ( int nodeIndex = 0; nodeIndex < nodeNames.length; ++nodeIndex ) { - if ( nodeNames[nodeIndex].length() == 0 ) - continue; - Node node = skipNonElementNodes( parent.getFirstChild() ); - while ( node != null ) { - if ( node.getNodeType() == Node.ELEMENT_NODE && nodeNames[nodeIndex].equals( node.getNodeName() ) ) - break; // Found existing - // Check next on same level - node = skipNonElementNodes( node.getNextSibling() ); - } - if ( node == null ) { - node = doc.createElement( nodeNames[nodeIndex] ); - parent.appendChild( node ); - } - parent = node; - latest = (Element)node; - } - return latest; - } - - private Element skipNonElementNodes( Node nn ) - { - while ( nn != null && nn.getNodeType() != Node.ELEMENT_NODE ) { - nn = nn.getNextSibling(); - } - return (Element)nn; - } - - public void setExtraData( String key, String value ) - { - NodeList nl = findNodes( "/VirtualBox/Machine/ExtraData/ExtraDataItem[@name='" + key + "']" ); - Element e = null; - for ( int i = 0; i < nl.getLength(); ++i ) { - Node n = nl.item( i ); - if ( n.getNodeType() == Node.ELEMENT_NODE ) { - e = (Element)n; - break; - } - } - if ( e == null ) { - Element p = createNodeRecursive( "/VirtualBox/Machine/ExtraData" ); - e = addNewNode( p, "ExtraDataItem" ); - e.setAttribute( "name", key ); - } - e.setAttribute( "value", value ); - } - - /** - * Creates a new element to the given parent node. - * - * @param parent to add the new element to - * @param childName name of the new element to create - * @return the newly created node - */ - public Element addNewNode( Node parent, String childName ) - { - if ( parent == null || parent.getNodeType() != Node.ELEMENT_NODE ) { - return null; - } - Element newNode = null; - try { - newNode = doc.createElement( childName ); - parent.appendChild( newNode ); - } catch ( DOMException e ) { - LOGGER.error( "Failed to add '" + childName + "' to '" + parent.getNodeName() + "'." ); - } - return newNode; - } - - /** - * Helper to remove given node from the DOM. - * - * @param node Node object to remove. - */ - private void removeNode( Node node ) - { - if ( node == null ) - return; - Node parent = node.getParentNode(); - if ( parent != null ) - parent.removeChild( node ); - } - - /** - * Helper to output the DOM as a String. - * - * @param prettyPrint sets whether to indent the output - * @return (un-)formatted XML - */ - public String toString( boolean prettyPrint ) - { - return XmlHelper.getXmlFromDocument( doc, prettyPrint ); - } - - /** - * Remove all nodes with name childName from parentPath - * @param parentPath XPath to parent node of where child nodes are to be deleted - * @param childName Name of nodes to delete - */ - public void removeNodes( String parentPath, String childName ) - { - NodeList parentNodes = findNodes( parentPath ); - // XPath might match multiple nodes - for ( int i = 0; i < parentNodes.getLength(); ++i ) { - Node parent = parentNodes.item( i ); - List<Node> delList = new ArrayList<>( 0 ); - // Iterate over child nodes - for ( Node child = parent.getFirstChild(); child != null; child = child.getNextSibling() ) { - if ( childName.equals( child.getNodeName() ) ) { - // Remember all to be deleted (don't delete while iterating) - delList.add( child ); - } - } - // Now delete them all - for ( Node child : delList ) { - parent.removeChild( child ); - } - } - } -} diff --git a/src/main/java/org/openslx/vm/VboxMetaData.java b/src/main/java/org/openslx/vm/VboxMetaData.java deleted file mode 100644 index a6ac14d..0000000 --- a/src/main/java/org/openslx/vm/VboxMetaData.java +++ /dev/null @@ -1,536 +0,0 @@ -package org.openslx.vm; - -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map.Entry; -import java.util.UUID; - -import org.apache.log4j.Logger; -import org.openslx.bwlp.thrift.iface.OperatingSystem; -import org.openslx.bwlp.thrift.iface.Virtualizer; -import org.openslx.thrifthelper.TConst; -import org.openslx.vm.VboxConfig.PlaceHolder; -import org.openslx.vm.disk.DiskImage; -import org.openslx.vm.disk.DiskImage.ImageFormat; -import org.w3c.dom.Attr; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -class VBoxSoundCardMeta -{ - public final boolean isPresent; - public final String value; - - public VBoxSoundCardMeta( boolean present, String val ) - { - isPresent = present; - value = val; - } -} - -class VBoxDDAccelMeta -{ - public final boolean isPresent; - - public VBoxDDAccelMeta( boolean present ) - { - isPresent = present; - } -} - -class VBoxHWVersionMeta -{ - public final int version; - - public VBoxHWVersionMeta( int vers ) - { - version = vers; - } -} - -class VBoxEthernetDevTypeMeta -{ - public final String value; - public final boolean isPresent; - - public VBoxEthernetDevTypeMeta( boolean present, String val ) - { - value = val; - isPresent = present; - } -} - -class VBoxUsbSpeedMeta -{ - public final String value; - public final int speed; - public VBoxUsbSpeedMeta( String value, int speed ) - { - this.value = value; - this.speed = speed; - } -} - -public class VboxMetaData extends VmMetaData<VBoxSoundCardMeta, VBoxDDAccelMeta, VBoxHWVersionMeta, VBoxEthernetDevTypeMeta, VBoxUsbSpeedMeta> -{ - /** - * List of supported image formats by the VirtualBox hypervisor. - */ - private static final List<DiskImage.ImageFormat> SUPPORTED_IMAGE_FORMATS = Collections.unmodifiableList( - Arrays.asList( ImageFormat.VDI ) ); - - private static final Logger LOGGER = Logger.getLogger( VboxMetaData.class ); - - private static final Virtualizer virtualizer = new Virtualizer( TConst.VIRT_VIRTUALBOX, "VirtualBox" ); - - private final VboxConfig config; - - public static enum EthernetType - { - NAT( "vboxnet1" ), BRIDGED( "vboxnet0" ), HOST_ONLY( "vboxnet2" ); - - public final String vnet; - - private EthernetType( String vnet ) - { - this.vnet = vnet; - } - } - - public VboxMetaData( List<OperatingSystem> osList, File file ) throws IOException, UnsupportedVirtualizerFormatException - { - super( osList ); - this.config = new VboxConfig( file ); - init(); - } - - public VboxMetaData( List<OperatingSystem> osList, byte[] vmContent, int length ) throws IOException, UnsupportedVirtualizerFormatException - { - super( osList ); - this.config = new VboxConfig( vmContent, length ); - init(); - } - - private void init() - { - registerVirtualHW(); - displayName = config.getDisplayName(); - setOs( config.getOsName() ); - this.isMachineSnapshot = config.isMachineSnapshot(); - for ( HardDisk hardDisk : config.getHdds() ) { - hdds.add( hardDisk ); - } - } - - @Override - public Virtualizer getVirtualizer() - { - return virtualizer; - } - - @Override - public List<DiskImage.ImageFormat> getSupportedImageFormats() - { - return VboxMetaData.SUPPORTED_IMAGE_FORMATS; - } - - @Override - public void applySettingsForLocalEdit() - { - // TODO Auto-generated method stub - } - - @Override - public byte[] getDefinitionArray() - { - return config.toString( false ).getBytes( StandardCharsets.UTF_8 ); - } - - @Override - public byte[] getFilteredDefinitionArray() - { - return config.toString( false ).getBytes( StandardCharsets.UTF_8 ); - } - - @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", "snapshotFolder", redoDir ); - return true; - } - - @Override - public boolean addHddTemplate( File diskImage, String hddMode, String redoDir ) - { - String diskImagePath = diskImage.getName(); - config.changeAttribute( "/VirtualBox/Machine/MediaRegistry/HardDisks/HardDisk", "location", diskImagePath ); - - UUID newhdduuid = UUID.randomUUID(); - - // 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 ); - - // 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 - // are in LITTLE_ENDIAN order in pairs of 4-2-2 not the whole 8 so just changing the - // order when we are adding them to the bytebuffer won't help - // - // the following is a workaround that works - ByteBuffer buffer = ByteBuffer.wrap( new byte[ 16 ] ); - buffer.putLong( newhdduuid.getMostSignificantBits() ); - buffer.putLong( newhdduuid.getLeastSignificantBits() ); - byte[] oldOrder = buffer.array(); - // make a coppy here because the last 8 Bytes don't need to change position - byte[] bytesToWrite = Arrays.copyOf( oldOrder, oldOrder.length ); - // use an offset int[] to help with the shuffle - int[] offsets = { 3, 2, 1, 0, 5, 4, 7, 6 }; - for ( int index = 0; index < 8; index++ ) { - bytesToWrite[index] = oldOrder[offsets[index]]; - } - try ( RandomAccessFile file = new RandomAccessFile( diskImage, "rw" ) ) { - file.seek( 392 ); - file.write( bytesToWrite, 0, 16 ); - } catch ( Exception e ) { - LOGGER.warn( "could not patch new uuid in the vdi", e ); - } - - // we need a new machine uuid - UUID newMachineUuid = UUID.randomUUID(); - if ( newMachineUuid.equals( newhdduuid ) ) { - LOGGER.warn( "The new Machine UUID is the same as the new HDD UUID; tying again...this vm might not start" ); - newMachineUuid = UUID.randomUUID(); - } - String machineUUid = "{" + newMachineUuid.toString() + "}"; - return config.changeAttribute( "/VirtualBox/Machine", "uuid", machineUUid ); - } - - @Override - public boolean addDefaultNat() - { - if ( config.addNewNode( "/VirtualBox/Machine/Hardware/Network/Adapter", "NAT" ) == null ) { - LOGGER.error( "Failed to set network adapter to NAT." ); - return false; - } - return config.changeAttribute( "/VirtualBox/Machine/Hardware/Network/Adapter", "MACAddress", "080027B86D12" ); - } - - @Override - public void setOs( String vendorOsId ) - { - config.changeAttribute( "/VirtualBox/Machine", "OSType", vendorOsId ); - setOs( TConst.VIRT_VIRTUALBOX, vendorOsId ); - } - - @Override - public boolean addDisplayName( String name ) - { - return config.changeAttribute( "/VirtualBox/Machine", "name", name ); - } - - @Override - public boolean addRam( int mem ) - { - return config.changeAttribute( "/VirtualBox/Machine/Hardware/Memory", "RAMSize", Integer.toString( mem ) ); - } - - @Override - public void addFloppy( int index, String image, boolean readOnly ) - { - Element floppyController = null; - 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 ) { - LOGGER.error( "Failed to add <Image> to floppy device." ); - return; - } - floppyController.setAttribute( "name", "Floppy" ); - floppyController.setAttribute( "type", "I82078" ); - floppyController.setAttribute( "PortCount", "1" ); - floppyController.setAttribute( "useHostIOCache", "true" ); - floppyController.setAttribute( "Bootable", "false" ); - } - // virtualbox only allows one controller per type - if ( matches.getLength() > 1 ) { - LOGGER.error( "Multiple floppy controllers detected, this should never happen! " ); - return; - } - // so if we had any matches, we know we have exactly one - if ( floppyController == null ) - floppyController = (Element)matches.item( 0 ); - - // add the floppy device - Element floppyDevice = (Element)config.addNewNode( floppyController, "AttachedDevice" ); - if ( floppyDevice == null ) { - LOGGER.error( "Failed to add <Image> to floppy device." ); - return; - } - floppyDevice.setAttribute( "type", "Floppy" ); - floppyDevice.setAttribute( "hotpluggable", "false" ); - floppyDevice.setAttribute( "port", "0" ); - floppyDevice.setAttribute( "device", Integer.toString( index ) ); - - // finally add the image to it, if one was given - if ( image != null ) { - Element floppyImage = (Element)config.addNewNode( floppyDevice, "Image" ); - if ( floppyImage == null ) { - LOGGER.error( "Failed to add <Image> to floppy device." ); - return; - } - floppyImage.setAttribute( "uuid", VboxConfig.PlaceHolder.FLOPPYUUID.toString() ); - // register the image in the media registry - Element floppyImages = (Element)config.addNewNode( "/VirtualBox/Machine/MediaRegistry", "FloppyImages" ); - if ( floppyImages == null ) { - LOGGER.error( "Failed to add <FloppyImages> to media registry." ); - return; - } - Element floppyImageReg = (Element)config.addNewNode( "/VirtualBox/Machine/MediaRegistry/FloppyImages", "Image" ); - if ( floppyImageReg == null ) { - LOGGER.error( "Failed to add <Image> to floppy images in the media registry." ); - return; - } - floppyImageReg.setAttribute( "uuid", VboxConfig.PlaceHolder.FLOPPYUUID.toString() ); - floppyImageReg.setAttribute( "location", VboxConfig.PlaceHolder.FLOPPYLOCATION.toString() ); - } - } - - @Override - public boolean addCdrom( String image ) - { - // TODO - done in run-virt currently - return false; - } - - @Override - public boolean addCpuCoreCount( int nrOfCores ) - { - return config.changeAttribute( "/VirtualBox/Machine/Hardware/CPU", "count", Integer.toString( nrOfCores ) ); - } - - @Override - public void setSoundCard( org.openslx.vm.VmMetaData.SoundCardType type ) - { - VBoxSoundCardMeta sound = soundCards.get( type ); - config.changeAttribute( "/VirtualBox/Machine/Hardware/AudioAdapter", "enabled", Boolean.toString( sound.isPresent ) ); - config.changeAttribute( "/VirtualBox/Machine/Hardware/AudioAdapter", "controller", sound.value ); - } - - @Override - public VmMetaData.SoundCardType getSoundCard() - { - // initialize here to type None to avoid all null pointer exceptions thrown for unknown user written sound cards - VmMetaData.SoundCardType returnsct = VmMetaData.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" ) ) ) { - return returnsct; - } else { - // extra separate case for the non-existing argument} - if ( !x.hasAttribute( "controller" ) ) { - returnsct = VmMetaData.SoundCardType.AC; - } else { - String controller = x.getAttribute( "controller" ); - VBoxSoundCardMeta soundMeta = null; - for ( VmMetaData.SoundCardType type : VmMetaData.SoundCardType.values() ) { - soundMeta = soundCards.get( type ); - if ( soundMeta != null ) { - if ( controller.equals( soundMeta.value ) ) { - returnsct = type; - } - } - } - } - } - return returnsct; - } - - @Override - public void setDDAcceleration( VmMetaData.DDAcceleration type ) - { - VBoxDDAccelMeta accel = ddacc.get( type ); - config.changeAttribute( "/VirtualBox/Machine/Hardware/Display", "accelerate3D", Boolean.toString( accel.isPresent ) ); - } - - @Override - public VmMetaData.DDAcceleration getDDAcceleration() - { - VmMetaData.DDAcceleration returndda = null; - Element x = (Element)config.findNodes( "/VirtualBox/Machine/Hardware/Display" ).item( 0 ); - if ( x.hasAttribute( "accelerate3D" ) ) { - if ( x.getAttribute( "accelerate3D" ).equals( "true" ) ) { - returndda = VmMetaData.DDAcceleration.ON; - } else { - returndda = VmMetaData.DDAcceleration.OFF; - } - } else { - returndda = VmMetaData.DDAcceleration.OFF; - } - return returndda; - } - - /** - * Function does nothing for Virtual Box; - * Virtual Box accepts per default only one hardware version and is hidden from the user - */ - @Override - public void setHWVersion( HWVersion type ) - { - } - - @Override - public VmMetaData.HWVersion getHWVersion() - { - // Virtual Box uses only one virtual hardware version and can't be changed - return VmMetaData.HWVersion.DEFAULT; - } - - @Override - public void setEthernetDevType( int cardIndex, EthernetDevType type ) - { - 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 ); - } - - @Override - public VmMetaData.EthernetDevType getEthernetDevType( int cardIndex ) - { - VmMetaData.EthernetDevType returnedt = VmMetaData.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" ) ) ) { - return returnedt; - } else { - // extra separate case for the non-existing argument} - if ( !x.hasAttribute( "type" ) ) { - returnedt = VmMetaData.EthernetDevType.PCNETFAST3; - } else { - String temp = x.getAttribute( "type" ); - VBoxEthernetDevTypeMeta etherMeta = null; - for ( VmMetaData.EthernetDevType type : VmMetaData.EthernetDevType.values() ) { - etherMeta = networkCards.get( type ); - if ( etherMeta != null ) { - if ( temp.equals( etherMeta.value ) ) { - returnedt = type; - } - } - } - } - } - return returnedt; - } - - public void registerVirtualHW() - { - // none type needs to have a valid value; it takes the value of AC97; if value is left null or empty vm will not start because value is not valid - // TODO: Maybe just remove the entire section from the XML? Same for ethernet... - soundCards.put( VmMetaData.SoundCardType.NONE, new VBoxSoundCardMeta( false, "AC97" ) ); - soundCards.put( VmMetaData.SoundCardType.SOUND_BLASTER, new VBoxSoundCardMeta( true, "SB16" ) ); - soundCards.put( VmMetaData.SoundCardType.HD_AUDIO, new VBoxSoundCardMeta( true, "HDA" ) ); - soundCards.put( VmMetaData.SoundCardType.AC, new VBoxSoundCardMeta( true, "AC97" ) ); - - ddacc.put( VmMetaData.DDAcceleration.OFF, new VBoxDDAccelMeta( false ) ); - ddacc.put( VmMetaData.DDAcceleration.ON, new VBoxDDAccelMeta( true ) ); - - hwversion.put( VmMetaData.HWVersion.DEFAULT, new VBoxHWVersionMeta( 0 ) ); - - // none type needs to have a valid value; it takes the value of pcnetcpi2; if value is left null or empty vm will not start because value is not valid - networkCards.put( VmMetaData.EthernetDevType.NONE, new VBoxEthernetDevTypeMeta( false, "Am79C970A" ) ); - networkCards.put( VmMetaData.EthernetDevType.PCNETPCI2, new VBoxEthernetDevTypeMeta( true, "Am79C970A" ) ); - networkCards.put( VmMetaData.EthernetDevType.PCNETFAST3, new VBoxEthernetDevTypeMeta( true, "Am79C973" ) ); - networkCards.put( VmMetaData.EthernetDevType.PRO1000MTD, new VBoxEthernetDevTypeMeta( true, "82540EM" ) ); - networkCards.put( VmMetaData.EthernetDevType.PRO1000TS, new VBoxEthernetDevTypeMeta( true, "82543GC" ) ); - networkCards.put( VmMetaData.EthernetDevType.PRO1000MTS, new VBoxEthernetDevTypeMeta( true, "82545EM" ) ); - networkCards.put( VmMetaData.EthernetDevType.PARAVIRT, new VBoxEthernetDevTypeMeta( true, "virtio" ) ); - - usbSpeeds.put( VmMetaData.UsbSpeed.NONE, new VBoxUsbSpeedMeta( null, 0 ) ); - usbSpeeds.put( VmMetaData.UsbSpeed.USB1_1, new VBoxUsbSpeedMeta( "OHCI", 1 ) ); - usbSpeeds.put( VmMetaData.UsbSpeed.USB2_0, new VBoxUsbSpeedMeta( "EHCI", 2 ) ); - usbSpeeds.put( VmMetaData.UsbSpeed.USB3_0, new VBoxUsbSpeedMeta( "XHCI", 3 ) ); - } - - @Override - public boolean addEthernet( VmMetaData.EtherType type ) - { - 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; - } - return config.addAttributeToNode( hostOnlyInterfaceNode, "name", EthernetType.valueOf( type.name() ).vnet ); - } - - @Override - public boolean tweakForNonPersistent() - { - // Cannot disable suspend - // https://forums.virtualbox.org/viewtopic.php?f=6&t=77169 - // https://forums.virtualbox.org/viewtopic.php?f=8&t=80338 - // But some other stuff that won't make sense in non-persistent mode - config.setExtraData( "GUI/LastCloseAction", "PowerOff" ); - // Could use "Default" instead of "Last" above, but you won't get any confirmation dialog in that case - config.setExtraData( "GUI/RestrictedRuntimeHelpMenuActions", "All" ); - config.setExtraData( "GUI/RestrictedRuntimeMachineMenuActions", "TakeSnapshot,Pause,SaveState" ); - config.setExtraData( "GUI/RestrictedRuntimeMenus", "Help" ); - config.setExtraData( "GUI/PreventSnapshotOperations", "true" ); - config.setExtraData( "GUI/PreventApplicationUpdate", "true" ); - config.setExtraData( "GUI/RestrictedCloseActions", "SaveState,PowerOffRestoringSnapshot,Detach" ); - return true; - } - - @Override - public void setMaxUsbSpeed( VmMetaData.UsbSpeed speed ) - { - // Wipe existing ones - config.removeNodes( "/VirtualBox/Machine/Hardware", "USB" ); - if ( speed == null || speed == VmMetaData.UsbSpeed.NONE ) { - // Add marker so we know it's not an old config and we really want no USB - Element node = config.createNodeRecursive( "/VirtualBox/OpenSLX/USB" ); - if ( node != null ) { - node.setAttribute( "disabled", "true" ); - } - return; // NO USB - } - Element node = config.createNodeRecursive( "/VirtualBox/Machine/Hardware/USB/Controllers/Controller" ); - VBoxUsbSpeedMeta vboxSpeed = usbSpeeds.get( speed ); - node.setAttribute( "type", vboxSpeed.value ); - node.setAttribute( "name", vboxSpeed.value ); - if ( speed == UsbSpeed.USB2_0 ) { - // If EHCI (2.0) is selected, VBox adds an OHCI controller too... - node.setAttribute( "type", "OHCI" ); - node.setAttribute( "name", "OHCI" ); - } - } - - @Override - public VmMetaData.UsbSpeed getMaxUsbSpeed() - { - NodeList nodes = config.findNodes( "/VirtualBox/Machine/Hardware/USB/Controllers/Controller/@type" ); - int maxSpeed = 0; - VmMetaData.UsbSpeed maxItem = VmMetaData.UsbSpeed.NONE; - for ( int i = 0; i < nodes.getLength(); ++i ) { - if ( nodes.item( i ).getNodeType() != Node.ATTRIBUTE_NODE ) { - LOGGER.info( "Not ATTRIBUTE type" ); - continue; - } - String type = ((Attr)nodes.item( i )).getValue(); - for ( Entry<VmMetaData.UsbSpeed, VBoxUsbSpeedMeta> s : usbSpeeds.entrySet() ) { - if ( s.getValue().speed > maxSpeed && type.equals( s.getValue().value ) ) { - maxSpeed = s.getValue().speed; - maxItem = s.getKey(); - } - } - } - return maxItem; - } -} diff --git a/src/main/java/org/openslx/vm/VmMetaData.java b/src/main/java/org/openslx/vm/VmMetaData.java deleted file mode 100644 index 0be07e4..0000000 --- a/src/main/java/org/openslx/vm/VmMetaData.java +++ /dev/null @@ -1,419 +0,0 @@ -package org.openslx.vm; - -import java.io.File; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import org.apache.log4j.Logger; -import org.openslx.bwlp.thrift.iface.OperatingSystem; -import org.openslx.bwlp.thrift.iface.Virtualizer; -import org.openslx.vm.disk.DiskImage; - -/** - * Describes a configured virtual machine. This class is parsed from a machine - * description, like a *.vmx for VMware machines. - */ -public abstract class VmMetaData<T, U, V, W, X> -{ - private static final Logger LOGGER = Logger.getLogger( VmMetaData.class ); - - /* - * Helper types - */ - protected Map<SoundCardType, T> soundCards = new HashMap<>(); - protected Map<DDAcceleration, U> ddacc = new HashMap<>(); - protected Map<HWVersion, V> hwversion = new HashMap<>(); - protected Map<EthernetDevType, W> networkCards = new HashMap<>(); - protected Map<UsbSpeed, X> usbSpeeds = new HashMap<>(); - - /** - * Virtual sound cards types - */ - public static enum SoundCardType - { - NONE( "None" ), DEFAULT( "(default)" ), SOUND_BLASTER( "Sound Blaster 16" ), ES( "ES 1371" ), HD_AUDIO( "Intel Integrated HD Audio" ), AC( "Intel ICH Audio Codec 97" ); - - public final String displayName; - - private SoundCardType( String dName ) - { - this.displayName = dName; - } - } - - /** - * 3D acceleration types - */ - public static enum DDAcceleration - { - OFF( "Off" ), ON( "On" ); - - public final String displayName; - - private DDAcceleration( String dName ) - { - this.displayName = dName; - } - } - - /** - * Virtual hardware version - currently only in use for VMPlayer - */ - public static enum HWVersion - { - NONE( "(invalid)" ), - THREE( " 3 (Workstation 4/5, Player 1)" ), - FOUR( " 4 (Workstation 4/5, Player 1/2, Fusion 1)" ), - SIX( " 6 (Workstation 6)" ), - SEVEN( " 7 (Workstation 6.5/7, Player 3, Fusion 2/3)" ), - EIGHT( " 8 (Workstation 8, Player/Fusion 4)" ), - NINE( " 9 (Workstation 9, Player/Fusion 5)" ), - TEN( "10 (Workstation 10, Player/Fusion 6)" ), - ELEVEN( "11 (Workstation 11, Player/Fusion 7)" ), - TWELVE( "12 (Workstation/Player 12, Fusion 8)" ), - FOURTEEN( "14 (Workstation/Player 14, Fusion 10)"), - FIFTEEN( "15 (Workstation/Player 15, Fusion 11)"), - FIFTEEN_ONE( "16 (Workstation/Player 15.1, Fusion 11.1)"), - SIXTEEN( "17 (Workstation/Player 16, Fusion 12)"), - SIXTEEN_ONE( "18 (Workstation/Player 16.1, Fusion 12.1)"), - DEFAULT( "default" ); - - public final String displayName; - - private HWVersion( String dName ) - { - this.displayName = dName; - } - } - - /** - * Virtual network cards - */ - public static enum EthernetDevType - { - AUTO( "(default)" ), PCNET32( "AMD PCnet32" ), E1000( "Intel E1000 (PCI)" ), E1000E( "Intel E1000e (PCI-Express)" ), VMXNET( "VMXnet" ), VMXNET3( "VMXnet 3" ), PCNETPCI2( - "PCnet-PCI II" ), PCNETFAST3( "PCnet-FAST III" ), PRO1000MTD( "Intel PRO/1000 MT Desktop" ), PRO1000TS( - "Intel PRO/1000 T Server" ), PRO1000MTS( "Intel PRO/1000 MT Server" ), PARAVIRT( "Paravirtualized Network" ), NONE( "No Network Card" ); - - public final String displayName; - - private EthernetDevType( String dName ) - { - this.displayName = dName; - } - } - - public static enum UsbSpeed - { - NONE( "None" ), - USB1_1( "USB 1.1" ), - USB2_0( "USB 2.0" ), - USB3_0( "USB 3.0" ); - - public final String displayName; - - private UsbSpeed( String dName ) - { - this.displayName = dName; - } - } - - public static enum DriveBusType - { - SCSI, IDE, SATA, NVME; - } - - public static class HardDisk - { - public final String chipsetDriver; - public final DriveBusType bus; - public final String diskImage; - - public HardDisk( String chipsetDriver, DriveBusType bus, String diskImage ) - { - this.chipsetDriver = chipsetDriver; - this.bus = bus; - this.diskImage = diskImage; - } - } - - public static enum EtherType - { - NAT, BRIDGED, HOST_ONLY; - } - /* - * Members - */ - - protected final List<HardDisk> hdds = new ArrayList<>(); - - private final List<OperatingSystem> osList; - - private OperatingSystem os = null; - - protected String displayName = null; - - protected boolean isMachineSnapshot; - - /* - * Getters for virtual hardware - */ - public List<SoundCardType> getSupportedSoundCards() - { - ArrayList<SoundCardType> availables = new ArrayList<SoundCardType>( soundCards.keySet() ); - Collections.sort( availables ); - return availables; - } - - public List<DDAcceleration> getSupportedDDAccs() - { - ArrayList<DDAcceleration> availables = new ArrayList<DDAcceleration>( ddacc.keySet() ); - Collections.sort( availables ); - return availables; - } - - public List<HWVersion> getSupportedHWVersions() - { - ArrayList<HWVersion> availables = new ArrayList<HWVersion>( hwversion.keySet() ); - Collections.sort( availables ); - return availables; - } - - public List<EthernetDevType> getSupportedEthernetDevices() - { - ArrayList<EthernetDevType> availables = new ArrayList<EthernetDevType>( networkCards.keySet() ); - Collections.sort( availables ); - return availables; - } - - public List<UsbSpeed> getSupportedUsbSpeeds() - { - ArrayList<UsbSpeed> availables = new ArrayList<>( usbSpeeds.keySet() ); - Collections.sort( availables ); - return availables; - } - - /** - * Get operating system of this VM. - */ - public OperatingSystem getOs() - { - return os; - } - - /** - * Get all hard disks of this VM. - */ - public List<HardDisk> getHdds() - { - return Collections.unmodifiableList( hdds ); - } - - /** - * Get display name of VM. - */ - public String getDisplayName() - { - return displayName; - } - - /* - * Getter for isMachineSnapshot - */ - public boolean isMachineSnapshot() - { - return isMachineSnapshot; - } - - /** - * This method should return a minimal representation of the input meta data. - * The representation is platform dependent, and should be stripped of all - * non-essential configuration, such as CD/DVD/FLoppy drives, serial or parallel - * ports, shared folders, or anything else that could be considered sensible - * information (absolute paths containing the local user's name). - */ - public abstract byte[] getFilteredDefinitionArray(); - - public final ByteBuffer getFilteredDefinition() - { - return ByteBuffer.wrap( getFilteredDefinitionArray() ); - } - - /* - * Methods - */ - - public VmMetaData( List<OperatingSystem> osList ) - { - this.osList = osList; - } - - /** - * Called from subclass to set the OS. If the OS cannot be determined from the - * given parameters, it will not be set. - * - * @param virtId - * virtualizer, eg "vmware" for VMware - * @param virtOsId - * the os identifier used by the virtualizer, eg. windows7-64 for - * 64bit Windows 7 on VMware - */ - protected final void setOs( String virtId, String virtOsId ) - { - OperatingSystem lazyMatch = null; - for ( OperatingSystem os : osList ) { - if ( os.getVirtualizerOsId() == null ) - continue; - for ( Entry<String, String> entry : os.getVirtualizerOsId().entrySet() ) { - if ( !entry.getValue().equals( virtOsId ) ) - continue; - if ( entry.getKey().equals( virtId ) ) { - this.os = os; - return; - } else { - lazyMatch = os; - } - } - } - this.os = lazyMatch; - } - - /** - * Returns list of image formats supported by the VM's hypervisor. - * - * @return list of image formats. - */ - public abstract List<DiskImage.ImageFormat> getSupportedImageFormats(); - - /** - * Apply config options that are desired when locally editing a VM. for vmware, - * this disables automatic DPI scaling of the guest. - */ - public abstract void applySettingsForLocalEdit(); - - /** - * Returns a VmMetaData instance of the given machine description given as file - * - * @param osList List of supported operating systems - * @param file VM's machine description file to get the metadata instance from - * @return VmMetaData object representing the relevant parts of the given machine description - */ - public static VmMetaData<?, ?, ?, ?, ?> getInstance( List<OperatingSystem> osList, File file ) - throws IOException - { - try { - return new VmwareMetaData( osList, file ); - } catch ( UnsupportedVirtualizerFormatException e ) { - LOGGER.info( "Not a VMware file", e ); - } - try { - return new VboxMetaData( osList, file ); - } catch ( UnsupportedVirtualizerFormatException e ) { - LOGGER.info( "Not a VirtualBox file", e ); - } - try { - return new QemuMetaData( osList, file ); - } catch ( Exception e ) { - LOGGER.info( "Not a Qemu file", e ); - } - try { - return new DockerMetaDataDummy(osList, file); - } catch ( Exception e ) { - LOGGER.info( "Not a tar.gz file, for docker container", e ); - } - LOGGER.error( "Could not detect any known virtualizer format" ); - return null; - } - - /** - * Returns a VmMetaData instance of the given machine description given as a byte array - * - * @param osList List of supported operating systems - * @param vmContent VM's machine description as byte array (e.g. stored in DB) - * @param length length of the byte array given as vmContent - * @return VmMetaData object representing the relevant parts of the given machine description - * @throws IOException - */ - public static VmMetaData<?, ?, ?, ?, ?> getInstance( List<OperatingSystem> osList, byte[] vmContent, int length ) throws IOException - { - Map<String, Exception> exceptions = new HashMap<>(); - try { - return new VmwareMetaData( osList, vmContent, length ); - } catch ( UnsupportedVirtualizerFormatException e ) { - exceptions.put( "Not a VMware file", e ); - } - try { - return new VboxMetaData( osList, vmContent, length ); - } catch ( UnsupportedVirtualizerFormatException e ) { - exceptions.put( "Not a VirtualBox file", e ); - } - try { - return new DockerMetaDataDummy(osList, vmContent, length); - } catch (UnsupportedVirtualizerFormatException e) { - exceptions.put( "Not tar.gz file for DockerMetaDataDummy ", e); - } - // TODO QEmu -- hack above expects qcow2 file, so we can't do anything here yet - LOGGER.error( "Could not detect any known virtualizer format" ); - for ( Entry<String, Exception> e : exceptions.entrySet() ) { - LOGGER.error( e.getKey(), e.getValue() ); - } - return null; - } - - public abstract boolean addHddTemplate( File diskImage, String hddMode, String redoDir ); - - public abstract boolean addHddTemplate( String diskImagePath, String hddMode, String redoDir ); - - public abstract boolean addDefaultNat(); - - public abstract void setOs( String vendorOsId ); - - public abstract boolean addDisplayName( String name ); - - public abstract boolean addRam( int mem ); - - public abstract void addFloppy( int index, String image, boolean readOnly ); - - public abstract boolean addCdrom( String image ); - - public abstract boolean addCpuCoreCount( int nrOfCores ); - - public abstract void setSoundCard( SoundCardType type ); - - public abstract SoundCardType getSoundCard(); - - public abstract void setDDAcceleration( DDAcceleration type ); - - public abstract DDAcceleration getDDAcceleration(); - - public abstract void setHWVersion( HWVersion type ); - - public abstract HWVersion getHWVersion(); - - public abstract void setEthernetDevType( int cardIndex, EthernetDevType type ); - - public abstract EthernetDevType getEthernetDevType( int cardIndex ); - - public abstract void setMaxUsbSpeed( UsbSpeed speed ); - - public abstract UsbSpeed getMaxUsbSpeed(); - - public abstract byte[] getDefinitionArray(); - - public abstract boolean addEthernet( EtherType type ); - - public abstract Virtualizer getVirtualizer(); - - public abstract boolean tweakForNonPersistent(); - - /** - * Function used to register virtual devices - */ - public abstract void registerVirtualHW(); -} diff --git a/src/main/java/org/openslx/vm/VmwareConfig.java b/src/main/java/org/openslx/vm/VmwareConfig.java deleted file mode 100644 index d98a1d4..0000000 --- a/src/main/java/org/openslx/vm/VmwareConfig.java +++ /dev/null @@ -1,276 +0,0 @@ -package org.openslx.vm; - -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.TreeMap; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.apache.log4j.Logger; -import org.openslx.util.Util; - -public class VmwareConfig -{ - - private static final Logger LOGGER = Logger.getLogger( VmwareConfig.class ); - - private Map<String, ConfigEntry> entries = new TreeMap<>( String.CASE_INSENSITIVE_ORDER ); - - public VmwareConfig() - { - // (void) - } - - public VmwareConfig( File file ) throws IOException, UnsupportedVirtualizerFormatException - { - int todo = (int)Math.min( 100000, file.length() ); - int offset = 0; - byte[] data = new byte[ todo ]; - FileInputStream fr = null; - try { - fr = new FileInputStream( file ); - while ( todo > 0 ) { - int ret = fr.read( data, offset, todo ); - if ( ret <= 0 ) - break; - todo -= ret; - offset += ret; - } - } finally { - Util.safeClose( fr ); - } - init( data, offset ); - - } - - public VmwareConfig( InputStream is ) throws IOException, UnsupportedVirtualizerFormatException - { - int todo = Math.max( 4000, Math.min( 100000, is.available() ) ); - int offset = 0; - byte[] data = new byte[ todo ]; - while ( todo > 0 ) { - int ret = is.read( data, offset, todo ); - if ( ret <= 0 ) - break; - todo -= ret; - offset += ret; - } - init( data, offset ); - } - - public VmwareConfig( byte[] vmxContent, int length ) throws UnsupportedVirtualizerFormatException - { - init( vmxContent, length ); - } - - // function is used for both .vmx and .vmdk files - private void init( byte[] vmxContent, int length ) throws UnsupportedVirtualizerFormatException - { - try { - boolean isValid = false; - BufferedReader reader = getVmxReader( vmxContent, length ); - String line; - while ( ( line = reader.readLine() ) != null ) { - KeyValuePair entry = parse( line ); - - if ( entry != null ) { - if ( entry.key.equals( "virtualHW.version" ) || entry.key.equals( "ddb.virtualHWVersion" ) - // TODO: This is supposed to be case insensitive. - // Check if there are other consequences from lowercase entries in converted vmx files. - || entry.key.equals( "virtualhw.version" )) { - isValid = true; - } - set( entry.key, unescape( entry.value ) ); - } - } - if ( !isValid ) { - throw new UnsupportedVirtualizerFormatException( "Not in VMX format." ); - } - } catch ( IOException e ) { - LOGGER.warn( "Exception when loading vmx from byte array (how!?)", e ); - } - } - - public static BufferedReader getVmxReader( byte[] vmxContent, int length ) throws IOException - { - Charset cs = getCharset( vmxContent, length ); - return new BufferedReader( new InputStreamReader( new ByteArrayInputStream( vmxContent, 0, length ), cs ) ); - } - - public static Charset getCharset( byte[] vmxContent, int length ) - { - String csName = detectCharset( new ByteArrayInputStream( vmxContent, 0, length ) ); - Charset cs = null; - try { - cs = Charset.forName( csName ); - } catch ( Exception e ) { - LOGGER.warn( "Could not instantiate charset " + csName, e ); - } - if ( cs == null ) - cs = StandardCharsets.ISO_8859_1; - return cs; - } - - private String unescape( String value ) - { - String ret = value; - if ( ret.contains( "|22" ) ) { - ret = ret.replace( "|22", "\"" ); - } - if ( ret.contains( "|7C" ) ) { - ret = ret.replace( "|7C", "|" ); - } - return ret; - } - - public static String detectCharset( InputStream is ) - { - try { - BufferedReader csDetectReader = new BufferedReader( new InputStreamReader( is, StandardCharsets.ISO_8859_1 ) ); - String line; - while ( ( line = csDetectReader.readLine() ) != null ) { - KeyValuePair entry = parse( line ); - if ( entry == null ) - continue; - if ( entry.key.equals( ".encoding" ) || entry.key.equals( "encoding" ) ) { - return entry.value; - } - } - } catch ( Exception e ) { - LOGGER.warn( "Could not detect charset, fallback to latin1", e ); - } - // Dumb fallback - return "ISO-8859-1"; - } - - public Set<Entry<String, ConfigEntry>> entrySet() - { - return entries.entrySet(); - } - - private static final Pattern settingMatcher1 = Pattern.compile( "^\\s*(#?[a-z0-9\\.\\:_]+)\\s*=\\s*\"(.*)\"\\s*$", Pattern.CASE_INSENSITIVE ); - private static final Pattern settingMatcher2 = Pattern.compile( "^\\s*(#?[a-z0-9\\.\\:_]+)\\s*=\\s*([^\"]*)\\s*$", Pattern.CASE_INSENSITIVE ); - - private static KeyValuePair parse( String line ) - { - Matcher matcher = settingMatcher1.matcher( line ); - if ( !matcher.matches() ) { - matcher = settingMatcher2.matcher( line ); - } - if ( !matcher.matches() ) { - return null; - } - return new KeyValuePair( matcher.group( 1 ), matcher.group( 2 ) ); - - } - - public ConfigEntry set( String key, String value, boolean replace ) - { - if ( !replace && entries.containsKey( key ) ) - return null; - ConfigEntry ce = new ConfigEntry( value ); - entries.put( key, ce ); - return ce; - } - - public ConfigEntry set( String key, String value ) - { - return set( key, value, true ); - } - - public ConfigEntry set( KeyValuePair entry ) - { - return set( entry.key, entry.value ); - } - - public void remove( String key ) - { - entries.remove( key ); - } - - public String get( String key ) - { - ConfigEntry ce = entries.get( key ); - if ( ce == null ) - return null; - return ce.value; - } - - public String toString( boolean filteredRequired, boolean generatedRequired ) - { - set( ".encoding", "UTF-8" ).filtered( true ).generated( true ); - StringBuilder sb = new StringBuilder( 300 ); - for ( Entry<String, ConfigEntry> entry : entries.entrySet() ) { - ConfigEntry value = entry.getValue(); - if ( ( !filteredRequired || value.forFiltered ) && ( !generatedRequired || value.forGenerated ) ) { - sb.append( entry.getKey() ); - sb.append( " = \"" ); - sb.append( value.getEscaped() ); - sb.append( "\"\n" ); - } - } - return sb.toString(); - } - - @Override - public String toString() - { - return toString( false, false ); - } - - public static class ConfigEntry - { - private String value; - private boolean forFiltered; - private boolean forGenerated; - - public ConfigEntry( String value ) - { - this.value = value; - } - - public ConfigEntry filtered( boolean set ) - { - this.forFiltered = set; - return this; - } - - public ConfigEntry generated( boolean set ) - { - this.forGenerated = set; - return this; - } - - public String getEscaped() - { - String ret = value; - if ( ret.contains( "|" ) ) { - ret = ret.replace( "|", "|7C" ); - } - if ( ret.contains( "\"" ) ) { - ret = ret.replace( "\"", "|22" ); - } - return ret; - } - - public String getValue() - { - return value; - } - - public void setValue( String value ) - { - this.value = value; - } - } -} diff --git a/src/main/java/org/openslx/vm/VmwareMetaData.java b/src/main/java/org/openslx/vm/VmwareMetaData.java deleted file mode 100644 index 9bbe581..0000000 --- a/src/main/java/org/openslx/vm/VmwareMetaData.java +++ /dev/null @@ -1,684 +0,0 @@ -package org.openslx.vm; - -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.apache.log4j.Logger; -import org.openslx.bwlp.thrift.iface.OperatingSystem; -import org.openslx.bwlp.thrift.iface.Virtualizer; -import org.openslx.thrifthelper.TConst; -import org.openslx.util.Util; -import org.openslx.vm.VmwareConfig.ConfigEntry; -import org.openslx.vm.disk.DiskImage; -import org.openslx.vm.disk.DiskImage.ImageFormat; - -class VmWareSoundCardMeta -{ - public final boolean isPresent; - public final String value; - - public VmWareSoundCardMeta( boolean present, String val ) - { - isPresent = present; - value = val; - } -} - -class VmWareDDAccelMeta -{ - public final boolean isPresent; - - public VmWareDDAccelMeta( boolean present ) - { - isPresent = present; - } -} - -class VmWareHWVersionMeta -{ - public final int version; - - public VmWareHWVersionMeta( int vers ) - { - version = vers; - } -} - -class VmWareEthernetDevTypeMeta -{ - public final String value; - - public VmWareEthernetDevTypeMeta( String val ) - { - value = val; - } -} - -class VmwareUsbSpeed -{ - public final String keyName; - public final int speedNumeric; - - public VmwareUsbSpeed( int speed, String key ) - { - this.keyName = key == null ? null : ( key + ".present" ); - this.speedNumeric = speed; - } -} - -public class VmwareMetaData extends VmMetaData<VmWareSoundCardMeta, VmWareDDAccelMeta, VmWareHWVersionMeta, VmWareEthernetDevTypeMeta, VmwareUsbSpeed> -{ - /** - * List of supported image formats by the VMware hypervisor. - */ - private static final List<DiskImage.ImageFormat> SUPPORTED_IMAGE_FORMATS = Collections.unmodifiableList( - Arrays.asList( ImageFormat.VMDK ) ); - - private static final Logger LOGGER = Logger.getLogger( VmwareMetaData.class ); - - private static final Virtualizer virtualizer = new Virtualizer( TConst.VIRT_VMWARE, "VMware" ); - - private static final Pattern hddKey = Pattern.compile( "^(ide\\d|scsi\\d|sata\\d|nvme\\d):?(\\d)?\\.(.*)", Pattern.CASE_INSENSITIVE ); - - // Lowercase list of allowed settings for upload (as regex) - private static final Pattern[] whitelist; - - private final VmwareConfig config; - - // 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[.:]", - "^firmware", "^hpet", "^vm\\.genid" }; - whitelist = new Pattern[ list.length ]; - for ( int i = 0; i < list.length; ++i ) { - whitelist[i] = Pattern.compile( list[i].toLowerCase() ); - } - } - - public static enum EthernetType - { - NAT( "vmnet1" ), BRIDGED( "vmnet0" ), HOST_ONLY( "vmnet2" ); - - public final String vmnet; - - private EthernetType( String vnet ) - { - this.vmnet = vnet; - } - } - - private final Map<String, Controller> disks = new HashMap<>(); - - public VmwareMetaData( List<OperatingSystem> osList, File file ) throws IOException, UnsupportedVirtualizerFormatException - { - super( osList ); - this.config = new VmwareConfig( file ); - init(); - } - - public VmwareMetaData( List<OperatingSystem> osList, byte[] vmxContent, int length ) throws UnsupportedVirtualizerFormatException - { - super( osList ); - this.config = new VmwareConfig( vmxContent, length ); // still unfiltered - init(); // now filtered - } - - private void init() - { - registerVirtualHW(); - - for ( Entry<String, ConfigEntry> entry : config.entrySet() ) { - handleLoadEntry( entry ); - } - // Fix accidentally filtered USB config if we see EHCI is present - if ( isSetAndTrue( "ehci.present" ) && !isSetAndTrue( "usb.present" ) ) { - addFiltered( "usb.present", "TRUE" ); - } - // if we find this tag, we already went through the hdd's - so we're done. - if ( config.get( "#SLX_HDD_BUS" ) != null ) { - return; - } - // Now find the HDDs and add to list - for ( Entry<String, Controller> cEntry : disks.entrySet() ) { - Controller controller = cEntry.getValue(); - String controllerType = cEntry.getKey(); - if ( !controller.present ) - continue; - for ( Entry<String, Device> dEntry : controller.devices.entrySet() ) { - Device device = dEntry.getValue(); - if ( !device.present ) - continue; // Not present - if ( device.deviceType != null && !device.deviceType.toLowerCase().endsWith( "disk" ) ) - continue; // Not a HDD - DriveBusType bus = null; - if ( controllerType.startsWith( "ide" ) ) { - bus = DriveBusType.IDE; - } else if ( controllerType.startsWith( "scsi" ) ) { - bus = DriveBusType.SCSI; - } else if ( controllerType.startsWith( "sata" ) ) { - bus = DriveBusType.SATA; - } else if ( controllerType.startsWith( "nvme" ) ) { - bus = DriveBusType.NVME; - } - hdds.add( new HardDisk( controller.virtualDev, bus, device.filename ) ); - } - } - // TODO check if this machine is in a paused/suspended state - this.isMachineSnapshot = false; - - // Add HDD to cleaned vmx - if ( !hdds.isEmpty() ) { - HardDisk hdd = hdds.get( 0 ); - addFiltered( "#SLX_HDD_BUS", hdd.bus.toString() ); - if ( hdd.chipsetDriver != null ) { - addFiltered( "#SLX_HDD_CHIP", hdd.chipsetDriver ); - } - } - } - - private void addFiltered( String key, String value ) - { - config.set( key, value ).filtered( true ); - } - - private boolean isSetAndTrue( String key ) - { - String value = config.get( key ); - return value != null && value.equalsIgnoreCase( "true" ); - } - - private void handleLoadEntry( Entry<String, ConfigEntry> entry ) - { - String lowerKey = entry.getKey().toLowerCase(); - // Cleaned vmx construction - for ( Pattern exp : whitelist ) { - if ( exp.matcher( lowerKey ).find() ) { - entry.getValue().filtered( true ); - break; - } - } - // - // Dig Usable meta data - String value = entry.getValue().getValue(); - if ( lowerKey.equals( "guestos" ) ) { - setOs( value ); - return; - } - if ( lowerKey.equals( "displayname" ) ) { - displayName = value; - return; - } - Matcher hdd = hddKey.matcher( entry.getKey() ); - if ( hdd.find() ) { - handleHddEntry( hdd.group( 1 ).toLowerCase(), hdd.group( 2 ), hdd.group( 3 ), value ); - } - } - - private void handleHddEntry( String controllerStr, String deviceStr, String property, String value ) - { - Controller controller = disks.get( controllerStr ); - if ( controller == null ) { - controller = new Controller(); - disks.put( controllerStr, controller ); - } - if ( deviceStr == null || deviceStr.isEmpty() ) { - // Controller property - if ( property.equalsIgnoreCase( "present" ) ) { - controller.present = Boolean.parseBoolean( value ); - } else if ( property.equalsIgnoreCase( "virtualDev" ) ) { - controller.virtualDev = value; - } - return; - } - // Device property - Device device = controller.devices.get( deviceStr ); - if ( device == null ) { - device = new Device(); - controller.devices.put( deviceStr, device ); - } - if ( property.equalsIgnoreCase( "deviceType" ) ) { - device.deviceType = value; - } else if ( property.equalsIgnoreCase( "filename" ) ) { - device.filename = value; - } else if ( property.equalsIgnoreCase( "present" ) ) { - device.present = Boolean.parseBoolean( value ); - } - } - - @Override - public List<DiskImage.ImageFormat> getSupportedImageFormats() - { - return VmwareMetaData.SUPPORTED_IMAGE_FORMATS; - } - - @Override - public boolean addHddTemplate( File diskImage, String hddMode, String redoDir ) - { - return addHddTemplate( diskImage.getName(), hddMode, redoDir ); - } - - @Override - public boolean addHddTemplate( String diskImagePath, String hddMode, String redoDir ) - { - if ( diskImagePath.isEmpty() ) { - LOGGER.error( "Empty disk image path given!" ); - return false; - } - DriveBusType bus; - try { - bus = DriveBusType.valueOf( config.get( "#SLX_HDD_BUS" ) ); - } catch ( Exception e ) { - LOGGER.warn( "Unknown bus type: " + config.get( "#SLX_HDD_BUS" ) + ". Cannot add hdd config." ); - return false; - } - String chipset = config.get( "#SLX_HDD_CHIP" ); - String prefix; - switch ( bus ) { - case SATA: - // Cannot happen?... use lsisas1068 - prefix = "scsi0"; - chipset = "lsisas1068"; - break; - case IDE: - case SCSI: - case NVME: - prefix = bus.name().toLowerCase() + "0"; - break; - default: - LOGGER.warn( "Unknown HDD bus type: " + bus.toString() ); - return false; - } - // Gen - addFiltered( prefix + ".present", "TRUE" ); - if ( chipset != null ) { - addFiltered( prefix + ".virtualDev", chipset ); - } - addFiltered( prefix + ":0.present", "TRUE" ); - addFiltered( prefix + ":0.deviceType", "disk" ); - addFiltered( prefix + ":0.fileName", diskImagePath ); - if ( hddMode != null ) { - addFiltered( prefix + ":0.mode", hddMode ); - addFiltered( prefix + ":0.redo", "" ); - addFiltered( prefix + ":0.redoLogDir", redoDir ); - } - config.remove( "#SLX_HDD_BUS" ); - config.remove( "#SLX_HDD_CHIP" ); - return true; - } - - public boolean addDefaultNat() - { - addFiltered( "ethernet0.present", "TRUE" ); - addFiltered( "ethernet0.connectionType", "nat" ); - return true; - } - - public boolean addEthernet( VmMetaData.EtherType type ) - { - boolean ret = false; - int index = 0; - for ( ;; ++index ) { - if ( config.get( "ethernet" + index + ".present" ) == null ) - break; - } - switch ( type ) { - case NAT: - ret = addEthernet( index, EthernetType.NAT ); - break; - case BRIDGED: - ret = addEthernet( index, EthernetType.BRIDGED ); - break; - case HOST_ONLY: - ret = addEthernet( index, EthernetType.HOST_ONLY ); - break; - default: - // Should not come to this... - break; - } - return ret; - } - - public boolean addEthernet( int index, EthernetType type ) - { - String ether = "ethernet" + index; - addFiltered( ether + ".present", "TRUE" ); - addFiltered( ether + ".connectionType", "custom" ); - addFiltered( ether + ".vnet", type.vmnet ); - if ( config.get( ether + ".virtualDev" ) == null ) { - String dev = config.get( "ethernet0.virtualDev" ); - if ( dev != null ) { - addFiltered( ether + ".virtualDev", dev ); - } - } - return true; - } - - public void addFloppy( int index, String image, boolean readOnly ) - { - String pre = "floppy" + index; - addFiltered( pre + ".present", "TRUE" ); - if ( image == null ) { - addFiltered( pre + ".startConnected", "FALSE" ); - addFiltered( pre + ".fileType", "device" ); - config.remove( pre + ".fileName" ); - config.remove( pre + ".readonly" ); - addFiltered( pre + ".autodetect", "TRUE" ); - } else { - addFiltered( pre + ".startConnected", "TRUE" ); - addFiltered( pre + ".fileType", "file" ); - addFiltered( pre + ".fileName", image ); - addFiltered( pre + ".readonly", vmBoolean( readOnly ) ); - config.remove( pre + ".autodetect" ); - } - } - - public boolean addCdrom( String image ) - { - for ( String port : new String[] { "ide0:0", "ide0:1", "ide1:0", "ide1:1", "scsi0:1" } ) { - if ( !isSetAndTrue( port + ".present" ) ) { - addFiltered( port + ".present", "TRUE" ); - if ( image == null ) { - addFiltered( port + ".autodetect", "TRUE" ); - addFiltered( port + ".deviceType", "cdrom-raw" ); - config.remove( port + ".fileName" ); - } else { - config.remove( port + ".autodetect" ); - addFiltered( port + ".deviceType", "cdrom-image" ); - addFiltered( port + ".fileName", image ); - } - return true; - } - } - return false; - } - - private static String vmBoolean( boolean var ) - { - return Boolean.toString( var ).toUpperCase(); - } - - private static String vmInteger( int val ) - { - return Integer.toString( val ); - } - - @Override - public boolean tweakForNonPersistent() - { - addFiltered( "suspend.disabled", "TRUE" ); - return true; - } - - @Override - public boolean addDisplayName( String name ) - { - addFiltered( "displayName", name ); - return true; - } - - @Override - public boolean addRam( int mem ) - { - addFiltered( "memsize", Integer.toString( mem ) ); - return true; - } - - public void setOs( String vendorOsId ) - { - addFiltered( "guestOS", vendorOsId ); - setOs( TConst.VIRT_VMWARE, vendorOsId ); - } - - @Override - public byte[] getFilteredDefinitionArray() - { - return config.toString( true, false ).getBytes( StandardCharsets.UTF_8 ); - } - - public byte[] getDefinitionArray() - { - return config.toString( false, false ).getBytes( StandardCharsets.UTF_8 ); - } - - @Override - public Virtualizer getVirtualizer() - { - return virtualizer; - } - - private static class Device - { - public boolean present = false; - public String deviceType = null; - public String filename = null; - - @Override - public String toString() - { - return filename + " is " + deviceType + " (present: " + present + ")"; - } - } - - private static class Controller - { - public boolean present = true; // Seems to be implicit, seen at least for IDE... - public String virtualDev = null; - Map<String, Device> devices = new HashMap<>(); - - @Override - public String toString() - { - return virtualDev + " is (present: " + present + "): " + devices.toString(); - } - } - - @Override - public void applySettingsForLocalEdit() - { - addFiltered( "gui.applyHostDisplayScalingToGuest", "FALSE" ); - } - - public String getValue( String key ) - { - return config.get( key ); - } - - public void setSoundCard( VmMetaData.SoundCardType type ) - { - VmWareSoundCardMeta soundCardMeta = soundCards.get( type ); - addFiltered( "sound.present", vmBoolean( soundCardMeta.isPresent ) ); - if ( soundCardMeta.value != null ) { - addFiltered( "sound.virtualDev", soundCardMeta.value ); - } else { - config.remove( "sound.virtualDev" ); - } - } - - public VmMetaData.SoundCardType getSoundCard() - { - if ( !isSetAndTrue( "sound.present" ) || !isSetAndTrue( "sound.autodetect" ) ) { - return VmMetaData.SoundCardType.NONE; - } - String current = config.get( "sound.virtualDev" ); - if ( current != null ) { - VmWareSoundCardMeta soundCardMeta = null; - for ( VmMetaData.SoundCardType type : VmMetaData.SoundCardType.values() ) { - soundCardMeta = soundCards.get( type ); - if ( soundCardMeta != null ) { - if ( current.equals( soundCardMeta.value ) ) { - return type; - } - } - } - } - return VmMetaData.SoundCardType.DEFAULT; - } - - public void setDDAcceleration( VmMetaData.DDAcceleration type ) - { - VmWareDDAccelMeta ddaMeta = ddacc.get( type ); - addFiltered( "mks.enable3d", vmBoolean( ddaMeta.isPresent ) ); - } - - public VmMetaData.DDAcceleration getDDAcceleration() - { - if ( isSetAndTrue( "mks.enable3d" ) ) { - return VmMetaData.DDAcceleration.ON; - } else { - return VmMetaData.DDAcceleration.OFF; - } - } - - public void setHWVersion( VmMetaData.HWVersion type ) - { - VmWareHWVersionMeta hwVersionMeta = hwversion.get( type ); - addFiltered( "virtualHW.version", vmInteger( hwVersionMeta.version ) ); - } - - public VmMetaData.HWVersion getHWVersion() - { - int currentValue = Util.parseInt( config.get( "virtualHW.version" ), -1 ); - VmWareHWVersionMeta hwVersionMeta = null; - for ( VmMetaData.HWVersion ver : VmMetaData.HWVersion.values() ) { - hwVersionMeta = hwversion.get( ver ); - if ( hwVersionMeta == null ) { - continue; - } - if ( currentValue == hwVersionMeta.version ) { - return ver; - } - } - return HWVersion.NONE; - } - - public void setEthernetDevType( int cardIndex, VmMetaData.EthernetDevType type ) - { - VmWareEthernetDevTypeMeta ethernetDevTypeMeta = networkCards.get( type ); - if ( ethernetDevTypeMeta.value != null ) { - addFiltered( "ethernet" + cardIndex + ".virtualDev", ethernetDevTypeMeta.value ); - } else { - config.remove( "ethernet" + cardIndex + ".virtualDev" ); - } - } - - public VmMetaData.EthernetDevType getEthernetDevType( int cardIndex ) - { - String temp = config.get( "ethernet" + cardIndex + ".virtualDev" ); - if ( temp != null ) { - VmWareEthernetDevTypeMeta ethernetDevTypeMeta = null; - for ( VmMetaData.EthernetDevType type : VmMetaData.EthernetDevType.values() ) { - ethernetDevTypeMeta = networkCards.get( type ); - if ( ethernetDevTypeMeta == null ) { - continue; - } - if ( temp.equals( ethernetDevTypeMeta.value ) ) { - return type; - } - } - } - return VmMetaData.EthernetDevType.AUTO; - } - - @Override - public void setMaxUsbSpeed( VmMetaData.UsbSpeed newSpeed ) - { - if ( newSpeed == null ) { - newSpeed = VmMetaData.UsbSpeed.NONE; - } - VmwareUsbSpeed newSpeedMeta = usbSpeeds.get( newSpeed ); - if ( newSpeedMeta == null ) { - throw new RuntimeException( "USB Speed " + newSpeed.name() + " not registered with VMware" ); - } - for ( VmwareUsbSpeed meta : usbSpeeds.values() ) { - if ( meta == null ) - continue; // Should not happen - if ( meta.keyName == null ) - continue; // "No USB" has no config entry, obviously - if ( meta.speedNumeric <= newSpeedMeta.speedNumeric ) { - // Enable desired speed class, plus all lower ones - addFiltered( meta.keyName, "TRUE" ); - } else { - // This one is higher – remove - config.remove( meta.keyName ); - } - } - // VMware 14+ needs this to use USB 3.0 devices at USB 3.0 ports in VMs configured for < 3.0 - if ( newSpeedMeta.speedNumeric > 0 && newSpeedMeta.speedNumeric < 3 ) { - addFiltered( "usb.mangleUsb3Speed", "TRUE" ); - } - } - - @Override - public VmMetaData.UsbSpeed getMaxUsbSpeed() - { - int max = 0; - VmMetaData.UsbSpeed maxEnum = VmMetaData.UsbSpeed.NONE; - for ( Entry<VmMetaData.UsbSpeed, VmwareUsbSpeed> entry : usbSpeeds.entrySet() ) { - VmwareUsbSpeed v = entry.getValue(); - if ( v.speedNumeric > max && isSetAndTrue( v.keyName ) ) { - max = v.speedNumeric; - maxEnum = entry.getKey(); - } - } - return maxEnum; - } - - @Override - public boolean addCpuCoreCount( int numCores ) - { - // TODO actually add the cpu core count to the machine description - return false; - } - - public void registerVirtualHW() - { - soundCards.put( VmMetaData.SoundCardType.NONE, new VmWareSoundCardMeta( false, null ) ); - soundCards.put( VmMetaData.SoundCardType.DEFAULT, new VmWareSoundCardMeta( true, null ) ); - soundCards.put( VmMetaData.SoundCardType.SOUND_BLASTER, new VmWareSoundCardMeta( true, "sb16" ) ); - soundCards.put( VmMetaData.SoundCardType.ES, new VmWareSoundCardMeta( true, "es1371" ) ); - soundCards.put( VmMetaData.SoundCardType.HD_AUDIO, new VmWareSoundCardMeta( true, "hdaudio" ) ); - - ddacc.put( VmMetaData.DDAcceleration.OFF, new VmWareDDAccelMeta( false ) ); - ddacc.put( VmMetaData.DDAcceleration.ON, new VmWareDDAccelMeta( true ) ); - - hwversion.put( VmMetaData.HWVersion.NONE, new VmWareHWVersionMeta( 0 ) ); - hwversion.put( VmMetaData.HWVersion.THREE, new VmWareHWVersionMeta( 3 ) ); - hwversion.put( VmMetaData.HWVersion.FOUR, new VmWareHWVersionMeta( 4 ) ); - hwversion.put( VmMetaData.HWVersion.SIX, new VmWareHWVersionMeta( 6 ) ); - hwversion.put( VmMetaData.HWVersion.SEVEN, new VmWareHWVersionMeta( 7 ) ); - hwversion.put( VmMetaData.HWVersion.EIGHT, new VmWareHWVersionMeta( 8 ) ); - hwversion.put( VmMetaData.HWVersion.NINE, new VmWareHWVersionMeta( 9 ) ); - hwversion.put( VmMetaData.HWVersion.TEN, new VmWareHWVersionMeta( 10 ) ); - hwversion.put( VmMetaData.HWVersion.ELEVEN, new VmWareHWVersionMeta( 11 ) ); - hwversion.put( VmMetaData.HWVersion.TWELVE, new VmWareHWVersionMeta( 12 ) ); - hwversion.put( VmMetaData.HWVersion.FOURTEEN, new VmWareHWVersionMeta( 14 ) ); - hwversion.put( VmMetaData.HWVersion.FIFTEEN, new VmWareHWVersionMeta( 15 ) ); - hwversion.put( VmMetaData.HWVersion.FIFTEEN_ONE, new VmWareHWVersionMeta( 16 ) ); - hwversion.put( VmMetaData.HWVersion.SIXTEEN, new VmWareHWVersionMeta( 17 ) ); - hwversion.put( VmMetaData.HWVersion.SIXTEEN_ONE, new VmWareHWVersionMeta( 18 ) ); - - networkCards.put( VmMetaData.EthernetDevType.AUTO, new VmWareEthernetDevTypeMeta( null ) ); - networkCards.put( VmMetaData.EthernetDevType.PCNET32, new VmWareEthernetDevTypeMeta( "vlance" ) ); - networkCards.put( VmMetaData.EthernetDevType.E1000, new VmWareEthernetDevTypeMeta( "e1000" ) ); - networkCards.put( VmMetaData.EthernetDevType.E1000E, new VmWareEthernetDevTypeMeta( "e1000e" ) ); - networkCards.put( VmMetaData.EthernetDevType.VMXNET, new VmWareEthernetDevTypeMeta( "vmxnet" ) ); - networkCards.put( VmMetaData.EthernetDevType.VMXNET3, new VmWareEthernetDevTypeMeta( "vmxnet3" ) ); - - usbSpeeds.put( VmMetaData.UsbSpeed.NONE, new VmwareUsbSpeed( 0, null )); - usbSpeeds.put( VmMetaData.UsbSpeed.USB1_1, new VmwareUsbSpeed( 1, "usb" ) ); - usbSpeeds.put( VmMetaData.UsbSpeed.USB2_0, new VmwareUsbSpeed( 2, "ehci" ) ); - usbSpeeds.put( VmMetaData.UsbSpeed.USB3_0, new VmwareUsbSpeed( 3, "usb_xhci" ) ); - } - -} diff --git a/src/main/java/org/openslx/vm/disk/DiskImage.java b/src/main/java/org/openslx/vm/disk/DiskImage.java index 5706db3..cf7df83 100644 --- a/src/main/java/org/openslx/vm/disk/DiskImage.java +++ b/src/main/java/org/openslx/vm/disk/DiskImage.java @@ -11,6 +11,7 @@ import java.util.function.Predicate; import org.openslx.bwlp.thrift.iface.Virtualizer; import org.openslx.thrifthelper.TConst; import org.openslx.util.Util; +import org.openslx.virtualization.Version; /** * Disk image for virtual machines. @@ -87,7 +88,7 @@ public abstract class DiskImage implements Closeable * * @throws DiskImageException unable to obtain version of the disk image format. */ - public abstract int getVersion() throws DiskImageException; + public abstract Version getVersion() throws DiskImageException; /** * Returns the disk image description. @@ -115,7 +116,8 @@ public abstract class DiskImage implements Closeable * @throws IOException cannot access the content of the disk image file. * @throws DiskImageException disk image file has an invalid and unknown disk image format. */ - public static DiskImage newInstance( File diskImagePath ) throws FileNotFoundException, IOException, DiskImageException + public static DiskImage newInstance( File diskImagePath ) + throws FileNotFoundException, IOException, DiskImageException { // Make sure this doesn't escape the scope, in case instantiation fails - we can't know when the GC // would come along and close this file, which is problematic on Windows (blocking rename/delete) @@ -193,7 +195,7 @@ public abstract class DiskImage implements Closeable /** * Checks if the disk image format is supported by a virtualizer. * - * @param supportedImageTypes list of supported disk image formats of a virtualizer. + * @param supportedImageFormats list of supported disk image formats of a virtualizer. * @return <code>true</code> if image type is supported by the virtualizer; otherwise * <code>false</code>. */ diff --git a/src/main/java/org/openslx/vm/disk/DiskImageQcow2.java b/src/main/java/org/openslx/vm/disk/DiskImageQcow2.java index a9826e4..e569708 100644 --- a/src/main/java/org/openslx/vm/disk/DiskImageQcow2.java +++ b/src/main/java/org/openslx/vm/disk/DiskImageQcow2.java @@ -2,6 +2,8 @@ package org.openslx.vm.disk; import java.io.RandomAccessFile; +import org.openslx.virtualization.Version; + /** * QCOW2 disk image for virtual machines. * @@ -48,9 +50,9 @@ public class DiskImageQcow2 extends DiskImage * * @param diskImage file to a QCOW2 disk storing the image content. */ - DiskImageQcow2( RandomAccessFile disk ) + DiskImageQcow2( RandomAccessFile diskImage ) { - super( disk ); + super( diskImage ); } /** @@ -104,7 +106,7 @@ public class DiskImageQcow2 extends DiskImage // check if QCOW2 image uses extended L2 tables // extended L2 tables are only possible in QCOW2 version 3 header format - if ( this.getVersion() >= 3 ) { + if ( this.getVersion().getMajor() >= Short.valueOf( "3" ) ) { // read incompatible feature bits final long qcowIncompatibleFeatures = DiskImageUtils.readLong( diskFile, 72 ); @@ -200,7 +202,7 @@ public class DiskImageQcow2 extends DiskImage } @Override - public int getVersion() throws DiskImageException + public Version getVersion() throws DiskImageException { final RandomAccessFile diskFile = this.getDiskImage(); final int qcowVersion = DiskImageUtils.readInt( diskFile, 4 ); @@ -212,7 +214,7 @@ public class DiskImageQcow2 extends DiskImage throw new DiskImageException( errorMsg ); } - return DiskImageUtils.versionFromMajor( Integer.valueOf( qcowVersion ).shortValue() ); + return new Version( Integer.valueOf( qcowVersion ).shortValue() ); } @Override diff --git a/src/main/java/org/openslx/vm/disk/DiskImageUtils.java b/src/main/java/org/openslx/vm/disk/DiskImageUtils.java index fbed6f9..ccb053f 100644 --- a/src/main/java/org/openslx/vm/disk/DiskImageUtils.java +++ b/src/main/java/org/openslx/vm/disk/DiskImageUtils.java @@ -114,12 +114,12 @@ public class DiskImageUtils } /** - * Reads two bytes ({@link Short}) at a given <code>offset</code> from the specified disk image - * file. + * Reads a variable number of bytes (<code>numBytes</code>) at a given <code>offset</code> from the specified disk image file. * * @param diskImage file to a disk storing the image content. - * @param offset offset in bytes for reading the two bytes. - * @return value of the two bytes from the disk image file as {@link Short}. + * @param offset offset in bytes for reading <code>numBytes</code> bytes. + * @param numBytes number of bytes to read at <code>offset</code>. + * @return read bytes from the disk image file as {@link String}. * * @throws DiskImageException unable to read two bytes from the disk image file. */ @@ -141,14 +141,4 @@ public class DiskImageUtils return new String( values ); } - - public static int versionFromMajorMinor( final short major, final short minor ) - { - return ( ( Integer.valueOf( major ) << 16 ) | minor ); - } - - public static int versionFromMajor( final short major ) - { - return DiskImageUtils.versionFromMajorMinor( major, Short.valueOf( "0" ) ); - } } diff --git a/src/main/java/org/openslx/vm/disk/DiskImageVdi.java b/src/main/java/org/openslx/vm/disk/DiskImageVdi.java index 9be49d8..37e45c1 100644 --- a/src/main/java/org/openslx/vm/disk/DiskImageVdi.java +++ b/src/main/java/org/openslx/vm/disk/DiskImageVdi.java @@ -2,6 +2,8 @@ package org.openslx.vm.disk; import java.io.RandomAccessFile; +import org.openslx.virtualization.Version; + /** * VDI disk image for virtual machines. * @@ -78,14 +80,14 @@ public class DiskImageVdi extends DiskImage } @Override - public int getVersion() throws DiskImageException + public Version getVersion() throws DiskImageException { final RandomAccessFile diskFile = this.getDiskImage(); final short vdiVersionMajor = Short.reverseBytes( DiskImageUtils.readShort( diskFile, 68 ) ); final short vdiVersionMinor = Short.reverseBytes( DiskImageUtils.readShort( diskFile, 70 ) ); - return DiskImageUtils.versionFromMajorMinor( vdiVersionMajor, vdiVersionMinor ); + return new Version( vdiVersionMajor, vdiVersionMinor ); } @Override diff --git a/src/main/java/org/openslx/vm/disk/DiskImageVmdk.java b/src/main/java/org/openslx/vm/disk/DiskImageVmdk.java index 58314fc..75a2bac 100644 --- a/src/main/java/org/openslx/vm/disk/DiskImageVmdk.java +++ b/src/main/java/org/openslx/vm/disk/DiskImageVmdk.java @@ -3,8 +3,9 @@ package org.openslx.vm.disk; import java.io.RandomAccessFile; import org.openslx.util.Util; -import org.openslx.vm.UnsupportedVirtualizerFormatException; -import org.openslx.vm.VmwareConfig; +import org.openslx.virtualization.configuration.VirtualizationConfigurationVmwareFileFormat; +import org.openslx.virtualization.Version; +import org.openslx.virtualization.configuration.VirtualizationConfigurationException; /** * VMDK (sparse extent) disk image for virtual machines. @@ -32,7 +33,7 @@ public class DiskImageVmdk extends DiskImage /** * Stores disk configuration if VMDK disk image contains an embedded descriptor file. */ - private final VmwareConfig vmdkConfig; + private final VirtualizationConfigurationVmwareFileFormat vmdkConfig; /** * Creates a new VMDK disk image from an existing VMDK image file. @@ -80,7 +81,7 @@ public class DiskImageVmdk extends DiskImage */ private String getCreationType() { - final VmwareConfig vmdkConfig = this.getVmdkConfig(); + final VirtualizationConfigurationVmwareFileFormat vmdkConfig = this.getVmdkConfig(); final String vmdkCreationType; if ( vmdkConfig == null ) { @@ -103,10 +104,10 @@ public class DiskImageVmdk extends DiskImage * * @throws DiskImageException parsing of the VMDK's embedded descriptor file failed. */ - protected VmwareConfig parseVmdkConfig() throws DiskImageException + protected VirtualizationConfigurationVmwareFileFormat parseVmdkConfig() throws DiskImageException { final RandomAccessFile diskFile = this.getDiskImage(); - final VmwareConfig vmdkConfig; + final VirtualizationConfigurationVmwareFileFormat vmdkConfig; // get offset and size of descriptor file embedded into the VMDK disk image final long vmdkDescriptorSectorOffset = Long.reverseBytes( DiskImageUtils.readLong( diskFile, 28 ) ); @@ -133,8 +134,8 @@ public class DiskImageVmdk extends DiskImage // create configuration instance from content of the descriptor file try { - vmdkConfig = new VmwareConfig( configStr.getBytes(), vmdkDescriptorSize ); - } catch ( UnsupportedVirtualizerFormatException e ) { + vmdkConfig = new VirtualizationConfigurationVmwareFileFormat( configStr.getBytes(), vmdkDescriptorSize ); + } catch ( VirtualizationConfigurationException e ) { throw new DiskImageException( e.getLocalizedMessage() ); } } else { @@ -150,7 +151,7 @@ public class DiskImageVmdk extends DiskImage * * @return parsed configuration of the VMDK's embedded descriptor file. */ - protected VmwareConfig getVmdkConfig() + protected VirtualizationConfigurationVmwareFileFormat getVmdkConfig() { return this.vmdkConfig; } @@ -163,12 +164,13 @@ public class DiskImageVmdk extends DiskImage * * @return hardware version from the VMDK's embedded descriptor file. * - * @throws DiskImageException + * @throws DiskImageException unable to obtain the VMDK's hardware version of the disk image + * format. */ - public int getHwVersion() throws DiskImageException + public Version getHwVersion() throws DiskImageException { - final VmwareConfig vmdkConfig = this.getVmdkConfig(); - final int hwVersion; + final VirtualizationConfigurationVmwareFileFormat vmdkConfig = this.getVmdkConfig(); + final Version hwVersion; if ( vmdkConfig != null ) { // VMDK image contains a hardware version, so return parsed hardware version @@ -176,11 +178,11 @@ public class DiskImageVmdk extends DiskImage final String hwVersionStr = vmdkConfig.get( "ddb.virtualHWVersion" ); final int hwVersionMajor = Util.parseInt( hwVersionStr, DiskImageVmdk.VMDK_DEFAULT_HW_VERSION ); - hwVersion = DiskImageUtils.versionFromMajor( Integer.valueOf( hwVersionMajor ).shortValue() ); + hwVersion = new Version( Integer.valueOf( hwVersionMajor ).shortValue() ); } else { // VMDK image does not contain any hardware version, so return default hardware version final int hwVersionMajor = DiskImageVmdk.VMDK_DEFAULT_HW_VERSION; - hwVersion = DiskImageUtils.versionFromMajor( Integer.valueOf( hwVersionMajor ).shortValue() ); + hwVersion = new Version( Integer.valueOf( hwVersionMajor ).shortValue() ); } return hwVersion; @@ -233,7 +235,7 @@ public class DiskImageVmdk extends DiskImage @Override public boolean isSnapshot() throws DiskImageException { - final VmwareConfig vmdkConfig = this.getVmdkConfig(); + final VirtualizationConfigurationVmwareFileFormat vmdkConfig = this.getVmdkConfig(); final boolean vmdkSnapshot; if ( vmdkConfig == null ) { @@ -257,12 +259,12 @@ public class DiskImageVmdk extends DiskImage } @Override - public int getVersion() throws DiskImageException + public Version getVersion() throws DiskImageException { final RandomAccessFile diskFile = this.getDiskImage(); final int vmdkVersion = Integer.reverseBytes( DiskImageUtils.readInt( diskFile, 4 ) ); - return DiskImageUtils.versionFromMajor( Integer.valueOf( vmdkVersion ).shortValue() ); + return new Version( Integer.valueOf( vmdkVersion ).shortValue() ); } @Override |