summaryrefslogblamecommitdiffstats
path: root/src/main/java/org/openslx/util/vm/QemuMetaData.java
blob: cf3b550b1e758c13e29786d60734ce90ec8287a2 (plain) (tree)
1
2
3
4
5
6
7
8
9


                            
                           



                                         
                         



                                                     
                                       













































































































































































































































































































































































                                                                                                                                               

 
package org.openslx.util.vm;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
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.QemuConfig.Header;
import static org.openslx.util.vm.QemuConfig.Header.MACHINE;

class QemuDDAccelMeta {

    public final boolean isPresent;

    public QemuDDAccelMeta(boolean present) {
        isPresent = present;
    }
}

class QemuHWVersionMeta {

    public final int version;

    public QemuHWVersionMeta(int vers) {
        version = vers;
    }
}

class QemuEthernetDevTypeMeta {

    public final String value;

    public QemuEthernetDevTypeMeta(String val) {
        value = val;
    }
}

class QemuSoundCardMeta {

    public final boolean isPresent;
    public final String value;

    public QemuSoundCardMeta(boolean present, String val) {

        isPresent = present;
        value = val;
    }
}

public final class QemuMetaData extends VmMetaData<QemuSoundCardMeta, QemuDDAccelMeta, QemuHWVersionMeta, QemuEthernetDevTypeMeta> {

    private final Map<String, String> arguments = new HashMap<>(); //to remove at the end. easier
    // the above map's elements will take the place of <args> in the config string
    private QemuConfig config;

    private String setup;

    private TreeMap<String, String> option;

    private static final Logger LOGGER = Logger.getLogger(QemuMetaData.class);

    private static final Virtualizer virtualizer = new Virtualizer(TConst.VIRT_QEMU, "QEMU-KVM");

    private int cdromCounter = 0;

    private int driveCounter = 0;

    private int floppyCounter = 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();
        displayName = config.getDisplayName();
        setOs(config.getOsName());
        isMachineSnapshot = config.isMachineSnapshot();
        config.setHdds();
        for (HardDisk hardDisk : config.getHdds()) {
            hdds.add(hardDisk);
        }
    }


    @Override
    public byte[] getFilteredDefinitionArray() {
        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) {
        option = new TreeMap<>();
        String bus = "anychipset";
        DriveBusType busType = DriveBusType.IDE;
        //drive
        option = config.get("[drive \"disk0\"]");
        if (option != null) {
            option.replace("file", "\"" + diskImage.getAbsolutePath() + "\"");
            bus = option.get("if");
        }
        switch (bus) {
            case "ide":
                busType = DriveBusType.IDE;
                break;
            case "scsi":
                busType = DriveBusType.SCSI;
                break;
            case "sata":
                //not available for Qemu. Others : sd, mtd, floppy, pflash, virtio
                break;
            default:
                break;
        }
        //device
        option = config.get("[dev0]");
        hdds.add(new HardDisk(option.get("driver"), busType, diskImage.getAbsolutePath()));
        return true;
    }

    @Override
    public boolean addHddTemplate(String diskImagePath, String hddMode, String redoDir) {
        option = new TreeMap<>();

        //drive
        option.put("file", "\"" + diskImagePath + "\"");
        option.put("if", "\"scsi\"");
        String status = (isMachineSnapshot == true ? "on" : "off");
        option.put("snapshot", "\"" + status + "\"");
        config.set("[drive \"drive" + driveCounter + "\"]", option);

        //device
        option.put("drive", "\"drive" + driveCounter + "\"");
        option.put("driver", "scsi-hd");
        config.set("[device]", option);

        hdds.add(new HardDisk("anychipset", DriveBusType.IDE, diskImagePath));
        driveCounter++;
        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 + "\"");
        config.set("[name]", option);
        return true;
    }

    @Override
    public boolean addRam(int mem) {
        option = new TreeMap<>();
        option.put("size", "\"" + mem + "\"");
        config.set("[memory]", 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);
        config.set("[drive \"floppy" + floppyCounter + "\"]", option);
        floppyCounter++;
    }

    @Override
    public boolean addCdrom(String image) {
        option = new TreeMap<>();
        option.put("media", "\"cdrom\"");
        option.put("file", image);
        config.set("[drive \"cdrom" + cdromCounter + "\"]", option);
        cdromCounter++;
        return true;
    }

    @Override
    public boolean addCpuCoreCount(int nrOfCores) {
        option = new TreeMap<>();
        option.put("cpus", "\"" + nrOfCores + "\"");
        config.set("[smp-opts]", option);
        return true;
    }

    @Override
    public void setSoundCard(VmMetaData.SoundCardType type) {
        //Not possible will be set as comment in config file
    }

    @Override
    public VmMetaData.SoundCardType getSoundCard() {
        //not possible to set just write comment
        VmMetaData.SoundCardType soundcard = null;
        return soundcard;
    }

    @Override
    public void setDDAcceleration(VmMetaData.DDAcceleration type) {
        //Not really used by qemu. TODO:
    }

    @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) {
        QemuEthernetDevTypeMeta dev = networkCards.get(type);
        option = new TreeMap<>();
        option.put("driver", "\"" + dev.value + "\"");
        option.put("netdev", "\"net" + cardIndex + "\"");
        config.set("[device]", option);
    }

    @Override
    public VmMetaData.EthernetDevType getEthernetDevType(int cardIndex) {
        QemuEthernetDevTypeMeta ethernetDevTypeMeta = null;
        for (String key : config.get().keySet()) {
            if (key.equals("[dev" + cardIndex + "]")) {//wont work dev0
                if (config.get(key).get("netdev").equals("\"net" + cardIndex + "\"")) {
                    String devs = config.get(key).get("driver");

                    for (EthernetDevType type : VmMetaData.EthernetDevType.values()) {
                        ethernetDevTypeMeta = networkCards.get(type);
                        if (ethernetDevTypeMeta == null) {
                            continue;
                        }
                        if (devs.equals(ethernetDevTypeMeta.value)) {
                            return type;
                        }
                    }
                }
            }
        }
        return EthernetDevType.AUTO;
    }

    @Override
    public boolean addEthernet(VmMetaData.EtherType type) {
        boolean ret = false;
        int index = 0;      
        for (;; ++index) {
            TreeMap<String, String> dev = config.get("[dev" + index + "]");
            
            if (dev == null) {
                break;
            } else {
                if (dev.get("netdev") == null) {
                    break;
                }
            }
        }
        switch (type) {
            case NAT:
                //netdev
                option = new TreeMap<>();
                option.put("br", "nat1");
                option.put("type", "bridge");
                config.set("[netdev \"net" + index + "\"]", option);
                //device
                option = new TreeMap<>();
                break;
            case BRIDGED:
                option = new TreeMap<>();
                option.put("br", "'br0'");
                option.put("type", "'bridge'");
                config.set("[netdev \"net" + index + "\"]", option);
                break;
            case HOST_ONLY:
                //Dont know how to do it...
                break;
            default:
                // Should not come to this...
                break;
        }
        return ret;
    }

    @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\"");
        }
        config.set(MACHINE.value(), option);
    }

    @Override
    public boolean disableSuspend() {
        return false;
    }

    @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(DDAcceleration.OFF, new QemuDDAccelMeta(false));
        ddacc.put(DDAcceleration.ON, new QemuDDAccelMeta(true));

        hwversion.put(HWVersion.DEFAULT, new QemuHWVersionMeta(0));

        networkCards.put(EthernetDevType.VIRTIO, new QemuEthernetDevTypeMeta("virtio-net-pci"));
        networkCards.put(EthernetDevType.E1000, new QemuEthernetDevTypeMeta("e1000"));
        networkCards.put(EthernetDevType.PCNET32, new QemuEthernetDevTypeMeta("pcnet"));
        networkCards.put(EthernetDevType.RTL8139, new QemuEthernetDevTypeMeta("rtl8139"));

    }

}