From 150b2366f88788b1415e6c43f33043ef4df908cb Mon Sep 17 00:00:00 2001
From: Manuel Bentele
Date: Fri, 5 Feb 2021 09:17:43 +0100
Subject: [qemu] Add empty Maven project for 'qemu' runvirt plugin
---
.../org/openslx/runvirt/plugin/qemu/AppTest.java | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/AppTest.java
(limited to 'core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/AppTest.java')
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/AppTest.java b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/AppTest.java
new file mode 100644
index 00000000..90b658cd
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/AppTest.java
@@ -0,0 +1,20 @@
+package org.openslx.runvirt.plugin.qemu;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+
+/**
+ * Unit test for simple App.
+ */
+public class AppTest
+{
+ /**
+ * Rigorous Test :-)
+ */
+ @Test
+ public void shouldAnswerWithTrue()
+ {
+ assertTrue( true );
+ }
+}
--
cgit v1.2.3-55-g7522
From cdd849cc9a5c748627f7882974c9e3cb7e9457ba Mon Sep 17 00:00:00 2001
From: Manuel Bentele
Date: Thu, 11 Feb 2021 09:00:09 +0100
Subject: [qemu] Add command line argument parsing to 'qemu' runvirt plugin
---
.../vmchooser/plugins/qemu/run-virt.include | 5 +-
core/modules/qemu/runvirt-plugin-qemu/pom.xml | 17 +
.../java/org/openslx/runvirt/plugin/qemu/App.java | 113 +++++-
.../runvirt/plugin/qemu/cmdln/CommandLineArgs.java | 406 +++++++++++++++++++++
.../qemu/cmdln/CommandLineArgsException.java | 25 ++
.../org/openslx/runvirt/plugin/qemu/AppTest.java | 16 +-
6 files changed, 571 insertions(+), 11 deletions(-)
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/cmdln/CommandLineArgs.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/cmdln/CommandLineArgsException.java
(limited to 'core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/AppTest.java')
diff --git a/core/modules/qemu/data/opt/openslx/vmchooser/plugins/qemu/run-virt.include b/core/modules/qemu/data/opt/openslx/vmchooser/plugins/qemu/run-virt.include
index ee9d8e36..5b320bcc 100644
--- a/core/modules/qemu/data/opt/openslx/vmchooser/plugins/qemu/run-virt.include
+++ b/core/modules/qemu/data/opt/openslx/vmchooser/plugins/qemu/run-virt.include
@@ -32,13 +32,12 @@ run_plugin() {
isset VM_CLEANNAME && VIRTCMDOPTS+=( "-vmname" "${VM_CLEANNAME}" )
isset VM_DISPLAYNAME && VIRTCMDOPTS+=( "-vmdsplname" "${VM_DISPLAYNAME}" )
isset VM_OS_TYPE && VIRTCMDOPTS+=( "-vmos" "${VM_OS_TYPE}" )
- isset VM_RUN_FILE && VIRTCMDOPTS+=( "-vminpcfg" "${VM_RUN_FILE}" )
- isset vm_final_run_file && VIRTCMDOPTS+=( "-vmoutcfg" "${vm_final_run_file}" )
+ isset VM_RUN_FILE && VIRTCMDOPTS+=( "-vmcfginp" "${VM_RUN_FILE}" )
+ isset vm_final_run_file && VIRTCMDOPTS+=( "-vmcfgout" "${vm_final_run_file}" )
isset IMGUUID && VIRTCMDOPTS+=( "-vmuuid" "${IMGUUID}" )
isset CPU_CORES && VIRTCMDOPTS+=( "-vmncpus" "${CPU_CORES}" )
isset VM_MEM && VIRTCMDOPTS+=( "-vmmem" "${VM_MEM}" )
isset VM_MAC_ADDR && VIRTCMDOPTS+=( "-vmmac0" "${VM_MAC_ADDR}" )
- isset VM_ETH0_NETWORK && VIRTCMDOPTS+=( "-vmeth0" "${VM_ETH0_NETWORK}" )
isset VM_DISKFILE_RO && VIRTCMDOPTS+=( "-vmhdd0" "${VM_DISKFILE_RO}" )
isset FLOPPY_0 && VIRTCMDOPTS+=( "-vmfloppy0" "${FLOPPY_0}" )
isset SLX_FLOPPY_IMG && VIRTCMDOPTS+=( "-vmfloppy1" "${SLX_FLOPPY_IMG}" )
diff --git a/core/modules/qemu/runvirt-plugin-qemu/pom.xml b/core/modules/qemu/runvirt-plugin-qemu/pom.xml
index d4aace6e..45b8f1d5 100644
--- a/core/modules/qemu/runvirt-plugin-qemu/pom.xml
+++ b/core/modules/qemu/runvirt-plugin-qemu/pom.xml
@@ -30,6 +30,23 @@
5.7.1
test
+
+ commons-cli
+ commons-cli
+ 1.4
+
+
+ log4j
+ log4j
+ [1.2.10,1.2.20]
+ compile
+
+
+ org.slf4j
+ slf4j-log4j12
+ 1.7.25
+ compile
+
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/App.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/App.java
index ce6e7e12..fb72f18a 100644
--- a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/App.java
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/App.java
@@ -1,12 +1,121 @@
package org.openslx.runvirt.plugin.qemu;
+import org.apache.log4j.BasicConfigurator;
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs.CmdLnOption;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgsException;
+
/**
- * Hello world!
+ * Run-virt QEMU plugin (command line tool) to finalize a Libvirt domain XML configuration.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
*/
public class App
{
+ /**
+ * Stores name of the run-virt QEMU plugin (command line tool).
+ */
+ private static final String APP_NAME = "run-virt QEMU plugin";
+
+ /**
+ * Stores description of the run-virt QEMU plugin (command line tool).
+ */
+ private static final String APP_DESC = "Finalize a Libvirt VM (domain XML) configuration and manage the VM.";
+
+ /**
+ * Stores additional information for the run-virt QEMU plugin (command line tool).
+ */
+ private static final String APP_INFO = "The " + APP_NAME + " is part of the bwLehrpool infrastructure.";
+
+ /**
+ * Instance of a logger to log messages.
+ */
+ private static final Logger LOGGER = LogManager.getLogger( App.class );
+
+ /**
+ * Entry point of the run-virt QEMU plugin (command line tool).
+ *
+ * @param args command line arguments passed to the run-virt QEMU plugin (command line tool).
+ */
public static void main( String[] args )
{
- System.out.println( "Hello World!" );
+ // initialize logging
+ BasicConfigurator.configure();
+
+ // parse command line arguments
+ CommandLineArgs cmdLn = new CommandLineArgs();
+
+ try {
+ cmdLn.parseCmdLnArgs( args );
+ } catch ( CommandLineArgsException e ) {
+ LOGGER.error( "Parsing of command line arguments failed: " + e.getLocalizedMessage() );
+ App.printUsage( cmdLn );
+ System.exit( 1 );
+ }
+
+ // show help if 'help' command line option is set
+ if ( cmdLn.isHelpAquired() ) {
+ App.printUsage( cmdLn );
+ System.exit( 0 );
+ }
+
+ // print command line arguments for debugging purposes
+ App.printCmdLnArgs( cmdLn );
+ }
+
+ /**
+ * Helper utility to print the run-virt QEMU plugin help text.
+ *
+ * @param cmdLn parsed command line arguments.
+ */
+ public static void printUsage( CommandLineArgs cmdLn )
+ {
+ final String newLine = System.lineSeparator();
+ final String fullAppDesc = newLine + App.APP_DESC + newLine + newLine;
+ final String fullAppInfo = newLine + App.APP_INFO;
+
+ cmdLn.printHelp( App.APP_NAME, fullAppDesc, fullAppInfo );
+ }
+
+ /**
+ * Helper utility to log the run-virt QEMU plugin's submitted command line arguments.
+ *
+ * @param cmdLn parsed command line arguments.
+ *
+ * @implNote This method is intended to be used for debugging purposes.
+ */
+ public static void printCmdLnArgs( CommandLineArgs cmdLn )
+ {
+ // determine length of longest command line option
+ int longOptionLengthMax = 0;
+
+ for ( CmdLnOption option : CmdLnOption.values() ) {
+ // store length of current long option
+ final int longOptionLength = option.getLongOption().length();
+
+ // if length is longer than every length before, store this length as longest length
+ if ( longOptionLength > longOptionLengthMax ) {
+ longOptionLengthMax = longOptionLength;
+ }
+ }
+
+ LOGGER.debug( "Command line arguments: --------------" );
+
+ for ( CmdLnOption option : CmdLnOption.values() ) {
+ final String paddedLongOption = String.format( "%-" + longOptionLengthMax + "s", option.getLongOption() );
+ final String longOptionArgument;
+
+ // only request and log argument if option has an command line argument
+ if ( option.hasArgument() ) {
+ longOptionArgument = cmdLn.getArgument( option );
+ } else {
+ longOptionArgument = new String( "[option has no argument]" );
+ }
+
+ LOGGER.debug( "\t" + paddedLongOption + ": " + longOptionArgument );
+ }
}
}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/cmdln/CommandLineArgs.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/cmdln/CommandLineArgs.java
new file mode 100644
index 00000000..13b8c0e2
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/cmdln/CommandLineArgs.java
@@ -0,0 +1,406 @@
+package org.openslx.runvirt.plugin.qemu.cmdln;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.DefaultParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+
+/**
+ * Command line argument parser for the run-virt QEMU plugin (command line tool).
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class CommandLineArgs
+{
+ /**
+ * Parser for parsing command line arguments.
+ */
+ private CommandLineParser cmdLnParser = null;
+
+ /**
+ * Stores specified command line options.
+ */
+ private Options cmdLnOptions = null;
+
+ /**
+ * Stores the parsed command line arguments.
+ */
+ private CommandLine cmdLn = null;
+
+ /**
+ * Creates a new command line argument parser for the run-virt QEMU plugin.
+ *
+ * @implNote Please call {@link CommandLineArgs#parseCmdLnArgs(String[])} manually after
+ * obtaining the command line argument parser from this method.
+ */
+ public CommandLineArgs()
+ {
+ this.createCmdLnParser();
+ this.createCmdLnOptions();
+ }
+
+ /**
+ * Creates a new command line argument parser for the run-virt QEMU plugin and parses the command
+ * line arguments.
+ *
+ * @param args command line arguments submitted to the application.
+ *
+ * @throws CommandLineArgsException parsing of command line arguments failed.
+ */
+ public CommandLineArgs( String[] args ) throws CommandLineArgsException
+ {
+ this();
+ this.parseCmdLnArgs( args );
+ }
+
+ /**
+ * Creates a new parser and empty command line options for parsing command line arguments.
+ */
+ private void createCmdLnParser()
+ {
+ this.cmdLnParser = new DefaultParser();
+ this.cmdLnOptions = new Options();
+ }
+
+ /**
+ * Creates command line options specified by {@link CmdLnOption}.
+ */
+ private void createCmdLnOptions()
+ {
+ for ( CmdLnOption option : CmdLnOption.values() ) {
+ this.cmdLnOptions.addOption( option.getShortOption(), option.getLongOption(), option.hasArgument(),
+ option.getDescription() );
+ }
+ }
+
+ /**
+ * Prints command line help for the current application.
+ *
+ * @param appName name of the current application.
+ * @param header header for the command line help.
+ * @param footer footer for the command line help.
+ */
+ public void printHelp( String appName, String header, String footer )
+ {
+ HelpFormatter formatter = new HelpFormatter();
+ formatter.setLeftPadding( 2 );
+ formatter.printHelp( appName, header, this.cmdLnOptions, footer, true );
+ }
+
+ /**
+ * Parses command line arguments from a given argument {@link String}.
+ *
+ * @param args command line arguments submitted to the application.
+ *
+ * @throws CommandLineArgsException parsing of command line arguments failed.
+ */
+ public void parseCmdLnArgs( String[] args ) throws CommandLineArgsException
+ {
+ try {
+ this.cmdLn = this.cmdLnParser.parse( this.cmdLnOptions, args );
+ } catch ( ParseException e ) {
+ throw new CommandLineArgsException( e.getLocalizedMessage() );
+ }
+ }
+
+ /**
+ * Returns the parsed argument of the specified command line option.
+ *
+ * @param cmdLnOption command line option for that the parsed argument should be returned.
+ * @return parsed argument of the command line option.
+ */
+ public String getArgument( CmdLnOption cmdLnOption )
+ {
+ return this.cmdLn.getOptionValue( cmdLnOption.getShortOption() );
+ }
+
+ /**
+ * Returns the presence of the command line option {@link CmdLnOption#HELP}.
+ *
+ * @return presence of the command line option {@link CmdLnOption#HELP}.
+ */
+ public boolean isHelpAquired()
+ {
+ return this.cmdLn.hasOption( CmdLnOption.HELP.getShortOption() );
+ }
+
+ /**
+ * Returns the argument of the command line option {@link CmdLnOption#VM_CFGINP}.
+ *
+ * @return argument of the command line option {@link CmdLnOption#VM_CFGINP}.
+ */
+ public String getVmCfgInpFileName()
+ {
+ return this.getArgument( CmdLnOption.VM_CFGINP );
+ }
+
+ /**
+ * Returns the argument of the command line option {@link CmdLnOption#VM_CFGOUT}.
+ *
+ * @return argument of the command line option {@link CmdLnOption#VM_CFGOUT}.
+ */
+ public String getVmCfgOutFileName()
+ {
+ return this.getArgument( CmdLnOption.VM_CFGOUT );
+ }
+
+ /**
+ * Returns the argument of the command line option {@link CmdLnOption#VM_NAME}.
+ *
+ * @return argument of the command line option {@link CmdLnOption#VM_NAME}.
+ */
+ public String getVmName()
+ {
+ return this.getArgument( CmdLnOption.VM_NAME );
+ }
+
+ /**
+ * Returns the argument of the command line option {@link CmdLnOption#VM_UUID}.
+ *
+ * @return argument of the command line option {@link CmdLnOption#VM_UUID}.
+ */
+ public String getVmUuid()
+ {
+ return this.getArgument( CmdLnOption.VM_UUID );
+ }
+
+ /**
+ * Returns the argument of the command line option {@link CmdLnOption#VM_DSPLNAME}.
+ *
+ * @return argument of the command line option {@link CmdLnOption#VM_DSPLNAME}.
+ */
+ public String getVmDisplayName()
+ {
+ return this.getArgument( CmdLnOption.VM_DSPLNAME );
+ }
+
+ /**
+ * Returns the argument of the command line option {@link CmdLnOption#VM_OS}.
+ *
+ * @return argument of the command line option {@link CmdLnOption#VM_OS}.
+ */
+ public String getVmOperatingSystem()
+ {
+ return this.getArgument( CmdLnOption.VM_OS );
+ }
+
+ /**
+ * Returns the argument of the command line option {@link CmdLnOption#VM_NCPUS}.
+ *
+ * @return argument of the command line option {@link CmdLnOption#VM_NCPUS}.
+ */
+ public int getVmNumCpus()
+ {
+ final String numCpus = this.getArgument( CmdLnOption.VM_NCPUS );
+ return Integer.parseInt( numCpus );
+ }
+
+ /**
+ * Returns the argument of the command line option {@link CmdLnOption#VM_MEM}.
+ *
+ * @return argument of the command line option {@link CmdLnOption#VM_MEM}.
+ */
+ public String getVmMemory()
+ {
+ return this.getArgument( CmdLnOption.VM_MEM );
+ }
+
+ /**
+ * Returns the argument of the command line option {@link CmdLnOption#VM_HDD0}.
+ *
+ * @return argument of the command line option {@link CmdLnOption#VM_HDD0}.
+ */
+ public String getVmDiskFileNameHDD0()
+ {
+ return this.getArgument( CmdLnOption.VM_HDD0 );
+ }
+
+ /**
+ * Returns the argument of the command line option {@link CmdLnOption#VM_FLOPPY0}.
+ *
+ * @return argument of the command line option {@link CmdLnOption#VM_FLOPPY0}.
+ */
+ public String getVmDiskFileNameFloppy0()
+ {
+ return this.getArgument( CmdLnOption.VM_FLOPPY0 );
+ }
+
+ /**
+ * Returns the argument of the command line option {@link CmdLnOption#VM_FLOPPY1}.
+ *
+ * @return argument of the command line option {@link CmdLnOption#VM_FLOPPY1}.
+ */
+ public String getVmDiskFileNameFloppy1()
+ {
+ return this.getArgument( CmdLnOption.VM_FLOPPY1 );
+ }
+
+ /**
+ * Returns the argument of the command line option {@link CmdLnOption#VM_CDROM0}.
+ *
+ * @return argument of the command line option {@link CmdLnOption#VM_CDROM0}.
+ */
+ public String getVmDiskFileNameCdrom0()
+ {
+ return this.getArgument( CmdLnOption.VM_CDROM0 );
+ }
+
+ /**
+ * Returns the argument of the command line option {@link CmdLnOption#VM_CDROM1}.
+ *
+ * @return argument of the command line option {@link CmdLnOption#VM_CDROM1}.
+ */
+ public String getVmDiskFileNameCdrom1()
+ {
+ return this.getArgument( CmdLnOption.VM_CDROM1 );
+ }
+
+ /**
+ * Returns the argument of the command line option {@link CmdLnOption#VM_PARALLEL0}.
+ *
+ * @return argument of the command line option {@link CmdLnOption#VM_SERIAL0}.
+ */
+ public String getVmDeviceParallel0()
+ {
+ return this.getArgument( CmdLnOption.VM_PARALLEL0 );
+ }
+
+ /**
+ * Returns the argument of the command line option {@link CmdLnOption#VM_SERIAL0}.
+ *
+ * @return argument of the command line option {@link CmdLnOption#VM_SERIAL0}.
+ */
+ public String getVmDeviceSerial0()
+ {
+ return this.getArgument( CmdLnOption.VM_SERIAL0 );
+ }
+
+ /**
+ * Returns the argument of the command line option {@link CmdLnOption#VM_MAC0}.
+ *
+ * @return argument of the command line option {@link CmdLnOption#VM_MAC0}.
+ */
+ public String getVmMacAddress0()
+ {
+ return this.getArgument( CmdLnOption.VM_MAC0 );
+ }
+
+ /**
+ * Returns the argument of the command line option {@link CmdLnOption#VM_AUDIO0}.
+ *
+ * @return argument of the command line option {@link CmdLnOption#VM_AUDIO0}.
+ */
+ public String getVmModelSoundCard0()
+ {
+ return this.getArgument( CmdLnOption.VM_AUDIO0 );
+ }
+
+ /**
+ * Command line options for the run-virt QEMU plugin (command line tool).
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+ public enum CmdLnOption
+ {
+ // @formatter:off
+ HELP ( 'h', "help", false, "" ),
+ VM_CFGINP ( 'i', "vmcfginp", true, "File name of an existing and filtered Libvirt domain XML configuration file" ),
+ VM_CFGOUT ( 'o', "vmcfgout", true, "File name to output a finalized Libvirt domain XML configuration file" ),
+ VM_NAME ( 'n', "vmname", true, "Name for the virtual machine" ),
+ VM_UUID ( 'u', "vmuuid", true, "UUID for the virtual machine" ),
+ VM_DSPLNAME ( 'd', "vmdsplname", true, "Display name for the virtual machine" ),
+ VM_OS ( 's', "vmos", true, "Operating system running in the virtual machine" ),
+ VM_NCPUS ( 'c', "vmncpus", true, "Number of virtual CPUs for the virtual machine" ),
+ VM_MEM ( 'm', "vmmem", true, "Amount of memory for the virtual machine" ),
+ VM_HDD0 ( 'r', "vmhdd0", true, "Disk image for the first HDD device" ),
+ VM_FLOPPY0 ( 'f', "vmfloppy0", true, "Disk image for the first floppy drive" ),
+ VM_FLOPPY1 ( 'g', "vmfloppy1", true, "Disk image for the second floppy drive" ),
+ VM_CDROM0 ( 'k', "vmcdrom0", true, "Disk image for the first CDROM drive" ),
+ VM_CDROM1 ( 'l', "vmcdrom1", true, "Disk image for the second CDROM drive" ),
+ VM_PARALLEL0( 'p', "vmparallel0", true, "Device for the first parallel port interface" ),
+ VM_SERIAL0 ( 'q', "vmserial0", true, "Device for the first serial port interface" ),
+ VM_MAC0 ( 'a', "vmmac0", true, "MAC address for the first network interface" ),
+ VM_AUDIO0 ( 'x', "vmaudio0", true, "Hardware model for the first sound card" );
+ // @formatter:on
+
+ /**
+ * Stores the {@link Character} of the short command line option.
+ */
+ private final char shortOption;
+
+ /**
+ * Stores the {@link String} of the long command line option.
+ */
+ private final String longOption;
+
+ /**
+ * Stores the presence of an argument for the command line option.
+ */
+ private final boolean hasArgument;
+
+ /**
+ * Stores the textual description of the command line option.
+ */
+ private final String description;
+
+ /**
+ * Creates a new command line option for the run-virt QEMU plugin (command line tool).
+ *
+ * @param shortOption {@link Character} for the short command line option.
+ * @param longOption {@link String} for the long command line option.
+ * @param hasArgument presence of an argument for the command line option.
+ * @param description textual description of the command line option.
+ */
+ CmdLnOption( char shortOption, String longOption, boolean hasArgument, String description )
+ {
+ this.shortOption = shortOption;
+ this.longOption = longOption;
+ this.hasArgument = hasArgument;
+ this.description = description;
+ }
+
+ /**
+ * Returns the {@link Character} of the short command line option.
+ *
+ * @return {@link Character} of the short command line option.
+ */
+ public String getShortOption()
+ {
+ return Character.toString( this.shortOption );
+ }
+
+ /**
+ * Returns the {@link String} of the long command line option.
+ *
+ * @return {@link String} of the long command line option.
+ */
+ public String getLongOption()
+ {
+ return this.longOption;
+ }
+
+ /**
+ * Returns the presence of an argument for the command line option.
+ *
+ * @return presence of an argument for the command line option.
+ */
+ public boolean hasArgument()
+ {
+ return this.hasArgument;
+ }
+
+ /**
+ * Returns the textual description of the command line option.
+ *
+ * @return textual description of the command line option.
+ */
+ public String getDescription()
+ {
+ return this.description;
+ }
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/cmdln/CommandLineArgsException.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/cmdln/CommandLineArgsException.java
new file mode 100644
index 00000000..a327b813
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/cmdln/CommandLineArgsException.java
@@ -0,0 +1,25 @@
+package org.openslx.runvirt.plugin.qemu.cmdln;
+
+/**
+ * An exception during the parsing of command line arguments.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class CommandLineArgsException extends Exception
+{
+ /**
+ * Version number for serialization.
+ */
+ private static final long serialVersionUID = 8371924151602194406L;
+
+ /**
+ * Creates an command line argument parsing exception including an error message.
+ *
+ * @param errorMsg message to describe a specific parsing error.
+ */
+ public CommandLineArgsException( String errorMsg )
+ {
+ super( errorMsg );
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/AppTest.java b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/AppTest.java
index 90b658cd..110fb639 100644
--- a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/AppTest.java
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/AppTest.java
@@ -2,16 +2,20 @@ package org.openslx.runvirt.plugin.qemu;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import org.apache.log4j.Level;
+import org.apache.log4j.LogManager;
+import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
-/**
- * Unit test for simple App.
- */
public class AppTest
{
- /**
- * Rigorous Test :-)
- */
+ @BeforeAll
+ public static void setUp()
+ {
+ // disable logging with log4j
+ LogManager.getRootLogger().setLevel( Level.OFF );
+ }
+
@Test
public void shouldAnswerWithTrue()
{
--
cgit v1.2.3-55-g7522
From 0d48a4b54de060725e3337af5664e94ba4f1a3ae Mon Sep 17 00:00:00 2001
From: Manuel Bentele
Date: Fri, 12 Feb 2021 12:07:24 +0100
Subject: [qemu] Add unit tests for run-virt plugin's help option
---
core/modules/qemu/runvirt-plugin-qemu/pom.xml | 6 +
.../java/org/openslx/runvirt/plugin/qemu/App.java | 9 +-
.../org/openslx/runvirt/plugin/qemu/AppTest.java | 186 ++++++++++++++++++++-
3 files changed, 194 insertions(+), 7 deletions(-)
(limited to 'core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/AppTest.java')
diff --git a/core/modules/qemu/runvirt-plugin-qemu/pom.xml b/core/modules/qemu/runvirt-plugin-qemu/pom.xml
index 45b8f1d5..f744c4f3 100644
--- a/core/modules/qemu/runvirt-plugin-qemu/pom.xml
+++ b/core/modules/qemu/runvirt-plugin-qemu/pom.xml
@@ -47,6 +47,12 @@
1.7.25
compile
+
+ com.ginsberg
+ junit5-system-exit
+ 1.0.0
+ test
+
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/App.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/App.java
index fb72f18a..8a70be33 100644
--- a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/App.java
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/App.java
@@ -18,17 +18,17 @@ public class App
/**
* Stores name of the run-virt QEMU plugin (command line tool).
*/
- private static final String APP_NAME = "run-virt QEMU plugin";
+ public static final String APP_NAME = "run-virt QEMU plugin";
/**
* Stores description of the run-virt QEMU plugin (command line tool).
*/
- private static final String APP_DESC = "Finalize a Libvirt VM (domain XML) configuration and manage the VM.";
+ public static final String APP_DESC = "Finalize a Libvirt VM (domain XML) configuration and manage the VM.";
/**
* Stores additional information for the run-virt QEMU plugin (command line tool).
*/
- private static final String APP_INFO = "The " + APP_NAME + " is part of the bwLehrpool infrastructure.";
+ public static final String APP_INFO = "The " + APP_NAME + " is part of the bwLehrpool infrastructure.";
/**
* Instance of a logger to log messages.
@@ -64,6 +64,9 @@ public class App
// print command line arguments for debugging purposes
App.printCmdLnArgs( cmdLn );
+
+ // return with successful exit code
+ System.exit( 0 );
}
/**
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/AppTest.java b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/AppTest.java
index 110fb639..126fd26d 100644
--- a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/AppTest.java
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/AppTest.java
@@ -1,24 +1,202 @@
package org.openslx.runvirt.plugin.qemu;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+
import org.apache.log4j.Level;
import org.apache.log4j.LogManager;
import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs.CmdLnOption;
+
+import com.ginsberg.junit.exit.ExpectSystemExit;
+import com.ginsberg.junit.exit.ExpectSystemExitWithStatus;
public class AppTest
{
@BeforeAll
- public static void setUp()
+ private static void setUp()
{
// disable logging with log4j
LogManager.getRootLogger().setLevel( Level.OFF );
}
- @Test
- public void shouldAnswerWithTrue()
+ @Nested
+ public class CmdLnTest
{
- assertTrue( true );
+ private final ByteArrayOutputStream out = new ByteArrayOutputStream();
+ private final ByteArrayOutputStream err = new ByteArrayOutputStream();
+
+ private void setUp()
+ {
+ // redirect output and error stream content
+ System.setOut( new PrintStream( this.out ) );
+ System.setErr( new PrintStream( this.err ) );
+ }
+
+ @Test
+ @DisplayName( "Test ouput of correct 'help' command line option (short version)" )
+ @ExpectSystemExit
+ public void testCmdLnOptionHelpShortCorrect()
+ {
+ String[] argsShortHelpOptionCorrect = { "-" + CmdLnOption.HELP.getShortOption() };
+
+ this.setUp();
+
+ // test correct usage of the short help option
+ try {
+ App.main( argsShortHelpOptionCorrect );
+ } catch ( Exception e ) {
+ // do nothing and check output afterwards
+ }
+
+ final String shortHelpOptionCorrectOutput = new String( this.out.toString() );
+ final String shortHelpOptionCorrectErrOutput = new String( this.err.toString() );
+ assertTrue( shortHelpOptionCorrectOutput.contains( "usage" ) );
+ assertTrue( shortHelpOptionCorrectOutput.contains( App.APP_NAME ) );
+ assertTrue( shortHelpOptionCorrectOutput.contains( App.APP_INFO ) );
+ assertTrue( shortHelpOptionCorrectOutput.contains( App.APP_DESC ) );
+
+ // test that no error was logged and output is available
+ assertEquals( 1641, shortHelpOptionCorrectOutput.length() );
+ assertEquals( 0, shortHelpOptionCorrectErrOutput.length() );
+ }
+
+ @Test
+ @DisplayName( "Test ouput of correct 'help' command line option (long version)" )
+ @ExpectSystemExit
+ public void testCmdLnOptionHelpLongCorrect()
+ {
+ String[] argsLongHelpOptionCorrect = { "--" + CmdLnOption.HELP.getLongOption() };
+
+ this.setUp();
+
+ // test correct usage of the long help option
+ try {
+ App.main( argsLongHelpOptionCorrect );
+ } catch ( Exception e ) {
+ // do nothing and check output afterwards
+ }
+
+ final String longHelpOptionCorrectOutput = this.out.toString();
+ final String longHelpOptionCorrectErrOutput = this.err.toString();
+ assertTrue( longHelpOptionCorrectOutput.contains( "usage" ) );
+ assertTrue( longHelpOptionCorrectOutput.contains( App.APP_NAME ) );
+ assertTrue( longHelpOptionCorrectOutput.contains( App.APP_INFO ) );
+ assertTrue( longHelpOptionCorrectOutput.contains( App.APP_DESC ) );
+
+ // test that no error was logged and output is available
+ assertEquals( 1641, longHelpOptionCorrectOutput.length() );
+ assertEquals( 0, longHelpOptionCorrectErrOutput.length() );
+ }
+
+ @Test
+ @DisplayName( "Test ouput of incorrect 'help' command line option (short version)" )
+ @ExpectSystemExit
+ public void testCmdLnOptionHelpShortIncorrect()
+ {
+ String[] argsShortHelpOptionIncorrect = { "---" + CmdLnOption.HELP.getShortOption() };
+
+ this.setUp();
+
+ // test incorrect usage of the short help option
+ try {
+ App.main( argsShortHelpOptionIncorrect );
+ } catch ( Exception e ) {
+ // do nothing and check output afterwards
+ }
+
+ final String shortHelpOptionIncorrectOutput = this.out.toString();
+ final String shortHelpOptionIncorrectErrOutput = this.err.toString();
+ assertTrue( shortHelpOptionIncorrectOutput.contains( "usage" ) );
+ assertTrue( shortHelpOptionIncorrectOutput.contains( App.APP_NAME ) );
+ assertTrue( shortHelpOptionIncorrectOutput.contains( App.APP_INFO ) );
+ assertTrue( shortHelpOptionIncorrectOutput.contains( App.APP_DESC ) );
+
+ // test that error was logged and output is available
+ assertEquals( 1641, shortHelpOptionIncorrectOutput.length() );
+ assertEquals( 0, shortHelpOptionIncorrectErrOutput.length() );
+ }
+
+ @Test
+ @DisplayName( "Test ouput of incorrect 'help' command line option (long version)" )
+ @ExpectSystemExit
+ public void testCmdLnOptionHelpLongIncorrect()
+ {
+ String[] argsLongHelpOptionIncorrect = { "---" + CmdLnOption.HELP.getLongOption() };
+
+ this.setUp();
+
+ // test incorrect usage of the long help option
+ try {
+ App.main( argsLongHelpOptionIncorrect );
+ } catch ( Exception e ) {
+ // do nothing and check output afterwards
+ }
+
+ final String longHelpOptionIncorrectOutput = this.out.toString();
+ final String longHelpOptionIncorrectErrOutput = this.err.toString();
+ assertTrue( longHelpOptionIncorrectOutput.contains( "usage" ) );
+ assertTrue( longHelpOptionIncorrectOutput.contains( App.APP_NAME ) );
+ assertTrue( longHelpOptionIncorrectOutput.contains( App.APP_INFO ) );
+ assertTrue( longHelpOptionIncorrectOutput.contains( App.APP_DESC ) );
+
+ // test that error was logged and output is available
+ assertEquals( 1641, longHelpOptionIncorrectOutput.length() );
+ assertEquals( 0, longHelpOptionIncorrectErrOutput.length() );
+ }
+
+ @Test
+ @DisplayName( "Test exit status of application invoked with correct 'help' command line option (short version)" )
+ @ExpectSystemExitWithStatus( 0 )
+ public void testCmdLnOptionHelpShortCorrectExit()
+ {
+ String[] argsShortHelpOptionCorrect = { "-" + CmdLnOption.HELP.getShortOption() };
+
+ this.setUp();
+
+ App.main( argsShortHelpOptionCorrect );
+ }
+
+ @Test
+ @DisplayName( "Test exit status of application invoked with correct 'help' command line option (long version)" )
+ @ExpectSystemExitWithStatus( 0 )
+ public void testCmdLnOptionHelpLongCorrectExit()
+ {
+ String[] argsLongHelpOptionCorrect = { "--" + CmdLnOption.HELP.getLongOption() };
+
+ this.setUp();
+
+ App.main( argsLongHelpOptionCorrect );
+ }
+
+ @Test
+ @DisplayName( "Test exit status of application invoked with incorrect 'help' command line option (short version)" )
+ @ExpectSystemExitWithStatus( 1 )
+ public void testCmdLnOptionHelpShortIncorrectExit()
+ {
+ String[] argsShortHelpOptionCorrect = { "---" + CmdLnOption.HELP.getShortOption() };
+
+ this.setUp();
+
+ App.main( argsShortHelpOptionCorrect );
+ }
+
+ @Test
+ @DisplayName( "Test exit status of application invoked with incorrect 'help' command line option (long version)" )
+ @ExpectSystemExitWithStatus( 1 )
+ public void testCmdLnOptionHelpLongIncorrectExit()
+ {
+ String[] argsLongHelpOptionCorrect = { "---" + CmdLnOption.HELP.getLongOption() };
+
+ this.setUp();
+
+ App.main( argsLongHelpOptionCorrect );
+ }
}
}
--
cgit v1.2.3-55-g7522
From 24d4ebdce0a3c022c7ae7c90139235bb4c8dad67 Mon Sep 17 00:00:00 2001
From: Manuel Bentele
Date: Thu, 25 Mar 2021 11:25:18 +0100
Subject: [qemu] Add filtering/transformation of config files and VM management
---
.../vmchooser/plugins/qemu/run-virt.include | 7 +-
core/modules/qemu/runvirt-plugin-qemu/.gitignore | 17 +-
core/modules/qemu/runvirt-plugin-qemu/pom.xml | 8 +
.../org/openslx/runvirt/configuration/Filter.java | 28 +
.../runvirt/configuration/FilterException.java | 14 +
.../runvirt/configuration/FilterFunction.java | 12 +
.../runvirt/configuration/FilterGeneric.java | 9 +
.../runvirt/configuration/FilterManager.java | 80 ++
.../runvirt/configuration/FilterSpecific.java | 18 +
.../java/org/openslx/runvirt/plugin/qemu/App.java | 121 +++
.../runvirt/plugin/qemu/cmdln/CommandLineArgs.java | 43 +-
.../qemu/configuration/FilterGenericCpu.java | 26 +
.../FilterGenericDiskCdromDevices.java | 54 ++
.../FilterGenericDiskFloppyDevices.java | 50 ++
.../FilterGenericDiskStorageDevices.java | 49 +
.../FilterGenericFileSystemDevices.java | 64 ++
.../FilterGenericInterfaceDevices.java | 48 +
.../qemu/configuration/FilterGenericMemory.java | 28 +
.../qemu/configuration/FilterGenericName.java | 23 +
.../FilterGenericParallelDevices.java | 58 ++
.../qemu/configuration/FilterGenericUuid.java | 22 +
.../FilterSpecificQemuArchitecture.java | 199 +++++
.../FilterSpecificQemuNvidiaGpuPassthrough.java | 26 +
.../FilterSpecificQemuSerialDevices.java | 69 ++
.../qemu/virtualization/LibvirtHypervisorQemu.java | 39 +
.../runvirt/virtualization/LibvirtHypervisor.java | 99 +++
.../virtualization/LibvirtHypervisorException.java | 14 +
.../virtualization/LibvirtVirtualMachine.java | 81 ++
.../LibvirtVirtualMachineException.java | 14 +
.../org/openslx/runvirt/plugin/qemu/AppTest.java | 8 +-
.../plugin/qemu/cmdln/CommandLineArgsTest.java | 109 ++-
.../qemu/configuration/FilterGenericCpuTest.java | 34 +
.../FilterGenericDiskStorageDevicesTest.java | 61 ++
.../configuration/FilterGenericMemoryTest.java | 35 +
.../qemu/configuration/FilterGenericNameTest.java | 30 +
.../qemu/configuration/FilterGenericUuidTest.java | 28 +
.../qemu/configuration/FilterTestResources.java | 17 +
.../plugin/qemu/configuration/FilterTestUtils.java | 112 +++
.../libvirt/xml/qemu-kvm_capabilities_default.xml | 986 +++++++++++++++++++++
.../xml/qemu-kvm_default-ubuntu-20-04-vm.xml | 164 ++++
40 files changed, 2877 insertions(+), 27 deletions(-)
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/configuration/Filter.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/configuration/FilterException.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/configuration/FilterFunction.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/configuration/FilterGeneric.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/configuration/FilterManager.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/configuration/FilterSpecific.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericCpu.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericDiskCdromDevices.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericDiskFloppyDevices.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericDiskStorageDevices.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericFileSystemDevices.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericInterfaceDevices.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericMemory.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericName.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericParallelDevices.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericUuid.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterSpecificQemuArchitecture.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterSpecificQemuNvidiaGpuPassthrough.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterSpecificQemuSerialDevices.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/virtualization/LibvirtHypervisorQemu.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/virtualization/LibvirtHypervisor.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/virtualization/LibvirtHypervisorException.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/virtualization/LibvirtVirtualMachine.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/virtualization/LibvirtVirtualMachineException.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericCpuTest.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericDiskStorageDevicesTest.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericMemoryTest.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericNameTest.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericUuidTest.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/FilterTestResources.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/FilterTestUtils.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/test/resources/libvirt/xml/qemu-kvm_capabilities_default.xml
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/test/resources/libvirt/xml/qemu-kvm_default-ubuntu-20-04-vm.xml
(limited to 'core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/AppTest.java')
diff --git a/core/modules/qemu/data/opt/openslx/vmchooser/plugins/qemu/run-virt.include b/core/modules/qemu/data/opt/openslx/vmchooser/plugins/qemu/run-virt.include
index 5b320bcc..90a00c6e 100644
--- a/core/modules/qemu/data/opt/openslx/vmchooser/plugins/qemu/run-virt.include
+++ b/core/modules/qemu/data/opt/openslx/vmchooser/plugins/qemu/run-virt.include
@@ -19,7 +19,7 @@
declare -rg QEMU_PLUGIN_DIR="$(dirname "${BASH_SOURCE[0]}")"
declare -rg QEMU_INCLUDE_DIR="${QEMU_PLUGIN_DIR}/includes"
-# Define which features the VMware plugin supports
+# Define which features the QEMU plugin supports
declare -rg PLUGIN_FEATURES="firewall printer usb slxfloppy sound netshares"
run_plugin() {
@@ -45,5 +45,8 @@ run_plugin() {
isset CDROM_1 && VIRTCMDOPTS+=( "-vmcdrom1" "${CDROM_1}" )
isset SERIAL0 && VIRTCMDOPTS+=( "-vmserial0" "${SERIAL0}" )
isset PARALLEL0 && VIRTCMDOPTS+=( "-vmparallel0" "${PARALLEL0}" )
- isset SOUND_DEV && VIRTCMDOPTS+=( "-vmsound0" "${SOUND_DEV}" )
+ isset HOME_SHARE_PATH && VIRTCMDOPTS+=( "-vmfssrc0" "${HOME_SHARE_PATH}" )
+ isset HOME_SHARE_NAME && VIRTCMDOPTS+=( "-vmfstgt0" "${HOME_SHARE_NAME}" )
+ isset COMMON_SHARE_PATH && VIRTCMDOPTS+=( "-vmfssrc1" "${COMMON_SHARE_PATH}" )
+ isset COMMON_SHARE_NAME && VIRTCMDOPTS+=( "-vmfstgt1" "${COMMON_SHARE_NAME}" )
}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/.gitignore b/core/modules/qemu/runvirt-plugin-qemu/.gitignore
index 49b2bfee..6090294a 100644
--- a/core/modules/qemu/runvirt-plugin-qemu/.gitignore
+++ b/core/modules/qemu/runvirt-plugin-qemu/.gitignore
@@ -1,3 +1,14 @@
-/target/
-.classpath
-.settings/
+/testing
+/.settings
+/.project
+/.classpath
+/target
+/gen-java
+*~
+!src/
+!test/
+*.swp
+
+# Ignore IntelliJ Project Files
+/.idea
+*.iml
diff --git a/core/modules/qemu/runvirt-plugin-qemu/pom.xml b/core/modules/qemu/runvirt-plugin-qemu/pom.xml
index 27f33991..197f3df3 100644
--- a/core/modules/qemu/runvirt-plugin-qemu/pom.xml
+++ b/core/modules/qemu/runvirt-plugin-qemu/pom.xml
@@ -154,5 +154,13 @@
3.0.0
+
+
+ ${basedir}/src/test/resources
+
+ libvirt/xml/*
+
+
+
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/configuration/Filter.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/configuration/Filter.java
new file mode 100644
index 00000000..3fb594a2
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/configuration/Filter.java
@@ -0,0 +1,28 @@
+package org.openslx.runvirt.configuration;
+
+public abstract class Filter implements FilterFunction
+{
+ private final String name;
+ private boolean enabled;
+
+ public Filter( String name )
+ {
+ this.name = name;
+ this.setEnabled( true );
+ }
+
+ public String getName()
+ {
+ return this.name;
+ }
+
+ public boolean isEnabled()
+ {
+ return this.enabled;
+ }
+
+ public void setEnabled( boolean enabled )
+ {
+ this.enabled = enabled;
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/configuration/FilterException.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/configuration/FilterException.java
new file mode 100644
index 00000000..8969d1a2
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/configuration/FilterException.java
@@ -0,0 +1,14 @@
+package org.openslx.runvirt.configuration;
+
+public class FilterException extends Exception
+{
+ /**
+ * Version for serialization.
+ */
+ private static final long serialVersionUID = 7293420658901349154L;
+
+ public FilterException( String errorMsg )
+ {
+ super( errorMsg );
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/configuration/FilterFunction.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/configuration/FilterFunction.java
new file mode 100644
index 00000000..1d716201
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/configuration/FilterFunction.java
@@ -0,0 +1,12 @@
+package org.openslx.runvirt.configuration;
+
+@FunctionalInterface
+public interface FilterFunction
+{
+ public void filter( T config, R args ) throws FilterException;
+
+ public default void apply( T config, R args ) throws FilterException
+ {
+ this.filter( config, args );
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/configuration/FilterGeneric.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/configuration/FilterGeneric.java
new file mode 100644
index 00000000..e66c8f21
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/configuration/FilterGeneric.java
@@ -0,0 +1,9 @@
+package org.openslx.runvirt.configuration;
+
+public abstract class FilterGeneric extends Filter
+{
+ public FilterGeneric( String name )
+ {
+ super( name );
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/configuration/FilterManager.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/configuration/FilterManager.java
new file mode 100644
index 00000000..a97ad6d1
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/configuration/FilterManager.java
@@ -0,0 +1,80 @@
+package org.openslx.runvirt.configuration;
+
+import java.util.ArrayList;
+
+public final class FilterManager
+{
+ private ArrayList> filters;
+ private T config;
+ private R args;
+
+ public FilterManager( T config, R args )
+ {
+ this.filters = new ArrayList>();
+ this.config = config;
+ this.args = args;
+ }
+
+ public void register( Filter filter )
+ {
+ this.register( filter, true );
+ }
+
+ public void register( Filter filter, boolean enabled )
+ {
+ filter.setEnabled( enabled );
+ this.filters.add( filter );
+ }
+
+ public void register( String name, FilterFunction filterFunction )
+ {
+ this.register( name, filterFunction, true );
+ }
+
+ public void register( String name, FilterFunction filterFunction, boolean enabled )
+ {
+ final Filter filter = new Filter( name ) {
+ @Override
+ public void filter( T document, R args ) throws FilterException
+ {
+ filterFunction.apply( document, args );
+ }
+ };
+
+ filter.setEnabled( enabled );
+ this.filters.add( filter );
+ }
+
+ public void filterAll() throws FilterException
+ {
+ for ( Filter filter : this.filters ) {
+ try {
+ filter.apply( this.config, this.args );
+ } catch ( FilterException e ) {
+ final String errorMsg = new String(
+ "Error in configuration filter '" + filter.getName() + "':" + e.getLocalizedMessage() );
+ throw new FilterException( errorMsg );
+ }
+ }
+ }
+
+ private String showFilters()
+ {
+ String filterSummary = new String();
+ final int maxFilterNumCharacters = ( this.filters.size() + 1 ) / 10;
+
+ for ( int i = 0; i < this.filters.size(); i++ ) {
+ final Filter filter = this.filters.get( i );
+ final String paddedNumber = String.format( "%-" + maxFilterNumCharacters + "s", i + 1 );
+ filterSummary += paddedNumber + ": " + filter.getName() + System.lineSeparator();
+ }
+
+ return filterSummary;
+ }
+
+ @Override
+ public String toString()
+ {
+ return this.showFilters();
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/configuration/FilterSpecific.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/configuration/FilterSpecific.java
new file mode 100644
index 00000000..8cff83bd
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/configuration/FilterSpecific.java
@@ -0,0 +1,18 @@
+package org.openslx.runvirt.configuration;
+
+public abstract class FilterSpecific extends Filter
+{
+ private final H hypervisor;
+
+ public FilterSpecific( String name, H hypervisor )
+ {
+ super( name );
+
+ this.hypervisor = hypervisor;
+ }
+
+ public H getHypervisor()
+ {
+ return this.hypervisor;
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/App.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/App.java
index 8a70be33..bf76ebf2 100644
--- a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/App.java
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/App.java
@@ -1,11 +1,38 @@
package org.openslx.runvirt.plugin.qemu;
+import java.io.File;
+
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
+import org.openslx.libvirt.domain.Domain;
+import org.openslx.libvirt.xml.LibvirtXmlDocumentException;
+import org.openslx.libvirt.xml.LibvirtXmlSerializationException;
+import org.openslx.libvirt.xml.LibvirtXmlValidationException;
+import org.openslx.runvirt.configuration.FilterException;
+import org.openslx.runvirt.configuration.FilterManager;
import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs.CmdLnOption;
import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgsException;
+import org.openslx.runvirt.plugin.qemu.configuration.FilterGenericCpu;
+import org.openslx.runvirt.plugin.qemu.configuration.FilterGenericDiskCdromDevices;
+import org.openslx.runvirt.plugin.qemu.configuration.FilterGenericDiskFloppyDevices;
+import org.openslx.runvirt.plugin.qemu.configuration.FilterGenericDiskStorageDevices;
+import org.openslx.runvirt.plugin.qemu.configuration.FilterGenericFileSystemDevices;
+import org.openslx.runvirt.plugin.qemu.configuration.FilterGenericInterfaceDevices;
+import org.openslx.runvirt.plugin.qemu.configuration.FilterGenericMemory;
+import org.openslx.runvirt.plugin.qemu.configuration.FilterGenericName;
+import org.openslx.runvirt.plugin.qemu.configuration.FilterGenericParallelDevices;
+import org.openslx.runvirt.plugin.qemu.configuration.FilterSpecificQemuSerialDevices;
+import org.openslx.runvirt.plugin.qemu.configuration.FilterGenericUuid;
+import org.openslx.runvirt.plugin.qemu.configuration.FilterSpecificQemuArchitecture;
+import org.openslx.runvirt.plugin.qemu.configuration.FilterSpecificQemuNvidiaGpuPassthrough;
+import org.openslx.runvirt.plugin.qemu.virtualization.LibvirtHypervisorQemu;
+import org.openslx.runvirt.plugin.qemu.virtualization.LibvirtHypervisorQemu.QemuSessionType;
+import org.openslx.runvirt.virtualization.LibvirtHypervisor;
+import org.openslx.runvirt.virtualization.LibvirtHypervisorException;
+import org.openslx.runvirt.virtualization.LibvirtVirtualMachine;
+import org.openslx.runvirt.virtualization.LibvirtVirtualMachineException;
/**
* Run-virt QEMU plugin (command line tool) to finalize a Libvirt domain XML configuration.
@@ -65,6 +92,100 @@ public class App
// print command line arguments for debugging purposes
App.printCmdLnArgs( cmdLn );
+ // create connection to the QEMU hypervisor via Libvirt
+ LibvirtHypervisor hypervisor = null;
+ try {
+ hypervisor = new LibvirtHypervisorQemu( QemuSessionType.LOCAL_USER_SESSION );
+ } catch ( LibvirtHypervisorException e ) {
+ LOGGER.error( "Failed to connect to the QEMU virtualizer (Libvirt daemon): " + e.getLocalizedMessage() );
+ System.exit( 2 );
+ }
+
+ // read Libvirt XML domain configuration template
+ final String xmlInputFileName = cmdLn.getVmCfgInpFileName();
+ Domain config = null;
+ try {
+ final File xmlInputFile = new File( xmlInputFileName );
+ config = new Domain( xmlInputFile );
+ } catch ( LibvirtXmlDocumentException | LibvirtXmlSerializationException | LibvirtXmlValidationException e ) {
+ LOGGER.error( "Failed to read VM input configuration file: " + e.getLocalizedMessage() );
+ hypervisor.close();
+ System.exit( 3 );
+ }
+
+ // create filter manager to finalize VM configuration
+ final FilterManager filterManager;
+ filterManager = new FilterManager( config, cmdLn );
+
+ // register necessary filters to finalize configuration template
+ filterManager.register( new FilterGenericName(), true );
+ filterManager.register( new FilterGenericUuid(), true );
+ filterManager.register( new FilterGenericCpu(), true );
+ filterManager.register( new FilterGenericMemory(), true );
+ filterManager.register( new FilterGenericDiskStorageDevices(), true );
+ filterManager.register( new FilterGenericDiskCdromDevices(), true );
+ filterManager.register( new FilterGenericDiskFloppyDevices(), true );
+ filterManager.register( new FilterGenericInterfaceDevices(), true );
+ filterManager.register( new FilterGenericParallelDevices(), true );
+ filterManager.register( new FilterGenericFileSystemDevices(), true );
+
+ // register QEMU specific filters to finalize configuration template
+ if ( hypervisor instanceof LibvirtHypervisorQemu ) {
+ final LibvirtHypervisorQemu hypervisorQemu = LibvirtHypervisorQemu.class.cast( hypervisor );
+
+ filterManager.register( new FilterSpecificQemuArchitecture( hypervisorQemu ), true );
+ filterManager.register( new FilterSpecificQemuSerialDevices( hypervisorQemu ), true );
+ filterManager.register( new FilterSpecificQemuNvidiaGpuPassthrough( hypervisorQemu ), false );
+ }
+
+ // finalize Libvirt VM configuration template
+ try {
+ filterManager.filterAll();
+ } catch ( FilterException e ) {
+ LOGGER.error( "Failed to finalize VM configuration file: " + e.getLocalizedMessage() );
+ hypervisor.close();
+ System.exit( 4 );
+ }
+
+ // write finalized configuration to file if output file is specified
+ final String xmlOutputFileName = cmdLn.getVmCfgOutFileName();
+ if ( xmlOutputFileName != null && !xmlOutputFileName.isEmpty() ) {
+ try {
+ final File xmlOutputFile = new File( xmlOutputFileName );
+ config.toXml( xmlOutputFile );
+ } catch ( LibvirtXmlSerializationException e ) {
+ LOGGER.error( "Failed to write VM output configuration file: " + e.getLocalizedMessage() );
+ hypervisor.close();
+ System.exit( 5 );
+ }
+ }
+
+ // define QEMU VM from finalized configuration
+ LibvirtVirtualMachine vm = null;
+ try {
+ vm = hypervisor.registerVm( config );
+ } catch ( LibvirtHypervisorException e ) {
+ LOGGER.error( "Failed to define VM from configuration file: " + e.getLocalizedMessage() );
+ hypervisor.close();
+ System.exit( 6 );
+ }
+
+ try {
+ vm.start();
+ } catch ( LibvirtVirtualMachineException e ) {
+ LOGGER.error( "Failed to start defined VM: " + e.getLocalizedMessage() );
+ try {
+ hypervisor.deregisterVm( vm );
+ } catch ( LibvirtHypervisorException | LibvirtVirtualMachineException e1 ) {
+ LOGGER.error( "Failed to undefine VM: " + e.getLocalizedMessage() );
+ }
+ hypervisor.close();
+ System.exit( 7 );
+ }
+
+ // close connection and let VM be running
+ hypervisor.close();
+
// return with successful exit code
System.exit( 0 );
}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/cmdln/CommandLineArgs.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/cmdln/CommandLineArgs.java
index 13b8c0e2..7e1a7a22 100644
--- a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/cmdln/CommandLineArgs.java
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/cmdln/CommandLineArgs.java
@@ -289,13 +289,43 @@ public class CommandLineArgs
}
/**
- * Returns the argument of the command line option {@link CmdLnOption#VM_AUDIO0}.
+ * Returns the argument of the command line option {@link CmdLnOption#VM_FSSRC0}.
*
- * @return argument of the command line option {@link CmdLnOption#VM_AUDIO0}.
+ * @return argument of the command line option {@link CmdLnOption#VM_FSSRC0}.
*/
- public String getVmModelSoundCard0()
+ public String getVmFsSrc0()
{
- return this.getArgument( CmdLnOption.VM_AUDIO0 );
+ return this.getArgument( CmdLnOption.VM_FSSRC0 );
+ }
+
+ /**
+ * Returns the argument of the command line option {@link CmdLnOption#VM_FSTGT0}.
+ *
+ * @return argument of the command line option {@link CmdLnOption#VM_FSTGT0}.
+ */
+ public String getVmFsTgt0()
+ {
+ return this.getArgument( CmdLnOption.VM_FSTGT0 );
+ }
+
+ /**
+ * Returns the argument of the command line option {@link CmdLnOption#VM_FSSRC1}.
+ *
+ * @return argument of the command line option {@link CmdLnOption#VM_FSSRC1}.
+ */
+ public String getVmFsSrc1()
+ {
+ return this.getArgument( CmdLnOption.VM_FSSRC1 );
+ }
+
+ /**
+ * Returns the argument of the command line option {@link CmdLnOption#VM_FSTGT1}.
+ *
+ * @return argument of the command line option {@link CmdLnOption#VM_FSTGT1}.
+ */
+ public String getVmFsTgt1()
+ {
+ return this.getArgument( CmdLnOption.VM_FSTGT1 );
}
/**
@@ -324,7 +354,10 @@ public class CommandLineArgs
VM_PARALLEL0( 'p', "vmparallel0", true, "Device for the first parallel port interface" ),
VM_SERIAL0 ( 'q', "vmserial0", true, "Device for the first serial port interface" ),
VM_MAC0 ( 'a', "vmmac0", true, "MAC address for the first network interface" ),
- VM_AUDIO0 ( 'x', "vmaudio0", true, "Hardware model for the first sound card" );
+ VM_FSSRC0 ( 't', "vmfssrc0", true, "Source directory for first file system passthrough (shared folder)" ),
+ VM_FSTGT0 ( 'u', "vmfstgt0", true, "Target directory for first file system passthrough (shared folder)" ),
+ VM_FSSRC1 ( 'v', "vmfssrc1", true, "Source directory for second file system passthrough (shared folder)" ),
+ VM_FSTGT1 ( 'w', "vmfstgt1", true, "Target directory for second file system passthrough (shared folder)" );
// @formatter:on
/**
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericCpu.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericCpu.java
new file mode 100644
index 00000000..1fbcd568
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericCpu.java
@@ -0,0 +1,26 @@
+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.configuration.FilterException;
+import org.openslx.runvirt.configuration.FilterGeneric;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+
+public class FilterGenericCpu extends FilterGeneric
+{
+ private static final String FILTER_NAME = "CPU [number of cores, mode, ...]";
+
+ public FilterGenericCpu()
+ {
+ super( FilterGenericCpu.FILTER_NAME );
+ }
+
+ @Override
+ public void filter( Domain config, CommandLineArgs args ) throws FilterException
+ {
+ 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/FilterGenericDiskCdromDevices.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericDiskCdromDevices.java
new file mode 100644
index 00000000..a17f3a8b
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericDiskCdromDevices.java
@@ -0,0 +1,54 @@
+package org.openslx.runvirt.plugin.qemu.configuration;
+
+import java.util.ArrayList;
+
+import org.openslx.libvirt.domain.Domain;
+import org.openslx.libvirt.domain.device.Disk.StorageType;
+import org.openslx.libvirt.domain.device.DiskCdrom;
+import org.openslx.runvirt.configuration.FilterException;
+import org.openslx.runvirt.configuration.FilterGeneric;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+import org.openslx.vm.QemuMetaData;
+import org.openslx.vm.QemuMetaDataUtils;
+
+public class FilterGenericDiskCdromDevices extends FilterGeneric
+{
+ private static final String FILTER_NAME = "Disk CDROM devices";
+
+ public FilterGenericDiskCdromDevices()
+ {
+ super( FilterGenericDiskCdromDevices.FILTER_NAME );
+ }
+
+ private void filterDiskCdromDevice( Domain config, String fileName, int index ) throws FilterException
+ {
+ final ArrayList devices = config.getDiskCdromDevices();
+ final DiskCdrom disk = QemuMetaDataUtils.getArrayIndex( devices, index );
+
+ if ( disk != null ) {
+ if ( fileName == null ) {
+ // do not remove disk CDROM drive, but set local physical drive as input source
+ disk.setStorage( StorageType.BLOCK, QemuMetaData.CDROM_DEFAULT_PHYSICAL_DRIVE );
+ } else if ( fileName.equals( "" ) ) {
+ // 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 filter( Domain config, CommandLineArgs args ) throws FilterException
+ {
+ this.filterDiskCdromDevice( config, args.getVmDiskFileNameCdrom0(), 0 );
+ this.filterDiskCdromDevice( config, args.getVmDiskFileNameCdrom1(), 1 );
+
+ // remove all additional disk CDROM devices
+ final ArrayList 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/FilterGenericDiskFloppyDevices.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericDiskFloppyDevices.java
new file mode 100644
index 00000000..106e499e
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericDiskFloppyDevices.java
@@ -0,0 +1,50 @@
+package org.openslx.runvirt.plugin.qemu.configuration;
+
+import java.util.ArrayList;
+
+import org.openslx.libvirt.domain.Domain;
+import org.openslx.libvirt.domain.device.Disk.StorageType;
+import org.openslx.libvirt.domain.device.DiskFloppy;
+import org.openslx.runvirt.configuration.FilterException;
+import org.openslx.runvirt.configuration.FilterGeneric;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+import org.openslx.vm.QemuMetaDataUtils;
+
+public class FilterGenericDiskFloppyDevices extends FilterGeneric
+{
+ private static final String FILTER_NAME = "Disk floppy devices";
+
+ public FilterGenericDiskFloppyDevices()
+ {
+ super( FilterGenericDiskFloppyDevices.FILTER_NAME );
+ }
+
+ private void filterDiskFloppyDevice( Domain config, String fileName, int index ) throws FilterException
+ {
+ final ArrayList devices = config.getDiskFloppyDevices();
+ final DiskFloppy disk = QemuMetaDataUtils.getArrayIndex( devices, index );
+
+ if ( disk != null ) {
+ if ( fileName == null ) {
+ // remove disk floppy device if disk image file name is not set
+ disk.remove();
+ } else {
+ // set image file of disk storage if disk floppy device is available
+ disk.setStorage( StorageType.FILE, fileName );
+ }
+ }
+ }
+
+ @Override
+ public void filter( Domain config, CommandLineArgs args ) throws FilterException
+ {
+ this.filterDiskFloppyDevice( config, args.getVmDiskFileNameFloppy0(), 0 );
+ this.filterDiskFloppyDevice( config, args.getVmDiskFileNameFloppy1(), 1 );
+
+ // remove all additional disk storage devices
+ final ArrayList 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/FilterGenericDiskStorageDevices.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericDiskStorageDevices.java
new file mode 100644
index 00000000..0dcfddf9
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericDiskStorageDevices.java
@@ -0,0 +1,49 @@
+package org.openslx.runvirt.plugin.qemu.configuration;
+
+import java.util.ArrayList;
+
+import org.openslx.libvirt.domain.Domain;
+import org.openslx.libvirt.domain.device.Disk.StorageType;
+import org.openslx.libvirt.domain.device.DiskStorage;
+import org.openslx.runvirt.configuration.FilterException;
+import org.openslx.runvirt.configuration.FilterGeneric;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+import org.openslx.vm.QemuMetaDataUtils;
+
+public class FilterGenericDiskStorageDevices extends FilterGeneric
+{
+ private static final String FILTER_NAME = "Disk storage devices [HDD, SSD, ...]";
+
+ public FilterGenericDiskStorageDevices()
+ {
+ super( FilterGenericDiskStorageDevices.FILTER_NAME );
+ }
+
+ private void filterDiskStorageDevice( Domain config, String fileName, int index ) throws FilterException
+ {
+ final ArrayList devices = config.getDiskStorageDevices();
+ final DiskStorage disk = QemuMetaDataUtils.getArrayIndex( devices, index );
+
+ if ( disk != null ) {
+ if ( fileName == null ) {
+ // 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 filter( Domain config, CommandLineArgs args ) throws FilterException
+ {
+ this.filterDiskStorageDevice( config, args.getVmDiskFileNameHDD0(), 0 );
+
+ // remove all additional disk storage devices
+ final ArrayList 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/FilterGenericFileSystemDevices.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericFileSystemDevices.java
new file mode 100644
index 00000000..1d06474f
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericFileSystemDevices.java
@@ -0,0 +1,64 @@
+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.configuration.FilterException;
+import org.openslx.runvirt.configuration.FilterGeneric;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+import org.openslx.vm.QemuMetaDataUtils;
+
+public class FilterGenericFileSystemDevices extends FilterGeneric
+{
+ private static final String FILTER_NAME = "File system devices";
+
+ public FilterGenericFileSystemDevices()
+ {
+ super( FilterGenericFileSystemDevices.FILTER_NAME );
+ }
+
+ private void filterFileSystemDevice( Domain config, String source, String target, int index ) throws FilterException
+ {
+ final ArrayList devices = config.getFileSystemDevices();
+ final FileSystem fileSystem = QemuMetaDataUtils.getArrayIndex( devices, index );
+
+ if ( fileSystem == null ) {
+ // check if file system device source directory is specified
+ if ( source != null && target != null ) {
+ // 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 || target == null ) {
+ // 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 filter( Domain config, CommandLineArgs args ) throws FilterException
+ {
+ this.filterFileSystemDevice( config, args.getVmFsSrc0(), args.getVmFsTgt0(), 0 );
+ this.filterFileSystemDevice( config, args.getVmFsSrc1(), args.getVmFsTgt1(), 1 );
+
+ // remove all additional file system devices
+ final ArrayList devices = config.getFileSystemDevices();
+ 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/FilterGenericInterfaceDevices.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericInterfaceDevices.java
new file mode 100644
index 00000000..ea2782ba
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericInterfaceDevices.java
@@ -0,0 +1,48 @@
+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.runvirt.configuration.FilterException;
+import org.openslx.runvirt.configuration.FilterGeneric;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+import org.openslx.vm.QemuMetaDataUtils;
+
+public class FilterGenericInterfaceDevices extends FilterGeneric
+{
+ private static final String FILTER_NAME = "Network interface devices";
+
+ public FilterGenericInterfaceDevices()
+ {
+ super( FilterGenericInterfaceDevices.FILTER_NAME );
+ }
+
+ private void filterInterfaceDevice( Domain config, String macAddress, int index ) throws FilterException
+ {
+ final ArrayList devices = config.getInterfaceDevices();
+ final Interface device = QemuMetaDataUtils.getArrayIndex( devices, index );
+
+ if ( device != null ) {
+ if ( macAddress == null ) {
+ // 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 filter( Domain config, CommandLineArgs args ) throws FilterException
+ {
+ this.filterInterfaceDevice( config, args.getVmMacAddress0(), 0 );
+
+ // remove all additional disk storage devices
+ final ArrayList 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/FilterGenericMemory.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericMemory.java
new file mode 100644
index 00000000..d8d901d4
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericMemory.java
@@ -0,0 +1,28 @@
+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.configuration.FilterException;
+import org.openslx.runvirt.configuration.FilterGeneric;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+
+public class FilterGenericMemory extends FilterGeneric
+{
+ private static final String FILTER_NAME = "Memory [normal, current (balloning)]";
+
+ public FilterGenericMemory()
+ {
+ super( FilterGenericMemory.FILTER_NAME );
+ }
+
+ @Override
+ public void filter( Domain config, CommandLineArgs args ) throws FilterException
+ {
+ 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/FilterGenericName.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericName.java
new file mode 100644
index 00000000..00644b23
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericName.java
@@ -0,0 +1,23 @@
+package org.openslx.runvirt.plugin.qemu.configuration;
+
+import org.openslx.libvirt.domain.Domain;
+import org.openslx.runvirt.configuration.FilterException;
+import org.openslx.runvirt.configuration.FilterGeneric;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+
+public class FilterGenericName extends FilterGeneric
+{
+ private static final String FILTER_NAME = "Name [(display) name]";
+
+ public FilterGenericName()
+ {
+ super( FilterGenericName.FILTER_NAME );
+ }
+
+ @Override
+ public void filter( Domain config, CommandLineArgs args ) throws FilterException
+ {
+ 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/FilterGenericParallelDevices.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericParallelDevices.java
new file mode 100644
index 00000000..458f69cb
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericParallelDevices.java
@@ -0,0 +1,58 @@
+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.configuration.FilterException;
+import org.openslx.runvirt.configuration.FilterGeneric;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+import org.openslx.vm.QemuMetaDataUtils;
+
+public class FilterGenericParallelDevices extends FilterGeneric
+{
+ private static final String FILTER_NAME = "Parallel devices";
+
+ public FilterGenericParallelDevices()
+ {
+ super( FilterGenericParallelDevices.FILTER_NAME );
+ }
+
+ private void filterParallelDevice( Domain config, String fileName, int index ) throws FilterException
+ {
+ final ArrayList devices = config.getParallelDevices();
+ final Parallel device = QemuMetaDataUtils.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 ) {
+ // 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 filter( Domain config, CommandLineArgs args ) throws FilterException
+ {
+ this.filterParallelDevice( config, args.getVmDeviceSerial0(), 0 );
+
+ // remove all additional parallel devices
+ final ArrayList 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/FilterGenericUuid.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericUuid.java
new file mode 100644
index 00000000..f10a32b7
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericUuid.java
@@ -0,0 +1,22 @@
+package org.openslx.runvirt.plugin.qemu.configuration;
+
+import org.openslx.libvirt.domain.Domain;
+import org.openslx.runvirt.configuration.FilterException;
+import org.openslx.runvirt.configuration.FilterGeneric;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+
+public class FilterGenericUuid extends FilterGeneric
+{
+ private static final String FILTER_NAME = "UUID";
+
+ public FilterGenericUuid()
+ {
+ super( FilterGenericUuid.FILTER_NAME );
+ }
+
+ @Override
+ public void filter( Domain config, CommandLineArgs args ) throws FilterException
+ {
+ config.setUuid( args.getVmUuid() );
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterSpecificQemuArchitecture.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterSpecificQemuArchitecture.java
new file mode 100644
index 00000000..0466b5e9
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterSpecificQemuArchitecture.java
@@ -0,0 +1,199 @@
+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.configuration.FilterException;
+import org.openslx.runvirt.configuration.FilterSpecific;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+import org.openslx.runvirt.plugin.qemu.virtualization.LibvirtHypervisorQemu;
+import org.openslx.runvirt.virtualization.LibvirtHypervisorException;
+
+public class FilterSpecificQemuArchitecture extends FilterSpecific
+{
+ private static final String FILTER_NAME = "QEMU Architecture [CPU architecture, machine type, ...]";
+
+ // used as instance of an singelton, always use getCapabilities to retrieve caps instance
+ private Capabilities capabilities = null;
+
+ public FilterSpecificQemuArchitecture( LibvirtHypervisorQemu hypervisor )
+ {
+ super( FilterSpecificQemuArchitecture.FILTER_NAME, hypervisor );
+ }
+
+ private Capabilities getCapabilities() throws FilterException
+ {
+ // retrieve capabilities from QEMU hypervisor only once
+ if ( this.capabilities == null ) {
+ try {
+ this.capabilities = this.getHypervisor().getCapabilites();
+ } catch ( LibvirtHypervisorException e ) {
+ final String errorMsg = new String(
+ "Failed to get host capabilities from QEMU virtualizer: " + e.getLocalizedMessage() );
+ throw new FilterException( errorMsg );
+ }
+ }
+
+ return this.capabilities;
+ }
+
+ private Guest getTargetGuestFromArchName( String architectureName ) throws FilterException
+ {
+ final List 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;
+ }
+
+ private Machine getTargetMachineFromGuest( Guest guest, String machineName ) throws FilterException
+ {
+ final List 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;
+ }
+
+ private List getCanonicalNamesFromTargetMachines( Guest guest ) throws FilterException
+ {
+ final List machines = guest.getArchMachines();
+ final List canonicalNames = new ArrayList();
+
+ for ( Machine machine : machines ) {
+ final String canonicalName = machine.getCanonicalMachine();
+ if ( canonicalName != null ) {
+ canonicalNames.add( canonicalName );
+ }
+ }
+
+ return canonicalNames;
+ }
+
+ @Override
+ public void filter( Domain config, CommandLineArgs args ) throws FilterException
+ {
+ // 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 FilterException( errorMsg );
+ } else {
+ targetGuest = this.getTargetGuestFromArchName( sourceArchitectureName );
+ if ( targetGuest == null ) {
+ final String errorMsg = new String( "Source architecture is not supported by the virtualizer!" );
+ throw new FilterException( 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 FilterException( 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 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 FilterException( 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 FilterException( errorMsg );
+ } else {
+ if ( !sourceOsType.toString().equals( targetGuest.getOsType().toString() ) ) {
+ final String errorMsg = new String( "OS type is not supported by the virtualizer!" );
+ throw new FilterException( 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 FilterException( errorMsg );
+ } else {
+ final List 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 FilterException( 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 FilterException( errorMsg );
+ } else {
+ config.setDevicesEmulator( targetGuest.getArchEmulator() );
+ }
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterSpecificQemuNvidiaGpuPassthrough.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterSpecificQemuNvidiaGpuPassthrough.java
new file mode 100644
index 00000000..913eeb5a
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterSpecificQemuNvidiaGpuPassthrough.java
@@ -0,0 +1,26 @@
+package org.openslx.runvirt.plugin.qemu.configuration;
+
+import org.openslx.libvirt.domain.Domain;
+import org.openslx.runvirt.configuration.FilterException;
+import org.openslx.runvirt.configuration.FilterSpecific;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+import org.openslx.runvirt.plugin.qemu.virtualization.LibvirtHypervisorQemu;
+
+public class FilterSpecificQemuNvidiaGpuPassthrough extends FilterSpecific
+{
+ private static final String FILTER_NAME = "QEMU GPU passthrough [Nvidia]";
+
+ public FilterSpecificQemuNvidiaGpuPassthrough( LibvirtHypervisorQemu hypervisor )
+ {
+ super( FilterSpecificQemuNvidiaGpuPassthrough.FILTER_NAME, hypervisor );
+ }
+
+ @Override
+ public void filter( Domain config, CommandLineArgs args ) throws FilterException
+ {
+ // check if IOMMU support is available on the host
+
+ // TODO: implement Nvidia hypervisor shadowing
+ // call this filter at the end, since -> override of software graphics to 'none' necessary
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterSpecificQemuSerialDevices.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterSpecificQemuSerialDevices.java
new file mode 100644
index 00000000..258027b8
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/FilterSpecificQemuSerialDevices.java
@@ -0,0 +1,69 @@
+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.configuration.FilterException;
+import org.openslx.runvirt.configuration.FilterSpecific;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+import org.openslx.runvirt.plugin.qemu.virtualization.LibvirtHypervisorQemu;
+import org.openslx.vm.QemuMetaDataUtils;
+
+public class FilterSpecificQemuSerialDevices extends FilterSpecific
+{
+ private static final String FILTER_NAME = "Serial devices";
+
+ public FilterSpecificQemuSerialDevices( LibvirtHypervisorQemu hypervisor )
+ {
+ super( FilterSpecificQemuSerialDevices.FILTER_NAME, hypervisor );
+ }
+
+ private ArrayList getSerialDevDevices( Domain config )
+ {
+ final ArrayList devices = config.getSerialDevices();
+ final Predicate byDeviceTypeDev = device -> device.getType() == Type.DEV;
+
+ return devices.stream().filter( byDeviceTypeDev ).collect( Collectors.toCollection( ArrayList::new ) );
+ }
+
+ private void filterSerialDevice( Domain config, String fileName, int index ) throws FilterException
+ {
+ final ArrayList devices = this.getSerialDevDevices( config );
+ final Serial device = QemuMetaDataUtils.getArrayIndex( devices, index );
+
+ if ( device == null ) {
+ // check if device file name is specified
+ if ( fileName != null ) {
+ // 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 ) {
+ // 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 filter( Domain config, CommandLineArgs args ) throws FilterException
+ {
+ this.filterSerialDevice( config, args.getVmDeviceSerial0(), 0 );
+
+ // remove all additional serial devices
+ final ArrayList devices = this.getSerialDevDevices( config );
+ 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/virtualization/LibvirtHypervisorQemu.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/virtualization/LibvirtHypervisorQemu.java
new file mode 100644
index 00000000..260c3f4e
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/virtualization/LibvirtHypervisorQemu.java
@@ -0,0 +1,39 @@
+package org.openslx.runvirt.plugin.qemu.virtualization;
+
+import org.openslx.runvirt.virtualization.LibvirtHypervisor;
+import org.openslx.runvirt.virtualization.LibvirtHypervisorException;
+
+public class LibvirtHypervisorQemu extends LibvirtHypervisor
+{
+ public LibvirtHypervisorQemu( QemuSessionType type ) throws LibvirtHypervisorException
+ {
+ super( type.getConnectionUri() );
+ }
+
+ public enum QemuSessionType
+ {
+ // @formatter:off
+ LOCAL_SYSTEM_SESSION( "qemu:///system" ),
+ LOCAL_USER_SESSION ( "qemu:///session" );
+ // @formatter:on
+
+ private final String connectionUri;
+
+ QemuSessionType( String connectionUri )
+ {
+ this.connectionUri = connectionUri;
+ }
+
+ public String getConnectionUri()
+ {
+ return this.connectionUri;
+ }
+
+ // TODO:
+ // Implement capabilities -> get host architecture => decision whether to emulate or use KVM? -> change domain of XML
+ // fill in given HDD file, CDROM, ...
+ // GPU-Passthrough: patch XML with hypervisor disable bit, ..., to get Nvidia driver working
+ // Add hostdev für GPU passthrough -> add PCI ID arguments to cmdln parser
+ //
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/virtualization/LibvirtHypervisor.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/virtualization/LibvirtHypervisor.java
new file mode 100644
index 00000000..345900ab
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/virtualization/LibvirtHypervisor.java
@@ -0,0 +1,99 @@
+package org.openslx.runvirt.virtualization;
+
+import java.io.Closeable;
+
+import org.libvirt.Connect;
+import org.libvirt.LibvirtException;
+import org.openslx.libvirt.capabilities.Capabilities;
+import org.openslx.libvirt.xml.LibvirtXmlDocumentException;
+import org.openslx.libvirt.xml.LibvirtXmlSerializationException;
+import org.openslx.libvirt.xml.LibvirtXmlValidationException;
+
+public abstract class LibvirtHypervisor implements Closeable
+{
+ protected Connect hypervisor = null;
+
+ public LibvirtHypervisor( String connectionUri ) throws LibvirtHypervisorException
+ {
+ this.connect( connectionUri );
+ }
+
+ protected void connect( String connectionUri ) throws LibvirtHypervisorException
+ {
+ try {
+ this.hypervisor = new Connect( connectionUri );
+ } catch ( LibvirtException e ) {
+ throw new LibvirtHypervisorException( e.getLocalizedMessage() );
+ }
+ }
+
+ public Capabilities getCapabilites() throws LibvirtHypervisorException
+ {
+ Capabilities hypervisorCapabilities = null;
+
+ try {
+ final String hypervisorCapabilitiesString = this.hypervisor.getCapabilities();
+ hypervisorCapabilities = new Capabilities( hypervisorCapabilitiesString );
+ } catch ( LibvirtException | LibvirtXmlDocumentException | LibvirtXmlSerializationException
+ | LibvirtXmlValidationException e ) {
+ throw new LibvirtHypervisorException( e.getLocalizedMessage() );
+ }
+
+ return hypervisorCapabilities;
+ }
+
+ public int getVersion() throws LibvirtHypervisorException
+ {
+ int hypervisorVersion = 0;
+
+ try {
+ final long hypervisorVersionLong = this.hypervisor.getVersion();
+ hypervisorVersion = Long.valueOf( hypervisorVersionLong ).intValue();
+ } catch ( LibvirtException e ) {
+ throw new LibvirtHypervisorException( e.getLocalizedMessage() );
+ }
+
+ return hypervisorVersion;
+ }
+
+ public LibvirtVirtualMachine registerVm( org.openslx.libvirt.domain.Domain vmConfiguration )
+ throws LibvirtHypervisorException
+ {
+ final String xmlVmConfiguration = vmConfiguration.toString();
+ org.libvirt.Domain libvirtDomain = null;
+
+ try {
+ libvirtDomain = this.hypervisor.domainDefineXML( xmlVmConfiguration );
+ } catch ( LibvirtException e ) {
+ throw new LibvirtHypervisorException( e.getLocalizedMessage() );
+ }
+
+ return new LibvirtVirtualMachine( libvirtDomain );
+ }
+
+ public void deregisterVm( LibvirtVirtualMachine vm )
+ throws LibvirtHypervisorException, LibvirtVirtualMachineException
+ {
+ // stop virtual machine if machine is running
+ if ( vm.isRunning() ) {
+ vm.stop();
+ }
+
+ // deregister and remove virtual machine from hypervisor
+ try {
+ vm.getLibvirtDomain().undefine();
+ } catch ( LibvirtException e ) {
+ throw new LibvirtHypervisorException( e.getLocalizedMessage() );
+ }
+ }
+
+ @Override
+ public void close()
+ {
+ try {
+ this.hypervisor.close();
+ } catch ( LibvirtException e ) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/virtualization/LibvirtHypervisorException.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/virtualization/LibvirtHypervisorException.java
new file mode 100644
index 00000000..acf640e1
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/virtualization/LibvirtHypervisorException.java
@@ -0,0 +1,14 @@
+package org.openslx.runvirt.virtualization;
+
+public class LibvirtHypervisorException extends Exception
+{
+ /**
+ * Version for serialization.
+ */
+ private static final long serialVersionUID = -3631452625806770209L;
+
+ LibvirtHypervisorException( String errorMsg )
+ {
+ super( errorMsg );
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/virtualization/LibvirtVirtualMachine.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/virtualization/LibvirtVirtualMachine.java
new file mode 100644
index 00000000..781bd938
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/virtualization/LibvirtVirtualMachine.java
@@ -0,0 +1,81 @@
+package org.openslx.runvirt.virtualization;
+
+import org.libvirt.Domain;
+import org.libvirt.LibvirtException;
+
+public class LibvirtVirtualMachine
+{
+ private Domain domain;
+
+ LibvirtVirtualMachine( Domain vm )
+ {
+ this.domain = vm;
+ }
+
+ public Domain getLibvirtDomain()
+ {
+ return this.domain;
+ }
+
+ public boolean isRunning() throws LibvirtVirtualMachineException
+ {
+ int state = 0;
+
+ try {
+ state = this.domain.isActive();
+ } catch ( LibvirtException e ) {
+ throw new LibvirtVirtualMachineException( e.getLocalizedMessage() );
+ }
+
+ return ( state == 0 ) ? false : true;
+ }
+
+ public void start() throws LibvirtVirtualMachineException
+ {
+ if ( !this.isRunning() ) {
+ try {
+ this.domain.create();
+ } catch ( LibvirtException e ) {
+ throw new LibvirtVirtualMachineException( e.getLocalizedMessage() );
+ }
+ }
+ }
+
+ public void stop() throws LibvirtVirtualMachineException
+ {
+ if ( this.isRunning() ) {
+ try {
+ this.domain.shutdown();
+ } catch ( LibvirtException e ) {
+ throw new LibvirtVirtualMachineException( e.getLocalizedMessage() );
+ }
+ }
+ }
+
+ public void suspend() throws LibvirtVirtualMachineException
+ {
+ try {
+ this.domain.suspend();
+ } catch ( LibvirtException e ) {
+ throw new LibvirtVirtualMachineException( e.getLocalizedMessage() );
+ }
+ }
+
+ public void resume() throws LibvirtVirtualMachineException
+ {
+ try {
+ this.domain.resume();
+ } catch ( LibvirtException e ) {
+ throw new LibvirtVirtualMachineException( e.getLocalizedMessage() );
+ }
+ }
+
+ public void reboot() throws LibvirtVirtualMachineException
+ {
+ try {
+ this.domain.reboot( 0 );
+ } catch ( LibvirtException e ) {
+ throw new LibvirtVirtualMachineException( e.getLocalizedMessage() );
+ }
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/virtualization/LibvirtVirtualMachineException.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/virtualization/LibvirtVirtualMachineException.java
new file mode 100644
index 00000000..4e8ee1ba
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/virtualization/LibvirtVirtualMachineException.java
@@ -0,0 +1,14 @@
+package org.openslx.runvirt.virtualization;
+
+public class LibvirtVirtualMachineException extends Exception
+{
+ /**
+ * Version for serialization.
+ */
+ private static final long serialVersionUID = -5371327391243047616L;
+
+ public LibvirtVirtualMachineException( String errorMsg )
+ {
+ super( errorMsg );
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/AppTest.java b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/AppTest.java
index 126fd26d..9f8f925f 100644
--- a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/AppTest.java
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/AppTest.java
@@ -63,7 +63,7 @@ public class AppTest
assertTrue( shortHelpOptionCorrectOutput.contains( App.APP_DESC ) );
// test that no error was logged and output is available
- assertEquals( 1641, shortHelpOptionCorrectOutput.length() );
+ assertEquals( 2026, shortHelpOptionCorrectOutput.length() );
assertEquals( 0, shortHelpOptionCorrectErrOutput.length() );
}
@@ -91,7 +91,7 @@ public class AppTest
assertTrue( longHelpOptionCorrectOutput.contains( App.APP_DESC ) );
// test that no error was logged and output is available
- assertEquals( 1641, longHelpOptionCorrectOutput.length() );
+ assertEquals( 2026, longHelpOptionCorrectOutput.length() );
assertEquals( 0, longHelpOptionCorrectErrOutput.length() );
}
@@ -119,7 +119,7 @@ public class AppTest
assertTrue( shortHelpOptionIncorrectOutput.contains( App.APP_DESC ) );
// test that error was logged and output is available
- assertEquals( 1641, shortHelpOptionIncorrectOutput.length() );
+ assertEquals( 2026, shortHelpOptionIncorrectOutput.length() );
assertEquals( 0, shortHelpOptionIncorrectErrOutput.length() );
}
@@ -147,7 +147,7 @@ public class AppTest
assertTrue( longHelpOptionIncorrectOutput.contains( App.APP_DESC ) );
// test that error was logged and output is available
- assertEquals( 1641, longHelpOptionIncorrectOutput.length() );
+ assertEquals( 2026, longHelpOptionIncorrectOutput.length() );
assertEquals( 0, longHelpOptionIncorrectErrOutput.length() );
}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/cmdln/CommandLineArgsTest.java b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/cmdln/CommandLineArgsTest.java
index 1399f9a4..ee3e0d1d 100644
--- a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/cmdln/CommandLineArgsTest.java
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/cmdln/CommandLineArgsTest.java
@@ -13,8 +13,8 @@ import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs.CmdLnOption;
public class CommandLineArgsTest
{
// @formatter:off
- private static final String CMDLN_PREFIX_OPTION_SHORT = "-";
- private static final String CMDLN_PREFIX_OPTION_LONG = "--";
+ public static final String CMDLN_PREFIX_OPTION_SHORT = "-";
+ public static final String CMDLN_PREFIX_OPTION_LONG = "--";
private static final String CMDLN_TEST_NAME = "test";
private static final String CMDLN_TEST_FILENAME = System.getProperty( "user.dir" ) + File.separator + CMDLN_TEST_NAME;
@@ -25,7 +25,6 @@ public class CommandLineArgsTest
private static final String CMDLN_TEST_PARPORT = "/dev/parport0";
private static final String CMDLN_TEST_SERPORT = "/dev/ttyS0";
private static final String CMDLN_TEST_MAC = "02:42:8e:77:1b:e6";
- private static final String CMDLN_TEST_AUDIO_MODEL = "sb16";
// @formatter:on
@Test
@@ -519,30 +518,114 @@ public class CommandLineArgsTest
}
@Test
- @DisplayName( "Test the parsing of the VM first sound card type command line option (short version)" )
- public void testCmdlnOptionVmAudio0Short() throws CommandLineArgsException
+ @DisplayName( "Test the parsing of the VM first file system source command line option (short version)" )
+ public void testCmdlnOptionVmFsSrc0Short() throws CommandLineArgsException
{
final String[] args = {
- CMDLN_PREFIX_OPTION_SHORT + CmdLnOption.VM_AUDIO0.getShortOption(),
- CMDLN_TEST_AUDIO_MODEL
+ CMDLN_PREFIX_OPTION_SHORT + CmdLnOption.VM_FSSRC0.getShortOption(),
+ CMDLN_TEST_FILENAME
+ };
+
+ CommandLineArgs cmdLn = new CommandLineArgs( args );
+
+ assertEquals( CMDLN_TEST_FILENAME, cmdLn.getVmFsSrc0() );
+ }
+
+ @Test
+ @DisplayName( "Test the parsing of the VM first file system source command line option (long version)" )
+ public void testCmdlnOptionVmFsSrc0Long() throws CommandLineArgsException
+ {
+ final String[] args = {
+ CMDLN_PREFIX_OPTION_LONG + CmdLnOption.VM_FSSRC0.getLongOption(),
+ CMDLN_TEST_FILENAME
+ };
+
+ CommandLineArgs cmdLn = new CommandLineArgs( args );
+
+ assertEquals( CMDLN_TEST_FILENAME, cmdLn.getVmFsSrc0() );
+ }
+
+ @Test
+ @DisplayName( "Test the parsing of the VM first file system target command line option (short version)" )
+ public void testCmdlnOptionVmFsTgt0Short() throws CommandLineArgsException
+ {
+ final String[] args = {
+ CMDLN_PREFIX_OPTION_SHORT + CmdLnOption.VM_FSTGT0.getShortOption(),
+ CMDLN_TEST_NAME
+ };
+
+ CommandLineArgs cmdLn = new CommandLineArgs( args );
+
+ assertEquals( CMDLN_TEST_NAME, cmdLn.getVmFsTgt0() );
+ }
+
+ @Test
+ @DisplayName( "Test the parsing of the VM first file system target command line option (long version)" )
+ public void testCmdlnOptionVmFsTgt0Long() throws CommandLineArgsException
+ {
+ final String[] args = {
+ CMDLN_PREFIX_OPTION_LONG + CmdLnOption.VM_FSTGT0.getLongOption(),
+ CMDLN_TEST_NAME
};
CommandLineArgs cmdLn = new CommandLineArgs( args );
- assertEquals( CMDLN_TEST_AUDIO_MODEL, cmdLn.getVmModelSoundCard0() );
+ assertEquals( CMDLN_TEST_NAME, cmdLn.getVmFsTgt0() );
}
@Test
- @DisplayName( "Test the parsing of the VM first sound card type command line option (long version)" )
- public void testCmdlnOptionVmAudio0Long() throws CommandLineArgsException
+ @DisplayName( "Test the parsing of the VM second file system source command line option (short version)" )
+ public void testCmdlnOptionVmFsSrc1Short() throws CommandLineArgsException
{
final String[] args = {
- CMDLN_PREFIX_OPTION_LONG + CmdLnOption.VM_AUDIO0.getLongOption(),
- CMDLN_TEST_AUDIO_MODEL
+ CMDLN_PREFIX_OPTION_SHORT + CmdLnOption.VM_FSSRC1.getShortOption(),
+ CMDLN_TEST_FILENAME
+ };
+
+ CommandLineArgs cmdLn = new CommandLineArgs( args );
+
+ assertEquals( CMDLN_TEST_FILENAME, cmdLn.getVmFsSrc1() );
+ }
+
+ @Test
+ @DisplayName( "Test the parsing of the VM second file system source command line option (long version)" )
+ public void testCmdlnOptionVmFsSrc1Long() throws CommandLineArgsException
+ {
+ final String[] args = {
+ CMDLN_PREFIX_OPTION_LONG + CmdLnOption.VM_FSSRC1.getLongOption(),
+ CMDLN_TEST_FILENAME
+ };
+
+ CommandLineArgs cmdLn = new CommandLineArgs( args );
+
+ assertEquals( CMDLN_TEST_FILENAME, cmdLn.getVmFsSrc1() );
+ }
+
+ @Test
+ @DisplayName( "Test the parsing of the VM second file system target command line option (short version)" )
+ public void testCmdlnOptionVmFsTgt1Short() throws CommandLineArgsException
+ {
+ final String[] args = {
+ CMDLN_PREFIX_OPTION_SHORT + CmdLnOption.VM_FSTGT1.getShortOption(),
+ CMDLN_TEST_NAME
+ };
+
+ CommandLineArgs cmdLn = new CommandLineArgs( args );
+
+ assertEquals( CMDLN_TEST_NAME, cmdLn.getVmFsTgt1() );
+ }
+
+ @Test
+ @DisplayName( "Test the parsing of the VM second file system target command line option (long version)" )
+ public void testCmdlnOptionVmFsTgt1Long() throws CommandLineArgsException
+ {
+ final String[] args = {
+ CMDLN_PREFIX_OPTION_LONG + CmdLnOption.VM_FSTGT1.getLongOption(),
+ CMDLN_TEST_NAME
};
CommandLineArgs cmdLn = new CommandLineArgs( args );
- assertEquals( CMDLN_TEST_AUDIO_MODEL, cmdLn.getVmModelSoundCard0() );
+ assertEquals( CMDLN_TEST_NAME, cmdLn.getVmFsTgt1() );
}
}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericCpuTest.java b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericCpuTest.java
new file mode 100644
index 00000000..3814bfb6
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericCpuTest.java
@@ -0,0 +1,34 @@
+package org.openslx.runvirt.plugin.qemu.configuration;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.openslx.libvirt.domain.Domain;
+import org.openslx.libvirt.domain.Domain.CpuCheck;
+import org.openslx.libvirt.domain.Domain.CpuMode;
+import org.openslx.runvirt.configuration.FilterException;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+
+public class FilterGenericCpuTest
+{
+ @Test
+ @DisplayName( "Test filtering of VM CPU configuration" )
+ public void testFilterGenericCpu() throws FilterException
+ {
+ final FilterGenericCpu filter = new FilterGenericCpu();
+ final Domain config = FilterTestUtils.getDefaultDomain();
+ final CommandLineArgs args = FilterTestUtils.getDefaultCmdLnArgs();
+
+ assertNotEquals( Integer.parseInt( FilterTestUtils.DEFAULT_VM_NCPUS ), config.getVCpu() );
+ assertNotEquals( CpuMode.HOST_PASSTHROUGH, config.getCpuMode() );
+ assertEquals( CpuCheck.PARTIAL, config.getCpuCheck() );
+
+ filter.filter( config, args );
+
+ assertEquals( Integer.parseInt( FilterTestUtils.DEFAULT_VM_NCPUS ), config.getVCpu() );
+ assertEquals( CpuMode.HOST_PASSTHROUGH, config.getCpuMode() );
+ assertEquals( CpuCheck.PARTIAL, config.getCpuCheck() );
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericDiskStorageDevicesTest.java b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericDiskStorageDevicesTest.java
new file mode 100644
index 00000000..93282e78
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericDiskStorageDevicesTest.java
@@ -0,0 +1,61 @@
+package org.openslx.runvirt.plugin.qemu.configuration;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+
+import java.util.ArrayList;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.openslx.libvirt.domain.Domain;
+import org.openslx.libvirt.domain.device.Disk.StorageType;
+import org.openslx.libvirt.domain.device.DiskStorage;
+import org.openslx.runvirt.configuration.FilterException;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+
+public class FilterGenericDiskStorageDevicesTest
+{
+ @Test
+ @DisplayName( "Test filtering of VM disk storage devices configuration with specified input data" )
+ public void testFilterGenericDiskStorageDevices() throws FilterException
+ {
+ final FilterGenericDiskStorageDevices filter = new FilterGenericDiskStorageDevices();
+ final Domain config = FilterTestUtils.getDefaultDomain();
+ final CommandLineArgs args = FilterTestUtils.getDefaultCmdLnArgs();
+
+ final ArrayList devicesBeforeFiltering = config.getDiskStorageDevices();
+ assertEquals( 1, devicesBeforeFiltering.size() );
+ assertNotEquals( StorageType.FILE, devicesBeforeFiltering.get( 0 ).getStorageType() );
+ assertNotEquals( FilterTestUtils.DEFAULT_VM_HDD0, devicesBeforeFiltering.get( 0 ).getStorageSource() );
+
+ filter.filter( config, args );
+
+ final ArrayList devicesAfterFiltering = config.getDiskStorageDevices();
+ assertEquals( 1, devicesAfterFiltering.size() );
+ assertEquals( StorageType.FILE, devicesAfterFiltering.get( 0 ).getStorageType() );
+ assertEquals( FilterTestUtils.DEFAULT_VM_HDD0, devicesAfterFiltering.get( 0 ).getStorageSource() );
+ }
+
+ @Test
+ @DisplayName( "Test filtering of VM disk storage devices configuration with unspecified input data" )
+ public void testFilterGenericDiskStorageDevicesNoData() throws FilterException
+ {
+ final FilterGenericDiskStorageDevices filter = new FilterGenericDiskStorageDevices();
+ final Domain config = FilterTestUtils.getDefaultDomain();
+ final CommandLineArgs args = FilterTestUtils.getEmptyCmdLnArgs();
+
+ final ArrayList devicesBeforeFiltering = config.getDiskStorageDevices();
+ assertEquals( 1, devicesBeforeFiltering.size() );
+
+ filter.filter( config, args );
+
+ final ArrayList devicesAfterFiltering = config.getDiskStorageDevices();
+ assertEquals( 0, devicesAfterFiltering.size() );
+ }
+
+ public static void main( String[] args ) throws FilterException
+ {
+ FilterGenericDiskStorageDevicesTest test = new FilterGenericDiskStorageDevicesTest();
+ test.testFilterGenericDiskStorageDevicesNoData();
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericMemoryTest.java b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericMemoryTest.java
new file mode 100644
index 00000000..794e251c
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericMemoryTest.java
@@ -0,0 +1,35 @@
+package org.openslx.runvirt.plugin.qemu.configuration;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+
+import java.math.BigInteger;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.openslx.libvirt.domain.Domain;
+import org.openslx.libvirt.domain.DomainUtils;
+import org.openslx.runvirt.configuration.FilterException;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+
+public class FilterGenericMemoryTest
+{
+ @Test
+ @DisplayName( "Test filtering of VM memory configuration" )
+ public void testFilterGenericMemory() throws FilterException
+ {
+ final FilterGenericMemory filter = new FilterGenericMemory();
+ final Domain config = FilterTestUtils.getDefaultDomain();
+ final CommandLineArgs args = FilterTestUtils.getDefaultCmdLnArgs();
+
+ final BigInteger defaultMemory = DomainUtils.decodeMemory( FilterTestUtils.DEFAULT_VM_MEM, "MiB" );
+
+ assertNotEquals( defaultMemory.toString(), config.getMemory().toString() );
+ assertNotEquals( defaultMemory.toString(), config.getCurrentMemory().toString() );
+
+ filter.filter( config, args );
+
+ assertEquals( defaultMemory.toString(), config.getMemory().toString() );
+ assertEquals( defaultMemory.toString(), config.getCurrentMemory().toString() );
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericNameTest.java b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericNameTest.java
new file mode 100644
index 00000000..93224702
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericNameTest.java
@@ -0,0 +1,30 @@
+package org.openslx.runvirt.plugin.qemu.configuration;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.openslx.libvirt.domain.Domain;
+import org.openslx.runvirt.configuration.FilterException;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+
+public class FilterGenericNameTest
+{
+ @Test
+ @DisplayName( "Test filtering of VM (display) name configuration" )
+ public void testFilterGenericName() throws FilterException
+ {
+ final FilterGenericName filter = new FilterGenericName();
+ final Domain config = FilterTestUtils.getDefaultDomain();
+ final CommandLineArgs args = FilterTestUtils.getDefaultCmdLnArgs();
+
+ assertNotEquals( FilterTestUtils.DEFAULT_VM_NAME, config.getName() );
+ assertNotEquals( FilterTestUtils.DEFAULT_VM_DSPLNAME, config.getTitle() );
+
+ filter.filter( config, args );
+
+ assertEquals( FilterTestUtils.DEFAULT_VM_NAME, config.getName() );
+ assertEquals( FilterTestUtils.DEFAULT_VM_DSPLNAME, config.getTitle() );
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericUuidTest.java b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericUuidTest.java
new file mode 100644
index 00000000..c206b0e9
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/FilterGenericUuidTest.java
@@ -0,0 +1,28 @@
+package org.openslx.runvirt.plugin.qemu.configuration;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.openslx.libvirt.domain.Domain;
+import org.openslx.runvirt.configuration.FilterException;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+
+public class FilterGenericUuidTest
+{
+ @Test
+ @DisplayName( "Test filtering of VM UUID configuration" )
+ public void testFilterGenericUuid() throws FilterException
+ {
+ final FilterGenericUuid filter = new FilterGenericUuid();
+ final Domain config = FilterTestUtils.getDefaultDomain();
+ final CommandLineArgs args = FilterTestUtils.getDefaultCmdLnArgs();
+
+ assertNotEquals( FilterTestUtils.DEFAULT_VM_UUID, config.getUuid() );
+
+ filter.filter( config, args );
+
+ assertEquals( FilterTestUtils.DEFAULT_VM_UUID, config.getUuid() );
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/FilterTestResources.java b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/FilterTestResources.java
new file mode 100644
index 00000000..80fa2636
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/FilterTestResources.java
@@ -0,0 +1,17 @@
+package org.openslx.runvirt.plugin.qemu.configuration;
+
+import java.io.File;
+import java.net.URL;
+
+public class FilterTestResources
+{
+ private static final String LIBVIRT_PREFIX_PATH = File.separator + "libvirt";
+ private static final String LIBVIRT_PREFIX_PATH_XML = LIBVIRT_PREFIX_PATH + File.separator + "xml";
+
+ public static File getLibvirtXmlFile( String libvirtXmlFileName )
+ {
+ String libvirtXmlPath = FilterTestResources.LIBVIRT_PREFIX_PATH_XML + File.separator + libvirtXmlFileName;
+ URL libvirtXml = FilterTestResources.class.getResource( libvirtXmlPath );
+ return new File( libvirtXml.getFile() );
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/FilterTestUtils.java b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/FilterTestUtils.java
new file mode 100644
index 00000000..45abb025
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/FilterTestUtils.java
@@ -0,0 +1,112 @@
+package org.openslx.runvirt.plugin.qemu.configuration;
+
+import static org.junit.jupiter.api.Assertions.fail;
+
+import org.openslx.libvirt.domain.Domain;
+import org.openslx.libvirt.xml.LibvirtXmlDocumentException;
+import org.openslx.libvirt.xml.LibvirtXmlSerializationException;
+import org.openslx.libvirt.xml.LibvirtXmlValidationException;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs.CmdLnOption;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgsException;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgsTest;
+
+public class FilterTestUtils
+{
+ // @formatter:off
+ public static final String DEFAULT_VM_NAME = "archlinux";
+ public static final String DEFAULT_VM_UUID = "4ec504d5-5eac-482f-a344-dbf1dd4956c8";
+ public static final String DEFAULT_VM_DSPLNAME = "Archlinux";
+ public static final String DEFAULT_VM_OS = "Windows 10 (x64)";
+ public static final String DEFAULT_VM_NCPUS = "16";
+ public static final String DEFAULT_VM_MEM = "1024";
+ public static final String DEFAULT_VM_HDD0 = "/mnt/vm/windows.qcow2";
+ public static final String DEFAULT_VM_FLOPPY0 = "/mnt/vm/floppy0.qcow2";
+ public static final String DEFAULT_VM_FLOPPY1 = "/mnt/vm/floppy1.qcow2";
+ public static final String DEFAULT_VM_CDROM0 = "/dev/sr0";
+ public static final String DEFAULT_VM_CDROM1 = "/mnt/vm/cdrom1.qcow2";
+ public static final String DEFAULT_VM_PARALLEL0 = "/dev/parport0";
+ public static final String DEFAULT_VM_SERIAL0 = "/dev/ttyS0";
+ public static final String DEFAULT_VM_MAC0 = "ca:06:29:84:f0:6d";
+ public static final String DEFAULT_VM_FSSRC0 = "/mnt/shared/folder0";
+ public static final String DEFAULT_VM_FSTGT0 = "folder0";
+ public static final String DEFAULT_VM_FSSRC1 = "/mnt/shared/folder1";
+ public static final String DEFAULT_VM_FSTGT1 = "folder1";
+ // @formatter:on
+
+ private static final String[] DEFAULT_CMDLN_ARGS = {
+ CommandLineArgsTest.CMDLN_PREFIX_OPTION_LONG + CmdLnOption.VM_NAME.getLongOption(),
+ FilterTestUtils.DEFAULT_VM_NAME,
+ CommandLineArgsTest.CMDLN_PREFIX_OPTION_LONG + CmdLnOption.VM_UUID.getLongOption(),
+ FilterTestUtils.DEFAULT_VM_UUID,
+ CommandLineArgsTest.CMDLN_PREFIX_OPTION_LONG + CmdLnOption.VM_DSPLNAME.getLongOption(),
+ FilterTestUtils.DEFAULT_VM_DSPLNAME,
+ CommandLineArgsTest.CMDLN_PREFIX_OPTION_LONG + CmdLnOption.VM_OS.getLongOption(),
+ FilterTestUtils.DEFAULT_VM_OS,
+ CommandLineArgsTest.CMDLN_PREFIX_OPTION_LONG + CmdLnOption.VM_NCPUS.getLongOption(),
+ FilterTestUtils.DEFAULT_VM_NCPUS,
+ CommandLineArgsTest.CMDLN_PREFIX_OPTION_LONG + CmdLnOption.VM_MEM.getLongOption(),
+ FilterTestUtils.DEFAULT_VM_MEM,
+ CommandLineArgsTest.CMDLN_PREFIX_OPTION_LONG + CmdLnOption.VM_HDD0.getLongOption(),
+ FilterTestUtils.DEFAULT_VM_HDD0,
+ CommandLineArgsTest.CMDLN_PREFIX_OPTION_LONG + CmdLnOption.VM_FLOPPY0.getLongOption(),
+ FilterTestUtils.DEFAULT_VM_FLOPPY0,
+ CommandLineArgsTest.CMDLN_PREFIX_OPTION_LONG + CmdLnOption.VM_FLOPPY1.getLongOption(),
+ FilterTestUtils.DEFAULT_VM_FLOPPY1,
+ CommandLineArgsTest.CMDLN_PREFIX_OPTION_LONG + CmdLnOption.VM_CDROM0.getLongOption(),
+ FilterTestUtils.DEFAULT_VM_CDROM0,
+ CommandLineArgsTest.CMDLN_PREFIX_OPTION_LONG + CmdLnOption.VM_CDROM1.getLongOption(),
+ FilterTestUtils.DEFAULT_VM_CDROM1,
+ CommandLineArgsTest.CMDLN_PREFIX_OPTION_LONG + CmdLnOption.VM_PARALLEL0.getLongOption(),
+ FilterTestUtils.DEFAULT_VM_PARALLEL0,
+ CommandLineArgsTest.CMDLN_PREFIX_OPTION_LONG + CmdLnOption.VM_SERIAL0.getLongOption(),
+ FilterTestUtils.DEFAULT_VM_SERIAL0,
+ CommandLineArgsTest.CMDLN_PREFIX_OPTION_LONG + CmdLnOption.VM_MAC0.getLongOption(),
+ FilterTestUtils.DEFAULT_VM_MAC0,
+ CommandLineArgsTest.CMDLN_PREFIX_OPTION_LONG + CmdLnOption.VM_FSSRC0.getLongOption(),
+ FilterTestUtils.DEFAULT_VM_FSSRC0,
+ CommandLineArgsTest.CMDLN_PREFIX_OPTION_LONG + CmdLnOption.VM_FSTGT0.getLongOption(),
+ FilterTestUtils.DEFAULT_VM_FSTGT0,
+ CommandLineArgsTest.CMDLN_PREFIX_OPTION_LONG + CmdLnOption.VM_FSSRC1.getLongOption(),
+ FilterTestUtils.DEFAULT_VM_FSSRC1,
+ CommandLineArgsTest.CMDLN_PREFIX_OPTION_LONG + CmdLnOption.VM_FSTGT1.getLongOption(),
+ FilterTestUtils.DEFAULT_VM_FSTGT1
+ };
+
+ private static CommandLineArgs getCmdLnArgs( String[] args )
+ {
+ final CommandLineArgs cmdLnArgs = new CommandLineArgs();
+
+ try {
+ cmdLnArgs.parseCmdLnArgs( args );
+ } catch ( CommandLineArgsException e ) {
+ fail( e.getLocalizedMessage() );
+ }
+
+ return cmdLnArgs;
+ }
+
+ public static CommandLineArgs getDefaultCmdLnArgs()
+ {
+ return FilterTestUtils.getCmdLnArgs( FilterTestUtils.DEFAULT_CMDLN_ARGS );
+ }
+
+ public static CommandLineArgs getEmptyCmdLnArgs()
+ {
+ return FilterTestUtils.getCmdLnArgs( new String[] {} );
+ }
+
+ public static Domain getDefaultDomain()
+ {
+ Domain domain = null;
+
+ try {
+ domain = new Domain( FilterTestResources.getLibvirtXmlFile( "qemu-kvm_default-ubuntu-20-04-vm.xml" ) );
+ } catch ( LibvirtXmlDocumentException | LibvirtXmlSerializationException | LibvirtXmlValidationException e ) {
+ fail( "Cannot prepare requested Libvirt domain XML file from the resources folder: "
+ + e.getLocalizedMessage() );
+ }
+
+ return domain;
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/resources/libvirt/xml/qemu-kvm_capabilities_default.xml b/core/modules/qemu/runvirt-plugin-qemu/src/test/resources/libvirt/xml/qemu-kvm_capabilities_default.xml
new file mode 100644
index 00000000..4f2a94f2
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/resources/libvirt/xml/qemu-kvm_capabilities_default.xml
@@ -0,0 +1,986 @@
+
+
+
+ 9b2f12af-1fba-444c-b72b-9cbc43fb3ca5
+
+ x86_64
+ Skylake-Client-IBRS
+ Intel
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tcp
+ rdma
+
+
+
+
+
+ 16161320
+ 4040330
+ 0
+ 0
+
+
+
+
+
+
+
+
+
+ |
+
+
+
+
+
+
+ none
+ 0
+
+
+
+
+ hvm
+
+ 64
+ /usr/bin/qemu-system-alpha
+ clipper
+
+
+
+
+
+
+
+
+
+
+ hvm
+
+ 32
+ /usr/bin/qemu-system-arm
+ integratorcp
+ ast2600-evb
+ borzoi
+ spitz
+ virt-2.7
+ nuri
+ mcimx7d-sabre
+ romulus-bmc
+ virt-3.0
+ virt-5.0
+ npcm750-evb
+ virt-2.10
+ musca-b1
+ virt-2.8
+ realview-pbx-a9
+ versatileab
+ kzm
+ musca-a
+ virt-3.1
+ mcimx6ul-evk
+ virt-5.1
+ smdkc210
+ sx1
+ virt-2.11
+ imx25-pdk
+ virt-2.9
+ orangepi-pc
+ z2
+ virt-5.2
+ virt
+ xilinx-zynq-a9
+ tosa
+ mps2-an500
+ virt-2.12
+ mps2-an521
+ sabrelite
+ mps2-an511
+ canon-a1100
+ realview-eb
+ emcraft-sf2
+ realview-pb-a8
+ virt-4.0
+ raspi1ap
+ palmetto-bmc
+ sx1-v1
+ n810
+ tacoma-bmc
+ n800
+ virt-4.1
+ quanta-gsj
+ versatilepb
+ terrier
+ mainstone
+ realview-eb-mpcore
+ supermicrox11-bmc
+ virt-4.2
+ witherspoon-bmc
+ swift-bmc
+ vexpress-a9
+ midway
+ musicpal
+ lm3s811evb
+ lm3s6965evb
+ microbit
+ mps2-an505
+ mps2-an385
+ cubieboard
+ verdex
+ netduino2
+ mps2-an386
+ raspi2b
+ raspi2
+ vexpress-a15
+ sonorapass-bmc
+ cheetah
+ virt-2.6
+ ast2500-evb
+ highbank
+ akita
+ connex
+ netduinoplus2
+ collie
+ raspi0
+
+
+
+
+
+
+
+
+
+
+ hvm
+
+ 32
+ /usr/bin/qemu-system-arm
+ integratorcp
+ ast2600-evb
+ borzoi
+ spitz
+ virt-2.7
+ nuri
+ mcimx7d-sabre
+ romulus-bmc
+ virt-3.0
+ virt-5.0
+ npcm750-evb
+ virt-2.10
+ musca-b1
+ virt-2.8
+ realview-pbx-a9
+ versatileab
+ kzm
+ musca-a
+ virt-3.1
+ mcimx6ul-evk
+ virt-5.1
+ smdkc210
+ sx1
+ virt-2.11
+ imx25-pdk
+ virt-2.9
+ orangepi-pc
+ z2
+ virt-5.2
+ virt
+ xilinx-zynq-a9
+ tosa
+ mps2-an500
+ virt-2.12
+ mps2-an521
+ sabrelite
+ mps2-an511
+ canon-a1100
+ realview-eb
+ emcraft-sf2
+ realview-pb-a8
+ virt-4.0
+ raspi1ap
+ palmetto-bmc
+ sx1-v1
+ n810
+ tacoma-bmc
+ n800
+ virt-4.1
+ quanta-gsj
+ versatilepb
+ terrier
+ mainstone
+ realview-eb-mpcore
+ supermicrox11-bmc
+ virt-4.2
+ witherspoon-bmc
+ swift-bmc
+ vexpress-a9
+ midway
+ musicpal
+ lm3s811evb
+ lm3s6965evb
+ microbit
+ mps2-an505
+ mps2-an385
+ cubieboard
+ verdex
+ netduino2
+ mps2-an386
+ raspi2b
+ raspi2
+ vexpress-a15
+ sonorapass-bmc
+ cheetah
+ virt-2.6
+ ast2500-evb
+ highbank
+ akita
+ connex
+ netduinoplus2
+ collie
+ raspi0
+
+
+
+
+
+
+
+
+
+
+ hvm
+
+ 64
+ /usr/bin/qemu-system-aarch64
+ integratorcp
+ ast2600-evb
+ borzoi
+ spitz
+ virt-2.7
+ nuri
+ mcimx7d-sabre
+ romulus-bmc
+ virt-3.0
+ virt-5.0
+ npcm750-evb
+ virt-2.10
+ musca-b1
+ virt-2.8
+ realview-pbx-a9
+ versatileab
+ kzm
+ musca-a
+ virt-3.1
+ mcimx6ul-evk
+ virt-5.1
+ smdkc210
+ sx1
+ virt-2.11
+ imx25-pdk
+ virt-2.9
+ orangepi-pc
+ z2
+ virt-5.2
+ virt
+ xilinx-zynq-a9
+ xlnx-zcu102
+ tosa
+ mps2-an500
+ virt-2.12
+ mps2-an521
+ sabrelite
+ mps2-an511
+ canon-a1100
+ realview-eb
+ emcraft-sf2
+ realview-pb-a8
+ sbsa-ref
+ virt-4.0
+ raspi1ap
+ palmetto-bmc
+ sx1-v1
+ n810
+ tacoma-bmc
+ n800
+ virt-4.1
+ quanta-gsj
+ versatilepb
+ terrier
+ mainstone
+ realview-eb-mpcore
+ supermicrox11-bmc
+ virt-4.2
+ witherspoon-bmc
+ swift-bmc
+ vexpress-a9
+ midway
+ musicpal
+ lm3s811evb
+ lm3s6965evb
+ microbit
+ mps2-an505
+ mps2-an385
+ raspi3ap
+ cubieboard
+ verdex
+ netduino2
+ xlnx-versal-virt
+ mps2-an386
+ raspi3b
+ raspi3
+ raspi2b
+ raspi2
+ vexpress-a15
+ sonorapass-bmc
+ cheetah
+ virt-2.6
+ ast2500-evb
+ highbank
+ akita
+ connex
+ netduinoplus2
+ collie
+ raspi0
+
+
+
+
+
+
+
+
+
+
+
+ hvm
+
+ 32
+ /usr/bin/qemu-system-cris
+ axis-dev88
+
+
+
+
+
+
+
+
+
+
+ hvm
+
+ 32
+ /usr/bin/qemu-system-i386
+ pc-i440fx-5.2
+ pc
+ pc-q35-5.2
+ q35
+ pc-i440fx-2.12
+ pc-i440fx-2.0
+ pc-q35-4.2
+ pc-i440fx-2.5
+ pc-i440fx-4.2
+ pc-i440fx-1.5
+ pc-q35-2.7
+ pc-i440fx-2.2
+ pc-1.1
+ pc-i440fx-2.7
+ pc-q35-2.4
+ pc-q35-2.10
+ pc-i440fx-1.7
+ pc-q35-5.1
+ pc-q35-2.9
+ pc-i440fx-2.11
+ pc-q35-3.1
+ pc-q35-4.1
+ pc-i440fx-2.4
+ pc-1.3
+ pc-i440fx-4.1
+ pc-i440fx-5.1
+ pc-i440fx-2.9
+ isapc
+ pc-i440fx-1.4
+ pc-q35-2.6
+ pc-i440fx-3.1
+ pc-q35-2.12
+ pc-i440fx-2.1
+ pc-1.0
+ pc-i440fx-2.6
+ pc-q35-4.0.1
+ pc-i440fx-1.6
+ pc-q35-5.0
+ pc-q35-2.8
+ pc-i440fx-2.10
+ pc-q35-3.0
+ pc-q35-4.0
+ microvm
+ pc-i440fx-2.3
+ pc-1.2
+ pc-i440fx-4.0
+ pc-i440fx-5.0
+ pc-i440fx-2.8
+ pc-q35-2.5
+ pc-i440fx-3.0
+ pc-q35-2.11
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ hvm
+
+ 32
+ /usr/bin/qemu-system-m68k
+ mcf5208evb
+ an5206
+ q800
+ next-cube
+
+
+
+
+
+
+
+
+
+
+ hvm
+
+ 32
+ /usr/bin/qemu-system-microblaze
+ petalogix-s3adsp1800
+ petalogix-ml605
+ xlnx-zynqmp-pmu
+
+
+
+
+
+
+
+
+
+
+ hvm
+
+ 32
+ /usr/bin/qemu-system-microblazeel
+ petalogix-s3adsp1800
+ petalogix-ml605
+ xlnx-zynqmp-pmu
+
+
+
+
+
+
+
+
+
+
+ hvm
+
+ 32
+ /usr/bin/qemu-system-mips
+ malta
+ mipssim
+
+
+
+
+
+
+
+
+
+
+ hvm
+
+ 32
+ /usr/bin/qemu-system-mipsel
+ malta
+ mipssim
+
+
+
+
+
+
+
+
+
+
+ hvm
+
+ 64
+ /usr/bin/qemu-system-mips64
+ malta
+ pica61
+ mipssim
+ magnum
+
+
+
+
+
+
+
+
+
+
+ hvm
+
+ 64
+ /usr/bin/qemu-system-mips64el
+ malta
+ mipssim
+ pica61
+ magnum
+ boston
+ fuloong2e
+ fulong2e
+
+
+
+
+
+
+
+
+
+
+ hvm
+
+ 32
+ /usr/bin/qemu-system-ppc
+ g3beige
+ virtex-ml507
+ mac99
+ ppce500
+ sam460ex
+ bamboo
+ 40p
+ ref405ep
+ mpc8544ds
+ taihu
+
+
+
+
+
+
+
+
+
+
+ hvm
+
+ 64
+ /usr/bin/qemu-system-ppc64
+ pseries-5.2
+ pseries
+ powernv9
+ powernv
+ taihu
+ pseries-4.1
+ mpc8544ds
+ pseries-2.5
+ powernv10
+ pseries-4.2
+ pseries-2.6
+ ppce500
+ pseries-2.7
+ pseries-3.0
+ pseries-5.0
+ 40p
+ pseries-2.8
+ pseries-3.1
+ pseries-5.1
+ pseries-2.9
+ bamboo
+ g3beige
+ pseries-2.12-sxxm
+ pseries-2.10
+ virtex-ml507
+ pseries-2.11
+ pseries-2.1
+ pseries-2.12
+ pseries-2.2
+ mac99
+ sam460ex
+ ref405ep
+ pseries-2.3
+ powernv8
+ pseries-4.0
+ pseries-2.4
+
+
+
+
+
+
+
+
+
+
+ hvm
+
+ 64
+ /usr/bin/qemu-system-ppc64
+ pseries-5.2
+ pseries
+ powernv9
+ powernv
+ taihu
+ pseries-4.1
+ mpc8544ds
+ pseries-2.5
+ powernv10
+ pseries-4.2
+ pseries-2.6
+ ppce500
+ pseries-2.7
+ pseries-3.0
+ pseries-5.0
+ 40p
+ pseries-2.8
+ pseries-3.1
+ pseries-5.1
+ pseries-2.9
+ bamboo
+ g3beige
+ pseries-2.12-sxxm
+ pseries-2.10
+ virtex-ml507
+ pseries-2.11
+ pseries-2.1
+ pseries-2.12
+ pseries-2.2
+ mac99
+ sam460ex
+ ref405ep
+ pseries-2.3
+ powernv8
+ pseries-4.0
+ pseries-2.4
+
+
+
+
+
+
+
+
+
+
+ hvm
+
+ 32
+ /usr/bin/qemu-system-riscv32
+ spike
+ virt
+ opentitan
+ sifive_e
+ sifive_u
+
+
+
+
+
+
+
+
+
+
+ hvm
+
+ 64
+ /usr/bin/qemu-system-riscv64
+ spike
+ virt
+ sifive_e
+ sifive_u
+ microchip-icicle-kit
+
+
+
+
+
+
+
+
+
+
+ hvm
+
+ 64
+ /usr/bin/qemu-system-s390x
+ s390-ccw-virtio-5.2
+ s390-ccw-virtio
+ s390-ccw-virtio-4.0
+ s390-ccw-virtio-3.1
+ s390-ccw-virtio-2.6
+ s390-ccw-virtio-2.12
+ s390-ccw-virtio-2.9
+ s390-ccw-virtio-5.1
+ s390-ccw-virtio-3.0
+ s390-ccw-virtio-4.2
+ s390-ccw-virtio-2.5
+ s390-ccw-virtio-2.11
+ s390-ccw-virtio-2.8
+ s390-ccw-virtio-5.0
+ s390-ccw-virtio-4.1
+ s390-ccw-virtio-2.4
+ s390-ccw-virtio-2.10
+ s390-ccw-virtio-2.7
+
+
+
+
+
+
+
+
+
+
+ hvm
+
+ 32
+ /usr/bin/qemu-system-sh4
+ shix
+ r2d
+
+
+
+
+
+
+
+
+
+
+ hvm
+
+ 64
+ /usr/bin/qemu-system-sh4eb
+ shix
+ r2d
+
+
+
+
+
+
+
+
+
+
+ hvm
+
+ 32
+ /usr/bin/qemu-system-sparc
+ SS-5
+ SS-20
+ LX
+ SPARCClassic
+ leon3_generic
+ SPARCbook
+ SS-4
+ SS-600MP
+ SS-10
+ Voyager
+
+
+
+
+
+
+
+
+
+
+ hvm
+
+ 64
+ /usr/bin/qemu-system-sparc64
+ sun4u
+ niagara
+ sun4v
+
+
+
+
+
+
+
+
+
+
+ hvm
+
+ 64
+ /usr/bin/qemu-system-x86_64
+ pc-i440fx-5.2
+ pc
+ pc-q35-5.2
+ q35
+ pc-i440fx-2.12
+ pc-i440fx-2.0
+ pc-q35-4.2
+ pc-i440fx-2.5
+ pc-i440fx-4.2
+ pc-i440fx-1.5
+ pc-q35-2.7
+ pc-i440fx-2.2
+ pc-1.1
+ pc-i440fx-2.7
+ pc-q35-2.4
+ pc-q35-2.10
+ pc-i440fx-1.7
+ pc-q35-5.1
+ pc-q35-2.9
+ pc-i440fx-2.11
+ pc-q35-3.1
+ pc-q35-4.1
+ pc-i440fx-2.4
+ pc-1.3
+ pc-i440fx-4.1
+ pc-i440fx-5.1
+ pc-i440fx-2.9
+ isapc
+ pc-i440fx-1.4
+ pc-q35-2.6
+ pc-i440fx-3.1
+ pc-q35-2.12
+ pc-i440fx-2.1
+ pc-1.0
+ pc-i440fx-2.6
+ pc-q35-4.0.1
+ pc-i440fx-1.6
+ pc-q35-5.0
+ pc-q35-2.8
+ pc-i440fx-2.10
+ pc-q35-3.0
+ pc-q35-4.0
+ microvm
+ pc-i440fx-2.3
+ pc-1.2
+ pc-i440fx-4.0
+ pc-i440fx-5.0
+ pc-i440fx-2.8
+ pc-q35-2.5
+ pc-i440fx-3.0
+ pc-q35-2.11
+
+
+
+
+
+
+
+
+
+
+
+
+
+ hvm
+
+ 32
+ /usr/bin/qemu-system-xtensa
+ sim
+ kc705
+ ml605
+ ml605-nommu
+ virt
+ lx60-nommu
+ lx200
+ lx200-nommu
+ lx60
+ kc705-nommu
+
+
+
+
+
+
+
+
+
+
+ hvm
+
+ 32
+ /usr/bin/qemu-system-xtensaeb
+ sim
+ kc705
+ ml605
+ ml605-nommu
+ virt
+ lx60-nommu
+ lx200
+ lx200-nommu
+ lx60
+ kc705-nommu
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/resources/libvirt/xml/qemu-kvm_default-ubuntu-20-04-vm.xml b/core/modules/qemu/runvirt-plugin-qemu/src/test/resources/libvirt/xml/qemu-kvm_default-ubuntu-20-04-vm.xml
new file mode 100644
index 00000000..241a6807
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/resources/libvirt/xml/qemu-kvm_default-ubuntu-20-04-vm.xml
@@ -0,0 +1,164 @@
+
+ ubuntu-20-04
+ 8dc5433c-0228-49e4-b019-fa2b606aa544
+ Ubuntu 20.04
+ Ubuntu 20.04 desktop installation
+
+
+
+
+
+ 4194304
+ 4194304
+ 2
+
+ hvm
+
+
+
+
+
+
+
+
+
+
+
+
+
+ destroy
+ restart
+ destroy
+
+
+
+
+
+ /usr/bin/qemu-system-x86_64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /dev/urandom
+
+
+
+
+
--
cgit v1.2.3-55-g7522
From 96768a5133953ea3fa57ab4f7eac145e98637739 Mon Sep 17 00:00:00 2001
From: Manuel Bentele
Date: Mon, 17 May 2021 14:49:24 +0200
Subject: [qemu] Show virt-manager in debug mode to inspect Libvirt VM
---
.../vmchooser/plugins/qemu/run-virt.include | 1 +
.../java/org/openslx/runvirt/plugin/qemu/App.java | 14 ++++-
.../runvirt/plugin/qemu/cmdln/CommandLineArgs.java | 12 ++++
.../org/openslx/runvirt/plugin/qemu/AppTest.java | 8 +--
.../plugin/qemu/cmdln/CommandLineArgsTest.java | 67 ++++++++++++++++++++++
5 files changed, 96 insertions(+), 6 deletions(-)
(limited to 'core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/AppTest.java')
diff --git a/core/modules/qemu/data/opt/openslx/vmchooser/plugins/qemu/run-virt.include b/core/modules/qemu/data/opt/openslx/vmchooser/plugins/qemu/run-virt.include
index 90a00c6e..b7e43df9 100644
--- a/core/modules/qemu/data/opt/openslx/vmchooser/plugins/qemu/run-virt.include
+++ b/core/modules/qemu/data/opt/openslx/vmchooser/plugins/qemu/run-virt.include
@@ -29,6 +29,7 @@ run_plugin() {
# call the Libvirt Java tool to finalize configuration and start VM
declare -rg VIRTCMD="java -jar /opt/openslx/share/java/runvirt-plugin-qemu.jar"
+ isset DEBUG && VIRTCMDOPTS+=( "-debug" "${DEBUG}" )
isset VM_CLEANNAME && VIRTCMDOPTS+=( "-vmname" "${VM_CLEANNAME}" )
isset VM_DISPLAYNAME && VIRTCMDOPTS+=( "-vmdsplname" "${VM_DISPLAYNAME}" )
isset VM_OS_TYPE && VIRTCMDOPTS+=( "-vmos" "${VM_OS_TYPE}" )
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/App.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/App.java
index e5bc4780..a3e1c5b7 100644
--- a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/App.java
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/App.java
@@ -29,6 +29,7 @@ import org.openslx.runvirt.plugin.qemu.virtualization.LibvirtHypervisorQemu;
import org.openslx.runvirt.plugin.qemu.virtualization.LibvirtHypervisorQemu.QemuSessionType;
import org.openslx.runvirt.viewer.Viewer;
import org.openslx.runvirt.viewer.ViewerException;
+import org.openslx.runvirt.viewer.ViewerVirtManager;
import org.openslx.runvirt.viewer.ViewerVirtViewer;
import org.openslx.runvirt.virtualization.LibvirtHypervisor;
import org.openslx.runvirt.virtualization.LibvirtHypervisorException;
@@ -182,8 +183,17 @@ public class App
System.exit( 7 );
}
- // display Libvirt VM with a specific viewer on the screen
- final Viewer vmViewer = new ViewerVirtViewer( vm, hypervisor );
+ // create specific viewer to display Libvirt VM
+ final Viewer vmViewer;
+ if ( cmdLn.isDebugEnabled() ) {
+ // create specific Virtual Machine Manager viewer if debug mode is enabled
+ vmViewer = new ViewerVirtManager( vm, hypervisor );
+ } else {
+ // create Virtual Viewer if debug mode is disabled
+ vmViewer = new ViewerVirtViewer( vm, hypervisor );
+ }
+
+ // display Libvirt VM with the specific viewer on the screen
try {
vmViewer.display();
} catch ( ViewerException e ) {
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/cmdln/CommandLineArgs.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/cmdln/CommandLineArgs.java
index 03df8923..eb7c8739 100644
--- a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/cmdln/CommandLineArgs.java
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/cmdln/CommandLineArgs.java
@@ -127,6 +127,17 @@ public class CommandLineArgs
return this.cmdLn.hasOption( CmdLnOption.HELP.getShortOption() );
}
+ /**
+ * Returns the state of the command line option {@link CmdLnOption#DEBUG}.
+ *
+ * @return state of the command line option {@link CmdLnOption#DEBUG}.
+ */
+ public boolean isDebugEnabled()
+ {
+ final String debugArg = this.getArgument( CmdLnOption.DEBUG );
+ return ( "true".equals( debugArg ) ) ? true : false;
+ }
+
/**
* Returns the argument of the command line option {@link CmdLnOption#VM_CFGINP}.
*
@@ -344,6 +355,7 @@ public class CommandLineArgs
{
// @formatter:off
HELP ( 'h', "help", false, "" ),
+ DEBUG ( 'b', "debug", true, "Enable or disable debug mode" ),
VM_CFGINP ( 'i', "vmcfginp", true, "File name of an existing and filtered Libvirt domain XML configuration file" ),
VM_CFGOUT ( 'o', "vmcfgout", true, "File name to output a finalized Libvirt domain XML configuration file" ),
VM_NAME ( 'n', "vmname", true, "Name for the virtual machine" ),
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/AppTest.java b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/AppTest.java
index 9f8f925f..a7929ab0 100644
--- a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/AppTest.java
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/AppTest.java
@@ -63,7 +63,7 @@ public class AppTest
assertTrue( shortHelpOptionCorrectOutput.contains( App.APP_DESC ) );
// test that no error was logged and output is available
- assertEquals( 2026, shortHelpOptionCorrectOutput.length() );
+ assertEquals( 2093, shortHelpOptionCorrectOutput.length() );
assertEquals( 0, shortHelpOptionCorrectErrOutput.length() );
}
@@ -91,7 +91,7 @@ public class AppTest
assertTrue( longHelpOptionCorrectOutput.contains( App.APP_DESC ) );
// test that no error was logged and output is available
- assertEquals( 2026, longHelpOptionCorrectOutput.length() );
+ assertEquals( 2093, longHelpOptionCorrectOutput.length() );
assertEquals( 0, longHelpOptionCorrectErrOutput.length() );
}
@@ -119,7 +119,7 @@ public class AppTest
assertTrue( shortHelpOptionIncorrectOutput.contains( App.APP_DESC ) );
// test that error was logged and output is available
- assertEquals( 2026, shortHelpOptionIncorrectOutput.length() );
+ assertEquals( 2093, shortHelpOptionIncorrectOutput.length() );
assertEquals( 0, shortHelpOptionIncorrectErrOutput.length() );
}
@@ -147,7 +147,7 @@ public class AppTest
assertTrue( longHelpOptionIncorrectOutput.contains( App.APP_DESC ) );
// test that error was logged and output is available
- assertEquals( 2026, longHelpOptionIncorrectOutput.length() );
+ assertEquals( 2093, longHelpOptionIncorrectOutput.length() );
assertEquals( 0, longHelpOptionIncorrectErrOutput.length() );
}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/cmdln/CommandLineArgsTest.java b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/cmdln/CommandLineArgsTest.java
index ee3e0d1d..972f5e4b 100644
--- a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/cmdln/CommandLineArgsTest.java
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/cmdln/CommandLineArgsTest.java
@@ -1,6 +1,7 @@
package org.openslx.runvirt.plugin.qemu.cmdln;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -16,6 +17,8 @@ public class CommandLineArgsTest
public static final String CMDLN_PREFIX_OPTION_SHORT = "-";
public static final String CMDLN_PREFIX_OPTION_LONG = "--";
+ private static final String CMDLN_TEST_DEBUG_OFF = "false";
+ private static final String CMDLN_TEST_DEBUG_ON = "true";
private static final String CMDLN_TEST_NAME = "test";
private static final String CMDLN_TEST_FILENAME = System.getProperty( "user.dir" ) + File.separator + CMDLN_TEST_NAME;
private static final String CMDLN_TEST_UUID = "c9570672-cbae-4cbd-801a-881b281b8d79";
@@ -69,6 +72,70 @@ public class CommandLineArgsTest
assertTrue( cmdLn.isHelpAquired() );
}
+ @Test
+ @DisplayName( "Test the parsing of the enabled debug command line option (short version)" )
+ public void testCmdlnOptionDebugEnabledShort() throws CommandLineArgsException
+ {
+ final String[] args = {
+ CMDLN_PREFIX_OPTION_SHORT + CmdLnOption.DEBUG.getShortOption(),
+ CMDLN_TEST_DEBUG_ON
+ };
+
+ CommandLineArgs cmdLn = new CommandLineArgs( args );
+
+ assertTrue( cmdLn.isDebugEnabled() );
+ }
+
+ @Test
+ @DisplayName( "Test the parsing of the enabled debug command line option (long version)" )
+ public void testCmdlnOptionDebugEnabledLong() throws CommandLineArgsException
+ {
+ final String[] args = {
+ CMDLN_PREFIX_OPTION_LONG + CmdLnOption.DEBUG.getLongOption(),
+ CMDLN_TEST_DEBUG_ON
+ };
+
+ CommandLineArgs cmdLn = new CommandLineArgs( args );
+
+ assertTrue( cmdLn.isDebugEnabled() );
+ }
+
+ @Test
+ @DisplayName( "Test the parsing of the disabled debug command line option (short version)" )
+ public void testCmdlnOptionDebugDisabledShort() throws CommandLineArgsException
+ {
+ final String[] argsDebugOff = {
+ CMDLN_PREFIX_OPTION_SHORT + CmdLnOption.DEBUG.getShortOption(),
+ CMDLN_TEST_DEBUG_OFF
+ };
+
+ final String[] argsDebugMissing = {};
+
+ CommandLineArgs cmdLnDebugOff = new CommandLineArgs( argsDebugOff );
+ CommandLineArgs cmdLnDebugMissing = new CommandLineArgs( argsDebugMissing );
+
+ assertFalse( cmdLnDebugOff.isDebugEnabled() );
+ assertFalse( cmdLnDebugMissing.isDebugEnabled() );
+ }
+
+ @Test
+ @DisplayName( "Test the parsing of the disabled debug command line option (long version)" )
+ public void testCmdlnOptionDebugDisabledLong() throws CommandLineArgsException
+ {
+ final String[] argsDebugOff = {
+ CMDLN_PREFIX_OPTION_LONG + CmdLnOption.DEBUG.getLongOption(),
+ CMDLN_TEST_DEBUG_OFF
+ };
+
+ final String[] argsDebugMissing = {};
+
+ CommandLineArgs cmdLnDebugOff = new CommandLineArgs( argsDebugOff );
+ CommandLineArgs cmdLnDebugMissing = new CommandLineArgs( argsDebugMissing );
+
+ assertFalse( cmdLnDebugOff.isDebugEnabled() );
+ assertFalse( cmdLnDebugMissing.isDebugEnabled() );
+ }
+
@Test
@DisplayName( "Test the parsing of the VM configuration input command line option (short version)" )
public void testCmdlnOptionVmCfgInpShort() throws CommandLineArgsException
--
cgit v1.2.3-55-g7522
From 985b51d7a308ce468105b2c38a293e9f4bd1f48e Mon Sep 17 00:00:00 2001
From: Manuel Bentele
Date: Wed, 26 May 2021 11:32:54 +0200
Subject: [qemu] Add unit tests for Libvirt configuration transformations
---
.../runvirt/plugin/qemu/cmdln/CommandLineArgs.java | 2 +-
.../TransformationGenericDiskCdromDevices.java | 27 +++++-
.../TransformationGenericDiskFloppyDevices.java | 22 ++++-
.../TransformationGenericDiskStorageDevices.java | 16 +++-
.../TransformationGenericFileSystemDevices.java | 6 +-
.../TransformationGenericInterfaceDevices.java | 17 +++-
.../TransformationGenericParallelDevices.java | 2 +-
.../TransformationSpecificQemuArchitecture.java | 6 +-
.../TransformationSpecificQemuSerialDevices.java | 4 +-
.../org/openslx/runvirt/plugin/qemu/AppTest.java | 8 +-
.../TransformationGenericCpuTest.java | 12 +++
.../TransformationGenericDiskCdromDevicesTest.java | 60 ++++++++++++
...TransformationGenericDiskFloppyDevicesTest.java | 61 ++++++++++++
...TransformationGenericFileSystemDevicesTest.java | 61 ++++++++++++
.../TransformationGenericInterfaceDevicesTest.java | 58 ++++++++++++
.../TransformationGenericMemoryTest.java | 12 +++
.../TransformationGenericNameTest.java | 12 +++
.../TransformationGenericParallelDevicesTest.java | 53 +++++++++++
.../TransformationGenericUuidTest.java | 12 +++
...TransformationSpecificQemuArchitectureTest.java | 102 +++++++++++++++++++++
...ransformationSpecificQemuSerialDevicesTest.java | 69 ++++++++++++++
21 files changed, 596 insertions(+), 26 deletions(-)
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericDiskCdromDevicesTest.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericDiskFloppyDevicesTest.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericFileSystemDevicesTest.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericInterfaceDevicesTest.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericParallelDevicesTest.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuArchitectureTest.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuSerialDevicesTest.java
(limited to 'core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/AppTest.java')
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/cmdln/CommandLineArgs.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/cmdln/CommandLineArgs.java
index eb7c8739..1fe342b1 100644
--- a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/cmdln/CommandLineArgs.java
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/cmdln/CommandLineArgs.java
@@ -373,7 +373,7 @@ public class CommandLineArgs
VM_SERIAL0 ( 'q', "vmserial0", true, "Device for the first serial port interface" ),
VM_MAC0 ( 'a', "vmmac0", true, "MAC address for the first network interface" ),
VM_FSSRC0 ( 't', "vmfssrc0", true, "Source directory for first file system passthrough (shared folder)" ),
- VM_FSTGT0 ( 'u', "vmfstgt0", true, "Target directory for first file system passthrough (shared folder)" ),
+ VM_FSTGT0 ( 'e', "vmfstgt0", true, "Target directory for first file system passthrough (shared folder)" ),
VM_FSSRC1 ( 'v', "vmfssrc1", true, "Source directory for second file system passthrough (shared folder)" ),
VM_FSTGT1 ( 'w', "vmfstgt1", true, "Target directory for second file system passthrough (shared folder)" );
// @formatter:on
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
index 066af763..643c40ed 100644
--- 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
@@ -3,10 +3,10 @@ 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.VirtualizationConfigurationQemu;
import org.openslx.virtualization.configuration.VirtualizationConfigurationQemuUtils;
import org.openslx.virtualization.configuration.transformation.TransformationException;
import org.openslx.virtualization.configuration.transformation.TransformationGeneric;
@@ -60,11 +60,28 @@ public class TransformationGenericDiskCdromDevices extends TransformationGeneric
final ArrayList devices = config.getDiskCdromDevices();
final DiskCdrom disk = VirtualizationConfigurationQemuUtils.getArrayIndex( devices, index );
- if ( disk != null ) {
+ 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 ) {
- // do not remove disk CDROM drive, but set local physical drive as input source
- disk.setStorage( StorageType.BLOCK, VirtualizationConfigurationQemu.CDROM_DEFAULT_PHYSICAL_DRIVE );
- } else if ( fileName.equals( "" ) ) {
+ // 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 {
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
index 87b0eb5c..fe3d3c34 100644
--- 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
@@ -3,6 +3,7 @@ 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;
@@ -58,12 +59,27 @@ public class TransformationGenericDiskFloppyDevices extends TransformationGeneri
final ArrayList devices = config.getDiskFloppyDevices();
final DiskFloppy disk = VirtualizationConfigurationQemuUtils.getArrayIndex( devices, index );
- if ( disk != null ) {
+ 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 ) {
- // remove disk floppy device if disk image file name is not set
disk.remove();
+ } else if ( fileName.isEmpty() ) {
+ disk.removeStorage();
} else {
- // set image file of disk storage if disk floppy device is available
disk.setStorage( StorageType.FILE, fileName );
}
}
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
index 30c26cae..9bd1edbb 100644
--- 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
@@ -3,7 +3,9 @@ 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;
@@ -61,8 +63,18 @@ public class TransformationGenericDiskStorageDevices extends TransformationGener
final ArrayList devices = config.getDiskStorageDevices();
final DiskStorage disk = VirtualizationConfigurationQemuUtils.getArrayIndex( devices, index );
- if ( disk != null ) {
- if ( fileName == null ) {
+ 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 {
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
index 88939302..a4f77b0d 100644
--- 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
@@ -66,7 +66,7 @@ public class TransformationGenericFileSystemDevices extends TransformationGeneri
if ( fileSystem == null ) {
// check if file system device source directory is specified
- if ( source != null && target != null ) {
+ 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 );
@@ -75,7 +75,7 @@ public class TransformationGenericFileSystemDevices extends TransformationGeneri
newFileSystem.setTarget( target );
}
} else {
- if ( source == null || target == null ) {
+ if ( source == null || source.isEmpty() || target == null || target.isEmpty() ) {
// remove file system device since device source or target is not specified
fileSystem.remove();
} else {
@@ -100,7 +100,7 @@ public class TransformationGenericFileSystemDevices extends TransformationGeneri
// remove all additional file system devices
final ArrayList devices = config.getFileSystemDevices();
- for ( int i = 1; i < devices.size(); i++ ) {
+ 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
index ab44b784..6cf12ce2 100644
--- 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
@@ -4,7 +4,11 @@ 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;
@@ -59,8 +63,17 @@ public class TransformationGenericInterfaceDevices extends TransformationGeneric
final ArrayList devices = config.getInterfaceDevices();
final Interface device = VirtualizationConfigurationQemuUtils.getArrayIndex( devices, index );
- if ( device != null ) {
- if ( macAddress == null ) {
+ 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 {
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
index dff86132..08d43ef0 100644
--- 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
@@ -68,7 +68,7 @@ public class TransformationGenericParallelDevices extends TransformationGeneric<
newDevice.setSource( fileName );
}
} else {
- if ( fileName == null ) {
+ if ( fileName == null || fileName.isEmpty() ) {
// remove device since device file is not specified
device.remove();
} else {
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
index 0c32a3b3..f507237d 100644
--- 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
@@ -42,9 +42,9 @@ public class TransformationSpecificQemuArchitecture
*
* @param hypervisor Libvirt/QEMU hypervisor.
*/
- public TransformationSpecificQemuArchitecture( LibvirtHypervisorQemu hypervisor )
+ public TransformationSpecificQemuArchitecture( LibvirtHypervisorQemu virtualizer )
{
- super( TransformationSpecificQemuArchitecture.NAME, hypervisor );
+ super( TransformationSpecificQemuArchitecture.NAME, virtualizer );
}
/**
@@ -68,7 +68,7 @@ public class TransformationSpecificQemuArchitecture
* @throws TransformationException failed to query and return the capabilities of the
* Libvirt/QEMU hypervisor.
*/
- private Capabilities getCapabilities() throws TransformationException
+ protected Capabilities getCapabilities() throws TransformationException
{
// retrieve capabilities from QEMU hypervisor only once
if ( this.capabilities == null ) {
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
index 1cd3c9b0..30f60289 100644
--- 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
@@ -81,14 +81,14 @@ public class TransformationSpecificQemuSerialDevices
if ( device == null ) {
// check if device file name is specified
- if ( fileName != null ) {
+ 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 ) {
+ if ( fileName == null || fileName.isEmpty() ) {
// remove serial port device if device file name is not set
device.remove();
} else {
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/AppTest.java b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/AppTest.java
index a7929ab0..1db1525b 100644
--- a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/AppTest.java
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/AppTest.java
@@ -63,7 +63,7 @@ public class AppTest
assertTrue( shortHelpOptionCorrectOutput.contains( App.APP_DESC ) );
// test that no error was logged and output is available
- assertEquals( 2093, shortHelpOptionCorrectOutput.length() );
+ assertEquals( 2160, shortHelpOptionCorrectOutput.length() );
assertEquals( 0, shortHelpOptionCorrectErrOutput.length() );
}
@@ -91,7 +91,7 @@ public class AppTest
assertTrue( longHelpOptionCorrectOutput.contains( App.APP_DESC ) );
// test that no error was logged and output is available
- assertEquals( 2093, longHelpOptionCorrectOutput.length() );
+ assertEquals( 2160, longHelpOptionCorrectOutput.length() );
assertEquals( 0, longHelpOptionCorrectErrOutput.length() );
}
@@ -119,7 +119,7 @@ public class AppTest
assertTrue( shortHelpOptionIncorrectOutput.contains( App.APP_DESC ) );
// test that error was logged and output is available
- assertEquals( 2093, shortHelpOptionIncorrectOutput.length() );
+ assertEquals( 2160, shortHelpOptionIncorrectOutput.length() );
assertEquals( 0, shortHelpOptionIncorrectErrOutput.length() );
}
@@ -147,7 +147,7 @@ public class AppTest
assertTrue( longHelpOptionIncorrectOutput.contains( App.APP_DESC ) );
// test that error was logged and output is available
- assertEquals( 2093, longHelpOptionIncorrectOutput.length() );
+ assertEquals( 2160, longHelpOptionIncorrectOutput.length() );
assertEquals( 0, longHelpOptionIncorrectErrOutput.length() );
}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericCpuTest.java b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericCpuTest.java
index 260adcc1..7e93513b 100644
--- a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericCpuTest.java
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericCpuTest.java
@@ -2,6 +2,7 @@ package org.openslx.runvirt.plugin.qemu.configuration;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
@@ -31,4 +32,15 @@ public class TransformationGenericCpuTest
assertEquals( CpuMode.HOST_PASSTHROUGH, config.getCpuMode() );
assertEquals( CpuCheck.PARTIAL, config.getCpuCheck() );
}
+
+ @Test
+ @DisplayName( "Test transformation of VM CPU configuration with unspecified input data" )
+ public void testTransformationGenericCpuNoData() throws TransformationException
+ {
+ final TransformationGenericCpu transformation = new TransformationGenericCpu();
+ final Domain config = TransformationTestUtils.getDefaultDomain();
+ final CommandLineArgs args = TransformationTestUtils.getEmptyCmdLnArgs();
+
+ assertThrows( TransformationException.class, () -> transformation.transform( config, args ) );
+ }
}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericDiskCdromDevicesTest.java b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericDiskCdromDevicesTest.java
new file mode 100644
index 00000000..842e30e6
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericDiskCdromDevicesTest.java
@@ -0,0 +1,60 @@
+package org.openslx.runvirt.plugin.qemu.configuration;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+
+import java.util.ArrayList;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.openslx.libvirt.domain.Domain;
+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.transformation.TransformationException;
+
+public class TransformationGenericDiskCdromDevicesTest
+{
+ @Test
+ @DisplayName( "Test transformation of VM disk CDROM devices configuration with specified input data" )
+ public void testTransformationGenericDiskCdromDevices() throws TransformationException
+ {
+ final TransformationGenericDiskCdromDevices transformation = new TransformationGenericDiskCdromDevices();
+ final Domain config = TransformationTestUtils.getDefaultDomain();
+ final CommandLineArgs args = TransformationTestUtils.getDefaultCmdLnArgs();
+
+ final ArrayList devicesBeforeTransformation = config.getDiskCdromDevices();
+ assertEquals( 1, devicesBeforeTransformation.size() );
+ final DiskCdrom cdromDeviceBeforeTransformation = devicesBeforeTransformation.get( 0 );
+ assertEquals( StorageType.FILE, cdromDeviceBeforeTransformation.getStorageType() );
+ assertNotEquals( TransformationTestUtils.DEFAULT_VM_CDROM0, cdromDeviceBeforeTransformation.getStorageSource() );
+
+ transformation.transform( config, args );
+
+ final ArrayList devicesAfterTransformation = config.getDiskCdromDevices();
+ assertEquals( 2, devicesAfterTransformation.size() );
+ final DiskCdrom cdromDevice1AfterTransformation = devicesAfterTransformation.get( 0 );
+ final DiskCdrom cdromDevice2AfterTransformation = devicesAfterTransformation.get( 1 );
+ assertEquals( StorageType.FILE, cdromDevice1AfterTransformation.getStorageType() );
+ assertEquals( TransformationTestUtils.DEFAULT_VM_CDROM0, cdromDevice1AfterTransformation.getStorageSource() );
+ assertEquals( StorageType.FILE, cdromDevice2AfterTransformation.getStorageType() );
+ assertEquals( TransformationTestUtils.DEFAULT_VM_CDROM1, cdromDevice2AfterTransformation.getStorageSource() );
+ }
+
+ @Test
+ @DisplayName( "Test transformation of VM disk CDROM devices configuration with unspecified input data" )
+ public void testTransformationGenericDiskCdromDevicesNoData() throws TransformationException
+ {
+ final TransformationGenericDiskCdromDevices transformation = new TransformationGenericDiskCdromDevices();
+ final Domain config = TransformationTestUtils.getDefaultDomain();
+ final CommandLineArgs args = TransformationTestUtils.getEmptyCmdLnArgs();
+
+ final ArrayList devicesBeforeTransformation = config.getDiskCdromDevices();
+ assertEquals( 1, devicesBeforeTransformation.size() );
+
+ transformation.transform( config, args );
+
+ final ArrayList devicesAfterTransformation = config.getDiskCdromDevices();
+ assertEquals( 0, devicesAfterTransformation.size() );
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericDiskFloppyDevicesTest.java b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericDiskFloppyDevicesTest.java
new file mode 100644
index 00000000..d4678f4f
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericDiskFloppyDevicesTest.java
@@ -0,0 +1,61 @@
+package org.openslx.runvirt.plugin.qemu.configuration;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+
+import java.util.ArrayList;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.openslx.libvirt.domain.Domain;
+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.transformation.TransformationException;
+
+public class TransformationGenericDiskFloppyDevicesTest
+{
+ @Test
+ @DisplayName( "Test transformation of VM disk floppy devices configuration with specified input data" )
+ public void testTransformationGenericDiskFloppyDevices() throws TransformationException
+ {
+ final TransformationGenericDiskFloppyDevices transformation = new TransformationGenericDiskFloppyDevices();
+ final Domain config = TransformationTestUtils.getDefaultDomain();
+ final CommandLineArgs args = TransformationTestUtils.getDefaultCmdLnArgs();
+
+ final ArrayList devicesBeforeTransformation = config.getDiskFloppyDevices();
+ assertEquals( 1, devicesBeforeTransformation.size() );
+ final DiskFloppy floppyDeviceBeforeTransformation = devicesBeforeTransformation.get( 0 );
+ assertEquals( StorageType.FILE, floppyDeviceBeforeTransformation.getStorageType() );
+ assertNotEquals( TransformationTestUtils.DEFAULT_VM_FLOPPY0,
+ floppyDeviceBeforeTransformation.getStorageSource() );
+
+ transformation.transform( config, args );
+
+ final ArrayList devicesAfterTransformation = config.getDiskFloppyDevices();
+ assertEquals( 2, devicesAfterTransformation.size() );
+ final DiskFloppy floppyDevice1AfterTransformation = devicesAfterTransformation.get( 0 );
+ final DiskFloppy floppyDevice2AfterTransformation = devicesAfterTransformation.get( 1 );
+ assertEquals( StorageType.FILE, floppyDevice1AfterTransformation.getStorageType() );
+ assertEquals( TransformationTestUtils.DEFAULT_VM_FLOPPY0, floppyDevice1AfterTransformation.getStorageSource() );
+ assertEquals( StorageType.FILE, floppyDevice2AfterTransformation.getStorageType() );
+ assertEquals( TransformationTestUtils.DEFAULT_VM_FLOPPY1, floppyDevice2AfterTransformation.getStorageSource() );
+ }
+
+ @Test
+ @DisplayName( "Test transformation of VM disk floppy devices configuration with unspecified input data" )
+ public void testTransformationGenericDiskFloppyDevicesNoData() throws TransformationException
+ {
+ final TransformationGenericDiskFloppyDevices transformation = new TransformationGenericDiskFloppyDevices();
+ final Domain config = TransformationTestUtils.getDefaultDomain();
+ final CommandLineArgs args = TransformationTestUtils.getEmptyCmdLnArgs();
+
+ final ArrayList devicesBeforeTransformation = config.getDiskFloppyDevices();
+ assertEquals( 1, devicesBeforeTransformation.size() );
+
+ transformation.transform( config, args );
+
+ final ArrayList devicesAfterTransformation = config.getDiskFloppyDevices();
+ assertEquals( 0, devicesAfterTransformation.size() );
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericFileSystemDevicesTest.java b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericFileSystemDevicesTest.java
new file mode 100644
index 00000000..38a07e38
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericFileSystemDevicesTest.java
@@ -0,0 +1,61 @@
+package org.openslx.runvirt.plugin.qemu.configuration;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.ArrayList;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+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.transformation.TransformationException;
+
+public class TransformationGenericFileSystemDevicesTest
+{
+ @Test
+ @DisplayName( "Test transformation of VM file system devices configuration with specified input data" )
+ public void testTransformationGenericFileSystemDevices() throws TransformationException
+ {
+ final TransformationGenericFileSystemDevices transformation = new TransformationGenericFileSystemDevices();
+ final Domain config = TransformationTestUtils.getDefaultDomain();
+ final CommandLineArgs args = TransformationTestUtils.getDefaultCmdLnArgs();
+
+ final ArrayList devicesBeforeTransformation = config.getFileSystemDevices();
+ assertEquals( 0, devicesBeforeTransformation.size() );
+
+ transformation.transform( config, args );
+
+ final ArrayList devicesAfterTransformation = config.getFileSystemDevices();
+ assertEquals( 2, devicesAfterTransformation.size() );
+ final FileSystem fs1AfterTransformation = devicesAfterTransformation.get( 0 );
+ final FileSystem fs2AfterTransformation = devicesAfterTransformation.get( 1 );
+ assertEquals( Type.MOUNT, fs1AfterTransformation.getType() );
+ assertEquals( AccessMode.MAPPED, fs1AfterTransformation.getAccessMode() );
+ assertEquals( TransformationTestUtils.DEFAULT_VM_FSSRC0, fs1AfterTransformation.getSource() );
+ assertEquals( TransformationTestUtils.DEFAULT_VM_FSTGT0, fs1AfterTransformation.getTarget() );
+ assertEquals( Type.MOUNT, fs2AfterTransformation.getType() );
+ assertEquals( AccessMode.MAPPED, fs2AfterTransformation.getAccessMode() );
+ assertEquals( TransformationTestUtils.DEFAULT_VM_FSSRC1, fs2AfterTransformation.getSource() );
+ assertEquals( TransformationTestUtils.DEFAULT_VM_FSTGT1, fs2AfterTransformation.getTarget() );
+ }
+
+ @Test
+ @DisplayName( "Test transformation of VM file system devices configuration with unspecified input data" )
+ public void testTransformationGenericFileSystemDevicesNoData() throws TransformationException
+ {
+ final TransformationGenericFileSystemDevices transformation = new TransformationGenericFileSystemDevices();
+ final Domain config = TransformationTestUtils.getDefaultDomain();
+ final CommandLineArgs args = TransformationTestUtils.getEmptyCmdLnArgs();
+
+ final ArrayList devicesBeforeTransformation = config.getFileSystemDevices();
+ assertEquals( 0, devicesBeforeTransformation.size() );
+
+ transformation.transform( config, args );
+
+ final ArrayList devicesAfterTransformation = config.getFileSystemDevices();
+ assertEquals( 0, devicesAfterTransformation.size() );
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericInterfaceDevicesTest.java b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericInterfaceDevicesTest.java
new file mode 100644
index 00000000..6257e98f
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericInterfaceDevicesTest.java
@@ -0,0 +1,58 @@
+package org.openslx.runvirt.plugin.qemu.configuration;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.ArrayList;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.openslx.libvirt.domain.Domain;
+import org.openslx.libvirt.domain.device.Interface;
+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.transformation.TransformationException;
+
+public class TransformationGenericInterfaceDevicesTest
+{
+ @Test
+ @DisplayName( "Test transformation of VM network interface devices configuration with specified input data" )
+ public void testTransformationGenericInterfaceDevices() throws TransformationException
+ {
+ final TransformationGenericInterfaceDevices transformation = new TransformationGenericInterfaceDevices();
+ final Domain config = TransformationTestUtils.getDefaultDomain();
+ final CommandLineArgs args = TransformationTestUtils.getDefaultCmdLnArgs();
+
+ final ArrayList devicesBeforeTransformation = config.getInterfaceDevices();
+ assertEquals( 1, devicesBeforeTransformation.size() );
+
+ transformation.transform( config, args );
+
+ final ArrayList devicesAfterTransformation = config.getInterfaceDevices();
+ assertEquals( 1, devicesAfterTransformation.size() );
+ final Interface interfaceAfterTransformation = devicesAfterTransformation.get( 0 );
+ assertEquals( Type.BRIDGE, interfaceAfterTransformation.getType() );
+ assertEquals( Model.VIRTIO, interfaceAfterTransformation.getModel() );
+ assertEquals( TransformationTestUtils.DEFAULT_VM_MAC0, interfaceAfterTransformation.getMacAddress() );
+ assertEquals( VirtualizationConfigurationQemu.NETWORK_BRIDGE_NAT_DEFAULT,
+ interfaceAfterTransformation.getSource() );
+ }
+
+ @Test
+ @DisplayName( "Test transformation of VM network interface devices configuration with unspecified input data" )
+ public void testTransformationGenericInterfaceDevicesNoData() throws TransformationException
+ {
+ final TransformationGenericInterfaceDevices transformation = new TransformationGenericInterfaceDevices();
+ final Domain config = TransformationTestUtils.getDefaultDomain();
+ final CommandLineArgs args = TransformationTestUtils.getEmptyCmdLnArgs();
+
+ final ArrayList devicesBeforeTransformation = config.getInterfaceDevices();
+ assertEquals( 1, devicesBeforeTransformation.size() );
+
+ transformation.transform( config, args );
+
+ final ArrayList devicesAfterTransformation = config.getInterfaceDevices();
+ assertEquals( 0, devicesAfterTransformation.size() );
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericMemoryTest.java b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericMemoryTest.java
index 812982ee..76f53e40 100644
--- a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericMemoryTest.java
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericMemoryTest.java
@@ -2,6 +2,7 @@ package org.openslx.runvirt.plugin.qemu.configuration;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import java.math.BigInteger;
@@ -32,4 +33,15 @@ public class TransformationGenericMemoryTest
assertEquals( defaultMemory.toString(), config.getMemory().toString() );
assertEquals( defaultMemory.toString(), config.getCurrentMemory().toString() );
}
+
+ @Test
+ @DisplayName( "Test transformation of VM memory configuration with unspecified input data" )
+ public void testTransformationGenericMemoryNoData() throws TransformationException
+ {
+ final TransformationGenericMemory transformation = new TransformationGenericMemory();
+ final Domain config = TransformationTestUtils.getDefaultDomain();
+ final CommandLineArgs args = TransformationTestUtils.getEmptyCmdLnArgs();
+
+ assertThrows( TransformationException.class, () -> transformation.transform( config, args ) );
+ }
}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericNameTest.java b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericNameTest.java
index 2403b83f..b52162d7 100644
--- a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericNameTest.java
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericNameTest.java
@@ -2,6 +2,7 @@ package org.openslx.runvirt.plugin.qemu.configuration;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
@@ -27,4 +28,15 @@ public class TransformationGenericNameTest
assertEquals( TransformationTestUtils.DEFAULT_VM_NAME, config.getName() );
assertEquals( TransformationTestUtils.DEFAULT_VM_DSPLNAME, config.getTitle() );
}
+
+ @Test
+ @DisplayName( "Test transformation of VM (display) name configuration with unspecified input data" )
+ public void testTransformationGenericNameNoData() throws TransformationException
+ {
+ final TransformationGenericName transformation = new TransformationGenericName();
+ final Domain config = TransformationTestUtils.getDefaultDomain();
+ final CommandLineArgs args = TransformationTestUtils.getEmptyCmdLnArgs();
+
+ assertThrows( TransformationException.class, () -> transformation.transform( config, args ) );
+ }
}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericParallelDevicesTest.java b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericParallelDevicesTest.java
new file mode 100644
index 00000000..63fb134c
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericParallelDevicesTest.java
@@ -0,0 +1,53 @@
+package org.openslx.runvirt.plugin.qemu.configuration;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.ArrayList;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+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.transformation.TransformationException;
+
+public class TransformationGenericParallelDevicesTest
+{
+ @Test
+ @DisplayName( "Test transformation of VM parallel devices configuration with specified input data" )
+ public void testTransformationGenericParallelDevices() throws TransformationException
+ {
+ final TransformationGenericParallelDevices transformation = new TransformationGenericParallelDevices();
+ final Domain config = TransformationTestUtils.getDefaultDomain();
+ final CommandLineArgs args = TransformationTestUtils.getDefaultCmdLnArgs();
+
+ final ArrayList devicesBeforeTransformation = config.getParallelDevices();
+ assertEquals( 0, devicesBeforeTransformation.size() );
+
+ transformation.transform( config, args );
+
+ final ArrayList devicesAfterTransformation = config.getParallelDevices();
+ assertEquals( 1, devicesAfterTransformation.size() );
+ final Parallel parallelDeviceAfterTransformation = devicesAfterTransformation.get( 0 );
+ assertEquals( Type.DEV, parallelDeviceAfterTransformation.getType() );
+ assertEquals( TransformationTestUtils.DEFAULT_VM_PARALLEL0, parallelDeviceAfterTransformation.getSource() );
+ }
+
+ @Test
+ @DisplayName( "Test transformation of VM parallel devices configuration with unspecified input data" )
+ public void testTransformationGenericParallelDevicesNoData() throws TransformationException
+ {
+ final TransformationGenericParallelDevices transformation = new TransformationGenericParallelDevices();
+ final Domain config = TransformationTestUtils.getDefaultDomain();
+ final CommandLineArgs args = TransformationTestUtils.getEmptyCmdLnArgs();
+
+ final ArrayList devicesBeforeTransformation = config.getParallelDevices();
+ assertEquals( 0, devicesBeforeTransformation.size() );
+
+ transformation.transform( config, args );
+
+ final ArrayList devicesAfterTransformation = config.getParallelDevices();
+ assertEquals( 0, devicesAfterTransformation.size() );
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericUuidTest.java b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericUuidTest.java
index d42a84eb..8fe20886 100644
--- a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericUuidTest.java
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationGenericUuidTest.java
@@ -2,6 +2,7 @@ package org.openslx.runvirt.plugin.qemu.configuration;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
@@ -25,4 +26,15 @@ public class TransformationGenericUuidTest
assertEquals( TransformationTestUtils.DEFAULT_VM_UUID, config.getUuid() );
}
+
+ @Test
+ @DisplayName( "Test transformation of VM UUID configuration with unspecified input data" )
+ public void testTransformationGenericUuidNoData() throws TransformationException
+ {
+ final TransformationGenericUuid transformation = new TransformationGenericUuid();
+ final Domain config = TransformationTestUtils.getDefaultDomain();
+ final CommandLineArgs args = TransformationTestUtils.getEmptyCmdLnArgs();
+
+ assertThrows( TransformationException.class, () -> transformation.transform( config, args ) );
+ }
}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuArchitectureTest.java b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuArchitectureTest.java
new file mode 100644
index 00000000..50689c4e
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuArchitectureTest.java
@@ -0,0 +1,102 @@
+package org.openslx.runvirt.plugin.qemu.configuration;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import java.io.InputStream;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.openslx.libvirt.capabilities.Capabilities;
+import org.openslx.libvirt.domain.Domain;
+import org.openslx.libvirt.domain.Domain.OsType;
+import org.openslx.libvirt.domain.Domain.Type;
+import org.openslx.libvirt.xml.LibvirtXmlDocumentException;
+import org.openslx.libvirt.xml.LibvirtXmlSerializationException;
+import org.openslx.libvirt.xml.LibvirtXmlTestResources;
+import org.openslx.libvirt.xml.LibvirtXmlValidationException;
+import org.openslx.virtualization.configuration.transformation.TransformationException;
+
+class TransformationSpecificQemuArchitectureStub extends TransformationSpecificQemuArchitecture
+{
+ final String capabilityFileName;
+
+ public TransformationSpecificQemuArchitectureStub( String capabilityFileName )
+ {
+ super( null );
+
+ this.capabilityFileName = capabilityFileName;
+ }
+
+ @Override
+ protected Capabilities getCapabilities() throws TransformationException
+ {
+ final InputStream capabilityContent = LibvirtXmlTestResources.getLibvirtXmlStream( this.capabilityFileName );
+ Capabilities capabilites = null;
+
+ try {
+ capabilites = new Capabilities( capabilityContent );
+ } catch ( LibvirtXmlDocumentException | LibvirtXmlSerializationException | LibvirtXmlValidationException e ) {
+ fail( "Could not create stub for getCapabilities(): " + e.getLocalizedMessage() );
+ }
+
+ return capabilites;
+ }
+}
+
+public class TransformationSpecificQemuArchitectureTest
+{
+ @Test
+ @DisplayName( "Test transformation of VM architecture configuration if KVM required and available" )
+ public void testTransformationSpecificQemuArchitectureKvm() throws TransformationException
+ {
+ final TransformationSpecificQemuArchitectureStub transformation;
+ transformation = new TransformationSpecificQemuArchitectureStub( "qemu-kvm_capabilities_default.xml" );
+ final Domain config = TransformationTestUtils.getDefaultDomain();
+
+ assertEquals( Type.KVM, config.getType() );
+ assertEquals( "x86_64", config.getOsArch() );
+ assertEquals( "pc-q35-5.1", config.getOsMachine() );
+ assertEquals( OsType.HVM, config.getOsType() );
+
+ transformation.transform( config, null );
+
+ assertEquals( Type.KVM, config.getType() );
+ assertEquals( "x86_64", config.getOsArch() );
+ assertEquals( "pc-q35-5.1", config.getOsMachine() );
+ assertEquals( OsType.HVM, config.getOsType() );
+ }
+
+ @Test
+ @DisplayName( "Test transformation of VM architecture configuration if KVM required but not available" )
+ public void testTransformationSpecificQemuArchitectureNoKvm() throws TransformationException
+ {
+ final TransformationSpecificQemuArchitectureStub transformation;
+ transformation = new TransformationSpecificQemuArchitectureStub( "qemu-kvm_capabilities_no-kvm.xml" );
+ final Domain config = TransformationTestUtils.getDefaultDomain();
+
+ assertEquals( Type.KVM, config.getType() );
+ assertEquals( "x86_64", config.getOsArch() );
+ assertEquals( "pc-q35-5.1", config.getOsMachine() );
+ assertEquals( OsType.HVM, config.getOsType() );
+
+ assertThrows( TransformationException.class, () -> transformation.transform( config, null ) );
+ }
+
+ @Test
+ @DisplayName( "Test transformation of VM architecture configuration if version is not supported (machine version too new)" )
+ public void testTransformationSpecificQemuArchitectureMachineVersionDowngrade() throws TransformationException
+ {
+ final TransformationSpecificQemuArchitectureStub transformation;
+ transformation = new TransformationSpecificQemuArchitectureStub( "qemu-kvm_capabilities_old-version.xml" );
+ final Domain config = TransformationTestUtils.getDefaultDomain();
+
+ assertEquals( Type.KVM, config.getType() );
+ assertEquals( "x86_64", config.getOsArch() );
+ assertEquals( "pc-q35-5.1", config.getOsMachine() );
+ assertEquals( OsType.HVM, config.getOsType() );
+
+ assertThrows( TransformationException.class, () -> transformation.transform( config, null ) );
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuSerialDevicesTest.java b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuSerialDevicesTest.java
new file mode 100644
index 00000000..270bfff9
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuSerialDevicesTest.java
@@ -0,0 +1,69 @@
+package org.openslx.runvirt.plugin.qemu.configuration;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.ArrayList;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.openslx.libvirt.domain.Domain;
+import org.openslx.libvirt.domain.device.Serial;
+import org.openslx.libvirt.domain.device.Serial.Type;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+import org.openslx.virtualization.configuration.transformation.TransformationException;
+
+class TransformationSpecificQemuSerialDevicesStub extends TransformationSpecificQemuSerialDevices
+{
+ public TransformationSpecificQemuSerialDevicesStub()
+ {
+ super( null );
+ }
+}
+
+public class TransformationSpecificQemuSerialDevicesTest
+{
+ @Test
+ @DisplayName( "Test transformation of VM serial devices configuration with specified input data" )
+ public void testTransformationGenericSerialDevices() throws TransformationException
+ {
+ final TransformationSpecificQemuSerialDevicesStub transformation = new TransformationSpecificQemuSerialDevicesStub();
+ final Domain config = TransformationTestUtils.getDefaultDomain();
+ final CommandLineArgs args = TransformationTestUtils.getDefaultCmdLnArgs();
+
+ final ArrayList devicesBeforeTransformation = config.getSerialDevices();
+ assertEquals( 1, devicesBeforeTransformation.size() );
+ final Serial serialDeviceBeforeTransformation = devicesBeforeTransformation.get( 0 );
+ assertEquals( Type.PTY, serialDeviceBeforeTransformation.getType() );
+
+ transformation.transform( config, args );
+
+ final ArrayList devicesAfterTransformation = config.getSerialDevices();
+ assertEquals( 2, devicesAfterTransformation.size() );
+ final Serial serialDevice1AfterTransformation = devicesAfterTransformation.get( 0 );
+ assertEquals( Type.PTY, serialDevice1AfterTransformation.getType() );
+ final Serial serialDevice2AfterTransformation = devicesAfterTransformation.get( 1 );
+ assertEquals( Type.DEV, serialDevice2AfterTransformation.getType() );
+ assertEquals( TransformationTestUtils.DEFAULT_VM_SERIAL0, serialDevice2AfterTransformation.getSource() );
+ }
+
+ @Test
+ @DisplayName( "Test transformation of VM serial devices configuration with unspecified input data" )
+ public void testTransformationGenericSerialDevicesNoData() throws TransformationException
+ {
+ final TransformationSpecificQemuSerialDevicesStub transformation = new TransformationSpecificQemuSerialDevicesStub();
+ final Domain config = TransformationTestUtils.getDefaultDomain();
+ final CommandLineArgs args = TransformationTestUtils.getEmptyCmdLnArgs();
+
+ final ArrayList devicesBeforeTransformation = config.getSerialDevices();
+ assertEquals( 1, devicesBeforeTransformation.size() );
+ final Serial serialDeviceBeforeTransformation = devicesBeforeTransformation.get( 0 );
+ assertEquals( Type.PTY, serialDeviceBeforeTransformation.getType() );
+
+ transformation.transform( config, args );
+
+ final ArrayList devicesAfterTransformation = config.getSerialDevices();
+ assertEquals( 1, devicesAfterTransformation.size() );
+ final Serial serialDeviceAfterTransformation = devicesBeforeTransformation.get( 0 );
+ assertEquals( Type.PTY, serialDeviceAfterTransformation.getType() );
+ }
+}
--
cgit v1.2.3-55-g7522
From f7d38bc10b11abadbcd9b12b1784d7108f0a5d7e Mon Sep 17 00:00:00 2001
From: Manuel Bentele
Date: Thu, 10 Jun 2021 10:47:03 +0200
Subject: [qemu] Implement passthrough of NVIDIA GPUs
The implementation adds specified PCI devics of a NVIDIA GPU on the host
system to the final Libvirt domain XML configuration for a NVIDIA GPU
passthrough. In addition to that, the implementation adds support for
the Looking Glass Client to display the framebuffer of the NVIDIA GPU
on the host system through a shared memory device.
---
.../java/org/openslx/runvirt/plugin/qemu/App.java | 32 ++--
.../runvirt/plugin/qemu/cmdln/CommandLineArgs.java | 120 ++++++++++----
.../TransformationSpecificQemuArchitecture.java | 27 ++--
...sformationSpecificQemuGpuPassthroughNvidia.java | 179 ++++++++++++++++++++-
.../runvirt/viewer/ViewerLookingGlassClient.java | 105 ++++++++++++
.../org/openslx/runvirt/plugin/qemu/AppTest.java | 8 +-
.../plugin/qemu/cmdln/CommandLineArgsTest.java | 54 +++++++
...mationSpecificQemuGpuPassthroughNvidiaTest.java | 129 +++++++++++++++
.../configuration/TransformationTestUtils.java | 7 +-
9 files changed, 592 insertions(+), 69 deletions(-)
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/viewer/ViewerLookingGlassClient.java
create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuGpuPassthroughNvidiaTest.java
(limited to 'core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/AppTest.java')
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/App.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/App.java
index a3e1c5b7..5ea7b720 100644
--- a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/App.java
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/App.java
@@ -1,6 +1,7 @@
package org.openslx.runvirt.plugin.qemu;
import java.io.File;
+import java.util.Arrays;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.LogManager;
@@ -29,6 +30,7 @@ import org.openslx.runvirt.plugin.qemu.virtualization.LibvirtHypervisorQemu;
import org.openslx.runvirt.plugin.qemu.virtualization.LibvirtHypervisorQemu.QemuSessionType;
import org.openslx.runvirt.viewer.Viewer;
import org.openslx.runvirt.viewer.ViewerException;
+import org.openslx.runvirt.viewer.ViewerLookingGlassClient;
import org.openslx.runvirt.viewer.ViewerVirtManager;
import org.openslx.runvirt.viewer.ViewerVirtViewer;
import org.openslx.runvirt.virtualization.LibvirtHypervisor;
@@ -185,12 +187,18 @@ public class App
// create specific viewer to display Libvirt VM
final Viewer vmViewer;
- if ( cmdLn.isDebugEnabled() ) {
- // create specific Virtual Machine Manager viewer if debug mode is enabled
- vmViewer = new ViewerVirtManager( vm, hypervisor );
+ if ( cmdLn.isNvidiaGpuPassthroughEnabled() ) {
+ // viewer for GPU passthrough (framebuffer access) is required
+ vmViewer = new ViewerLookingGlassClient( vm, hypervisor, cmdLn.isDebugEnabled() );
} else {
- // create Virtual Viewer if debug mode is disabled
- vmViewer = new ViewerVirtViewer( vm, hypervisor );
+ // viewer for non-GPU passthrough (no framebuffer access) is required
+ if ( cmdLn.isDebugEnabled() ) {
+ // create specific Virtual Machine Manager viewer if debug mode is enabled
+ vmViewer = new ViewerVirtManager( vm, hypervisor );
+ } else {
+ // create Virtual Viewer if debug mode is disabled
+ vmViewer = new ViewerVirtViewer( vm, hypervisor );
+ }
}
// display Libvirt VM with the specific viewer on the screen
@@ -258,16 +266,20 @@ public class App
for ( CmdLnOption option : CmdLnOption.values() ) {
final String paddedLongOption = String.format( "%-" + longOptionLengthMax + "s", option.getLongOption() );
- final String longOptionArgument;
+ String[] longOptionArguments;
// only request and log argument if option has an command line argument
- if ( option.hasArgument() ) {
- longOptionArgument = cmdLn.getArgument( option );
+ if ( option.getNumArguments() > 0 ) {
+ longOptionArguments = cmdLn.getArguments( option );
+
+ if ( longOptionArguments == null ) {
+ longOptionArguments = new String[] { "no argument specified" };
+ }
} else {
- longOptionArgument = new String( "[option has no argument]" );
+ longOptionArguments = new String[] { "option has no argument" };
}
- LOGGER.debug( "\t" + paddedLongOption + ": " + longOptionArgument );
+ LOGGER.debug( "\t" + paddedLongOption + ": " + Arrays.toString( longOptionArguments ) );
}
}
}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/cmdln/CommandLineArgs.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/cmdln/CommandLineArgs.java
index 1fe342b1..589dd197 100644
--- a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/cmdln/CommandLineArgs.java
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/cmdln/CommandLineArgs.java
@@ -1,9 +1,14 @@
package org.openslx.runvirt.plugin.qemu.cmdln;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
@@ -71,8 +76,14 @@ public class CommandLineArgs
private void createCmdLnOptions()
{
for ( CmdLnOption option : CmdLnOption.values() ) {
- this.cmdLnOptions.addOption( option.getShortOption(), option.getLongOption(), option.hasArgument(),
- option.getDescription() );
+ final Option cmdlnOption;
+
+ final boolean hasArg = ( option.getNumArguments() > 0 ) ? true : false;
+ cmdlnOption = new Option( option.getShortOption(), option.getLongOption(), hasArg, option.getDescription() );
+ cmdlnOption.setValueSeparator( ',' );
+ cmdlnOption.setArgs( option.getNumArguments() );
+
+ this.cmdLnOptions.addOption( cmdlnOption );
}
}
@@ -117,6 +128,17 @@ public class CommandLineArgs
return this.cmdLn.getOptionValue( cmdLnOption.getShortOption() );
}
+ /**
+ * Returns the parsed arguments of the specified command line option.
+ *
+ * @param cmdLnOption command line option for that the parsed arguments should be returned.
+ * @return parsed argument of the command line option.
+ */
+ public String[] getArguments( CmdLnOption cmdLnOption )
+ {
+ return this.cmdLn.getOptionValues( cmdLnOption.getShortOption() );
+ }
+
/**
* Returns the presence of the command line option {@link CmdLnOption#HELP}.
*
@@ -345,6 +367,35 @@ public class CommandLineArgs
return this.getArgument( CmdLnOption.VM_FSTGT1 );
}
+ /**
+ * Returns the argument of the command line option {@link CmdLnOption#VM_NVGPUIDS0}.
+ *
+ * @return argument of the command line option {@link CmdLnOption#VM_NVGPUIDS0}.
+ */
+ public List getVmNvGpuIds0()
+ {
+ final String[] nvidiaPciIdsRaw = this.getArguments( CmdLnOption.VM_NVGPUIDS0 );
+ final ArrayList nvidiaPciIds;
+
+ if ( nvidiaPciIdsRaw == null || nvidiaPciIdsRaw.length <= 0 ) {
+ nvidiaPciIds = new ArrayList();
+ } else {
+ nvidiaPciIds = new ArrayList( Arrays.asList( nvidiaPciIdsRaw ) );
+ }
+
+ return nvidiaPciIds;
+ }
+
+ /**
+ * Returns the state whether a passthrough of a NVIDIA GPU is required.
+ *
+ * @return state whether a passthrough of a NVIDIA GPU is required.
+ */
+ public boolean isNvidiaGpuPassthroughEnabled()
+ {
+ return this.getVmNvGpuIds0().size() > 0;
+ }
+
/**
* Command line options for the run-virt QEMU plugin (command line tool).
*
@@ -354,28 +405,31 @@ public class CommandLineArgs
public enum CmdLnOption
{
// @formatter:off
- HELP ( 'h', "help", false, "" ),
- DEBUG ( 'b', "debug", true, "Enable or disable debug mode" ),
- VM_CFGINP ( 'i', "vmcfginp", true, "File name of an existing and filtered Libvirt domain XML configuration file" ),
- VM_CFGOUT ( 'o', "vmcfgout", true, "File name to output a finalized Libvirt domain XML configuration file" ),
- VM_NAME ( 'n', "vmname", true, "Name for the virtual machine" ),
- VM_UUID ( 'u', "vmuuid", true, "UUID for the virtual machine" ),
- VM_DSPLNAME ( 'd', "vmdsplname", true, "Display name for the virtual machine" ),
- VM_OS ( 's', "vmos", true, "Operating system running in the virtual machine" ),
- VM_NCPUS ( 'c', "vmncpus", true, "Number of virtual CPUs for the virtual machine" ),
- VM_MEM ( 'm', "vmmem", true, "Amount of memory for the virtual machine" ),
- VM_HDD0 ( 'r', "vmhdd0", true, "Disk image for the first HDD device" ),
- VM_FLOPPY0 ( 'f', "vmfloppy0", true, "Disk image for the first floppy drive" ),
- VM_FLOPPY1 ( 'g', "vmfloppy1", true, "Disk image for the second floppy drive" ),
- VM_CDROM0 ( 'k', "vmcdrom0", true, "Disk image for the first CDROM drive" ),
- VM_CDROM1 ( 'l', "vmcdrom1", true, "Disk image for the second CDROM drive" ),
- VM_PARALLEL0( 'p', "vmparallel0", true, "Device for the first parallel port interface" ),
- VM_SERIAL0 ( 'q', "vmserial0", true, "Device for the first serial port interface" ),
- VM_MAC0 ( 'a', "vmmac0", true, "MAC address for the first network interface" ),
- VM_FSSRC0 ( 't', "vmfssrc0", true, "Source directory for first file system passthrough (shared folder)" ),
- VM_FSTGT0 ( 'e', "vmfstgt0", true, "Target directory for first file system passthrough (shared folder)" ),
- VM_FSSRC1 ( 'v', "vmfssrc1", true, "Source directory for second file system passthrough (shared folder)" ),
- VM_FSTGT1 ( 'w', "vmfstgt1", true, "Target directory for second file system passthrough (shared folder)" );
+ HELP ( 'h', "help", 0, "" ),
+ DEBUG ( 'b', "debug", 1, "Enable or disable debug mode" ),
+ VM_CFGINP ( 'i', "vmcfginp", 1, "File name of an existing and filtered Libvirt domain XML configuration file" ),
+ VM_CFGOUT ( 'o', "vmcfgout", 1, "File name to output a finalized Libvirt domain XML configuration file" ),
+ VM_NAME ( 'n', "vmname", 1, "Name for the virtual machine" ),
+ VM_UUID ( 'u', "vmuuid", 1, "UUID for the virtual machine" ),
+ VM_DSPLNAME ( 'd', "vmdsplname", 1, "Display name for the virtual machine" ),
+ VM_OS ( 's', "vmos", 1, "Operating system running in the virtual machine" ),
+ VM_NCPUS ( 'c', "vmncpus", 1, "Number of virtual CPUs for the virtual machine" ),
+ VM_MEM ( 'm', "vmmem", 1, "Amount of memory for the virtual machine" ),
+ VM_HDD0 ( 'r', "vmhdd0", 1, "Disk image for the first HDD device" ),
+ VM_FLOPPY0 ( 'f', "vmfloppy0", 1, "Disk image for the first floppy drive" ),
+ VM_FLOPPY1 ( 'g', "vmfloppy1", 1, "Disk image for the second floppy drive" ),
+ VM_CDROM0 ( 'k', "vmcdrom0", 1, "Disk image for the first CDROM drive" ),
+ VM_CDROM1 ( 'l', "vmcdrom1", 1, "Disk image for the second CDROM drive" ),
+ VM_PARALLEL0( 'p', "vmparallel0", 1, "Device for the first parallel port interface" ),
+ VM_SERIAL0 ( 'q', "vmserial0", 1, "Device for the first serial port interface" ),
+ VM_MAC0 ( 'a', "vmmac0", 1, "MAC address for the first network interface" ),
+ VM_FSSRC0 ( 't', "vmfssrc0", 1, "Source directory for first file system passthrough (shared folder)" ),
+ VM_FSTGT0 ( 'e', "vmfstgt0", 1, "Target directory for first file system passthrough (shared folder)" ),
+ VM_FSSRC1 ( 'v', "vmfssrc1", 1, "Source directory for second file system passthrough (shared folder)" ),
+ VM_FSTGT1 ( 'w', "vmfstgt1", 1, "Target directory for second file system passthrough (shared folder)" ),
+ VM_NVGPUIDS0( 'y', "vmnvgpuids0", 2, "PCI device description and address for passthrough of the first Nvidia GPU. " +
+ "The argument follow the pattern: " +
+ "\":,::.\"" );
// @formatter:on
/**
@@ -389,9 +443,9 @@ public class CommandLineArgs
private final String longOption;
/**
- * Stores the presence of an argument for the command line option.
+ * Stores the number of arguments for the command line option.
*/
- private final boolean hasArgument;
+ private final int numArguments;
/**
* Stores the textual description of the command line option.
@@ -403,14 +457,14 @@ public class CommandLineArgs
*
* @param shortOption {@link Character} for the short command line option.
* @param longOption {@link String} for the long command line option.
- * @param hasArgument presence of an argument for the command line option.
+ * @param numArguments number of arguments for the command line option.
* @param description textual description of the command line option.
*/
- CmdLnOption( char shortOption, String longOption, boolean hasArgument, String description )
+ CmdLnOption( char shortOption, String longOption, int numArguments, String description )
{
this.shortOption = shortOption;
this.longOption = longOption;
- this.hasArgument = hasArgument;
+ this.numArguments = numArguments;
this.description = description;
}
@@ -435,13 +489,13 @@ public class CommandLineArgs
}
/**
- * Returns the presence of an argument for the command line option.
+ * Returns the number of arguments for the command line option.
*
- * @return presence of an argument for the command line option.
+ * @return number of arguments for the command line option.
*/
- public boolean hasArgument()
+ public int getNumArguments()
{
- return this.hasArgument;
+ return this.numArguments;
}
/**
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
index f507237d..a51c829d 100644
--- 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
@@ -29,14 +29,6 @@ public class TransformationSpecificQemuArchitecture
*/
private static final String NAME = "QEMU Architecture [CPU architecture, machine type, ...]";
- /**
- * Capabilities of the Libvirt/QEMU hypervisor.
- *
- * @implNote This field is used as an instance of a singelton. Please always use
- * {@link #getCapabilities()} to retrieve the {@code capabilities} instance.
- */
- private Capabilities capabilities = null;
-
/**
* Creates a new architecture transformation for Libvirt/QEMU virtualization configurations.
*
@@ -70,18 +62,17 @@ public class TransformationSpecificQemuArchitecture
*/
protected Capabilities getCapabilities() throws TransformationException
{
- // retrieve capabilities from QEMU hypervisor only once
- if ( this.capabilities == null ) {
- try {
- this.capabilities = this.getVirtualizer().getCapabilites();
- } catch ( LibvirtHypervisorException e ) {
- final String errorMsg = new String(
- "Failed to get host capabilities from QEMU virtualizer: " + e.getLocalizedMessage() );
- throw new TransformationException( errorMsg );
- }
+ 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 this.capabilities;
+ return capabilities;
}
/**
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
index c41f989c..a22bf027 100644
--- 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
@@ -1,8 +1,19 @@
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;
@@ -20,6 +31,31 @@ public class TransformationSpecificQemuGpuPassthroughNvidia
*/
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.
@@ -31,6 +67,63 @@ public class TransformationSpecificQemuGpuPassthroughNvidia
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 validateParseNvidiaPciIds( List pciIds )
+ throws TransformationException
+ {
+ final List parsedPciAddresses = new ArrayList();
+
+ if ( pciIds != null && pciIds.size() > 0 ) {
+ // abort if arguments do not follow the pattern:
+ //
+ // [0]: :
+ // [1]: ::.
+ // [2]: :
+ // [3]: ::.
+ // ...
+ //
+ 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.
*
@@ -43,6 +136,55 @@ public class TransformationSpecificQemuGpuPassthroughNvidia
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
@@ -51,9 +193,40 @@ public class TransformationSpecificQemuGpuPassthroughNvidia
// validate configuration and input arguments
this.validateInputs( config, args );
- // check if IOMMU support is available on the host
+ // check if passthrough of Nvidia GPU takes place
+ if ( args.isNvidiaGpuPassthroughEnabled() ) {
+ // validate submitted PCI IDs
+ final List 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 );
+ }
- // TODO: implement Nvidia hypervisor shadowing
- // call this filter at the end, since -> override of software graphics to 'none' necessary
+ // 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/viewer/ViewerLookingGlassClient.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/viewer/ViewerLookingGlassClient.java
new file mode 100644
index 00000000..cea9ccd8
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/viewer/ViewerLookingGlassClient.java
@@ -0,0 +1,105 @@
+package org.openslx.runvirt.viewer;
+
+import org.openslx.runvirt.virtualization.LibvirtHypervisor;
+import org.openslx.runvirt.virtualization.LibvirtVirtualMachine;
+import org.openslx.virtualization.Version;
+
+/**
+ * Looking Glass Client to view the exposed framebuffer (through a shared memory) of a virtual
+ * machine running the Looking Glass Host application.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class ViewerLookingGlassClient extends Viewer
+{
+ /**
+ * Name of the Looking Glass Client program.
+ */
+ private final static String NAME = "looking-glass-client";
+
+ /**
+ * Maximum number of supported displays by the Looking Glass Client.
+ */
+ private final static int NUM_SUPPORTED_DISPLAYS = 1;
+
+ /**
+ * File name of the shared memory file to receive display content from the Looking Glass Host.
+ */
+ private final static String SHARED_MEMORY_FILENAME = "/dev/shm/looking-glass";
+
+ /**
+ * State whether showing debug information during virtual machine rendering or not.
+ */
+ private final boolean debug;
+
+ /**
+ * Creates a new Looking Glass Client for a Libvirt virtual machine running on a Libvirt
+ * hypervisor.
+ *
+ * @param machine virtual machine to display.
+ * @param hypervisor remote (hypervisor) endpoint for the viewer to connect to.
+ */
+ public ViewerLookingGlassClient( LibvirtVirtualMachine machine, LibvirtHypervisor hypervisor )
+ {
+ this( machine, hypervisor, false );
+ }
+
+ /**
+ * Creates a new Looking Glass Client for a Libvirt virtual machine running on a Libvirt
+ * hypervisor.
+ *
+ * @param machine virtual machine to display.
+ * @param hypervisor remote (hypervisor) endpoint for the viewer to connect to.
+ * @param debug state whether showing debug information during virtual machine rendering or not.
+ */
+ public ViewerLookingGlassClient( LibvirtVirtualMachine machine, LibvirtHypervisor hypervisor, boolean debug )
+ {
+ super( ViewerLookingGlassClient.NAME, ViewerLookingGlassClient.NUM_SUPPORTED_DISPLAYS, machine, hypervisor );
+
+ this.debug = debug;
+ }
+
+ /**
+ * Returns the state whether showing debug information during virtual machine rendering or not.
+ *
+ * @return state whether showing debug information during virtual machine rendering or not.
+ */
+ public boolean isDebugEnabled()
+ {
+ return this.debug;
+ }
+
+ @Override
+ public Version getVersion() throws ViewerException
+ {
+ return null;
+ }
+
+ @Override
+ public void render() throws ViewerException
+ {
+ // execute viewer process with arguments:
+ // in non-debug mode:
+ // "looking-glass-client app:shmFile= win:fullScreen=yes spice:enable=yes win:alerts=no"
+ // in debug mode:
+ // "looking-glass-client app:shmFile= win:fullScreen=yes spice:enable=yes win:alerts=yes win:showFPS=yes"
+ final String[] viewerParameters;
+ if ( this.isDebugEnabled() ) {
+ viewerParameters = new String[] {
+ "app:shmFile=" + ViewerLookingGlassClient.SHARED_MEMORY_FILENAME,
+ "win:fullScreen=yes",
+ "spice:enable=yes",
+ "win:alerts=no" };
+ } else {
+ viewerParameters = new String[] {
+ "app:shmFile=" + ViewerLookingGlassClient.SHARED_MEMORY_FILENAME,
+ "win:fullScreen=yes",
+ "spice:enable=yes",
+ "win:alerts=yes",
+ "win:showFPS=yes" };
+ }
+
+ ViewerUtils.executeViewer( ViewerLookingGlassClient.NAME, viewerParameters );
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/AppTest.java b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/AppTest.java
index 1db1525b..d0eef82a 100644
--- a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/AppTest.java
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/AppTest.java
@@ -63,7 +63,7 @@ public class AppTest
assertTrue( shortHelpOptionCorrectOutput.contains( App.APP_DESC ) );
// test that no error was logged and output is available
- assertEquals( 2160, shortHelpOptionCorrectOutput.length() );
+ assertEquals( 2503, shortHelpOptionCorrectOutput.length() );
assertEquals( 0, shortHelpOptionCorrectErrOutput.length() );
}
@@ -91,7 +91,7 @@ public class AppTest
assertTrue( longHelpOptionCorrectOutput.contains( App.APP_DESC ) );
// test that no error was logged and output is available
- assertEquals( 2160, longHelpOptionCorrectOutput.length() );
+ assertEquals( 2503, longHelpOptionCorrectOutput.length() );
assertEquals( 0, longHelpOptionCorrectErrOutput.length() );
}
@@ -119,7 +119,7 @@ public class AppTest
assertTrue( shortHelpOptionIncorrectOutput.contains( App.APP_DESC ) );
// test that error was logged and output is available
- assertEquals( 2160, shortHelpOptionIncorrectOutput.length() );
+ assertEquals( 2503, shortHelpOptionIncorrectOutput.length() );
assertEquals( 0, shortHelpOptionIncorrectErrOutput.length() );
}
@@ -147,7 +147,7 @@ public class AppTest
assertTrue( longHelpOptionIncorrectOutput.contains( App.APP_DESC ) );
// test that error was logged and output is available
- assertEquals( 2160, longHelpOptionIncorrectOutput.length() );
+ assertEquals( 2503, longHelpOptionIncorrectOutput.length() );
assertEquals( 0, longHelpOptionIncorrectErrOutput.length() );
}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/cmdln/CommandLineArgsTest.java b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/cmdln/CommandLineArgsTest.java
index 972f5e4b..77522bd6 100644
--- a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/cmdln/CommandLineArgsTest.java
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/cmdln/CommandLineArgsTest.java
@@ -6,6 +6,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.File;
+import java.util.List;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
@@ -28,6 +29,8 @@ public class CommandLineArgsTest
private static final String CMDLN_TEST_PARPORT = "/dev/parport0";
private static final String CMDLN_TEST_SERPORT = "/dev/ttyS0";
private static final String CMDLN_TEST_MAC = "02:42:8e:77:1b:e6";
+ private static final String CMDLN_TEST_NVGPU_DESC = "10de:0ff9";
+ private static final String CMDLN_TEST_NVGPU_ADDR = "0000:00:01.0";
// @formatter:on
@Test
@@ -695,4 +698,55 @@ public class CommandLineArgsTest
assertEquals( CMDLN_TEST_NAME, cmdLn.getVmFsTgt1() );
}
+
+ @Test
+ @DisplayName( "Test the parsing of NVIDIA PCI IDs command line option for the first GPU passthrough (short version)" )
+ public void testCmdlnOptionVmNvGpuIds0Short() throws CommandLineArgsException
+ {
+ final String[] args = {
+ CMDLN_PREFIX_OPTION_SHORT + CmdLnOption.VM_NVGPUIDS0.getShortOption(),
+ CMDLN_TEST_NVGPU_DESC, CMDLN_TEST_NVGPU_ADDR
+ };
+
+ CommandLineArgs cmdLn = new CommandLineArgs( args );
+
+ final List nvidiaGpuIds = cmdLn.getVmNvGpuIds0();
+ assertEquals( 2, nvidiaGpuIds.size() );
+ assertEquals( CMDLN_TEST_NVGPU_DESC, nvidiaGpuIds.get( 0 ) );
+ assertEquals( CMDLN_TEST_NVGPU_ADDR, nvidiaGpuIds.get( 1 ) );
+ }
+
+ @Test
+ @DisplayName( "Test the parsing of NVIDIA PCI IDs command line option for the first GPU passthrough (long version)" )
+ public void testCmdlnOptionVmNvGpuIds0Long() throws CommandLineArgsException
+ {
+ final String[] args = {
+ CMDLN_PREFIX_OPTION_LONG + CmdLnOption.VM_NVGPUIDS0.getLongOption(),
+ CMDLN_TEST_NVGPU_DESC, CMDLN_TEST_NVGPU_ADDR
+ };
+
+ CommandLineArgs cmdLn = new CommandLineArgs( args );
+
+ final List nvidiaGpuIds = cmdLn.getVmNvGpuIds0();
+ assertEquals( 2, nvidiaGpuIds.size() );
+ assertEquals( CMDLN_TEST_NVGPU_DESC, nvidiaGpuIds.get( 0 ) );
+ assertEquals( CMDLN_TEST_NVGPU_ADDR, nvidiaGpuIds.get( 1 ) );
+ }
+
+ @Test
+ @DisplayName( "Test whether a NVIDIA GPU passthrough is enabled" )
+ public void testIsNvidiaGpuPassthroughEnabled() throws CommandLineArgsException
+ {
+ final String[] args1 = {
+ CMDLN_PREFIX_OPTION_LONG + CmdLnOption.VM_NVGPUIDS0.getLongOption(),
+ CMDLN_TEST_NVGPU_DESC, CMDLN_TEST_NVGPU_ADDR
+ };
+ final String[] args2 = {};
+
+ CommandLineArgs cmdLn1 = new CommandLineArgs( args1 );
+ CommandLineArgs cmdLn2 = new CommandLineArgs( args2 );
+
+ assertTrue( cmdLn1.isNvidiaGpuPassthroughEnabled() );
+ assertFalse( cmdLn2.isNvidiaGpuPassthroughEnabled() );
+ }
}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuGpuPassthroughNvidiaTest.java b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuGpuPassthroughNvidiaTest.java
new file mode 100644
index 00000000..3a9624b3
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuGpuPassthroughNvidiaTest.java
@@ -0,0 +1,129 @@
+package org.openslx.runvirt.plugin.qemu.configuration;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.util.List;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+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.Shmem;
+import org.openslx.libvirt.domain.device.Video;
+import org.openslx.libvirt.xml.LibvirtXmlDocumentException;
+import org.openslx.libvirt.xml.LibvirtXmlSerializationException;
+import org.openslx.libvirt.xml.LibvirtXmlTestResources;
+import org.openslx.libvirt.xml.LibvirtXmlValidationException;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+import org.openslx.virtualization.configuration.transformation.TransformationException;
+
+class TransformationSpecificQemuGpuPassthroughNvidiaStub extends TransformationSpecificQemuGpuPassthroughNvidia
+{
+ final String capabilityFileName;
+
+ public TransformationSpecificQemuGpuPassthroughNvidiaStub( String capabilityFileName )
+ {
+ super( null );
+
+ this.capabilityFileName = capabilityFileName;
+ }
+
+ @Override
+ protected Capabilities getCapabilities() throws TransformationException
+ {
+ final InputStream capabilityContent = LibvirtXmlTestResources.getLibvirtXmlStream( this.capabilityFileName );
+ Capabilities capabilites = null;
+
+ try {
+ capabilites = new Capabilities( capabilityContent );
+ } catch ( LibvirtXmlDocumentException | LibvirtXmlSerializationException | LibvirtXmlValidationException e ) {
+ fail( "Could not create stub for getCapabilities(): " + e.getLocalizedMessage() );
+ }
+
+ return capabilites;
+ }
+}
+
+public class TransformationSpecificQemuGpuPassthroughNvidiaTest
+{
+ @Test
+ @DisplayName( "Test transformation of VM GPU passthrough configuration if NVIDIA GPU passthrouh is required" )
+ public void testTransformationSpecificQemuGpuPassthroughNvidia() throws TransformationException
+ {
+ final TransformationSpecificQemuGpuPassthroughNvidiaStub transformation;
+ transformation = new TransformationSpecificQemuGpuPassthroughNvidiaStub( "qemu-kvm_capabilities_default.xml" );
+ final Domain config = TransformationTestUtils.getDefaultDomain();
+ final CommandLineArgs args = TransformationTestUtils.getDefaultCmdLnArgs();
+
+ transformation.transform( config, args );
+
+ final List pciDevices = config.getHostdevPciDevices();
+ assertNotNull( pciDevices );
+ assertEquals( 1, pciDevices.size() );
+
+ final HostdevPci pciDevice = pciDevices.get( 0 );
+ assertTrue( pciDevice.isManaged() );
+ assertEquals( HostdevPciDeviceAddress.valueOf( TransformationTestUtils.DEFAULT_VM_GPU0_ADDR ),
+ pciDevice.getSource() );
+
+ final List shmemDevices = config.getShmemDevices();
+ assertNotNull( shmemDevices );
+ assertEquals( 1, shmemDevices.size() );
+
+ final Shmem shmemDevice = shmemDevices.get( 0 );
+ assertEquals( "looking-glass", shmemDevice.getName() );
+ assertEquals( Shmem.Model.IVSHMEM_PLAIN, shmemDevice.getModel() );
+ assertEquals( BigInteger.valueOf( 67108864 ).toString(), shmemDevice.getSize().toString() );
+
+ assertEquals( TransformationSpecificQemuGpuPassthroughNvidia.HYPERV_VENDOR_ID,
+ config.getFeatureHypervVendorIdValue() );
+ assertTrue( config.isFeatureHypervVendorIdStateOn() );
+ assertTrue( config.isFeatureKvmHiddenStateOn() );
+
+ final List