package org.openslx.util.vm;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.log4j.Logger;
import org.openslx.bwlp.thrift.iface.OperatingSystem;
import org.openslx.bwlp.thrift.iface.Virtualizer;
/**
* Describes a configured virtual machine. This class is parsed from a machine
* description, like a *.vmx for VMware machines.
*/
public abstract class VmMetaData<T, U, V, W>
{
private static final Logger LOGGER = Logger.getLogger( VmMetaData.class );
/*
* Helper types
*/
protected Map<SoundCardType, T> soundCards = new HashMap<>();
protected Map<DDAcceleration, U> ddacc = new HashMap<>();
protected Map<HWVersion, V> hwversion = new HashMap<>();
protected Map<EthernetDevType, W> networkCards = new HashMap<>();
/**
* All the available virtual Sound Cards that are supported by VmxPlayer and VBoxPlayer
* <add further entries when incorporating other Hypervisors>
*
* @author victorm
*
*/
public static enum SoundCardType
{
NONE( "None" ),
DEFAULT( "(default)" ),
SOUND_BLASTER( "Sound Blaster 16" ),
ES( "ES 1371" ),
HD_AUDIO( "Intel Integrated HD Audio" ),
AC( "Intel ICH Audio Codec 97" );
public final String displayName;
private SoundCardType( String dName )
{
this.displayName = dName;
}
}
/**
* All the available settings for the 3D acceleration that are supported by VmxPlayer and
* VBoxPlayer
* <add further entries when incorporating other Hypervisors>
*
* @author victorm
*
*/
public static enum DDAcceleration
{
OFF( "Off" ),
ON( "On" );
public final String displayName;
private DDAcceleration( String dName )
{
this.displayName = dName;
}
}
/**
* All the available virtual Hardware Versions that are supported by VmxPlayer and VBoxPlayer
* <add further entries when incorporating other Hypervisors>
*
* @author victorm
*
*/
public static enum HWVersion
{
NONE( "(invalid)" ),
THREE( " 3 (Workstation 4/5, Player 1)" ),
FOUR( " 4 (Workstation 4/5, Player 1/2, Fusion 1)" ),
SIX( " 6 (Workstation 6)" ),
SEVEN( " 7 (Workstation 6.5/7, Player 3, Fusion 2/3)" ),
EIGHT( " 8 (Workstation 8, Player/Fusion 4)" ),
NINE( " 9 (Workstation 9, Player/Fusion 5)" ),
TEN( "10 (Workstation 10, Player/Fusion 6)" ),
ELEVEN( "11 (Workstation 11, Player/Fusion 7)" ),
TWELVE( "12 (Workstation/Player 12, Fusion 8)" ),
DEFAULT( "default" );
public final String displayName;
private HWVersion( String dName )
{
this.displayName = dName;
}
}
/**
* All the available virtual Network Cards that are supported by VmxPlayer and VBoxPlayer
* <add further entries when incorporating other Hypervisors>
*
* @author victorm
*
*/
public static enum EthernetDevType
{
AUTO( "(default)" ),
PCNET32( "AMD PCnet32" ),
E1000( "Intel E1000 (PCI)" ),
E1000E( "Intel E1000e (PCI-Express)" ),
VMXNET( "VMXnet" ),
VMXNET3( "VMXnet 3" ),
PCNETPCI2( "PCnet-PCI II" ),
PCNETFAST3( "PCnet-FAST III" ),
PRO1000MTD( "Intel PRO/1000 MT Desktop" ),
PRO1000TS( "Intel PRO/1000 T Server" ),
PRO1000MTS( "Intel PRO/1000 MT Server" ),
PARAVIRT( "Paravirtualized Network" ),
NONE( "No Network Card" );
public final String displayName;
private EthernetDevType( String dName )
{
this.displayName = dName;
}
}
public static enum DriveBusType
{
SCSI,
IDE,
SATA;
}
public static class HardDisk
{
public final String chipsetDriver;
public final DriveBusType bus;
public final String diskImage;
public HardDisk( String chipsetDriver, DriveBusType bus, String diskImage )
{
this.chipsetDriver = chipsetDriver;
this.bus = bus;
this.diskImage = diskImage;
}
}
public static enum EtherType
{
NAT,
BRIDGED,
HOST_ONLY;
}
/*
* Members
*/
protected final List<HardDisk> hdds = new ArrayList<>();
private final List<OperatingSystem> osList;
private OperatingSystem os = null;
protected String displayName = null;
/*
* Guettas
*/
public List<SoundCardType> getSupportedSoundCards()
{
ArrayList<SoundCardType> availables = new ArrayList<SoundCardType>( soundCards.keySet() );
// availables must be sorted else the user always gets another order of the dropdown list at startup
Collections.sort( availables );
return availables;
}
public List<DDAcceleration> getSupportedDDAccs()
{
ArrayList<DDAcceleration> availables = new ArrayList<DDAcceleration>( ddacc.keySet() );
// availables must be sorted else the user always gets another order of the dropdown list at startup
Collections.sort( availables );
return availables;
}
public List<HWVersion> getSupportedHWVersions()
{
ArrayList<HWVersion> availables = new ArrayList<HWVersion>( hwversion.keySet() );
// availables must be sorted else the user always gets another order of the dropdown list at startup
Collections.sort( availables );
return availables;
}
public List<EthernetDevType> getSupportedEthernetDevices()
{
ArrayList<EthernetDevType> availables = new ArrayList<EthernetDevType>( networkCards.keySet() );
// availables must be sorted else the user always gets another order of the dropdown list at startup
Collections.sort( availables );
return availables;
}
/**
* Get operating system of this VM.
*/
public OperatingSystem getOs()
{
return os;
}
/**
* Get all hard disks of this VM.
*/
public List<HardDisk> getHdds()
{
return Collections.unmodifiableList( hdds );
}
/**
* Get display name of VM.
*/
public String getDisplayName()
{
return displayName;
}
/**
* This method should return a minimal representation of the input meta data.
* The representation is platform dependent, and should be stripped of all
* non-essential configuration, such as CD/DVD/FLoppy drives, serial or parallel
* ports, shared folders, or anything else that could be considered sensible
* information (absolute paths containing the local user's name).
*/
public abstract byte[] getFilteredDefinitionArray();
public final ByteBuffer getFilteredDefinition()
{
return ByteBuffer.wrap( getFilteredDefinitionArray() );
}
/*
* Methods
*/
public VmMetaData( List<OperatingSystem> osList )
{
this.osList = osList;
}
/**
* Called from subclass to set the OS. If the OS cannot be determined from the
* given parameters, it will not be set.
*
* @param virtId
* virtualizer, eg "vmware" for VMware
* @param virtOsId
* the os identifier used by the virtualizer, eg. windows7-64 for
* 64bit Windows 7 on VMware
*/
protected final void setOs( String virtId, String virtOsId )
{
OperatingSystem lazyMatch = null;
for ( OperatingSystem os : osList ) {
if ( os.getVirtualizerOsId() == null )
continue;
for ( Entry<String, String> entry : os.getVirtualizerOsId().entrySet() ) {
if ( !entry.getValue().equals( virtOsId ) )
continue;
if ( entry.getKey().equals( virtId ) ) {
this.os = os;
return;
} else {
lazyMatch = os;
}
}
}
this.os = lazyMatch;
}
/**
* Apply config options that are desired when locally editing a VM. for vmware,
* this disables automatic DPI scaling of the guest.
*/
public abstract void applySettingsForLocalEdit();
// meta object needed when reading vm from file
public static VmMetaData<?, ?, ?, ?> getInstance( List<OperatingSystem> osList, File file ) throws IOException
{
Exception errEx = null;
try {
return new VmwareMetaData( osList, file );
} catch ( UnsupportedVirtualizerFormatException e ) {
LOGGER.debug( "Disk file not .vmdk" );
errEx = e;
}
try {
return new VboxMetaData( osList, file );
} catch ( UnsupportedVirtualizerFormatException e ) {
LOGGER.debug( "Disk file not .vdi" );
errEx = e;
}
try {
return new QemuMetaData( osList, file );
} catch ( Exception e ) {
LOGGER.debug( "Disk file not qemu supported format" );
errEx = e;
}
if ( errEx != null ) {
LOGGER.error( "Unsupported disk file format!", errEx );
}
return null;
}
// meta object needed when reading from configarray
public static VmMetaData<?, ?, ?, ?> getInstance( List<OperatingSystem> osList, byte[] vmContent, int length ) throws IOException
{
Exception errEx = null;
try {
return new VmwareMetaData( osList, vmContent, length );
} catch ( UnsupportedVirtualizerFormatException e ) {
LOGGER.debug( "Machine description not in .vmx format." );
errEx = e;
}
try {
LOGGER.debug( "versuche vbox" );
return new VboxMetaData( osList, vmContent, length );
} catch ( UnsupportedVirtualizerFormatException | NullPointerException e ) {
LOGGER.debug( "Machine description not in .vbox format." );
errEx = e;
}
// how to do this check ??
try {
return new QemuMetaData( osList, vmContent);
} catch ( Exception e ) {
LOGGER.debug( "Disk file not qemu supported format" );
errEx = e;
}
if ( errEx != null ) {
LOGGER.error( "Machine description has an unknown format!", errEx );
}
return null;
}
public abstract boolean addHddTemplate( File diskImage, String hddMode, String redoDir );
public abstract boolean addHddTemplate( String diskImagePath, String hddMode, String redoDir );
public abstract boolean addDefaultNat();
public abstract void setOs( String vendorOsId );
public abstract boolean addDisplayName( String name );
public abstract boolean addRam( int mem );
public abstract void addFloppy( int index, String image, boolean readOnly );
public abstract boolean addCdrom( String image );
public abstract boolean addCpuCoreCount( int nrOfCores );
public abstract void setSoundCard( SoundCardType type );
public abstract SoundCardType getSoundCard();
public abstract void setDDAcceleration( DDAcceleration type );
public abstract DDAcceleration getDDAcceleration();
public abstract void setHWVersion( HWVersion type );
public abstract HWVersion getHWVersion();
public abstract void setEthernetDevType( int cardIndex, EthernetDevType type );
public abstract EthernetDevType getEthernetDevType( int cardIndex );
public abstract byte[] getDefinitionArray();
public abstract boolean addEthernet( EtherType type );
public abstract Virtualizer getVirtualizer();
public abstract void enableUsb( boolean enabled );
public abstract boolean disableSuspend();
/**
*
* Function used by subclasses to put the virtual devices, which the subclass supports in the
* respected map
* (i.e. a supported virtual Soundcard in the soundCards Map
*/
public abstract void registerVirtualHW();
}