From e0b1c430ae36c2b8f58155811bb975adf8a1286a Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Thu, 27 Jun 2024 17:08:32 +0200 Subject: [qemu] Improve finding a fallback os machine type if no perfect match --- .../java/org/openslx/runvirt/plugin/qemu/App.java | 19 ++++- .../TransformationSpecificQemuArchitecture.java | 85 +++++++++++----------- 2 files changed, 58 insertions(+), 46 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 index 6e1efa61..c89872e7 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 @@ -7,8 +7,11 @@ import java.util.Arrays; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.config.Configuration; import org.apache.logging.log4j.core.config.Configurator; import org.apache.logging.log4j.core.config.DefaultConfiguration; +import org.apache.logging.log4j.core.config.LoggerConfig; import org.openslx.libvirt.domain.Domain; import org.openslx.libvirt.xml.LibvirtXmlDocumentException; import org.openslx.libvirt.xml.LibvirtXmlSerializationException; @@ -98,7 +101,19 @@ public class App } if ( cmdLn.isDebugEnabled() || cmdLn.isDebugDevicePassthroughEnabled() ) { - Configurator.setRootLevel( Level.ALL ); + // Someone please exterminate all Java devs. What's wrong with those fuckheads who come up with this? + // https://stackoverflow.com/a/65151249/2043481 + LoggerContext ctx = (LoggerContext) LogManager.getContext(App.class.getClassLoader(), false); + Configuration config = ctx.getConfiguration(); + LoggerConfig loggerConfig = config.getLoggerConfig(LogManager.ROOT_LOGGER_NAME); + loggerConfig.setLevel(Level.DEBUG); + ctx.updateLoggers(); + } else { + LoggerContext ctx = (LoggerContext) LogManager.getContext(App.class.getClassLoader(), false); + Configuration config = ctx.getConfiguration(); + LoggerConfig loggerConfig = config.getLoggerConfig(LogManager.ROOT_LOGGER_NAME); + loggerConfig.setLevel(Level.INFO); + ctx.updateLoggers(); } // show help if 'help' command line option is set @@ -170,7 +185,7 @@ public class App try { transformationManager.transform(); } catch ( TransformationException e ) { - LOGGER.error( "Failed to finalize VM configuration file: " + e.getLocalizedMessage() ); + LOGGER.error( "Failed to transform VM configuration file", e ); hypervisor.close(); System.exit( 4 ); } 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 16956ce9..48426ac7 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 @@ -3,6 +3,8 @@ package org.openslx.runvirt.plugin.qemu.configuration; import java.util.ArrayList; import java.util.List; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.openslx.libvirt.capabilities.Capabilities; import org.openslx.libvirt.capabilities.guest.Guest; import org.openslx.libvirt.capabilities.guest.Machine; @@ -12,7 +14,7 @@ import org.openslx.libvirt.domain.Domain.Type; import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs; import org.openslx.runvirt.plugin.qemu.virtualization.LibvirtHypervisorQemu; import org.openslx.runvirt.virtualization.LibvirtHypervisorException; -import org.openslx.virtualization.configuration.VirtualizationConfigurationQemuUtils; +import org.openslx.util.Util; import org.openslx.virtualization.configuration.transformation.TransformationException; import org.openslx.virtualization.configuration.transformation.TransformationSpecific; @@ -25,6 +27,8 @@ import org.openslx.virtualization.configuration.transformation.TransformationSpe public class TransformationSpecificQemuArchitecture extends TransformationSpecific { + private static final Logger LOGGER = LogManager.getLogger( TransformationSpecificQemuArchitecture.class ); + /** * Name of the configuration transformation. */ @@ -134,24 +138,15 @@ public class TransformationSpecificQemuArchitecture } /** - * Returns the canonical names of a target machine description of a host system's guest - * capability. - * - * @param guest guest capability of a host system. - * @return canonical names of a target machine description of a host system's guest capability. - * @throws TransformationException failed to return the canonical names of a target machine - * description of a host system's guest capability + * Return all supported machines for given guest. */ - private List getCanonicalNamesFromTargetMachines( Guest guest ) throws TransformationException + private List getTargetMachines( Guest guest ) { 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 ); - } + canonicalNames.add( machine.getName() ); } return canonicalNames; @@ -172,67 +167,71 @@ public class TransformationSpecificQemuArchitecture // check if source architecture is supported by one of the hypervisor's guests Guest targetGuest = null; if ( sourceArchitectureName == null ) { - final String errorMsg = new String( "Source architecture is not specified!" ); - throw new TransformationException( errorMsg ); + throw new TransformationException( "Source architecture is not specified!" ); } else { targetGuest = this.getTargetGuestFromArchName( sourceArchitectureName ); if ( targetGuest == null ) { - final String errorMsg = new String( "Source architecture is not supported by the virtualizer!" ); - throw new TransformationException( errorMsg ); + throw new TransformationException( "Source architecture '" + sourceArchitectureName + "' " + + "is not supported by the virtualizer!" ); } } // check if source machine is supported by the hypervisor - Machine targetMachine = null; if ( sourceMachine == null ) { - final String errorMsg = new String( "Source machine type is not specified!" ); - throw new TransformationException( errorMsg ); + throw new TransformationException( "Source machine type is not specified!" ); } else { - // get all possible machine type for supported source architecture - targetMachine = this.getTargetMachineFromGuest( targetGuest, sourceMachine ); + Machine targetMachine = this.getTargetMachineFromGuest( targetGuest, sourceMachine ); - if ( targetMachine == null ) { + if ( targetMachine != null ) { + // Canonicalize, otherwise UEFI firmware cannot be found -.- + String cn = targetMachine.getCanonicalMachine(); + if ( !Util.isEmptyString( cn ) ) { + config.setOsMachine( cn ); + } + } else { // 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 ); + LOGGER.info( "Machine '" + sourceMachine + "' not known" ); + // Get best fallback + List supportedMachineNames = this.getTargetMachines( targetGuest ); - // retrieve overwrite chipset name from canonical machine names + // Look for best (=longest) match in supported list String sourceMachineOverwrite = null; - for ( String targetMachineCanonicalName : targetMachineCanonicalNames ) { - final String targetMachineName = VirtualizationConfigurationQemuUtils - .getOsMachineName( targetMachineCanonicalName ); - if ( targetMachineName != null && sourceMachine.contains( targetMachineName ) ) { - sourceMachineOverwrite = targetMachineCanonicalName; - break; + for ( String name : supportedMachineNames ) { + LOGGER.debug( "Does '" + sourceMachine + "' start with (or contain) '" + name + "'?" ); + if ( ( sourceMachine.startsWith( name ) || sourceMachine.contains( "-" + name ) ) + && ( sourceMachineOverwrite == null || sourceMachineOverwrite.length() < name.length() ) ) { + sourceMachineOverwrite = name; } } // if overwrite available, patch the machine type if ( sourceMachineOverwrite != null ) { + targetMachine = this.getTargetMachineFromGuest( targetGuest, sourceMachineOverwrite ); + if (targetMachine != null && !Util.isEmptyString( targetMachine.getCanonicalMachine() ) ) { + sourceMachineOverwrite = targetMachine.getCanonicalMachine(); + } + LOGGER.info( "Overriding unsupported machine '" + sourceMachine + "' with '" + sourceMachineOverwrite + "'" ); config.setOsMachine( sourceMachineOverwrite ); } else { - final String errorMsg = new String( "Source machine type is not supported by the virtualizer!" ); - throw new TransformationException( errorMsg ); + LOGGER.info( "Don't know how to override unsupported machine '" + sourceMachine + "'" ); + throw new TransformationException( "Source machine type is not supported by the virtualizer!" ); } } } // check if source OS type is supported by the hypervisor's architecture if ( sourceOsType == null ) { - final String errorMsg = new String( "OS type is not specified!" ); - throw new TransformationException( errorMsg ); + throw new TransformationException( "OS type is not specified!" ); } else { if ( !sourceOsType.toString().equals( targetGuest.getOsType().toString() ) ) { - final String errorMsg = new String( "OS type is not supported by the virtualizer!" ); - throw new TransformationException( errorMsg ); + throw new TransformationException( "OS type is not supported by the virtualizer!" ); } } // check if source domain type is supported by the hypervisor's architecture Type targetDomainType = null; if ( sourceDomainType == null ) { - final String errorMsg = new String( "Source domain type is not specified!" ); - throw new TransformationException( errorMsg ); + throw new TransformationException( "Source domain type is not specified!" ); } else { final List targetDomains = targetGuest.getArchDomains(); @@ -247,16 +246,14 @@ public class TransformationSpecificQemuArchitecture // check supported domain type if ( targetDomainType == null ) { - final String errorMsg = new String( "Source domain type is not supported by the virtualizer!" ); - throw new TransformationException( errorMsg ); + throw new TransformationException( "Source domain type is not supported by the virtualizer!" ); } } // patch path of QEMU emulator binary final String archEmulator = targetGuest.getArchEmulator(); if ( archEmulator == null ) { - final String errorMsg = new String( "Emulation of source architecture is not supported by the virtualizer!" ); - throw new TransformationException( errorMsg ); + throw new TransformationException( "Emulation of source architecture is not supported by the virtualizer!" ); } else { config.setDevicesEmulator( targetGuest.getArchEmulator() ); } -- cgit v1.2.3-55-g7522