diff options
-rw-r--r-- | src/main/java/org/openslx/util/vm/DiskImage.java | 40 | ||||
-rw-r--r-- | src/main/java/org/openslx/util/vm/QemuConfig.java | 441 | ||||
-rw-r--r-- | src/main/java/org/openslx/util/vm/QemuMetaData.java | 589 | ||||
-rw-r--r-- | src/main/java/org/openslx/util/vm/VboxConfig.java | 4 | ||||
-rw-r--r-- | src/main/java/org/openslx/util/vm/VmMetaData.java | 63 | ||||
-rw-r--r-- | src/main/java/org/openslx/util/vm/VmwareMetaData.java | 57 |
6 files changed, 926 insertions, 268 deletions
diff --git a/src/main/java/org/openslx/util/vm/DiskImage.java b/src/main/java/org/openslx/util/vm/DiskImage.java index 2b24a3f..30fea99 100644 --- a/src/main/java/org/openslx/util/vm/DiskImage.java +++ b/src/main/java/org/openslx/util/vm/DiskImage.java @@ -19,9 +19,6 @@ public class DiskImage */ private static final int VMDK_MAGIC = 0x4b444d56; private static final int VDI_MAGIC = 0x7f10dabe; - /** - * Big endian representation of the 4 bytes 'QFI\xFB' - */ private static final int QEMU_MAGIC = 0x514649fb; public enum ImageFormat @@ -163,19 +160,30 @@ public class DiskImage return; } - // TODO: qcow - file.seek( 0 ); - if ( file.readInt() == QEMU_MAGIC ) { - // dummy values - this.isStandalone = true; - this.isCompressed = false; - this.isSnapshot = false; - this.format = ImageFormat.QCOW2; - this.subFormat = null; - this.diskDescription = null; - this.hwVersion = 0; - return; - } + file.seek(0); + //TODO: Standalone & Snapshot + if (file.readInt() == QEMU_MAGIC) { + //skip the next 14 ints as they don't interest us + // - QFI version (4 bytes) + // - backing file offset (8 bytes) + // - backing (8 bytes) + // - crypt method (4 bytes) + // - l1 size (4 bytes) + // - l1 table offset (8 bytes) + // - refcount table offset (8 bytes) + // - refcount cluster (4 bytes) + file.skipBytes( 14 * 4 ); + this.isSnapshot = file.readInt() > 0; + //skip the next 14 ints as they don't interest us + file.seek(374); + this.isCompressed = file.read() == 1; + this.diskDescription = null; + this.format = ImageFormat.QCOW2; + this.isStandalone = true; + this.subFormat = null; + this.hwVersion = 0; + return; + } } throw new UnknownImageFormatException(); } diff --git a/src/main/java/org/openslx/util/vm/QemuConfig.java b/src/main/java/org/openslx/util/vm/QemuConfig.java new file mode 100644 index 0000000..89df62c --- /dev/null +++ b/src/main/java/org/openslx/util/vm/QemuConfig.java @@ -0,0 +1,441 @@ +package org.openslx.util.vm; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.LinkedHashMap; + +import java.util.Map; +import java.util.TreeMap; +import org.apache.log4j.Logger; +import static org.openslx.util.vm.QemuConfig.Header.*; +import org.openslx.util.vm.VmMetaData.DriveBusType; + +public final class QemuConfig { + + private static final Logger LOGGER = Logger.getLogger(QemuConfig.class); + + private Map<LinkedHashMap<String, String>, TreeMap<String, String>> entries = new LinkedHashMap<>(); + + private String osName = new String(); + + private final static String QUOTE = "\""; + + private ArrayList<VmMetaData.HardDisk> hddsArray = new ArrayList<>(); + + public static enum Header { + BOOT("boot-opts", null), DEVICE("device", null), DRIVE("drive", ""), + MACHINE("machine", null), MEMORY("memory", null), NAME("name", null), + NETDEV("netdev", ""), SMP("smp-opts", null); + + private final String header; + + private String id; + + private Header(String header, String id) { + this.header = header; + this.id = id; + } + + public String getHeader() { + return this.header; + } + + public String getID() { + return id; + } + + public void setID(String id) { + this.id = id; + } + + @Override + public String toString() { + String result; + if (id == null) { + result = "[" + header + "]"; + } else { + result = "[" + header + " " + QUOTE + id + QUOTE + "]"; + } + return result; + } + } + + public QemuConfig(byte[] vmContent, int length) { + ArrayList<String> result; + BufferedReader stream = null; + try { + stream = new BufferedReader( + new InputStreamReader( + new ByteArrayInputStream(vmContent, 0, length), StandardCharsets.ISO_8859_1)); + result = new ArrayList<>(); + String line; + + while ((line = stream.readLine()) != null) { + if (line.startsWith("#") == false) { + if (line.isEmpty() == false) { + result.add(line.trim()); + } + } + } + stream.close(); + stream = null; + } catch (IOException e) { + result = null; + } finally { + if (stream != null) { + try { + stream.close(); + stream = null; + } catch (IOException ioe2) { + } + } + } + init(result); + } + + public QemuConfig(File configFile) { + ArrayList<String> result; + BufferedReader stream = null; + try { + stream = new BufferedReader( + new InputStreamReader( + new FileInputStream(configFile), StandardCharsets.ISO_8859_1)); + result = new ArrayList<>(); + String line; + + while ((line = stream.readLine()) != null) { + if (line.startsWith("#") == false) { + if (line.isEmpty() == false) { + result.add(line.trim()); + } + } + } + stream.close(); + stream = null; + } catch (IOException e) { + result = null; + } finally { + if (stream != null) { + try { + stream.close(); + stream = null; + } catch (IOException ioe2) { + } + } + } + init(result); + } + + public void init(ArrayList<String> lines) { + int index = -1; + int nbDev = 0; + int nbDrive = 0; + int nbNetDev = 0; + + ArrayList<String> listID = new ArrayList<>(); + LinkedHashMap<String, String> headers = null; + TreeMap<String, String> options = null; + boolean exist = false; + boolean save = true; + if (lines != null) { + for (String option : lines) { + if (option.startsWith("[") && option.endsWith("]")) { + option = option.replaceAll("\\[|\\]", ""); + headers = new LinkedHashMap<>(); + if (option.contains(DRIVE.getHeader()) && option.contains(QUOTE)) { //Check drive with id + String[] drive = option.split(QUOTE); + for (String id : listID) { + if (drive[1].equals(id)) { + DRIVE.setID("id-disk-" + nbDrive); + listID.add(DRIVE.getID()); + exist = true; + } + } + if (!exist) { + DRIVE.setID(drive[1]); + listID.add(DRIVE.getID()); + } + headers.put(DRIVE.getHeader(), DRIVE.getID()); + nbDrive++; + exist = false; + } else if (option.equals(DRIVE.getHeader())) {//Check drive without id + DRIVE.setID("id-disk-" + nbDrive); + listID.add(DRIVE.getID()); + headers.put(option, DRIVE.getID()); + nbDrive++; + } else if (option.contains(NETDEV.getHeader()) && option.contains(QUOTE)) {//Check netdev with id + String[] netdev = option.split(QUOTE); + for (String id : listID) { + if (netdev[1].equals(id)) { + NETDEV.setID("id-netdev-" + nbNetDev); + listID.add(NETDEV.getID()); + exist = true; + } + } + if (!exist) { + NETDEV.setID(netdev[1]); + listID.add(NETDEV.getID()); + } + headers.put(NETDEV.getHeader(), NETDEV.getID()); + nbNetDev++; + exist = false; + } else if (option.equals(NETDEV.toString())) {//Check netdev without id + NETDEV.setID("id-netdev-" + nbNetDev); + listID.add(NETDEV.getID()); + headers.put(option, NETDEV.getID()); + } else if (option.equals(DEVICE.getHeader())) {//This will always come as [device] + DEVICE.setID("dev" + nbDev); + headers.put(option, DEVICE.getID()); + nbDev++; + } else { + if (option.equals(MEMORY.getHeader()) || option.equals(SMP.getHeader()) || option.equals(MACHINE.getHeader())) { + save = false; + continue; + } else { + headers.put(option, null); + } + } + options = new TreeMap<>(); + index++; + } else if (index == -1) { + //In case file doesn't begin with a header + LOGGER.error("This config file is invalid. Chech syntax. Must begin with [..]"); + } else { + if (save) { + String[] parameter = option.split("="); + options.put(parameter[0].trim(), parameter[1].trim().replace(QUOTE, "")); + entries.put(headers, options); + }else{ + save = true; + } + } + } + } + } + + public TreeMap<String, String> get(String key, String id) { + TreeMap<String, String> value = null; + LinkedHashMap keys = new LinkedHashMap(); + keys.put(key, id); + if (entries.containsKey(keys)) { + value = entries.get(keys); + } + return value; + } + + public void set(LinkedHashMap<String, String> key, TreeMap value) { + entries.put(key, value); + } + + public TreeMap<LinkedHashMap<String, String>, TreeMap<String, String>> get() { + return (TreeMap<LinkedHashMap<String, String>, TreeMap<String, String>>) entries; + } + + public String getDisplayName() { + String result = ""; + LinkedHashMap key = new LinkedHashMap(); + key.put(NAME.getHeader(), null); + + if (entries.containsKey(key)) { + result = entries.get(key).get("guest"); + } + return result; + } + + public boolean isMachineSnapshot() { + boolean isSnapshot = false; + LinkedHashMap key = new LinkedHashMap(); + key.put(DRIVE.getHeader(), DRIVE.getID()); + String active = entries.get(key).get("snapshot"); + + if (active != null && active.equals("on")) { + isSnapshot = true; + } + return isSnapshot; + } + + public void setOsName() { + //It is not defined in config file. Using dummy name. Will be set in combo box later + osName = "QemuOS"; + } + + public String getOsName() { + return osName; + } + + public void setHdds() { + int dev = 0; + String filename = null; + DriveBusType bus = null; + String controllerDevice = null; + LinkedHashMap<String, String> keys; + TreeMap<String, String> options; + for (Map.Entry<LinkedHashMap<String, String>, TreeMap<String, String>> entry : entries.entrySet()) { + String busType; + if (entry.getKey().containsKey(DRIVE.getHeader())) { + if (entry.getValue().containsKey("index")) { + if (entry.getValue().get("index").equals("0")) { + DRIVE.setID(entry.getKey().get(DRIVE.getHeader())); + + filename = entry.getValue().get("file"); + if (filename == null) { + LOGGER.error("Please make sure your harddrive has a path"); + } + + busType = entry.getValue().get("if"); + if (busType != null) { + switch (busType) { + case "ide": + bus = DriveBusType.IDE; + break; + case "scsi": + bus = DriveBusType.SCSI; + break; +// case "virtio": + // bus = DriveBusType.VIRTIO; + case "sata": + //not available for Qemu. Others : sd, mtd, floppy, pflash + break; + default: + bus = DriveBusType.SCSI; + break; + } + } else { + bus = DriveBusType.SCSI; + busType = "scsi"; + keys = new LinkedHashMap<>(); + keys.put(DRIVE.getHeader(), DRIVE.getID()); + options = entries.get(entry.getKey()); + options.put("if", busType); + entries.put(keys, options); + } + } + } + } + if (entry.getKey().containsKey(DEVICE.getHeader())) { + String drive = entry.getValue().get("drive"); + if (drive != null && drive.equals(DRIVE.getID())) { + controllerDevice = entry.getValue().get("driver"); + dev++; + } + } else { + for (LinkedHashMap<String, String> key : entries.keySet()) { + if (key.containsKey(DEVICE.getHeader())) { + dev++; + } + } + } + if (dev == 0) { + if (bus != null) { + switch (bus) { + case IDE: + controllerDevice = "ide-hd"; + break; + case SCSI: + controllerDevice = "scsi-generic"; + break; + default: + controllerDevice = "scsi-generic"; + break; + } + } + } + if ((bus != null) && (filename != null) && (controllerDevice != null)) { + hddsArray.add(new VmMetaData.HardDisk(controllerDevice, bus, filename));; + + if (dev == 0) { + keys = new LinkedHashMap<>(); + options = new TreeMap<>(); + DEVICE.setID(DRIVE.getID()); + keys.put(DEVICE.getHeader(), DEVICE.getID()); + options.put("drive", DRIVE.getID()); + options.put("driver", controllerDevice); + entries.put(keys, options); + } + break; + } + } + } + + public ArrayList<VmMetaData.HardDisk> getHdds() { + return hddsArray; + } + + public String toString(boolean filtered) { + StringBuilder sb = new StringBuilder(300); + LinkedHashMap<LinkedHashMap<String, String>, TreeMap<String, String>> sortedArray = null; + if (filtered) { + sortedArray = new LinkedHashMap<>(); + for (Map.Entry<LinkedHashMap<String, String>, TreeMap<String, String>> entry : entries.entrySet()) { + if (entry.getKey().containsKey(DEVICE.getHeader())) { + DEVICE.setID(null); + entry.getKey().replace(DEVICE.getHeader(), null); + sortedArray.put(entry.getKey(), entry.getValue()); + } + if (entry.getKey().containsKey(NAME.getHeader()) || entry.getKey().containsKey(DRIVE.getHeader())) { + sortedArray.put(entry.getKey(), entry.getValue()); + } + } + } + + for (Map.Entry<LinkedHashMap<String, String>, TreeMap<String, String>> entry : sortedArray == null ? entries.entrySet() : sortedArray.entrySet()) { + + String header = entry.getKey().keySet().toString(); + + if (entry.getKey().containsKey(DRIVE.getHeader())) { + if ((entry.getValue().get("index") != null)) { + if ((entry.getValue().get("index").equals("0"))) { + header = DRIVE.toString(); + } else { + continue; + } + } else if (entry.getValue().get("media") != null) { + DRIVE.setID(entry.getKey().get(DRIVE.getHeader())); + header = DRIVE.toString(); + } else if (entry.getValue().get("if") != null) { + if (entry.getValue().get("if").equals("floppy")) { + DRIVE.setID(entry.getKey().get(DRIVE.getHeader())); + header = DRIVE.toString(); + } + } else { + continue; + } + } + + if (entry.getKey().containsKey(DEVICE.getHeader())) { + DEVICE.setID(null); + entry.getKey().remove(DEVICE.getHeader()); + entry.getKey().put(DEVICE.getHeader(), null); + header = DEVICE.toString(); + } + + if (entry.getKey().containsKey(NETDEV.getHeader())) { + header = NETDEV.toString(); + } + + sb.append(header + "\n"); + TreeMap<String, String> values = entry.getValue(); + + for (String key : values.keySet()) { + String value = values.get(key); + if (value == null) { + sb.append(" " + key + " = " + value + "\n"); + } else { + if (key.equals("driver")) { + if (value.isEmpty()) { + continue; + } + } + sb.append(" " + key + " = " + QUOTE + value + QUOTE + "\n"); + } + } + } + return sb.toString(); + } +} diff --git a/src/main/java/org/openslx/util/vm/QemuMetaData.java b/src/main/java/org/openslx/util/vm/QemuMetaData.java index 201ffd8..814bfa4 100644 --- a/src/main/java/org/openslx/util/vm/QemuMetaData.java +++ b/src/main/java/org/openslx/util/vm/QemuMetaData.java @@ -1,233 +1,442 @@ package org.openslx.util.vm; import java.io.File; -import java.io.FileNotFoundException; import java.io.IOException; import java.nio.charset.StandardCharsets; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; +import java.util.TreeMap; import org.apache.log4j.Logger; import org.openslx.bwlp.thrift.iface.OperatingSystem; import org.openslx.bwlp.thrift.iface.Virtualizer; import org.openslx.thrifthelper.TConst; -import org.openslx.util.vm.DiskImage.ImageFormat; -import org.openslx.util.vm.DiskImage.UnknownImageFormatException; +import static org.openslx.util.vm.QemuConfig.Header.*; -public class QemuMetaData extends VmMetaData<VBoxSoundCardMeta, VBoxDDAccelMeta, VBoxHWVersionMeta, VBoxEthernetDevTypeMeta, VBoxUsbSpeedMeta> -{ +class QemuDDAccelMeta { - private final Map<String, String> arguments = new HashMap<String, String>(); - // the above map's elements will take the place of <args> in the config string - private String config; - private static final Logger LOGGER = Logger.getLogger( QemuMetaData.class ); + public final boolean isPresent; - private static final Virtualizer virtualizer = new Virtualizer( TConst.VIRT_QEMU, "QEMU-KVM" ); - - public QemuMetaData( List<OperatingSystem> osList, File file ) throws FileNotFoundException, IOException, UnsupportedVirtualizerFormatException - { - super( osList ); - DiskImage di; - try { - di = new DiskImage( file ); - } catch ( UnknownImageFormatException e ) { - di = null; - } - if ( di == null || di.format != ImageFormat.QCOW2 ) { - throw new UnsupportedVirtualizerFormatException( "This is not a qcow2 disk image" ); - } - config = "qemu-system-i386 <args> <image> -enable-kvm\nqemu-system-x86_64 <args> <image> -enable-kvm"; - displayName = file.getName().substring( 0, file.getName().indexOf( "." ) ); - setOs( "anyOs" ); - hdds.add( new HardDisk( "anychipset", DriveBusType.IDE, file.getAbsolutePath() ) ); - makeStartSequence(); - } - - // initiates the arguments map with a default working sequence that will later be used in the definition array - public void makeStartSequence() - { - arguments.put( "cpu", "host" ); - arguments.put( "smp", "2" ); - arguments.put( "m", "1024" ); - arguments.put( "vga", "std" ); - } - - private String configWithArgs() - { - String tempString = ""; - for ( String key : arguments.keySet() ) { - tempString += "-" + key + " " + arguments.get( key ) + " "; - } - return config.replaceAll( "<args>", tempString ); - } - - @Override - public byte[] getFilteredDefinitionArray() - { - return configWithArgs().getBytes( StandardCharsets.UTF_8 ); - } - - @Override - public void applySettingsForLocalEdit() - { - } - - @Override - public boolean addHddTemplate( File diskImage, String hddMode, String redoDir ) - { - String tempS = config.replaceAll( "<image>", diskImage.getAbsolutePath() ); - config = tempS; - hdds.add( new HardDisk( "anychipset", DriveBusType.IDE, diskImage.getAbsolutePath() ) ); - return true; - } - - @Override - public boolean addHddTemplate( String diskImagePath, String hddMode, String redoDir ) - { - String tempS = config.replaceAll( "<image>", diskImagePath ); - config = tempS; - hdds.add( new HardDisk( "anychipset", DriveBusType.IDE, diskImagePath ) ); - return true; - } - - @Override - public boolean addDefaultNat() - { - return true; - } - - @Override - public void setOs( String vendorOsId ) - { - setOs( TConst.VIRT_QEMU, vendorOsId ); - } - - @Override - public boolean addDisplayName( String name ) - { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean addRam( int mem ) - { - this.arguments.put( "m", Integer.toString( mem ) ); - return true; - } - - @Override - public void addFloppy( int index, String image, boolean readOnly ) - { - // TODO Auto-generated method stub - - } - - @Override - public boolean addCdrom( String image ) - { - // TODO Auto-generated method stub - return false; - } + public QemuDDAccelMeta(boolean present) { + isPresent = present; + } +} - @Override - public boolean addCpuCoreCount( int nrOfCores ) - { - this.arguments.put( "smp", Integer.toString( nrOfCores ) ); - return true; - } +class QemuHWVersionMeta { - @Override - public void setSoundCard( VmMetaData.SoundCardType type ) - { - } - - @Override - public VmMetaData.SoundCardType getSoundCard() - { - return null; - } + public final int version; - @Override - public void setDDAcceleration( VmMetaData.DDAcceleration type ) - { - } + public QemuHWVersionMeta(int vers) { + version = vers; + } +} - @Override - public VmMetaData.DDAcceleration getDDAcceleration() - { - return null; - } +class QemuEthernetDevTypeMeta { - @Override - public void setHWVersion( VmMetaData.HWVersion type ) - { - } + public final String value; - @Override - public VmMetaData.HWVersion getHWVersion() - { - return null; - } + public QemuEthernetDevTypeMeta(String val) { + value = val; + } +} - @Override - public void setEthernetDevType( int cardIndex, VmMetaData.EthernetDevType type ) - { - } +class QemuSoundCardMeta { - @Override - public VmMetaData.EthernetDevType getEthernetDevType( int cardIndex ) - { - return null; - } + public final boolean isPresent; + public final String value; - @Override - public byte[] getDefinitionArray() - { - return configWithArgs().getBytes( StandardCharsets.UTF_8 ); - } + public QemuSoundCardMeta(boolean present, String val) { - @Override - public boolean addEthernet( VmMetaData.EtherType type ) - { - return false; - } + isPresent = present; + value = val; + } +} +class QemuUSBMeta { - @Override - public Virtualizer getVirtualizer() - { - return virtualizer; - } + public final String value; + public final int speed; - @Override - public boolean tweakForNonPersistent() - { - return false; - } + public QemuUSBMeta(String value, int speed) { - @Override - public void registerVirtualHW() - { - } + this.value = value; + this.speed = speed; + } +} - @Override +public final class QemuMetaData extends VmMetaData<QemuSoundCardMeta, QemuDDAccelMeta, QemuHWVersionMeta, QemuEthernetDevTypeMeta, QemuUSBMeta> { + + private static final Logger LOGGER = Logger.getLogger(QemuMetaData.class); + + private static final Virtualizer virtualizer = new Virtualizer(TConst.VIRT_QEMU, "QEMU-KVM"); + + private final QemuConfig config; + + private TreeMap<String, String> option; + + private LinkedHashMap<String, String> header; + + private int cdromCounter = 0; + + private int floppyCounter = 0; + + private int netdevCounter = 0; + + public static enum EthernetType { + NAT("qnet1"), BRIDGED("qnet0"), HOST_ONLY("qnet2"); + + public final String vmnet; + + private EthernetType(String vnet) { + this.vmnet = vnet; + } + } + + public QemuMetaData(List<OperatingSystem> osList, File config) { + super(osList); + this.config = new QemuConfig(config); + init(); + } + + public QemuMetaData(List<OperatingSystem> osList, byte[] vmContent, int length) throws IOException, UnsupportedVirtualizerFormatException { + super(osList); + this.config = new QemuConfig(vmContent, length); + init(); + } + + public void init() { + registerVirtualHW(); + config.setHdds(); + displayName = config.getDisplayName(); + setOs(config.getOsName()); + isMachineSnapshot = config.isMachineSnapshot(); + for (HardDisk hardDisk : config.getHdds()) { + hdds.add(hardDisk); + } + } + + @Override + public byte[] getFilteredDefinitionArray() { + //TODO: Filter is done fix server side + return config.toString(false).getBytes(StandardCharsets.UTF_8); + } + + @Override + public byte[] getDefinitionArray() { + return config.toString(true).getBytes(StandardCharsets.UTF_8); + } + + @Override + public void applySettingsForLocalEdit() { + //nothing ! for VMware + } + + @Override + public boolean addHddTemplate(File diskImage, String hddMode, String redoDir) { + return addHddTemplate(diskImage.getName(), hddMode, redoDir); + } + + @Override + public boolean addHddTemplate(String diskImagePath, String hddMode, String redoDir) { + DriveBusType bus = null; + option = new TreeMap<>(); + option = config.get(DRIVE.getHeader(), DRIVE.getID()); + + if (option != null) { + option.remove("file"); + option.put("file", diskImagePath); + if (option.get("if") == null) { + + } else { + switch (option.get("if")) { + case "ide": + bus = DriveBusType.IDE; + break; + case "scsi": + bus = DriveBusType.SCSI; + break; + case "sata": + //not available for Qemu. Others : sd, mtd, floppy, pflash, virtio + break; + default: + break; + } + } + } else { + LOGGER.error("Missing disk"); + } + header = new LinkedHashMap<>(); + header.put(DRIVE.getHeader(), DRIVE.getID()); + config.set(header, option); + + option = new TreeMap<>(); + option = config.get(DEVICE.getHeader(), DEVICE.getID()); + + if (option == null) { + option = new TreeMap<>(); + header = new LinkedHashMap<>(); + header.put(DEVICE.getHeader(), null); + + option.put("drive", DRIVE.getID()); + if (bus != null) { + if (bus.equals(DriveBusType.IDE)) { + option.put("driver", "ide-hd"); + } else if (bus.equals(DriveBusType.SCSI)) { + option.put("driver", "scsi-hd"); + } + } else { + //Shouldn't come to this but to check TODO + } + config.set(header, option); + } + return true; + } + + @Override + public boolean addDefaultNat() { + //No arguments needed, default on nat. But cannot receive + return true; + } + + @Override + public void setOs(String vendorOsId) { + setOs(TConst.VIRT_QEMU, vendorOsId); + } + + @Override + public boolean addDisplayName(String name) { + option = new TreeMap<>(); + option.put("guest", name); + + header = new LinkedHashMap<>(); + header.put(NAME.getHeader(), null); + + config.set(header, option); + return true; + } + + @Override + public boolean addRam(int mem) { + option = new TreeMap<>(); + option.put("size", "" + mem); + + header = new LinkedHashMap<>(); + header.put(MEMORY.getHeader(), null); + + config.set(header, option); + return true; + } + + @Override + public void addFloppy(int index, String image, boolean readOnly) { + option = new TreeMap<>(); + if (readOnly) { + option.put("readonly", "on"); + } else { + option.put("readonly", "off"); + } + option.put("if", "floppy"); + option.put("file", image); + + header = new LinkedHashMap<>(); + header.put(DRIVE.getHeader(), "floppy" + floppyCounter); + config.set(header, option); + floppyCounter++; + } + + @Override + public boolean addCdrom(String image) { + option = new TreeMap<>(); + option.put("media", "cdrom"); + option.put("file", image); + header = new LinkedHashMap<>(); + header.put(DRIVE.getHeader(), "cdrom" + cdromCounter); + config.set(header, option); + cdromCounter++; + return true; + } + + @Override + public boolean addCpuCoreCount(int nrOfCores) { + option = new TreeMap<>(); + option.put("cpus", nrOfCores + ""); + + header = new LinkedHashMap<>(); + header.put(SMP.getHeader(), null); + config.set(header, option); + return true; + } + + @Override + public void setSoundCard(VmMetaData.SoundCardType type) { + //TODO Not possible will be set as comment in config file + } + + @Override + public VmMetaData.SoundCardType getSoundCard() { + //TODO set to default, just write comment + return VmMetaData.SoundCardType.DEFAULT; + } + + @Override + public void setDDAcceleration(VmMetaData.DDAcceleration type) { + //TODO: Not really used by qemu. + } + + @Override + public VmMetaData.DDAcceleration getDDAcceleration() { + return DDAcceleration.OFF; + } + + @Override + public void setHWVersion(VmMetaData.HWVersion type) { + //nothing... + } + + @Override + public VmMetaData.HWVersion getHWVersion() { + return VmMetaData.HWVersion.DEFAULT; + } + + @Override + public void setEthernetDevType(int cardIndex, VmMetaData.EthernetDevType type) { + /* + //TODO + QemuEthernetDevTypeMeta dev = networkCards.get(type); + header = new LinkedHashMap<>(); + header.put(DEVICE.getHeader(), "net" + netdevCounter); + option = new TreeMap<>(); + option.put("driver", dev.value); + //option.put("netdev", "net" + cardIndex); + config.set(header, option); + netdevCounter++; + */ + } + + @Override + public VmMetaData.EthernetDevType getEthernetDevType(int cardIndex) { + //TO DO + return EthernetDevType.AUTO; + } + + @Override + public boolean addEthernet(VmMetaData.EtherType type) { + boolean ret = false; + int index = 0; + //TODO use existing interface if given or create a new one + for (;; ++index) { + DEVICE.setID("netType" + index); + TreeMap<String, String> dev = config.get(DEVICE.getHeader(), DEVICE.getID()); + + if (dev == null || dev.get("netdev") == null) { + break; + } + + } + + switch (type) { + case NAT: + ret = addEthernet(index, EthernetType.NAT); + break; + case BRIDGED: + ret = addEthernet(index, EthernetType.BRIDGED); + break; + case HOST_ONLY: + ret = addEthernet(index, EthernetType.HOST_ONLY); + break; + default: + // Should not come to this... + break; + } + return ret; + } + + public boolean addEthernet(int index, EthernetType type) { + NETDEV.setID("net" + index); + header = new LinkedHashMap<>(); + header.put(NETDEV.getHeader(), NETDEV.getID()); + //netdev + option = new TreeMap<>(); + //device tap,ifname=nat1 + option.put("ifname", type.vmnet); + option.put("type", "tap"); + config.set(header, option); + //device + header = new LinkedHashMap<>(); + header.put(DEVICE.getHeader(), "netType" + netdevCounter); + option = new TreeMap<>(); + option.put("driver", "e1000"); + option.put("netdev", NETDEV.getID()); + config.set(header, option); + netdevCounter++; + return true; + } + + @Override + public Virtualizer getVirtualizer() { + return virtualizer; + } + +// @Override +// public void enableUsb(boolean enabled) { +// option = new TreeMap<>(); +// if (enabled) { +// option.put("usb", "on"); +// } else { +// option.put("usb", "off"); +// } +// +// header = new LinkedHashMap<>(); +// header.put(MACHINE.getHeader(), MACHINE.getID()); +// config.set(header, option); +// } + +// @Override +// public boolean disableSuspend() { +// return false; +// } + @Override + public boolean tweakForNonPersistent() { + return false; + } public void setMaxUsbSpeed( VmMetaData.UsbSpeed speed ) { // TODO: Actual speed setting? if ( speed == null || speed == VmMetaData.UsbSpeed.NONE ) { - arguments.remove( "usb" ); + option.remove( "usb" ); } else { - arguments.put( "usb", "" ); + option.put( "usb", "" ); } } @Override public VmMetaData.UsbSpeed getMaxUsbSpeed() { - if ( arguments.containsKey( "usb" ) ) + if (option.containsKey( "usb" ) ) return VmMetaData.UsbSpeed.USB2_0; // TODO return VmMetaData.UsbSpeed.NONE; } - + @Override + public void registerVirtualHW() { + soundCards.put(VmMetaData.SoundCardType.NONE, new QemuSoundCardMeta(false, null)); + soundCards.put(VmMetaData.SoundCardType.DEFAULT, new QemuSoundCardMeta(true, "ich6")); + soundCards.put(VmMetaData.SoundCardType.AC, new QemuSoundCardMeta(true, "ac97")); + soundCards.put(VmMetaData.SoundCardType.ES, new QemuSoundCardMeta(true, "es1370")); + soundCards.put(VmMetaData.SoundCardType.SOUND_BLASTER, new QemuSoundCardMeta(true, "sb16")); + + ddacc.put(VmMetaData.DDAcceleration.OFF, new QemuDDAccelMeta(false)); + ddacc.put(VmMetaData.DDAcceleration.ON, new QemuDDAccelMeta(true)); + + hwversion.put(VmMetaData.HWVersion.DEFAULT, new QemuHWVersionMeta(0)); + + usbSpeeds.put(VmMetaData.UsbSpeed.NONE, new QemuUSBMeta(null, 0)); + usbSpeeds.put(VmMetaData.UsbSpeed.USB1_1, new QemuUSBMeta("usb", 1)); + usbSpeeds.put(VmMetaData.UsbSpeed.USB2_0, new QemuUSBMeta("ehci", 2)); + usbSpeeds.put(VmMetaData.UsbSpeed.USB3_0, new QemuUSBMeta("usb_xhci", 3)); + + //networkCards.put(VmMetaData.EthernetDevType.VIRTIO, new QemuEthernetDevTypeMeta("virtio-net-pci")); + networkCards.put(VmMetaData.EthernetDevType.E1000, new QemuEthernetDevTypeMeta("e1000")); + networkCards.put(VmMetaData.EthernetDevType.PCNET32, new QemuEthernetDevTypeMeta("pcnet")); + //networkCards.put(VmMetaData.EthernetDevType.RTL8139, new QemuEthernetDevTypeMeta("rtl8139")); + + } } diff --git a/src/main/java/org/openslx/util/vm/VboxConfig.java b/src/main/java/org/openslx/util/vm/VboxConfig.java index e9870a5..6153abf 100644 --- a/src/main/java/org/openslx/util/vm/VboxConfig.java +++ b/src/main/java/org/openslx/util/vm/VboxConfig.java @@ -101,7 +101,9 @@ public class VboxConfig } } catch ( SAXException e ) { LOGGER.error( "Selected vbox file was not validated against the XSD schema: " + e.getMessage() ); - } + } catch ( Exception e) { + LOGGER.error( "Some error occured while trying to parse select virtualbox machine files: " + e.getMessage() ); + } // valid xml, try to create the DOM doc = XmlHelper.parseDocumentFromStream( new FileInputStream( file ) ); doc = XmlHelper.removeFormattingNodes( doc ); diff --git a/src/main/java/org/openslx/util/vm/VmMetaData.java b/src/main/java/org/openslx/util/vm/VmMetaData.java index 29e2db9..714a7e4 100644 --- a/src/main/java/org/openslx/util/vm/VmMetaData.java +++ b/src/main/java/org/openslx/util/vm/VmMetaData.java @@ -20,9 +20,9 @@ import org.openslx.bwlp.thrift.iface.Virtualizer; */ public abstract class VmMetaData<T, U, V, W, X> { - private static final Logger LOGGER = Logger.getLogger( VmMetaData.class ); + private static final Logger LOGGER = Logger.getLogger(VmMetaData.class); - /* + /* * Helper types */ protected Map<SoundCardType, T> soundCards = new HashMap<>(); @@ -146,19 +146,19 @@ public abstract class VmMetaData<T, U, V, W, X> } /* * Members - */ + */ - protected final List<HardDisk> hdds = new ArrayList<>(); + protected final List<HardDisk> hdds = new ArrayList<>(); - private final List<OperatingSystem> osList; + private final List<OperatingSystem> osList; - private OperatingSystem os = null; + private OperatingSystem os = null; - protected String displayName = null; + protected String displayName = null; - protected boolean isMachineSnapshot; + protected boolean isMachineSnapshot; - /* + /* * Getters for virtual hardware */ public List<SoundCardType> getSupportedSoundCards() @@ -222,27 +222,25 @@ public abstract class VmMetaData<T, U, V, W, X> /* * Getter for isMachineSnapshot - */ - public boolean isMachineSnapshot() - { - return isMachineSnapshot; - } - - /** - * 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() ); - } - - /* + */ + public boolean isMachineSnapshot() { + return isMachineSnapshot; + } + + /** + * 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 */ @@ -338,6 +336,11 @@ public abstract class VmMetaData<T, U, V, W, X> } catch ( UnsupportedVirtualizerFormatException e ) { exceptions.put( "Not a VirtualBox file", e ); } + try { + return new QemuMetaData( osList, vmContent, length ); + } catch ( UnsupportedVirtualizerFormatException e ) { + exceptions.put( "Not a QEMU file", e ); + } // TODO QEmu -- hack above expects qcow2 file, so we can't do anything here yet LOGGER.error( "Could not detect any known virtualizer format" ); for ( Entry<String, Exception> e : exceptions.entrySet() ) { diff --git a/src/main/java/org/openslx/util/vm/VmwareMetaData.java b/src/main/java/org/openslx/util/vm/VmwareMetaData.java index 29227a7..fab90de 100644 --- a/src/main/java/org/openslx/util/vm/VmwareMetaData.java +++ b/src/main/java/org/openslx/util/vm/VmwareMetaData.java @@ -17,46 +17,42 @@ import org.openslx.thrifthelper.TConst; import org.openslx.util.Util; import org.openslx.util.vm.VmwareConfig.ConfigEntry; -class VmWareSoundCardMeta -{ - public final boolean isPresent; - public final String value; +class VmWareSoundCardMeta { - public VmWareSoundCardMeta( boolean present, String val ) - { - isPresent = present; - value = val; - } + public final boolean isPresent; + public final String value; + + public VmWareSoundCardMeta(boolean present, String val) { + isPresent = present; + value = val; + } } -class VmWareDDAccelMeta -{ - public final boolean isPresent; +class VmWareDDAccelMeta { - public VmWareDDAccelMeta( boolean present ) - { - isPresent = present; - } + public final boolean isPresent; + + public VmWareDDAccelMeta(boolean present) { + isPresent = present; + } } -class VmWareHWVersionMeta -{ - public final int version; +class VmWareHWVersionMeta { - public VmWareHWVersionMeta( int vers ) - { - version = vers; - } + public final int version; + + public VmWareHWVersionMeta(int vers) { + version = vers; + } } -class VmWareEthernetDevTypeMeta -{ - public final String value; +class VmWareEthernetDevTypeMeta { - public VmWareEthernetDevTypeMeta( String val ) - { - value = val; - } + public final String value; + + public VmWareEthernetDevTypeMeta(String val) { + value = val; + } } class VmwareUsbSpeed @@ -660,5 +656,4 @@ public class VmwareMetaData extends VmMetaData<VmWareSoundCardMeta, VmWareDDAcce usbSpeeds.put( VmMetaData.UsbSpeed.USB2_0, new VmwareUsbSpeed( 2, "ehci" ) ); usbSpeeds.put( VmMetaData.UsbSpeed.USB3_0, new VmwareUsbSpeed( 3, "usb_xhci" ) ); } - } |