package org.openslx.runvirt.plugin.qemu.configuration; import java.util.ArrayList; import java.util.List; import org.openslx.libvirt.capabilities.Capabilities; import org.openslx.libvirt.capabilities.guest.Guest; import org.openslx.libvirt.capabilities.guest.Machine; import org.openslx.libvirt.domain.Domain; import org.openslx.libvirt.domain.Domain.OsType; import org.openslx.libvirt.domain.Domain.Type; import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs; import org.openslx.runvirt.plugin.qemu.virtualization.LibvirtHypervisorQemu; import org.openslx.runvirt.virtualization.LibvirtHypervisorException; import org.openslx.virtualization.configuration.transformation.TransformationException; import org.openslx.virtualization.configuration.transformation.TransformationSpecific; public class TransformationSpecificQemuArchitecture extends TransformationSpecific { 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 TransformationSpecificQemuArchitecture( LibvirtHypervisorQemu hypervisor ) { super( TransformationSpecificQemuArchitecture.FILTER_NAME, hypervisor ); } private 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 ); } } return this.capabilities; } private Guest getTargetGuestFromArchName( String architectureName ) throws TransformationException { 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 TransformationException { 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 TransformationException { 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 transform( Domain config, CommandLineArgs args ) throws TransformationException { // get source architecture, machine- and OS type final String sourceArchitectureName = config.getOsArch(); final String sourceMachine = config.getOsMachine(); final OsType sourceOsType = config.getOsType(); final Type sourceDomainType = config.getType(); // check if source architecture is supported by one of the hypervisor's guests Guest targetGuest = null; if ( sourceArchitectureName == null ) { final String errorMsg = new String( "Source architecture is not specified!" ); throw new TransformationException( errorMsg ); } else { targetGuest = this.getTargetGuestFromArchName( sourceArchitectureName ); if ( targetGuest == null ) { final String errorMsg = new String( "Source architecture is not supported by the virtualizer!" ); throw new TransformationException( errorMsg ); } } // check if source machine is supported by the hypervisor Machine targetMachine = null; if ( sourceMachine == null ) { final String errorMsg = new String( "Source machine type is not specified!" ); throw new TransformationException( errorMsg ); } else { // get all possible machine type for supported source architecture targetMachine = this.getTargetMachineFromGuest( targetGuest, sourceMachine ); if ( targetMachine == null ) { // source machine is not directly supported by the hypervisor // check if up- or downgraded version of the chipset is supported by the hypervisor List targetMachineCanonicalNames = this.getCanonicalNamesFromTargetMachines( targetGuest ); // retrieve overwrite chipset name from canonical machine names String sourceMachineOverwrite = null; for ( String targetMachineCanonicalName : targetMachineCanonicalNames ) { if ( sourceMachine.contains( targetMachineCanonicalName ) ) { sourceMachineOverwrite = targetMachineCanonicalName; break; } } // if overwrite available, patch the machine type if ( sourceMachineOverwrite != null ) { config.setOsMachine( sourceMachineOverwrite ); } else { final String errorMsg = new String( "Source machine type is not supported by the virtualizer!" ); throw new TransformationException( errorMsg ); } } } // check if source OS type is supported by the hypervisor's architecture if ( sourceOsType == null ) { final String errorMsg = new String( "OS type is not specified!" ); throw new TransformationException( errorMsg ); } else { if ( !sourceOsType.toString().equals( targetGuest.getOsType().toString() ) ) { final String errorMsg = new String( "OS type is not supported by the virtualizer!" ); throw new TransformationException( errorMsg ); } } // check if source domain type is supported by the hypervisor's architecture Type targetDomainType = null; if ( sourceDomainType == null ) { final String errorMsg = new String( "Source domain type is not specified!" ); throw new TransformationException( errorMsg ); } else { final List targetDomains = targetGuest.getArchDomains(); // retrieve supported domain type for ( org.openslx.libvirt.capabilities.guest.Domain domain : targetDomains ) { final Type domainType = domain.getType(); if ( domainType == sourceDomainType ) { targetDomainType = domainType; break; } } // check supported domain type if ( targetDomainType == null ) { final String errorMsg = new String( "Source domain type is not supported by the virtualizer!" ); throw new TransformationException( errorMsg ); } } // patch path of QEMU emulator binary final String archEmulator = targetGuest.getArchEmulator(); if ( archEmulator == null ) { final String errorMsg = new String( "Emulation of source architecture is not supported by the virtualizer!" ); throw new TransformationException( errorMsg ); } else { config.setDevicesEmulator( targetGuest.getArchEmulator() ); } } }