summaryrefslogtreecommitdiffstats
path: root/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/App.java
diff options
context:
space:
mode:
Diffstat (limited to 'core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/App.java')
-rw-r--r--core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/App.java285
1 files changed, 285 insertions, 0 deletions
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
new file mode 100644
index 00000000..5ea7b720
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/App.java
@@ -0,0 +1,285 @@
+package org.openslx.runvirt.plugin.qemu;
+
+import java.io.File;
+import java.util.Arrays;
+
+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.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.TransformationGenericCpu;
+import org.openslx.runvirt.plugin.qemu.configuration.TransformationGenericDiskCdromDevices;
+import org.openslx.runvirt.plugin.qemu.configuration.TransformationGenericDiskFloppyDevices;
+import org.openslx.runvirt.plugin.qemu.configuration.TransformationGenericDiskStorageDevices;
+import org.openslx.runvirt.plugin.qemu.configuration.TransformationGenericFileSystemDevices;
+import org.openslx.runvirt.plugin.qemu.configuration.TransformationGenericInterfaceDevices;
+import org.openslx.runvirt.plugin.qemu.configuration.TransformationGenericMemory;
+import org.openslx.runvirt.plugin.qemu.configuration.TransformationGenericName;
+import org.openslx.runvirt.plugin.qemu.configuration.TransformationGenericParallelDevices;
+import org.openslx.runvirt.plugin.qemu.configuration.TransformationSpecificQemuSerialDevices;
+import org.openslx.runvirt.plugin.qemu.configuration.TransformationGenericUuid;
+import org.openslx.runvirt.plugin.qemu.configuration.TransformationSpecificQemuArchitecture;
+import org.openslx.runvirt.plugin.qemu.configuration.TransformationSpecificQemuGpuPassthroughNvidia;
+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;
+import org.openslx.runvirt.virtualization.LibvirtHypervisorException;
+import org.openslx.runvirt.virtualization.LibvirtVirtualMachine;
+import org.openslx.runvirt.virtualization.LibvirtVirtualMachineException;
+import org.openslx.virtualization.configuration.transformation.TransformationException;
+import org.openslx.virtualization.configuration.transformation.TransformationManager;
+
+/**
+ * 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).
+ */
+ public static final String APP_NAME = "run-virt QEMU plugin";
+
+ /**
+ * Stores description of the run-virt QEMU plugin (command line tool).
+ */
+ 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).
+ */
+ public 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 )
+ {
+ // 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 );
+
+ // 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 transformation manager to finalize VM configuration
+ final TransformationManager<Domain, CommandLineArgs> transformationManager;
+ transformationManager = new TransformationManager<Domain, CommandLineArgs>( config, cmdLn );
+
+ // register necessary transformations to finalize configuration template
+ transformationManager.register( new TransformationGenericName(), true );
+ transformationManager.register( new TransformationGenericUuid(), true );
+ transformationManager.register( new TransformationGenericCpu(), true );
+ transformationManager.register( new TransformationGenericMemory(), true );
+ transformationManager.register( new TransformationGenericDiskStorageDevices(), true );
+ transformationManager.register( new TransformationGenericDiskCdromDevices(), true );
+ transformationManager.register( new TransformationGenericDiskFloppyDevices(), true );
+ transformationManager.register( new TransformationGenericInterfaceDevices(), true );
+ transformationManager.register( new TransformationGenericParallelDevices(), true );
+ transformationManager.register( new TransformationGenericFileSystemDevices(), true );
+
+ // register QEMU specific transformations to finalize configuration template
+ if ( hypervisor instanceof LibvirtHypervisorQemu ) {
+ final LibvirtHypervisorQemu hypervisorQemu = LibvirtHypervisorQemu.class.cast( hypervisor );
+
+ transformationManager.register( new TransformationSpecificQemuArchitecture( hypervisorQemu ), true );
+ transformationManager.register( new TransformationSpecificQemuSerialDevices( hypervisorQemu ), true );
+ transformationManager.register( new TransformationSpecificQemuGpuPassthroughNvidia( hypervisorQemu ), false );
+ }
+
+ // finalize Libvirt VM configuration template
+ try {
+ transformationManager.transform();
+ } catch ( TransformationException 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 Libvirt 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 );
+ }
+
+ // start defined Libvirt VM
+ try {
+ vm.start();
+ } catch ( LibvirtVirtualMachineException e ) {
+ LOGGER.error( "Failed to start defined VM: " + e.getLocalizedMessage() );
+ hypervisor.close();
+ System.exit( 7 );
+ }
+
+ // create specific viewer to display Libvirt VM
+ final Viewer vmViewer;
+ if ( cmdLn.isNvidiaGpuPassthroughEnabled() ) {
+ // viewer for GPU passthrough (framebuffer access) is required
+ vmViewer = new ViewerLookingGlassClient( vm, hypervisor, cmdLn.isDebugEnabled() );
+ } else {
+ // 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
+ try {
+ vmViewer.display();
+ } catch ( ViewerException e ) {
+ LOGGER.error( "Failed to display VM: " + e.getLocalizedMessage() );
+ hypervisor.close();
+ System.exit( 8 );
+ }
+
+ // undefine VM after usage
+ try {
+ hypervisor.deregisterVm( vm );
+ } catch ( LibvirtHypervisorException | LibvirtVirtualMachineException e ) {
+ LOGGER.error( "Failed to undefine VM: " + e.getLocalizedMessage() );
+ hypervisor.close();
+ System.exit( 9 );
+ }
+
+ // close connection to hypervisor
+ hypervisor.close();
+
+ // return with successful exit code
+ System.exit( 0 );
+ }
+
+ /**
+ * 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() );
+ String[] longOptionArguments;
+
+ // only request and log argument if option has an command line argument
+ if ( option.getNumArguments() > 0 ) {
+ longOptionArguments = cmdLn.getArguments( option );
+
+ if ( longOptionArguments == null ) {
+ longOptionArguments = new String[] { "no argument specified" };
+ }
+ } else {
+ longOptionArguments = new String[] { "option has no argument" };
+ }
+
+ LOGGER.debug( "\t" + paddedLongOption + ": " + Arrays.toString( longOptionArguments ) );
+ }
+ }
+}