summaryrefslogtreecommitdiffstats
path: root/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration
diff options
context:
space:
mode:
Diffstat (limited to 'core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration')
-rw-r--r--core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericCpu.java57
-rw-r--r--core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericDiskCdromDevices.java110
-rw-r--r--core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericDiskFloppyDevices.java104
-rw-r--r--core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericDiskStorageDevices.java102
-rw-r--r--core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericFileSystemDevices.java107
-rw-r--r--core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericInterfaceDevices.java101
-rw-r--r--core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericMemory.java59
-rw-r--r--core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericName.java57
-rw-r--r--core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericParallelDevices.java97
-rw-r--r--core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericUuid.java53
-rw-r--r--core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuArchitecture.java261
-rw-r--r--core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuGpuPassthroughNvidia.java232
-rw-r--r--core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuSerialDevices.java117
13 files changed, 1457 insertions, 0 deletions
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericCpu.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericCpu.java
new file mode 100644
index 00000000..9d9237c7
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericCpu.java
@@ -0,0 +1,57 @@
+package org.openslx.runvirt.plugin.qemu.configuration;
+
+import org.openslx.libvirt.domain.Domain;
+import org.openslx.libvirt.domain.Domain.CpuCheck;
+import org.openslx.libvirt.domain.Domain.CpuMode;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+import org.openslx.virtualization.configuration.transformation.TransformationException;
+import org.openslx.virtualization.configuration.transformation.TransformationGeneric;
+
+/**
+ * Generic CPU transformation for Libvirt/QEMU virtualization configurations.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class TransformationGenericCpu extends TransformationGeneric<Domain, CommandLineArgs>
+{
+ /**
+ * Name of the configuration transformation.
+ */
+ private static final String NAME = "CPU [number of cores, mode, ...]";
+
+ /**
+ * Creates a new generic CPU transformation for Libvirt/QEMU virtualization configurations.
+ */
+ public TransformationGenericCpu()
+ {
+ super( TransformationGenericCpu.NAME );
+ }
+
+ /**
+ * Validates a virtualization configuration and input arguments for this transformation.
+ *
+ * @param config virtualization configuration for the validation.
+ * @param args input arguments for the validation.
+ * @throws TransformationException validation has failed.
+ */
+ private void validateInputs( Domain config, CommandLineArgs args ) throws TransformationException
+ {
+ if ( config == null || args == null ) {
+ throw new TransformationException( "Virtualization configuration or input arguments are missing!" );
+ } else if ( args.getVmNumCpus() < 1 ) {
+ throw new TransformationException( "Invalid number of CPUs specified! Expected a number n > 0!" );
+ }
+ }
+
+ @Override
+ public void transform( Domain config, CommandLineArgs args ) throws TransformationException
+ {
+ // validate configuration and input arguments
+ this.validateInputs( config, args );
+
+ config.setVCpu( args.getVmNumCpus() );
+ config.setCpuMode( CpuMode.HOST_PASSTHROUGH );
+ config.setCpuCheck( CpuCheck.PARTIAL );
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericDiskCdromDevices.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericDiskCdromDevices.java
new file mode 100644
index 00000000..643c40ed
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericDiskCdromDevices.java
@@ -0,0 +1,110 @@
+package org.openslx.runvirt.plugin.qemu.configuration;
+
+import java.util.ArrayList;
+
+import org.openslx.libvirt.domain.Domain;
+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.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+import org.openslx.virtualization.configuration.VirtualizationConfigurationQemuUtils;
+import org.openslx.virtualization.configuration.transformation.TransformationException;
+import org.openslx.virtualization.configuration.transformation.TransformationGeneric;
+
+/**
+ * Generic CDROM drive transformation for Libvirt/QEMU virtualization configurations.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class TransformationGenericDiskCdromDevices extends TransformationGeneric<Domain, CommandLineArgs>
+{
+ /**
+ * Name of the configuration transformation.
+ */
+ private static final String NAME = "Disk CDROM devices";
+
+ /**
+ * Creates a new generic CDROM drive transformation for Libvirt/QEMU virtualization
+ * configurations.
+ */
+ public TransformationGenericDiskCdromDevices()
+ {
+ super( TransformationGenericDiskCdromDevices.NAME );
+ }
+
+ /**
+ * Validates a virtualization configuration and input arguments for this transformation.
+ *
+ * @param config virtualization configuration for the validation.
+ * @param args input arguments for the validation.
+ * @throws TransformationException validation has failed.
+ */
+ private void validateInputs( Domain config, CommandLineArgs args ) throws TransformationException
+ {
+ if ( config == null || args == null ) {
+ throw new TransformationException( "Virtualization configuration or input arguments are missing!" );
+ }
+ }
+
+ /**
+ * Transforms a CDROM drive in a virtualization configuration selected by its {@code index}.
+ *
+ * @param config virtualization configuration for the transformation.
+ * @param fileName name of the image file for the CDROM drive.
+ * @param index number of the CDROM drive in the virtualization configuration that is selected.
+ * @throws TransformationException transformation has failed.
+ */
+ private void transformDiskCdromDevice( Domain config, String fileName, int index ) throws TransformationException
+ {
+ final ArrayList<DiskCdrom> devices = config.getDiskCdromDevices();
+ final DiskCdrom disk = VirtualizationConfigurationQemuUtils.getArrayIndex( devices, index );
+
+ if ( disk == null ) {
+ if ( fileName != null ) {
+ // CDROM drive does not exist, so create new CDROM drive
+ final DiskCdrom newDisk = config.addDiskCdromDevice();
+ newDisk.setBusType( BusType.SATA );
+ String targetDevName = VirtualizationConfigurationQemuUtils.createAlphabeticalDeviceName( "sd", index );
+ newDisk.setTargetDevice( targetDevName );
+
+ if ( fileName.isEmpty() ) {
+ // remove storage source if empty string is specified to emulate an empty CDROM drive
+ newDisk.removeStorage();
+ } else {
+ // set disk image file as storage source of the disk CDROM drive
+ newDisk.setStorage( StorageType.FILE, fileName );
+ }
+ }
+ } else {
+ // CDROM drive exists, so update existing CDROM drive
+ if ( fileName == null ) {
+ // remove disk storage device if disk image file name is not set
+ disk.remove();
+ } else if ( fileName.isEmpty() ) {
+ // remove storage source if empty string is specified to emulate an empty CDROM drive
+ disk.removeStorage();
+ } else {
+ // set disk image file as storage source of the disk CDROM drive
+ disk.setStorage( StorageType.FILE, fileName );
+ }
+ }
+ }
+
+ @Override
+ public void transform( Domain config, CommandLineArgs args ) throws TransformationException
+ {
+ // validate configuration and input arguments
+ this.validateInputs( config, args );
+
+ // alter CDROM drives
+ this.transformDiskCdromDevice( config, args.getVmDiskFileNameCdrom0(), 0 );
+ this.transformDiskCdromDevice( config, args.getVmDiskFileNameCdrom1(), 1 );
+
+ // remove all additional disk CDROM devices
+ final ArrayList<DiskCdrom> devices = config.getDiskCdromDevices();
+ for ( int i = 2; i < devices.size(); i++ ) {
+ devices.get( i ).remove();
+ }
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericDiskFloppyDevices.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericDiskFloppyDevices.java
new file mode 100644
index 00000000..fe3d3c34
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericDiskFloppyDevices.java
@@ -0,0 +1,104 @@
+package org.openslx.runvirt.plugin.qemu.configuration;
+
+import java.util.ArrayList;
+
+import org.openslx.libvirt.domain.Domain;
+import org.openslx.libvirt.domain.device.Disk.BusType;
+import org.openslx.libvirt.domain.device.Disk.StorageType;
+import org.openslx.libvirt.domain.device.DiskFloppy;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+import org.openslx.virtualization.configuration.VirtualizationConfigurationQemuUtils;
+import org.openslx.virtualization.configuration.transformation.TransformationException;
+import org.openslx.virtualization.configuration.transformation.TransformationGeneric;
+
+/**
+ * Generic floppy drive transformation for Libvirt/QEMU virtualization configurations.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class TransformationGenericDiskFloppyDevices extends TransformationGeneric<Domain, CommandLineArgs>
+{
+ /**
+ * Name of the configuration transformation.
+ */
+ private static final String NAME = "Disk floppy devices";
+
+ /**
+ * Creates a new floppy drive transformation for Libvirt/QEMU virtualization configurations.
+ */
+ public TransformationGenericDiskFloppyDevices()
+ {
+ super( TransformationGenericDiskFloppyDevices.NAME );
+ }
+
+ /**
+ * Validates a virtualization configuration and input arguments for this transformation.
+ *
+ * @param config virtualization configuration for the validation.
+ * @param args input arguments for the validation.
+ * @throws TransformationException validation has failed.
+ */
+ private void validateInputs( Domain config, CommandLineArgs args ) throws TransformationException
+ {
+ if ( config == null || args == null ) {
+ throw new TransformationException( "Virtualization configuration or input arguments are missing!" );
+ }
+ }
+
+ /**
+ * Transforms a floppy drive in a virtualization configuration selected by its {@code index}.
+ *
+ * @param config virtualization configuration for the transformation.
+ * @param fileName name of the image file for the floppy drive.
+ * @param index number of the floppy drive in the virtualization configuration that is selected.
+ * @throws TransformationException transformation has failed.
+ */
+ private void transformDiskFloppyDevice( Domain config, String fileName, int index ) throws TransformationException
+ {
+ final ArrayList<DiskFloppy> devices = config.getDiskFloppyDevices();
+ final DiskFloppy disk = VirtualizationConfigurationQemuUtils.getArrayIndex( devices, index );
+
+ if ( disk == null ) {
+ if ( fileName != null ) {
+ // floppy device does not exist, so create new floppy device
+ final DiskFloppy newDisk = config.addDiskFloppyDevice();
+ newDisk.setBusType( BusType.FDC );
+ String targetDevName = VirtualizationConfigurationQemuUtils.createAlphabeticalDeviceName( "fd", index );
+ newDisk.setTargetDevice( targetDevName );
+
+ if ( fileName.isEmpty() ) {
+ newDisk.removeStorage();
+ } else {
+ newDisk.setStorage( StorageType.FILE, fileName );
+ }
+ }
+ } else {
+ // floppy device exists, so update existing floppy device
+ if ( fileName == null ) {
+ disk.remove();
+ } else if ( fileName.isEmpty() ) {
+ disk.removeStorage();
+ } else {
+ disk.setStorage( StorageType.FILE, fileName );
+ }
+ }
+ }
+
+ @Override
+ public void transform( Domain config, CommandLineArgs args ) throws TransformationException
+ {
+ // validate configuration and input arguments
+ this.validateInputs( config, args );
+
+ // alter floppy drives
+ this.transformDiskFloppyDevice( config, args.getVmDiskFileNameFloppy0(), 0 );
+ this.transformDiskFloppyDevice( config, args.getVmDiskFileNameFloppy1(), 1 );
+
+ // remove all additional disk storage devices
+ final ArrayList<DiskFloppy> devices = config.getDiskFloppyDevices();
+ for ( int i = 2; i < devices.size(); i++ ) {
+ devices.get( i ).remove();
+ }
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericDiskStorageDevices.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericDiskStorageDevices.java
new file mode 100644
index 00000000..9bd1edbb
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericDiskStorageDevices.java
@@ -0,0 +1,102 @@
+package org.openslx.runvirt.plugin.qemu.configuration;
+
+import java.util.ArrayList;
+
+import org.openslx.libvirt.domain.Domain;
+import org.openslx.libvirt.domain.device.Disk.BusType;
+import org.openslx.libvirt.domain.device.Disk.StorageType;
+import org.openslx.libvirt.domain.device.DiskFloppy;
+import org.openslx.libvirt.domain.device.DiskStorage;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+import org.openslx.virtualization.configuration.VirtualizationConfigurationQemuUtils;
+import org.openslx.virtualization.configuration.transformation.TransformationException;
+import org.openslx.virtualization.configuration.transformation.TransformationGeneric;
+
+/**
+ * Generic storage device (HDD, SSD, ...) transformation for Libvirt/QEMU virtualization
+ * configurations.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class TransformationGenericDiskStorageDevices extends TransformationGeneric<Domain, CommandLineArgs>
+{
+ /**
+ * Name of the configuration transformation.
+ */
+ private static final String NAME = "Disk storage devices [HDD, SSD, ...]";
+
+ /**
+ * Creates a new storage device (HDD, SSD, ...) transformation for Libvirt/QEMU virtualization
+ * configurations.
+ */
+ public TransformationGenericDiskStorageDevices()
+ {
+ super( TransformationGenericDiskStorageDevices.NAME );
+ }
+
+ /**
+ * Validates a virtualization configuration and input arguments for this transformation.
+ *
+ * @param config virtualization configuration for the validation.
+ * @param args input arguments for the validation.
+ * @throws TransformationException validation has failed.
+ */
+ private void validateInputs( Domain config, CommandLineArgs args ) throws TransformationException
+ {
+ if ( config == null || args == null ) {
+ throw new TransformationException( "Virtualization configuration or input arguments are missing!" );
+ }
+ }
+
+ /**
+ * Transforms a storage device in a virtualization configuration selected by its {@code index}.
+ *
+ * @param config virtualization configuration for the transformation.
+ * @param fileName name of the image file for the storage device.
+ * @param index number of the storage device in the virtualization configuration that is
+ * selected.
+ * @throws TransformationException transformation has failed.
+ */
+ private void transformDiskStorageDevice( Domain config, String fileName, int index ) throws TransformationException
+ {
+ final ArrayList<DiskStorage> devices = config.getDiskStorageDevices();
+ final DiskStorage disk = VirtualizationConfigurationQemuUtils.getArrayIndex( devices, index );
+
+ if ( disk == null ) {
+ if ( fileName != null && !fileName.isEmpty() ) {
+ // storage device does not exist, so create new storage device
+ final DiskFloppy newDisk = config.addDiskFloppyDevice();
+ newDisk.setBusType( BusType.VIRTIO );
+ String targetDevName = VirtualizationConfigurationQemuUtils.createAlphabeticalDeviceName( "vd", index );
+ newDisk.setTargetDevice( targetDevName );
+ newDisk.setStorage( StorageType.FILE, fileName );
+ }
+ } else {
+ // storage device exists, so update existing storage device
+ if ( fileName == null || fileName.isEmpty() ) {
+ // remove disk storage device if disk image file name is not set
+ disk.remove();
+ } else {
+ // set image file of disk storage if disk storage device is available
+ disk.setStorage( StorageType.FILE, fileName );
+ }
+ }
+ }
+
+ @Override
+ public void transform( Domain config, CommandLineArgs args ) throws TransformationException
+ {
+ // validate configuration and input arguments
+ this.validateInputs( config, args );
+
+ // alter storage device
+ this.transformDiskStorageDevice( config, args.getVmDiskFileNameHDD0(), 0 );
+
+ // remove all additional disk storage devices
+ final ArrayList<DiskStorage> devices = config.getDiskStorageDevices();
+ for ( int i = 1; i < devices.size(); i++ ) {
+ devices.get( i ).remove();
+ }
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericFileSystemDevices.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericFileSystemDevices.java
new file mode 100644
index 00000000..a4f77b0d
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericFileSystemDevices.java
@@ -0,0 +1,107 @@
+package org.openslx.runvirt.plugin.qemu.configuration;
+
+import java.util.ArrayList;
+
+import org.openslx.libvirt.domain.Domain;
+import org.openslx.libvirt.domain.device.FileSystem;
+import org.openslx.libvirt.domain.device.FileSystem.AccessMode;
+import org.openslx.libvirt.domain.device.FileSystem.Type;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+import org.openslx.virtualization.configuration.VirtualizationConfigurationQemuUtils;
+import org.openslx.virtualization.configuration.transformation.TransformationException;
+import org.openslx.virtualization.configuration.transformation.TransformationGeneric;
+
+/**
+ * Generic file system device (shared folder) transformation for Libvirt/QEMU virtualization
+ * configurations.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class TransformationGenericFileSystemDevices extends TransformationGeneric<Domain, CommandLineArgs>
+{
+ /**
+ * Name of the configuration transformation.
+ */
+ private static final String NAME = "File system devices";
+
+ /**
+ * Creates a new file system device (shared folder) transformation for Libvirt/QEMU
+ * virtualization configurations.
+ */
+ public TransformationGenericFileSystemDevices()
+ {
+ super( TransformationGenericFileSystemDevices.NAME );
+ }
+
+ /**
+ * Validates a virtualization configuration and input arguments for this transformation.
+ *
+ * @param config virtualization configuration for the validation.
+ * @param args input arguments for the validation.
+ * @throws TransformationException validation has failed.
+ */
+ private void validateInputs( Domain config, CommandLineArgs args ) throws TransformationException
+ {
+ if ( config == null || args == null ) {
+ throw new TransformationException( "Virtualization configuration or input arguments are missing!" );
+ }
+ }
+
+ /**
+ * Transforms a storage device in a virtualization configuration selected by its {@code index}.
+ *
+ * @param config virtualization configuration for the transformation.
+ * @param source path of the file system source on a host system.
+ * @param target path of the file system destination in a virtualization guest.
+ * @param index number of the file system device in the virtualization configuration that is
+ * selected.
+ * @throws TransformationException transformation has failed.
+ */
+ private void transformFileSystemDevice( Domain config, String source, String target, int index )
+ throws TransformationException
+ {
+ final ArrayList<FileSystem> devices = config.getFileSystemDevices();
+ final FileSystem fileSystem = VirtualizationConfigurationQemuUtils.getArrayIndex( devices, index );
+
+ if ( fileSystem == null ) {
+ // check if file system device source directory is specified
+ if ( source != null && !source.isEmpty() && target != null && !target.isEmpty() ) {
+ // file system device does not exist, so create new file system device
+ final FileSystem newFileSystem = config.addFileSystemDevice();
+ newFileSystem.setType( Type.MOUNT );
+ newFileSystem.setAccessMode( AccessMode.MAPPED );
+ newFileSystem.setSource( source );
+ newFileSystem.setTarget( target );
+ }
+ } else {
+ if ( source == null || source.isEmpty() || target == null || target.isEmpty() ) {
+ // remove file system device since device source or target is not specified
+ fileSystem.remove();
+ } else {
+ // change type, access mode, source and target of existing file system device
+ fileSystem.setType( Type.MOUNT );
+ fileSystem.setAccessMode( AccessMode.MAPPED );
+ fileSystem.setSource( source );
+ fileSystem.setTarget( target );
+ }
+ }
+ }
+
+ @Override
+ public void transform( Domain config, CommandLineArgs args ) throws TransformationException
+ {
+ // validate configuration and input arguments
+ this.validateInputs( config, args );
+
+ // alter file system devices
+ this.transformFileSystemDevice( config, args.getVmFsSrc0(), args.getVmFsTgt0(), 0 );
+ this.transformFileSystemDevice( config, args.getVmFsSrc1(), args.getVmFsTgt1(), 1 );
+
+ // remove all additional file system devices
+ final ArrayList<FileSystem> devices = config.getFileSystemDevices();
+ for ( int i = 2; i < devices.size(); i++ ) {
+ devices.get( i ).remove();
+ }
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericInterfaceDevices.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericInterfaceDevices.java
new file mode 100644
index 00000000..6cf12ce2
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericInterfaceDevices.java
@@ -0,0 +1,101 @@
+package org.openslx.runvirt.plugin.qemu.configuration;
+
+import java.util.ArrayList;
+
+import org.openslx.libvirt.domain.Domain;
+import org.openslx.libvirt.domain.device.Interface;
+import org.openslx.libvirt.domain.device.InterfaceBridge;
+import org.openslx.libvirt.domain.device.Interface.Model;
+import org.openslx.libvirt.domain.device.Interface.Type;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+import org.openslx.virtualization.configuration.VirtualizationConfigurationQemu;
+import org.openslx.virtualization.configuration.VirtualizationConfigurationQemuUtils;
+import org.openslx.virtualization.configuration.transformation.TransformationException;
+import org.openslx.virtualization.configuration.transformation.TransformationGeneric;
+
+/**
+ * Generic network interface transformation for Libvirt/QEMU virtualization configurations.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class TransformationGenericInterfaceDevices extends TransformationGeneric<Domain, CommandLineArgs>
+{
+ /**
+ * Name of the configuration transformation.
+ */
+ private static final String NAME = "Network interface devices";
+
+ /**
+ * Creates a new network interface transformation for Libvirt/QEMU virtualization configurations.
+ */
+ public TransformationGenericInterfaceDevices()
+ {
+ super( TransformationGenericInterfaceDevices.NAME );
+ }
+
+ /**
+ * Validates a virtualization configuration and input arguments for this transformation.
+ *
+ * @param config virtualization configuration for the validation.
+ * @param args input arguments for the validation.
+ * @throws TransformationException validation has failed.
+ */
+ private void validateInputs( Domain config, CommandLineArgs args ) throws TransformationException
+ {
+ if ( config == null || args == null ) {
+ throw new TransformationException( "Virtualization configuration or input arguments are missing!" );
+ }
+ }
+
+ /**
+ * Transforms a network interface in a virtualization configuration selected by its
+ * {@code index}.
+ *
+ * @param config virtualization configuration for the transformation.
+ * @param macAddress MAC address for the network interface.
+ * @param index number of the network interface in the virtualization configuration that is
+ * selected.
+ * @throws TransformationException transformation has failed.
+ */
+ private void transformInterfaceDevice( Domain config, String macAddress, int index ) throws TransformationException
+ {
+ final ArrayList<Interface> devices = config.getInterfaceDevices();
+ final Interface device = VirtualizationConfigurationQemuUtils.getArrayIndex( devices, index );
+
+ if ( device == null ) {
+ if ( macAddress != null && !macAddress.isEmpty() ) {
+ // create network interface if it does not exists
+ final InterfaceBridge newDevice = config.addInterfaceBridgeDevice();
+ newDevice.setType( Type.BRIDGE );
+ newDevice.setModel( Model.VIRTIO );
+ newDevice.setMacAddress( macAddress );
+ newDevice.setSource( VirtualizationConfigurationQemu.NETWORK_BRIDGE_NAT_DEFAULT );
+ }
+ } else {
+ if ( macAddress == null || macAddress.isEmpty() ) {
+ // remove network interface device if MAC address is not set
+ device.remove();
+ } else {
+ // set MAC address of network interface device if network interface device is available
+ device.setMacAddress( macAddress );
+ }
+ }
+ }
+
+ @Override
+ public void transform( Domain config, CommandLineArgs args ) throws TransformationException
+ {
+ // validate configuration and input arguments
+ this.validateInputs( config, args );
+
+ // alter network interface
+ this.transformInterfaceDevice( config, args.getVmMacAddress0(), 0 );
+
+ // remove all additional disk storage devices
+ final ArrayList<Interface> devices = config.getInterfaceDevices();
+ for ( int i = 1; i < devices.size(); i++ ) {
+ devices.get( i ).remove();
+ }
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericMemory.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericMemory.java
new file mode 100644
index 00000000..fce373f7
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericMemory.java
@@ -0,0 +1,59 @@
+package org.openslx.runvirt.plugin.qemu.configuration;
+
+import java.math.BigInteger;
+
+import org.openslx.libvirt.domain.Domain;
+import org.openslx.libvirt.domain.DomainUtils;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+import org.openslx.virtualization.configuration.transformation.TransformationException;
+import org.openslx.virtualization.configuration.transformation.TransformationGeneric;
+
+/**
+ * Generic memory transformation for Libvirt/QEMU virtualization configurations.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class TransformationGenericMemory extends TransformationGeneric<Domain, CommandLineArgs>
+{
+ /**
+ * Name of the configuration transformation.
+ */
+ private static final String NAME = "Memory [normal, current (balloning)]";
+
+ /**
+ * Creates a new memory transformation for Libvirt/QEMU virtualization configurations.
+ */
+ public TransformationGenericMemory()
+ {
+ super( TransformationGenericMemory.NAME );
+ }
+
+ /**
+ * Validates a virtualization configuration and input arguments for this transformation.
+ *
+ * @param config virtualization configuration for the validation.
+ * @param args input arguments for the validation.
+ * @throws TransformationException validation has failed.
+ */
+ private void validateInputs( Domain config, CommandLineArgs args ) throws TransformationException
+ {
+ if ( config == null || args == null ) {
+ throw new TransformationException( "Virtualization configuration or input arguments are missing!" );
+ } else if ( args.getVmMemory() == null || args.getVmMemory().isEmpty() ) {
+ throw new TransformationException( "Amount of memory in MiB is not specified!" );
+ }
+ }
+
+ @Override
+ public void transform( Domain config, CommandLineArgs args ) throws TransformationException
+ {
+ // validate configuration and input arguments
+ this.validateInputs( config, args );
+
+ BigInteger memory = DomainUtils.decodeMemory( args.getVmMemory(), "MiB" );
+
+ config.setMemory( memory );
+ config.setCurrentMemory( memory );
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericName.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericName.java
new file mode 100644
index 00000000..b96793d5
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericName.java
@@ -0,0 +1,57 @@
+package org.openslx.runvirt.plugin.qemu.configuration;
+
+import org.openslx.libvirt.domain.Domain;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+import org.openslx.virtualization.configuration.transformation.TransformationException;
+import org.openslx.virtualization.configuration.transformation.TransformationGeneric;
+
+/**
+ * Generic name transformation for Libvirt/QEMU virtualization configurations.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class TransformationGenericName extends TransformationGeneric<Domain, CommandLineArgs>
+{
+ /**
+ * Name of the configuration transformation.
+ */
+ private static final String NAME = "Name [(display) name]";
+
+ /**
+ * Creates a new name transformation for Libvirt/QEMU virtualization configurations.
+ */
+ public TransformationGenericName()
+ {
+ super( TransformationGenericName.NAME );
+ }
+
+ /**
+ * Validates a virtualization configuration and input arguments for this transformation.
+ *
+ * @param config virtualization configuration for the validation.
+ * @param args input arguments for the validation.
+ * @throws TransformationException validation has failed.
+ */
+ private void validateInputs( Domain config, CommandLineArgs args ) throws TransformationException
+ {
+ if ( config == null || args == null ) {
+ throw new TransformationException( "Virtualization configuration or input arguments are missing!" );
+ } else if ( args.getVmName() == null || args.getVmName().isEmpty() ) {
+ throw new TransformationException( "Name is not specified!" );
+ } else if ( args.getVmDisplayName() == null || args.getVmDisplayName().isEmpty() ) {
+ throw new TransformationException( "Display name is not specified!" );
+ }
+ }
+
+ @Override
+ public void transform( Domain config, CommandLineArgs args ) throws TransformationException
+ {
+ // validate configuration and input arguments
+ this.validateInputs( config, args );
+
+ // alter names in the configuration
+ config.setName( args.getVmName() );
+ config.setTitle( args.getVmDisplayName() );
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericParallelDevices.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericParallelDevices.java
new file mode 100644
index 00000000..08d43ef0
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericParallelDevices.java
@@ -0,0 +1,97 @@
+package org.openslx.runvirt.plugin.qemu.configuration;
+
+import java.util.ArrayList;
+
+import org.openslx.libvirt.domain.Domain;
+import org.openslx.libvirt.domain.device.Parallel;
+import org.openslx.libvirt.domain.device.Parallel.Type;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+import org.openslx.virtualization.configuration.VirtualizationConfigurationQemuUtils;
+import org.openslx.virtualization.configuration.transformation.TransformationException;
+import org.openslx.virtualization.configuration.transformation.TransformationGeneric;
+
+/**
+ * Generic parallel device transformation for Libvirt/QEMU virtualization configurations.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class TransformationGenericParallelDevices extends TransformationGeneric<Domain, CommandLineArgs>
+{
+ /**
+ * Name of the configuration transformation.
+ */
+ private static final String NAME = "Parallel devices";
+
+ /**
+ * Creates a new parallel device transformation for Libvirt/QEMU virtualization configurations.
+ */
+ public TransformationGenericParallelDevices()
+ {
+ super( TransformationGenericParallelDevices.NAME );
+ }
+
+ /**
+ * Validates a virtualization configuration and input arguments for this transformation.
+ *
+ * @param config virtualization configuration for the validation.
+ * @param args input arguments for the validation.
+ * @throws TransformationException validation has failed.
+ */
+ private void validateInputs( Domain config, CommandLineArgs args ) throws TransformationException
+ {
+ if ( config == null || args == null ) {
+ throw new TransformationException( "Virtualization configuration or input arguments are missing!" );
+ }
+ }
+
+ /**
+ * Transforms a parallel device in a virtualization configuration selected by its {@code index}.
+ *
+ * @param config virtualization configuration for the transformation.
+ * @param fileName path to the parallel device file on the host system.
+ * @param index number of the parallel device in the virtualization configuration that is
+ * selected.
+ * @throws TransformationException transformation has failed.
+ */
+ private void transformParallelDevice( Domain config, String fileName, int index ) throws TransformationException
+ {
+ final ArrayList<Parallel> devices = config.getParallelDevices();
+ final Parallel device = VirtualizationConfigurationQemuUtils.getArrayIndex( devices, index );
+
+ if ( device == null ) {
+ // check if device file name is specified
+ if ( fileName != null ) {
+ // parallel port device does not exist, so create new parallel port device
+ final Parallel newDevice = config.addParallelDevice();
+ newDevice.setType( Type.DEV );
+ newDevice.setSource( fileName );
+ }
+ } else {
+ if ( fileName == null || fileName.isEmpty() ) {
+ // remove device since device file is not specified
+ device.remove();
+ } else {
+ // change type and source of existing parallel port device
+ device.setType( Type.DEV );
+ device.setSource( fileName );
+ }
+ }
+ }
+
+ @Override
+ public void transform( Domain config, CommandLineArgs args ) throws TransformationException
+ {
+ // validate configuration and input arguments
+ this.validateInputs( config, args );
+
+ // alter parallel device
+ this.transformParallelDevice( config, args.getVmDeviceParallel0(), 0 );
+
+ // remove all additional parallel devices
+ final ArrayList<Parallel> devices = config.getParallelDevices();
+ for ( int i = 1; i < devices.size(); i++ ) {
+ devices.get( i ).remove();
+ }
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericUuid.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericUuid.java
new file mode 100644
index 00000000..43fb6412
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericUuid.java
@@ -0,0 +1,53 @@
+package org.openslx.runvirt.plugin.qemu.configuration;
+
+import org.openslx.libvirt.domain.Domain;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+import org.openslx.virtualization.configuration.transformation.TransformationException;
+import org.openslx.virtualization.configuration.transformation.TransformationGeneric;
+
+/**
+ * Generic UUID transformation for Libvirt/QEMU virtualization configurations.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class TransformationGenericUuid extends TransformationGeneric<Domain, CommandLineArgs>
+{
+ /**
+ * Name of the configuration transformation.
+ */
+ private static final String NAME = "UUID";
+
+ /**
+ * Creates a new UUID transformation for Libvirt/QEMU virtualization configurations.
+ */
+ public TransformationGenericUuid()
+ {
+ super( TransformationGenericUuid.NAME );
+ }
+
+ /**
+ * Validates a virtualization configuration and input arguments for this transformation.
+ *
+ * @param config virtualization configuration for the validation.
+ * @param args input arguments for the validation.
+ * @throws TransformationException validation has failed.
+ */
+ private void validateInputs( Domain config, CommandLineArgs args ) throws TransformationException
+ {
+ if ( config == null || args == null ) {
+ throw new TransformationException( "Virtualization configuration or input arguments are missing!" );
+ } else if ( args.getVmUuid() == null || args.getVmUuid().isEmpty() ) {
+ throw new TransformationException( "UUID is not specified!" );
+ }
+ }
+
+ @Override
+ public void transform( Domain config, CommandLineArgs args ) throws TransformationException
+ {
+ // validate configuration and input arguments
+ this.validateInputs( config, args );
+
+ config.setUuid( args.getVmUuid() );
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuArchitecture.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuArchitecture.java
new file mode 100644
index 00000000..a51c829d
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuArchitecture.java
@@ -0,0 +1,261 @@
+package org.openslx.runvirt.plugin.qemu.configuration;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.openslx.libvirt.capabilities.Capabilities;
+import org.openslx.libvirt.capabilities.guest.Guest;
+import org.openslx.libvirt.capabilities.guest.Machine;
+import org.openslx.libvirt.domain.Domain;
+import org.openslx.libvirt.domain.Domain.OsType;
+import org.openslx.libvirt.domain.Domain.Type;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+import org.openslx.runvirt.plugin.qemu.virtualization.LibvirtHypervisorQemu;
+import org.openslx.runvirt.virtualization.LibvirtHypervisorException;
+import org.openslx.virtualization.configuration.transformation.TransformationException;
+import org.openslx.virtualization.configuration.transformation.TransformationSpecific;
+
+/**
+ * Specific architecture transformation for Libvirt/QEMU virtualization configurations.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class TransformationSpecificQemuArchitecture
+ extends TransformationSpecific<Domain, CommandLineArgs, LibvirtHypervisorQemu>
+{
+ /**
+ * Name of the configuration transformation.
+ */
+ private static final String NAME = "QEMU Architecture [CPU architecture, machine type, ...]";
+
+ /**
+ * Creates a new architecture transformation for Libvirt/QEMU virtualization configurations.
+ *
+ * @param hypervisor Libvirt/QEMU hypervisor.
+ */
+ public TransformationSpecificQemuArchitecture( LibvirtHypervisorQemu virtualizer )
+ {
+ super( TransformationSpecificQemuArchitecture.NAME, virtualizer );
+ }
+
+ /**
+ * Validates a virtualization configuration and input arguments for this transformation.
+ *
+ * @param config virtualization configuration for the validation.
+ * @param args input arguments for the validation.
+ * @throws TransformationException validation has failed.
+ */
+ private void validateInputs( Domain config, CommandLineArgs args ) throws TransformationException
+ {
+ if ( config == null ) {
+ throw new TransformationException( "Virtualization configuration is missing!" );
+ }
+ }
+
+ /**
+ * Queries and returns the capabilities of the Libvirt/QEMU hypervisor.
+ *
+ * @return capabilities of the Libvirt/QEMU hypervisor.
+ * @throws TransformationException failed to query and return the capabilities of the
+ * Libvirt/QEMU hypervisor.
+ */
+ protected Capabilities getCapabilities() throws TransformationException
+ {
+ final Capabilities capabilities;
+
+ try {
+ capabilities = this.getVirtualizer().getCapabilites();
+ } catch ( LibvirtHypervisorException e ) {
+ final String errorMsg = new String(
+ "Failed to retrieve host capabilities from QEMU virtualizer: " + e.getLocalizedMessage() );
+ throw new TransformationException( errorMsg );
+ }
+
+ return capabilities;
+ }
+
+ /**
+ * Returns a guest capability of the hypervisor's host system based on a given target
+ * architecture name.
+ *
+ * @param architectureName target architecture of the guest that is returned
+ * @return guest capability of the hypervisor's host system with target architecture name.
+ * @throws TransformationException failed to return guest capability of the hypervisor's host.
+ */
+ private Guest getTargetGuestFromArchName( String architectureName ) throws TransformationException
+ {
+ final List<Guest> guests = this.getCapabilities().getGuests();
+ Guest targetGuest = null;
+
+ if ( architectureName == null ) {
+ return targetGuest;
+ }
+
+ for ( Guest guest : guests ) {
+ final String guestArchitectureName = guest.getArchName();
+ if ( architectureName.equals( guestArchitectureName ) ) {
+ targetGuest = guest;
+ break;
+ }
+ }
+
+ return targetGuest;
+ }
+
+ /**
+ * Returns the target machine description of a host system's guest capability based on a given
+ * target machine name.
+ *
+ * @param guest guest capability of a host system.
+ * @param machineName name of the machine description.
+ * @return target machine description of a host system's guest capability.
+ * @throws TransformationException failed to return the target machine description of a host
+ * system's guest capabilities.
+ */
+ private Machine getTargetMachineFromGuest( Guest guest, String machineName ) throws TransformationException
+ {
+ final List<Machine> machines = guest.getArchMachines();
+ Machine targetMachine = null;
+
+ if ( machineName == null ) {
+ return targetMachine;
+ }
+
+ for ( Machine machine : machines ) {
+ if ( machineName.equals( machine.getName() ) ) {
+ targetMachine = machine;
+ break;
+ }
+ }
+
+ return targetMachine;
+ }
+
+ /**
+ * Returns the canonical names of a target machine description of a host system's guest
+ * capability.
+ *
+ * @param guest guest capability of a host system.
+ * @return canonical names of a target machine description of a host system's guest capability.
+ * @throws TransformationException failed to return the canonical names of a target machine
+ * description of a host system's guest capability
+ */
+ private List<String> getCanonicalNamesFromTargetMachines( Guest guest ) throws TransformationException
+ {
+ final List<Machine> machines = guest.getArchMachines();
+ final List<String> canonicalNames = new ArrayList<String>();
+
+ for ( Machine machine : machines ) {
+ final String canonicalName = machine.getCanonicalMachine();
+ if ( canonicalName != null ) {
+ canonicalNames.add( canonicalName );
+ }
+ }
+
+ return canonicalNames;
+ }
+
+ @Override
+ public void transform( Domain config, CommandLineArgs args ) throws TransformationException
+ {
+ // validate configuration and input arguments
+ this.validateInputs( config, args );
+
+ // get source architecture, machine- and OS type
+ final String sourceArchitectureName = config.getOsArch();
+ final String sourceMachine = config.getOsMachine();
+ final OsType sourceOsType = config.getOsType();
+ final Type sourceDomainType = config.getType();
+
+ // check if source architecture is supported by one of the hypervisor's guests
+ Guest targetGuest = null;
+ if ( sourceArchitectureName == null ) {
+ final String errorMsg = new String( "Source architecture is not specified!" );
+ throw new TransformationException( errorMsg );
+ } else {
+ targetGuest = this.getTargetGuestFromArchName( sourceArchitectureName );
+ if ( targetGuest == null ) {
+ final String errorMsg = new String( "Source architecture is not supported by the virtualizer!" );
+ throw new TransformationException( errorMsg );
+ }
+ }
+
+ // check if source machine is supported by the hypervisor
+ Machine targetMachine = null;
+ if ( sourceMachine == null ) {
+ final String errorMsg = new String( "Source machine type is not specified!" );
+ throw new TransformationException( errorMsg );
+ } else {
+ // get all possible machine type for supported source architecture
+ targetMachine = this.getTargetMachineFromGuest( targetGuest, sourceMachine );
+
+ if ( targetMachine == null ) {
+ // source machine is not directly supported by the hypervisor
+ // check if up- or downgraded version of the chipset is supported by the hypervisor
+ List<String> targetMachineCanonicalNames = this.getCanonicalNamesFromTargetMachines( targetGuest );
+
+ // retrieve overwrite chipset name from canonical machine names
+ String sourceMachineOverwrite = null;
+ for ( String targetMachineCanonicalName : targetMachineCanonicalNames ) {
+ if ( sourceMachine.contains( targetMachineCanonicalName ) ) {
+ sourceMachineOverwrite = targetMachineCanonicalName;
+ break;
+ }
+ }
+
+ // if overwrite available, patch the machine type
+ if ( sourceMachineOverwrite != null ) {
+ config.setOsMachine( sourceMachineOverwrite );
+ } else {
+ final String errorMsg = new String( "Source machine type is not supported by the virtualizer!" );
+ throw new TransformationException( errorMsg );
+ }
+ }
+ }
+
+ // check if source OS type is supported by the hypervisor's architecture
+ if ( sourceOsType == null ) {
+ final String errorMsg = new String( "OS type is not specified!" );
+ throw new TransformationException( errorMsg );
+ } else {
+ if ( !sourceOsType.toString().equals( targetGuest.getOsType().toString() ) ) {
+ final String errorMsg = new String( "OS type is not supported by the virtualizer!" );
+ throw new TransformationException( errorMsg );
+ }
+ }
+
+ // check if source domain type is supported by the hypervisor's architecture
+ Type targetDomainType = null;
+ if ( sourceDomainType == null ) {
+ final String errorMsg = new String( "Source domain type is not specified!" );
+ throw new TransformationException( errorMsg );
+ } else {
+ final List<org.openslx.libvirt.capabilities.guest.Domain> targetDomains = targetGuest.getArchDomains();
+
+ // retrieve supported domain type
+ for ( org.openslx.libvirt.capabilities.guest.Domain domain : targetDomains ) {
+ final Type domainType = domain.getType();
+ if ( domainType == sourceDomainType ) {
+ targetDomainType = domainType;
+ break;
+ }
+ }
+
+ // check supported domain type
+ if ( targetDomainType == null ) {
+ final String errorMsg = new String( "Source domain type is not supported by the virtualizer!" );
+ throw new TransformationException( errorMsg );
+ }
+ }
+
+ // patch path of QEMU emulator binary
+ final String archEmulator = targetGuest.getArchEmulator();
+ if ( archEmulator == null ) {
+ final String errorMsg = new String( "Emulation of source architecture is not supported by the virtualizer!" );
+ throw new TransformationException( errorMsg );
+ } else {
+ config.setDevicesEmulator( targetGuest.getArchEmulator() );
+ }
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuGpuPassthroughNvidia.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuGpuPassthroughNvidia.java
new file mode 100644
index 00000000..a22bf027
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuGpuPassthroughNvidia.java
@@ -0,0 +1,232 @@
+package org.openslx.runvirt.plugin.qemu.configuration;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.openslx.libvirt.capabilities.Capabilities;
+import org.openslx.libvirt.domain.Domain;
+import org.openslx.libvirt.domain.device.HostdevPci;
+import org.openslx.libvirt.domain.device.HostdevPciDeviceAddress;
+import org.openslx.libvirt.domain.device.HostdevPciDeviceDescription;
+import org.openslx.libvirt.domain.device.Shmem;
+import org.openslx.libvirt.domain.device.Video;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+import org.openslx.runvirt.plugin.qemu.virtualization.LibvirtHypervisorQemu;
+import org.openslx.runvirt.virtualization.LibvirtHypervisorException;
+import org.openslx.virtualization.configuration.transformation.TransformationException;
+import org.openslx.virtualization.configuration.transformation.TransformationSpecific;
+
+/**
+ * Specific Nvidia GPU passthrough transformation for Libvirt/QEMU virtualization configurations.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class TransformationSpecificQemuGpuPassthroughNvidia
+ extends TransformationSpecific<Domain, CommandLineArgs, LibvirtHypervisorQemu>
+{
+ /**
+ * Name of the configuration transformation.
+ */
+ private static final String NAME = "QEMU GPU passthrough [Nvidia]";
+
+ /**
+ * Vendor identifier of PCI devices from Nvidia.
+ */
+ private static final int NVIDIA_PCI_VENDOR_ID = 0x10de;
+
+ /**
+ * Vendor identifier of the Hyper-V enlightenment for hypervisor shadowing.
+ */
+ public static final String HYPERV_VENDOR_ID = "62776c706277";
+
+ /**
+ * Maximum width in pixel of the GPU passthrough rendered display.
+ */
+ private static final long MAX_DISPLAY_WIDTH = 2560;
+
+ /**
+ * Maximum height in pixel of the GPU passthrough rendered display.
+ */
+ private static final long MAX_DISPLAY_HEIGHT = 1440;
+
+ /**
+ * Reserved memory for framebuffer meta data of the Looking Glass shared memory device in MiB.
+ */
+ private static final long RESERVED_MEMORY_FRAMEBUFFER = 10;
+
+ /**
+ * Creates a new Nvidia GPU passthrough transformation for Libvirt/QEMU virtualization
+ * configurations.
+ *
+ * @param hypervisor Libvirt/QEMU hypervisor.
+ */
+ public TransformationSpecificQemuGpuPassthroughNvidia( LibvirtHypervisorQemu hypervisor )
+ {
+ super( TransformationSpecificQemuGpuPassthroughNvidia.NAME, hypervisor );
+ }
+
+ /**
+ * Validates a PCI device description and address of a PCI device from a Nvidia GPU and parses
+ * the validated PCI device addresses.
+ *
+ * @param pciIds textual PCI device description and address to be validated.
+ *
+ * @return list of validated and parsed PCI device addresses for a NVIDIA GPU passthrough.
+ *
+ * @throws TransformationException validation of PCI device description and address failed.
+ */
+ private static List<HostdevPciDeviceAddress> validateParseNvidiaPciIds( List<String> pciIds )
+ throws TransformationException
+ {
+ final List<HostdevPciDeviceAddress> parsedPciAddresses = new ArrayList<HostdevPciDeviceAddress>();
+
+ if ( pciIds != null && pciIds.size() > 0 ) {
+ // abort if arguments do not follow the pattern:
+ //
+ // [0]: <VENDOR ID 0>:<DEVICE ID 0>
+ // [1]: <PCI DOMAIN 0>:<PCI BUS 0>:<PCI DEVICE 0>.<PCI FUNCTION 0>
+ // [2]: <VENDOR ID 1>:<DEVICE ID 1>
+ // [3]: <PCI DOMAIN 1>:<PCI BUS 1>:<PCI DEVICE 1>.<PCI FUNCTION 1>
+ // ...
+ //
+ if ( pciIds.size() % 2 != 0 ) {
+ throw new TransformationException(
+ "Arguments of PCI IDs are not follow the pattern for a GPU passthrough!" );
+ }
+
+ // parse PCI device description and PCI device address
+ for ( int i = 0; i < pciIds.size(); i += 2 ) {
+ // parse vendor and device ID
+ HostdevPciDeviceDescription deviceDescription = null;
+ try {
+ deviceDescription = HostdevPciDeviceDescription.valueOf( pciIds.get( i ) );
+ } catch ( IllegalArgumentException e ) {
+ throw new TransformationException( "Invalid vendor or device ID of the PCI device description!" );
+ }
+
+ // validate vendor ID
+ final int vendorId = deviceDescription.getVendorId();
+ if ( TransformationSpecificQemuGpuPassthroughNvidia.NVIDIA_PCI_VENDOR_ID != vendorId ) {
+ final String errorMsg = "Vendor ID '" + vendorId + "' of the PCI device is not from Nvidia!";
+ throw new TransformationException( errorMsg );
+ }
+
+ // parse PCI domain, PCI bus, PCI device and PCI function
+ final HostdevPciDeviceAddress parsedPciAddress = HostdevPciDeviceAddress.valueOf( pciIds.get( i + 1 ) );
+ if ( parsedPciAddress != null ) {
+ parsedPciAddresses.add( parsedPciAddress );
+ }
+ }
+ }
+
+ return parsedPciAddresses;
+ }
+
+ /**
+ * Validates a virtualization configuration and input arguments for this transformation.
+ *
+ * @param config virtualization configuration for the validation.
+ * @param args input arguments for the validation.
+ * @throws TransformationException validation has failed.
+ */
+ private void validateInputs( Domain config, CommandLineArgs args ) throws TransformationException
+ {
+ if ( config == null || args == null ) {
+ throw new TransformationException( "Virtualization configuration or input arguments are missing!" );
+ }
+
+ TransformationSpecificQemuGpuPassthroughNvidia.validateParseNvidiaPciIds( args.getVmNvGpuIds0() );
+ }
+
+ /**
+ * Queries and returns the capabilities of the Libvirt/QEMU hypervisor.
+ *
+ * @return capabilities of the Libvirt/QEMU hypervisor.
+ * @throws TransformationException failed to query and return the capabilities of the
+ * Libvirt/QEMU hypervisor.
+ */
+ protected Capabilities getCapabilities() throws TransformationException
+ {
+ Capabilities capabilities = null;
+
+ try {
+ capabilities = this.getVirtualizer().getCapabilites();
+ } catch ( LibvirtHypervisorException e ) {
+ final String errorMsg = new String(
+ "Failed to retrieve host capabilities from QEMU virtualizer: " + e.getLocalizedMessage() );
+ throw new TransformationException( errorMsg );
+ }
+
+ return capabilities;
+ }
+
+ private static BigInteger roundToNearestPowerOf2( BigInteger value )
+ {
+ BigInteger k = BigInteger.valueOf( 1 );
+
+ while ( k.compareTo( value ) == -1 ) {
+ k = k.multiply( BigInteger.valueOf( 2 ) );
+ }
+
+ return k;
+ }
+
+ /**
+ * Calculates the framebuffer memory size for the Looking Glass shared memory device.
+ *
+ * @return framebuffer memory size in bytes for the Looking Glass shared memory device.
+ */
+ private static BigInteger calculateFramebufferSize()
+ {
+ final long totalBytesFramebuffer = MAX_DISPLAY_WIDTH * MAX_DISPLAY_HEIGHT * 4 * 2;
+ final long totalBytesReserved = RESERVED_MEMORY_FRAMEBUFFER * 1048576;
+
+ // round sum of total memory in bytes to nearest power of two
+ return roundToNearestPowerOf2( BigInteger.valueOf( totalBytesFramebuffer + totalBytesReserved ) );
+ }
+
+ @Override
+ public void transform( Domain config, CommandLineArgs args ) throws TransformationException
+ {
+ // validate configuration and input arguments
+ this.validateInputs( config, args );
+
+ // check if passthrough of Nvidia GPU takes place
+ if ( args.isNvidiaGpuPassthroughEnabled() ) {
+ // validate submitted PCI IDs
+ final List<HostdevPciDeviceAddress> pciDeviceAddresses = TransformationSpecificQemuGpuPassthroughNvidia
+ .validateParseNvidiaPciIds( args.getVmNvGpuIds0() );
+
+ // check if IOMMU support is available on the host
+ if ( !this.getCapabilities().hasHostIommuSupport() ) {
+ final String errorMsg = "IOMMU support is not available on the hypervisor but required for GPU passthrough!";
+ throw new TransformationException( errorMsg );
+ }
+
+ // passthrough PCI devices of the GPU
+ for ( final HostdevPciDeviceAddress pciDeviceAddress : pciDeviceAddresses ) {
+ final HostdevPci pciDevice = config.addHostdevPciDevice();
+ pciDevice.setManaged( true );
+ pciDevice.setSource( pciDeviceAddress );
+ }
+
+ // add shared memory device for Looking Glass
+ final Shmem shmemDevice = config.addShmemDevice();
+ shmemDevice.setName( "looking-glass" );
+ shmemDevice.setModel( Shmem.Model.IVSHMEM_PLAIN );
+ shmemDevice.setSize( TransformationSpecificQemuGpuPassthroughNvidia.calculateFramebufferSize() );
+
+ // enable hypervisor shadowing to avoid error code 43 of Nvidia drivers in virtual machines
+ config.setFeatureHypervVendorIdValue( TransformationSpecificQemuGpuPassthroughNvidia.HYPERV_VENDOR_ID );
+ config.setFeatureHypervVendorIdState( true );
+ config.setFeatureKvmHiddenState( true );
+
+ // disable all software video devices by disable them
+ for ( Video videoDevice : config.getVideoDevices() ) {
+ videoDevice.disable();
+ }
+ }
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuSerialDevices.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuSerialDevices.java
new file mode 100644
index 00000000..30f60289
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuSerialDevices.java
@@ -0,0 +1,117 @@
+package org.openslx.runvirt.plugin.qemu.configuration;
+
+import java.util.ArrayList;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+import org.openslx.libvirt.domain.Domain;
+import org.openslx.libvirt.domain.device.Serial.Type;
+import org.openslx.libvirt.domain.device.Serial;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+import org.openslx.runvirt.plugin.qemu.virtualization.LibvirtHypervisorQemu;
+import org.openslx.virtualization.configuration.VirtualizationConfigurationQemuUtils;
+import org.openslx.virtualization.configuration.transformation.TransformationException;
+import org.openslx.virtualization.configuration.transformation.TransformationSpecific;
+
+/**
+ * Specific serial device transformation for Libvirt/QEMU virtualization configurations.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class TransformationSpecificQemuSerialDevices
+ extends TransformationSpecific<Domain, CommandLineArgs, LibvirtHypervisorQemu>
+{
+ /**
+ * Name of the configuration transformation.
+ */
+ private static final String NAME = "Serial devices";
+
+ /**
+ * Creates a new serial device transformation for Libvirt/QEMU virtualization configurations.
+ *
+ * @param hypervisor Libvirt/QEMU hypervisor.
+ */
+ public TransformationSpecificQemuSerialDevices( LibvirtHypervisorQemu hypervisor )
+ {
+ super( TransformationSpecificQemuSerialDevices.NAME, hypervisor );
+ }
+
+ /**
+ * Validates a virtualization configuration and input arguments for this transformation.
+ *
+ * @param config virtualization configuration for the validation.
+ * @param args input arguments for the validation.
+ * @throws TransformationException validation has failed.
+ */
+ private void validateInputs( Domain config, CommandLineArgs args ) throws TransformationException
+ {
+ if ( config == null || args == null ) {
+ throw new TransformationException( "Virtualization configuration or input arguments are missing!" );
+ }
+ }
+
+ /**
+ * Returns all serial devices from a virtualization configuration that link to a host system's
+ * serial device.
+ *
+ * @param config virtualization configuration.
+ * @return all serial devices that link to a host system's serial device.
+ */
+ private ArrayList<Serial> getSerialDevDevices( Domain config )
+ {
+ final ArrayList<Serial> devices = config.getSerialDevices();
+ final Predicate<Serial> byDeviceTypeDev = device -> device.getType() == Type.DEV;
+
+ return devices.stream().filter( byDeviceTypeDev ).collect( Collectors.toCollection( ArrayList::new ) );
+ }
+
+ /**
+ * Transforms a serial device in a virtualization configuration selected by its {@code index}.
+ *
+ * @param config virtualization configuration for the transformation.
+ * @param fileName path to the serial device file on the host system.
+ * @param index number of the serial device in the virtualization configuration that is selected.
+ * @throws TransformationException transformation has failed.
+ */
+ private void transformSerialDevice( Domain config, String fileName, int index ) throws TransformationException
+ {
+ final ArrayList<Serial> devices = this.getSerialDevDevices( config );
+ final Serial device = VirtualizationConfigurationQemuUtils.getArrayIndex( devices, index );
+
+ if ( device == null ) {
+ // check if device file name is specified
+ if ( fileName != null && !fileName.isEmpty() ) {
+ // serial port device is not available, so create new serial port device
+ final Serial newDevice = config.addSerialDevice();
+ newDevice.setType( Type.DEV );
+ newDevice.setSource( fileName );
+ }
+ } else {
+ if ( fileName == null || fileName.isEmpty() ) {
+ // remove serial port device if device file name is not set
+ device.remove();
+ } else {
+ // set type and source of existing serial port device
+ device.setType( Type.DEV );
+ device.setSource( fileName );
+ }
+ }
+ }
+
+ @Override
+ public void transform( Domain config, CommandLineArgs args ) throws TransformationException
+ {
+ // validate configuration and input arguments
+ this.validateInputs( config, args );
+
+ // alter serial device
+ this.transformSerialDevice( config, args.getVmDeviceSerial0(), 0 );
+
+ // remove all additional serial devices
+ final ArrayList<Serial> devices = this.getSerialDevDevices( config );
+ for ( int i = 1; i < devices.size(); i++ ) {
+ devices.get( i ).remove();
+ }
+ }
+}