From 7a4522d6b59ad2936e5ce0ed466f57b8546991b3 Mon Sep 17 00:00:00 2001 From: Manuel Bentele Date: Tue, 9 Nov 2021 14:18:51 +0100 Subject: [qemu] Add automatic firmware path transformation for UEFI based VMs --- .../vmchooser/plugins/qemukvm/run-virt.include | 4 + core/modules/qemu/runvirt-plugin-qemu/pom.xml | 6 + .../java/org/openslx/runvirt/plugin/qemu/App.java | 2 + .../runvirt/plugin/qemu/cmdln/CommandLineArgs.java | 11 + .../TransformationSpecificQemuFirmware.java | 289 +++++++++++++++++++++ .../org/openslx/runvirt/plugin/qemu/AppTest.java | 8 +- .../plugin/qemu/cmdln/CommandLineArgsTest.java | 28 ++ .../TransformationSpecificQemuFirmwareTest.java | 60 +++++ .../configuration/TransformationTestResources.java | 11 +- .../configuration/TransformationTestUtils.java | 3 + .../qemu/firmware/50-edk2-i386-secure.json | 34 +++ .../qemu/firmware/50-edk2-x86_64-secure.json | 35 +++ .../resources/qemu/firmware/60-edk2-aarch64.json | 31 +++ .../test/resources/qemu/firmware/60-edk2-arm.json | 31 +++ .../test/resources/qemu/firmware/60-edk2-i386.json | 33 +++ .../resources/qemu/firmware/60-edk2-x86_64.json | 34 +++ 16 files changed, 610 insertions(+), 10 deletions(-) create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuFirmware.java create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuFirmwareTest.java create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/test/resources/qemu/firmware/50-edk2-i386-secure.json create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/test/resources/qemu/firmware/50-edk2-x86_64-secure.json create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/test/resources/qemu/firmware/60-edk2-aarch64.json create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/test/resources/qemu/firmware/60-edk2-arm.json create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/test/resources/qemu/firmware/60-edk2-i386.json create mode 100644 core/modules/qemu/runvirt-plugin-qemu/src/test/resources/qemu/firmware/60-edk2-x86_64.json (limited to 'core/modules/qemu') diff --git a/core/modules/qemu/data/opt/openslx/vmchooser/plugins/qemukvm/run-virt.include b/core/modules/qemu/data/opt/openslx/vmchooser/plugins/qemukvm/run-virt.include index 1f61f5d9..3e0aa68c 100644 --- a/core/modules/qemu/data/opt/openslx/vmchooser/plugins/qemukvm/run-virt.include +++ b/core/modules/qemu/data/opt/openslx/vmchooser/plugins/qemukvm/run-virt.include @@ -54,6 +54,9 @@ run_plugin() { writelog "Failed to set up mediated device (Intel GVT-g) for GPU passthrough!" fi + # set path to QEMU firmware specification files + local firmware_path="/usr/share/qemu/firmware" + # set debug related options if [ "${DEBUG}" = "true" ]; then # write finalized config in debug mode to temporary folder for debugging purposes @@ -75,6 +78,7 @@ run_plugin() { VIRTCMDOPTS=( "-jar" "${QEMU_PLUGIN_DIR}/runvirt-plugin-qemu.jar" ) notempty DEBUG && VIRTCMDOPTS+=( "-debug" "${DEBUG}" ) + notempty firmware_path && VIRTCMDOPTS+=( "-firmware" "${firmware_path}" ) notempty VM_CLEANNAME && VIRTCMDOPTS+=( "-vmname" "${VM_CLEANNAME}" ) notempty VM_DISPLAYNAME && VIRTCMDOPTS+=( "-vmdsplname" "${VM_DISPLAYNAME}" ) notempty VM_OS_TYPE && VIRTCMDOPTS+=( "-vmos" "${VM_OS_TYPE}" ) diff --git a/core/modules/qemu/runvirt-plugin-qemu/pom.xml b/core/modules/qemu/runvirt-plugin-qemu/pom.xml index 893f8d5c..6354a4e9 100644 --- a/core/modules/qemu/runvirt-plugin-qemu/pom.xml +++ b/core/modules/qemu/runvirt-plugin-qemu/pom.xml @@ -83,6 +83,11 @@ 1.7.25 compile + + com.google.code.gson + gson + 2.8.8 + com.ginsberg junit5-system-exit @@ -226,6 +231,7 @@ ${basedir}/src/test/resources libvirt/xml/* + qemu/firmware/* 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 e1c2e311..86ea6e58 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 @@ -25,6 +25,7 @@ import org.openslx.runvirt.plugin.qemu.configuration.TransformationGenericParall 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.TransformationSpecificQemuFirmware; import org.openslx.runvirt.plugin.qemu.configuration.TransformationSpecificQemuGpuPassthroughNvidia; import org.openslx.runvirt.plugin.qemu.configuration.TransformationSpecificQemuGraphics; import org.openslx.runvirt.plugin.qemu.configuration.TransformationSpecificQemuMdevPassthroughIntel; @@ -147,6 +148,7 @@ public class App final LibvirtHypervisorQemu hypervisorQemu = LibvirtHypervisorQemu.class.cast( hypervisor ); transformationManager.register( new TransformationSpecificQemuArchitecture( hypervisorQemu ), true ); + transformationManager.register( new TransformationSpecificQemuFirmware( hypervisorQemu ), true ); transformationManager.register( new TransformationSpecificQemuGraphics( hypervisorQemu ), true ); transformationManager.register( new TransformationSpecificQemuSerialDevices( hypervisorQemu ), true ); transformationManager.register( new TransformationSpecificQemuMdevPassthroughIntel( hypervisorQemu ), false ); 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 cc989c75..49825813 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 @@ -160,6 +160,16 @@ public class CommandLineArgs return ( "true".equals( debugArg ) ) ? true : false; } + /** + * Returns the argument of the command line option {@link CmdLnOption#FIRMWARE}. + * + * @return argument of the command line option {@link CmdLnOption#FIRMWARE}. + */ + public String getFirmware() + { + return this.getArgument( CmdLnOption.FIRMWARE ); + } + /** * Returns the argument of the command line option {@link CmdLnOption#VM_CFGINP}. * @@ -427,6 +437,7 @@ public class CommandLineArgs // @formatter:off HELP ( 'h', "help", 0, "" ), DEBUG ( 'b', "debug", 1, "Enable or disable debug mode" ), + FIRMWARE ( 'x', "firmware", 1, "Path to QEMU firmware specifications directory" ), 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" ), diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuFirmware.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuFirmware.java new file mode 100644 index 00000000..6be0368e --- /dev/null +++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuFirmware.java @@ -0,0 +1,289 @@ +package org.openslx.runvirt.plugin.qemu.configuration; + +import java.io.File; +import java.io.FileFilter; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.Reader; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.function.Predicate; + +import org.openslx.libvirt.domain.Domain; +import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs; +import org.openslx.runvirt.plugin.qemu.virtualization.LibvirtHypervisorQemu; +import org.openslx.util.LevenshteinDistance; +import org.openslx.virtualization.configuration.transformation.TransformationException; +import org.openslx.virtualization.configuration.transformation.TransformationSpecific; + +import com.google.gson.Gson; +import com.google.gson.JsonIOException; +import com.google.gson.JsonSyntaxException; +import com.google.gson.annotations.SerializedName; + +class QemuFirmware +{ + @SerializedName( "description" ) + private String description; + @SerializedName( "interface-types" ) + private ArrayList interfaceTypes; + @SerializedName( "mapping" ) + private QemuFirmwareMapping mapping; + @SerializedName( "targets" ) + private ArrayList targets; + @SerializedName( "features" ) + private ArrayList features; + @SerializedName( "tags" ) + private ArrayList tags; + + public String getDescription() + { + return description; + } + + public ArrayList getInterfaceTypes() + { + return interfaceTypes; + } + + public QemuFirmwareMapping getMapping() + { + return mapping; + } + + public ArrayList getTargets() + { + return targets; + } + + public ArrayList getFeatures() + { + return features; + } + + public ArrayList getTags() + { + return tags; + } +} + +class QemuFirmwareMapping +{ + @SerializedName( "device" ) + private String device; + @SerializedName( "executable" ) + private QemuFirmwareMappingExecutable executable; + @SerializedName( "nvram-template" ) + private QemuFirmwareMappingNvramTemplate nvramTemplate; + + public String getDevice() + { + return device; + } + + public QemuFirmwareMappingExecutable getExecutable() + { + return executable; + } + + public QemuFirmwareMappingNvramTemplate getNvramTemplate() + { + return nvramTemplate; + } +} + +class QemuFirmwareMappingExecutable +{ + @SerializedName( "filename" ) + private String fileName; + @SerializedName( "format" ) + private String format; + + public String getFileName() + { + return fileName; + } + + public String getFormat() + { + return format; + } +} + +class QemuFirmwareMappingNvramTemplate +{ + @SerializedName( "filename" ) + private String fileName; + @SerializedName( "format" ) + private String format; + + public String getFileName() + { + return fileName; + } + + public String getFormat() + { + return format; + } +} + +class QemuFirmwareTarget +{ + @SerializedName( "architecture" ) + private String architecture; + @SerializedName( "machines" ) + private ArrayList machines; + + public String getArchitecture() + { + return architecture; + } + + public ArrayList getMachines() + { + return machines; + } +} + +/** + * Specific firmware transformation for Libvirt/QEMU virtualization configurations. + * + * @author Manuel Bentele + * @version 1.0 + */ +public class TransformationSpecificQemuFirmware + extends TransformationSpecific +{ + /** + * Name of the configuration transformation. + */ + private static final String NAME = "QEMU Firmware [Seabios, UEFI (OVMF)]"; + + /** + * Creates a new firmware transformation for Libvirt/QEMU virtualization configurations. + * + * @param hypervisor Libvirt/QEMU hypervisor. + */ + public TransformationSpecificQemuFirmware( LibvirtHypervisorQemu virtualizer ) + { + super( TransformationSpecificQemuFirmware.NAME, virtualizer ); + } + + /** + * Validates a virtualization configuration and input arguments for this transformation. + * + * @param config virtualization configuration for the validation. + * @param args input arguments for the validation. + * @throws TransformationException validation has failed. + */ + private void validateInputs( Domain config, CommandLineArgs args ) throws TransformationException + { + if ( config == null || args == null ) { + throw new TransformationException( "Virtualization configuration or input arguments are missing!" ); + } else if ( args.getFirmware() == null || args.getFirmware().isEmpty() ) { + throw new TransformationException( "Path to QEMU firmware specifications directory is not specified!" ); + } + } + + private String lookupTargetOsLoader( String firmwareSpecDirectory, String sourceOsLoader, String sourceOsArch, + String sourceOsMachine ) + throws TransformationException + { + String lookupOsLoader = null; + + // parse and check firmware specification directory + final File fwSpecDirectory = new File( firmwareSpecDirectory ); + if ( !fwSpecDirectory.exists() || !fwSpecDirectory.isDirectory() ) { + throw new TransformationException( "Path to QEMU firmware specifications directory is invalid!" ); + } + + // get all firmware specification files + final FileFilter fwSpecFilesFilter = file -> !file.isDirectory() && file.getName().endsWith( ".json" ); + final File[] fwSpecFiles = fwSpecDirectory.listFiles( fwSpecFilesFilter ); + + // get paths to firmware files from firmware specification files + if ( fwSpecFiles != null ) { + final ArrayList uefiFirmwares = new ArrayList(); + final Gson gson = new Gson(); + for ( final File fwSpecFile : fwSpecFiles ) { + QemuFirmware firmware = null; + + try { + final Reader jsonContent = new FileReader( fwSpecFile ); + firmware = gson.fromJson( jsonContent, QemuFirmware.class ); + } catch ( FileNotFoundException | JsonSyntaxException | JsonIOException e ) { + throw new TransformationException( e.getLocalizedMessage() ); + } + + final Predicate byInterfaceType = s -> s.toLowerCase().equals( "uefi" ); + if ( firmware.getInterfaceTypes().stream().filter( byInterfaceType ).findAny().isPresent() ) { + // found valid UEFI firmware + // check if architecture and machine type of the VM is supported by the firmware + final Predicate byArchitecture = t -> sourceOsArch.equals( t.getArchitecture() ); + final Predicate byMachineType = s -> sourceOsMachine.startsWith( s.replace( "*", "" ) ); + final Predicate byMachines = t -> t.getMachines().stream().filter( byMachineType ) + .findAny().isPresent(); + + if ( firmware.getTargets().stream().filter( byArchitecture ).filter( byMachines ).findAny() + .isPresent() ) { + // found UEFI firmware supporting suitable architecture and machine type from VM + uefiFirmwares.add( firmware ); + } + } + } + + if ( uefiFirmwares.isEmpty() ) { + throw new TransformationException( "There aren't any suitable UEFI firmwares locally available!" ); + } else { + final LevenshteinDistance distance = new LevenshteinDistance( 1, 1, 1 ); + int minFileNameDistance = Integer.MAX_VALUE; + Path suitablestUefiFirmwarePath = null; + + for ( final QemuFirmware uefiFirmware : uefiFirmwares ) { + final Path uefiFirmwarePath = Paths.get( uefiFirmware.getMapping().getExecutable().getFileName() ); + final Path sourceOsLoaderPath = Paths.get( sourceOsLoader ); + final String uefiFirmwareFileName = uefiFirmwarePath.getFileName().toString().toLowerCase(); + final String sourceOsLoaderFileName = sourceOsLoaderPath.getFileName().toString().toLowerCase(); + + final int fileNameDistance = distance.calculateDistance( uefiFirmwareFileName, sourceOsLoaderFileName ); + if ( fileNameDistance < minFileNameDistance ) { + minFileNameDistance = fileNameDistance; + suitablestUefiFirmwarePath = uefiFirmwarePath; + } + } + + lookupOsLoader = suitablestUefiFirmwarePath.toString(); + } + } + + return lookupOsLoader; + } + + @Override + public void transform( Domain config, CommandLineArgs args ) throws TransformationException + { + // validate configuration and input arguments + this.validateInputs( config, args ); + + // get OS loader from VM + final String sourceOsLoader = config.getOsLoader(); + + // get OS architecture from VM + final String sourceOsArch = config.getOsArch(); + + // get OS machine type from VM + final String sourceOsMachine = config.getOsMachine(); + + // check if OS loader is specified + if ( sourceOsLoader != null && !sourceOsLoader.isEmpty() ) { + // OS loader is specified so transform path to specified firmware path + final String targetOsLoader = this.lookupTargetOsLoader( args.getFirmware(), sourceOsLoader, sourceOsArch, + sourceOsMachine ); + if ( targetOsLoader != null && !targetOsLoader.isEmpty() ) { + config.setOsLoader( targetOsLoader ); + } + } + } +} 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 a8618878..aca51d07 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( 2655, shortHelpOptionCorrectOutput.length() ); + assertEquals( 2740, 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( 2655, longHelpOptionCorrectOutput.length() ); + assertEquals( 2740, 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( 2655, shortHelpOptionIncorrectOutput.length() ); + assertEquals( 2740, 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( 2655, longHelpOptionIncorrectOutput.length() ); + assertEquals( 2740, 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 dc863088..b61e41d9 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 @@ -141,6 +141,34 @@ public class CommandLineArgsTest assertFalse( cmdLnDebugMissing.isDebugEnabled() ); } + @Test + @DisplayName( "Test the parsing of the firmware path command line option (short version)" ) + public void testCmdlnOptionFirmwareShort() throws CommandLineArgsException + { + final String[] args = { + CMDLN_PREFIX_OPTION_SHORT + CmdLnOption.FIRMWARE.getShortOption(), + CMDLN_TEST_FILENAME + }; + + CommandLineArgs cmdLn = new CommandLineArgs( args ); + + assertEquals( CMDLN_TEST_FILENAME, cmdLn.getFirmware() ); + } + + @Test + @DisplayName( "Test the parsing of the firmware command line option (long version)" ) + public void testCmdlnOptionFirmwareLong() throws CommandLineArgsException + { + final String[] args = { + CMDLN_PREFIX_OPTION_LONG + CmdLnOption.FIRMWARE.getLongOption(), + CMDLN_TEST_FILENAME + }; + + CommandLineArgs cmdLn = new CommandLineArgs( args ); + + assertEquals( CMDLN_TEST_FILENAME, cmdLn.getFirmware() ); + } + @Test @DisplayName( "Test the parsing of the VM configuration input command line option (short version)" ) public void testCmdlnOptionVmCfgInpShort() throws CommandLineArgsException diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuFirmwareTest.java b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuFirmwareTest.java new file mode 100644 index 00000000..f469e3fc --- /dev/null +++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuFirmwareTest.java @@ -0,0 +1,60 @@ +package org.openslx.runvirt.plugin.qemu.configuration; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +import java.nio.file.Paths; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.openslx.libvirt.domain.Domain; +import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs; +import org.openslx.virtualization.configuration.transformation.TransformationException; + +class TransformationSpecificQemuFirmwareStub extends TransformationSpecificQemuFirmware +{ + public TransformationSpecificQemuFirmwareStub() + { + super( null ); + } +} + +public class TransformationSpecificQemuFirmwareTest +{ + @Test + @DisplayName( "Test transformation of VM OS loader (firmware) configuration with specified input data" ) + public void testTransformationSpecificQemuFirmwareUefiLoader() throws TransformationException + { + final TransformationSpecificQemuFirmwareStub transformation = new TransformationSpecificQemuFirmwareStub(); + final Domain config = TransformationTestUtils + .getDomain( "qemu-kvm_default-ubuntu-20-04-vm_transform-non-persistent_uefi.xml" ); + final CommandLineArgs args = TransformationTestUtils.getDefaultCmdLnArgs(); + + assertEquals( Paths.get( "/usr/share/edk2-ovmf/x64/OVMF_CODE.fd" ).toString(), config.getOsLoader() ); + + transformation.transform( config, args ); + + assertEquals( Paths.get( "/usr/share/qemu/edk2-x86_64-code.fd" ).toString(), config.getOsLoader() ); + + assertDoesNotThrow( () -> config.validateXml() ); + } + + @Test + @DisplayName( "Test transformation of missing VM OS loader (firmware) configuration" ) + public void testTransformationSpecificQemuFirmwareNoLoader() throws TransformationException + { + final TransformationSpecificQemuFirmwareStub transformation = new TransformationSpecificQemuFirmwareStub(); + final Domain config = TransformationTestUtils + .getDomain( "qemu-kvm_default-ubuntu-20-04-vm_transform-non-persistent.xml" ); + final CommandLineArgs args = TransformationTestUtils.getDefaultCmdLnArgs(); + + assertNull( config.getOsLoader() ); + + transformation.transform( config, args ); + + assertNull( config.getOsLoader() ); + + assertDoesNotThrow( () -> config.validateXml() ); + } +} diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationTestResources.java b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationTestResources.java index b04685f9..2c278f23 100644 --- a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationTestResources.java +++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationTestResources.java @@ -5,13 +5,12 @@ import java.net.URL; public class TransformationTestResources { - private static final String LIBVIRT_PREFIX_PATH = File.separator + "libvirt"; - private static final String LIBVIRT_PREFIX_PATH_XML = LIBVIRT_PREFIX_PATH + File.separator + "xml"; + private static final String QEMU_PREFIX_PATH = File.separator + "qemu"; + private static final String QEMU_PREFIX_PATH_FW = QEMU_PREFIX_PATH + File.separator + "firmware"; - public static File getLibvirtXmlFile( String libvirtXmlFileName ) + public static String getQemuFirmwareSpecPath() { - String libvirtXmlPath = TransformationTestResources.LIBVIRT_PREFIX_PATH_XML + File.separator + libvirtXmlFileName; - URL libvirtXml = TransformationTestResources.class.getResource( libvirtXmlPath ); - return new File( libvirtXml.getFile() ); + final URL qemuFwSpecPath = TransformationTestResources.class.getResource( QEMU_PREFIX_PATH_FW ); + return qemuFwSpecPath.getFile(); } } diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationTestUtils.java b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationTestUtils.java index 2a811f2a..5123cae1 100644 --- a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationTestUtils.java +++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationTestUtils.java @@ -15,6 +15,7 @@ import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgsTest; public class TransformationTestUtils { // @formatter:off + public static final String DEFAULT_FW_PATH = TransformationTestResources.getQemuFirmwareSpecPath(); 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"; @@ -40,6 +41,8 @@ public class TransformationTestUtils // @formatter:on private static final String[] DEFAULT_CMDLN_ARGS = { + CommandLineArgsTest.CMDLN_PREFIX_OPTION_LONG + CmdLnOption.FIRMWARE.getLongOption(), + TransformationTestUtils.DEFAULT_FW_PATH, CommandLineArgsTest.CMDLN_PREFIX_OPTION_LONG + CmdLnOption.VM_NAME.getLongOption(), TransformationTestUtils.DEFAULT_VM_NAME, CommandLineArgsTest.CMDLN_PREFIX_OPTION_LONG + CmdLnOption.VM_UUID.getLongOption(), diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/resources/qemu/firmware/50-edk2-i386-secure.json b/core/modules/qemu/runvirt-plugin-qemu/src/test/resources/qemu/firmware/50-edk2-i386-secure.json new file mode 100644 index 00000000..9838f16a --- /dev/null +++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/resources/qemu/firmware/50-edk2-i386-secure.json @@ -0,0 +1,34 @@ +{ + "description": "UEFI firmware for i386, with Secure Boot and SMM", + "interface-types": [ + "uefi" + ], + "mapping": { + "device": "flash", + "executable": { + "filename": "/usr/share/qemu/edk2-i386-secure-code.fd", + "format": "raw" + }, + "nvram-template": { + "filename": "/usr/share/qemu/edk2-i386-vars.fd", + "format": "raw" + } + }, + "targets": [ + { + "architecture": "i386", + "machines": [ + "pc-q35-*" + ] + } + ], + "features": [ + "acpi-s3", + "requires-smm", + "secure-boot", + "verbose-dynamic" + ], + "tags": [ + + ] +} diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/resources/qemu/firmware/50-edk2-x86_64-secure.json b/core/modules/qemu/runvirt-plugin-qemu/src/test/resources/qemu/firmware/50-edk2-x86_64-secure.json new file mode 100644 index 00000000..12fa688c --- /dev/null +++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/resources/qemu/firmware/50-edk2-x86_64-secure.json @@ -0,0 +1,35 @@ +{ + "description": "UEFI firmware for x86_64, with Secure Boot and SMM", + "interface-types": [ + "uefi" + ], + "mapping": { + "device": "flash", + "executable": { + "filename": "/usr/share/qemu/edk2-x86_64-secure-code.fd", + "format": "raw" + }, + "nvram-template": { + "filename": "/usr/share/qemu/edk2-i386-vars.fd", + "format": "raw" + } + }, + "targets": [ + { + "architecture": "x86_64", + "machines": [ + "pc-q35-*" + ] + } + ], + "features": [ + "acpi-s3", + "amd-sev", + "requires-smm", + "secure-boot", + "verbose-dynamic" + ], + "tags": [ + + ] +} diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/resources/qemu/firmware/60-edk2-aarch64.json b/core/modules/qemu/runvirt-plugin-qemu/src/test/resources/qemu/firmware/60-edk2-aarch64.json new file mode 100644 index 00000000..52a65c73 --- /dev/null +++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/resources/qemu/firmware/60-edk2-aarch64.json @@ -0,0 +1,31 @@ +{ + "description": "UEFI firmware for aarch64", + "interface-types": [ + "uefi" + ], + "mapping": { + "device": "flash", + "executable": { + "filename": "/usr/share/qemu/edk2-aarch64-code.fd", + "format": "raw" + }, + "nvram-template": { + "filename": "/usr/share/qemu/edk2-arm-vars.fd", + "format": "raw" + } + }, + "targets": [ + { + "architecture": "aarch64", + "machines": [ + "virt-*" + ] + } + ], + "features": [ + "verbose-static" + ], + "tags": [ + + ] +} diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/resources/qemu/firmware/60-edk2-arm.json b/core/modules/qemu/runvirt-plugin-qemu/src/test/resources/qemu/firmware/60-edk2-arm.json new file mode 100644 index 00000000..8dc6e0f1 --- /dev/null +++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/resources/qemu/firmware/60-edk2-arm.json @@ -0,0 +1,31 @@ +{ + "description": "UEFI firmware for arm", + "interface-types": [ + "uefi" + ], + "mapping": { + "device": "flash", + "executable": { + "filename": "/usr/share/qemu/edk2-arm-code.fd", + "format": "raw" + }, + "nvram-template": { + "filename": "/usr/share/qemu/edk2-arm-vars.fd", + "format": "raw" + } + }, + "targets": [ + { + "architecture": "arm", + "machines": [ + "virt-*" + ] + } + ], + "features": [ + "verbose-static" + ], + "tags": [ + + ] +} diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/resources/qemu/firmware/60-edk2-i386.json b/core/modules/qemu/runvirt-plugin-qemu/src/test/resources/qemu/firmware/60-edk2-i386.json new file mode 100644 index 00000000..f0929ed5 --- /dev/null +++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/resources/qemu/firmware/60-edk2-i386.json @@ -0,0 +1,33 @@ +{ + "description": "UEFI firmware for i386", + "interface-types": [ + "uefi" + ], + "mapping": { + "device": "flash", + "executable": { + "filename": "/usr/share/qemu/edk2-i386-code.fd", + "format": "raw" + }, + "nvram-template": { + "filename": "/usr/share/qemu/edk2-i386-vars.fd", + "format": "raw" + } + }, + "targets": [ + { + "architecture": "i386", + "machines": [ + "pc-i440fx-*", + "pc-q35-*" + ] + } + ], + "features": [ + "acpi-s3", + "verbose-dynamic" + ], + "tags": [ + + ] +} diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/resources/qemu/firmware/60-edk2-x86_64.json b/core/modules/qemu/runvirt-plugin-qemu/src/test/resources/qemu/firmware/60-edk2-x86_64.json new file mode 100644 index 00000000..d0b6542c --- /dev/null +++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/resources/qemu/firmware/60-edk2-x86_64.json @@ -0,0 +1,34 @@ +{ + "description": "UEFI firmware for x86_64", + "interface-types": [ + "uefi" + ], + "mapping": { + "device": "flash", + "executable": { + "filename": "/usr/share/qemu/edk2-x86_64-code.fd", + "format": "raw" + }, + "nvram-template": { + "filename": "/usr/share/qemu/edk2-i386-vars.fd", + "format": "raw" + } + }, + "targets": [ + { + "architecture": "x86_64", + "machines": [ + "pc-i440fx-*", + "pc-q35-*" + ] + } + ], + "features": [ + "acpi-s3", + "amd-sev", + "verbose-dynamic" + ], + "tags": [ + + ] +} -- cgit v1.2.3-55-g7522