summaryrefslogblamecommitdiffstats
path: root/src/main/java/org/openslx/util/vm/QemuMetaData.java
blob: 73612abc0bd9984ea28230e7ef77df452f14b5f7 (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.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 static org.openslx.util.vm.QemuConfig.Header.*;

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 final QemuConfig config;

    private String setup;

    private final static String QUOTE = "\"";

    private TreeMap<String, String> option;

    private LinkedHashMap<String, String> header;

    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 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 String getVMnet() {
            return this.vmnet;
        }
    }

    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());

        // Drive Filename && Bus
        if (option != null) {
            option.replace("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");
        }
        //Setting settings
        header = new LinkedHashMap<>();
        header.put(DRIVE.getHeader(), DRIVE.getID());
        config.set(header, option);

        // Device
        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) {
        //Not possible will be set as comment in config file
    }

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

    @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) {
        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) {
            DEVICE.setID("dev"+index);
            TreeMap<String, String> dev = config.get(DEVICE.getHeader(), DEVICE.getID());

            if (dev == null) {
                break;
            } else {
                if (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<>();
        option.put("ifname", type.vmnet);
        option.put("type", "tap");
        config.set(header, option);
        //device
        header = new LinkedHashMap<>();
        header.put(DEVICE.getHeader(), "");
        option = new TreeMap<>();
        option.put("driver", "e1000");
        option.put("netdev", NETDEV.getID());
        config.set(header, option);
        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 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"));

    }

}