diff options
Diffstat (limited to 'src/main/java/org/openslx/util/vm/QemuConfig.java')
-rw-r--r-- | src/main/java/org/openslx/util/vm/QemuConfig.java | 441 |
1 files changed, 441 insertions, 0 deletions
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(); + } +} |