summaryrefslogblamecommitdiffstats
path: root/dozentenmodul/src/main/java/org/openslx/dozmod/util/VmWrapper.java
blob: e58653e716b60a3cc0cbbefd3b220fc5970fd828 (plain) (tree)
1
2
3
4
5
6
7
8
9


                                
                                     
                                
                           
                           
                                              
                                         







                                                     
 
                                       
                                     

                                                     

                                                 
                                                     
                                       
                                     


                                        





                                                                               
                                                                                             

                                                                                                                 

                                                                                                                       
 
                                                                                   
                                                                        

                                                                     
                                                                           
                 



                                                                                                           
                                    
                                                                                              

                                                             




                                                                                       
                                   




                                                                                        
                                                               
                                 


                                                                 

                         
                                                 
                                                      

                                   


                                                         
                 









                                                                       




                                                         
























                                                                                                                                   

         





                                                                                                          

                                                                                
                                                                     
           


                                                          
           
                                                                                   



                                                                                    
                                                               
                                           
                        
                                                    
                 
                                





                                                                                   
















                                                                                                                    
 
package org.openslx.dozmod.util;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.management.ManagementFactory;
import java.nio.charset.StandardCharsets;

import javax.management.AttributeNotFoundException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.openslx.bwlp.thrift.iface.OperatingSystem;
import org.openslx.dozmod.gui.Gui;
import org.openslx.dozmod.gui.helper.MessageType;
import org.openslx.dozmod.thrift.cache.MetaDataCache;
import org.openslx.thrifthelper.TConst;
import org.openslx.util.vm.DiskImage;
import org.openslx.util.vm.QemuMetaData;
import org.openslx.util.vm.VboxMetaData;
import org.openslx.util.vm.VmMetaData;
import org.openslx.util.vm.VmwareMetaData;

public class VmWrapper {

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

	public static void wrapVm(File diskFile, String imageName, byte[] machineDescription,
			String virtualizerId, int osId, DiskImage diskImageInfo) throws MetaDataMissingException,
			IOException {
		if (!diskFile.exists())
			throw new FileNotFoundException("Disk file " + diskFile.getAbsolutePath() + " does not exist");

		if (machineDescription == null || machineDescription.length < 10) {
			if (!TConst.VIRT_VMWARE.equals(virtualizerId)) {
				throw new MetaDataMissingException();
			}
			machineDescription = getFallbackVmx(diskImageInfo);
		}
		// Handle machine description to generate configuration file
		VmMetaData<?, ?, ?, ?> vmMeta = VmMetaData.getInstance(MetaDataCache.getOperatingSystems(),
				machineDescription, machineDescription.length);

		// Append disk & NAT
		if (!vmMeta.addDefaultNat() || !vmMeta.addHddTemplate(diskFile, null, null)) {
			throw new MetaDataMissingException();
		}

		// The guestOS should be in the vmx, but the user could have changed it
		// by editing
		// the image via the GUI. Those changes are not written back to the
		// stored vmx
		int osMaxMemMb = 0;
		if (virtualizerId != null && osId != 0) {
			OperatingSystem os = MetaDataCache.getOsById(osId);
			if (os != null && os.virtualizerOsId != null) {
				String virtOsId = os.virtualizerOsId.get(virtualizerId);
				if (virtOsId != null) {
					vmMeta.setOs(virtOsId);
				}
				if (os.maxMemMb > 0) {
					osMaxMemMb = os.maxMemMb;
				}
			}
		}
		vmMeta.addDisplayName(imageName);
		int mem = getMainMemoryMb() / 2 - 512;
		if (mem < 1024) {
			mem = 1024;
		}
		if (osMaxMemMb > 0 && mem > osMaxMemMb) {
			mem = osMaxMemMb;
		}
		vmMeta.addCpuCoreCount(1);
		vmMeta.addRam((mem / 4) * 4);
		vmMeta.addFloppy(0, null, true);
		vmMeta.addFloppy(1, null, true);
		vmMeta.addCdrom(""); // ISO-Based with no disk in drive
		vmMeta.addCdrom(null); // Autodetect real drive
		vmMeta.enableUsb(true);
		vmMeta.applySettingsForLocalEdit();

		// Output vm
		String base = diskFile.getAbsolutePath();
		int dot = base.lastIndexOf('.');
		if (dot > 0) {
			base = base.substring(0, dot);
		}

		String fileType = null;
		if (vmMeta instanceof VmwareMetaData) {
			fileType = ".vmx";
			// Copy BIOS with both floppies enabled
			try (FileOutputStream output = new FileOutputStream(new File(diskFile.getAbsoluteFile()
					.getParentFile(), "nvram")); InputStream input = ResourceLoader.getStream("/data/nvram")) {
				IOUtils.copy(input, output);
			} catch (Exception e) {
				Gui.asyncMessageBox("Konnte das BIOS für die VM nicht kopieren", MessageType.ERROR, LOGGER, e);
			}

		} else if (vmMeta instanceof VboxMetaData) {
			fileType = ".vbox";
		} else if (vmMeta instanceof QemuMetaData) {
			fileType = "_startCommand.txt";
		}
		if (fileType == null) {
			LOGGER.warn("file type somehow unclear; application could stop working here!");
		}

		File vmFile = new File(base + fileType);
		vmFile.delete();
		// actually write vmx to disk
		FileUtils.writeByteArrayToFile(vmFile, vmMeta.getFilteredDefinitionArray());
	}

	private static byte[] getFallbackVmx(DiskImage diskImageInfo) throws IOException {
		String vmx = ResourceLoader.getTextFile("/txt/vmx_template");
		return vmx.replace("%VM_HW_VERSION%", Integer.toString(diskImageInfo.hwVersion)).getBytes(
				StandardCharsets.UTF_8);
	}

	/**
	 * Generates a filename based on the given imageName and with the proper
	 * extension. The given imageName is sanitized and shortened.
	 * 
	 * @param imageName desired basename of image file
	 * @param extension desired extension
	 * @return the generated name
	 */
	public static String generateFilename(String imageName, String extension) {
		String fileName = imageName.replaceAll("[^a-zA-Z0-9_\\.\\-]+", "_");
		if (fileName.length() > 50) {
			fileName = fileName.substring(0, 50);
		}
		if (extension == null || extension.isEmpty()) {
			fileName += ".img";
		} else {
			fileName += "." + extension;
		}
		return fileName;
	}

	public static class MetaDataMissingException extends Exception {
		private static final long serialVersionUID = -7842986428831219758L;
	}

	private static int getMainMemoryMb() {
		MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
		Object attribute;
		try {
			attribute = mBeanServer.getAttribute(new ObjectName("java.lang", "type", "OperatingSystem"),
					"TotalPhysicalMemorySize");
		} catch (AttributeNotFoundException | InstanceNotFoundException | MalformedObjectNameException
				| MBeanException | ReflectionException e) {
			return -1;
		}
		try {
			return (int) (Long.parseLong(attribute.toString()) / (1024 * 1024));
		} catch (Exception e) {
			return -1;
		}
	}

}