summaryrefslogblamecommitdiffstats
path: root/src/main/java/org/openslx/util/vm/QemuConfig.java
blob: 89df62cafbc5d9a0a92397c80f7404e7a6fedb73 (plain) (tree)





















                                                                            
                                                                                                        


                                         
                                             
 
                                                                         
 
                               
                                                                            


                                                                             
                                    



                                                  
                                 
                         
         

                                   

                               










                                      



                                            
                                                                       

                          
         
     
 
                                                     











                                                                                                          
                                                



















                                            


































                                                                                           
                        
                         
 



                                                     
                            
                            

                                                                                       

                                                              

                                                                                                             












                                                                      
                                      




                                                                                          

                                                                                                                                             

                                                       
                                                                      










                                                                        
                                                                                           
                                                              

                                                            
                                                                                                      

                                                            
                                
                            





                                                                                                                                        
                     
                                              

                                         

                                                                                                    
                        






                                                                                                 




                 
                                                               
                                             



                                                 
         
                     

     
                                                                       


                                

                                                                                         



                                    

                                                
 


                                                   




                                        



                                                         















                                                                                            
                    


                                       

                                           
                                                                                                            
                           



                                                                           
 



                                                                                       
 
                                                             
                                              






                                                            

                                                                
                                            
                                                                                              

                                          
                                                            

                                          
                                






                                                                       
                         

                     
             



                                                                      

                          
                    




                                                                            
             
                           





                                                        

                                                              
                                
                                                              

                                  

                 
                                                                                    










                                                                                         
                      









                                                     
                                                                                                 

                                                
                                                                                                                





                                                                                                                    




                                                                      
                                                                                                                                                           
 
                                                               
 






                                                                      







                                                                           





                                                                 
                                   

                                                             




                                                                 






                                                              







                                                                 
                                                                                 
                 

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