package org.openslx.dozmod.util; import java.io.File; 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.FilenameUtils; import org.apache.commons.io.IOUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.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.virtualization.configuration.VirtualizationConfiguration; import org.openslx.virtualization.configuration.VirtualizationConfigurationException; import org.openslx.virtualization.configuration.VirtualizationConfigurationQemu; import org.openslx.virtualization.configuration.VirtualizationConfigurationVmware; import org.openslx.virtualization.configuration.data.ConfigurationDataDozModServerToDozModClient; import org.openslx.virtualization.configuration.logic.ConfigurationLogicDozModServerToDozModClient; import org.openslx.virtualization.configuration.transformation.TransformationException; import org.openslx.virtualization.disk.DiskImage; import org.openslx.virtualization.disk.DiskImageException; import org.openslx.virtualization.disk.DiskImageVmdk; public class VmWrapper { private static final Logger LOGGER = LogManager.getLogger(VmWrapper.class); public static void wrapVm(File diskFile, String imageName, byte[] machineDescription, String virtualizerId, int osId, DiskImage diskImageInfo) throws VirtualizationConfigurationException, IOException { // check if virtualization configuration is missing if (machineDescription == null) { // configuration is not available if (TConst.VIRT_VMWARE.equals(virtualizerId) && diskImageInfo instanceof DiskImageVmdk) { // get fallback VMX if virtualizer is VMware with VMDK disk image final DiskImageVmdk vmdkImageInfo = DiskImageVmdk.class.cast( diskImageInfo ); try { machineDescription = VmWrapper.getFallbackVmx(vmdkImageInfo); } catch (DiskImageException e) { throw new VirtualizationConfigurationException("Can not get fallback VMX configuration!"); } } else { // there is no way to reconstruct a configuration for other virtualizer throw new VirtualizationConfigurationException("Virtualization configuration is missing!"); } } // get guest operating system if possible OperatingSystem guestOs = null; if (osId != 0) { guestOs = MetaDataCache.getOsById(osId); } // handle machine description to generate configuration file final VirtualizationConfiguration virtualizationConfig = VirtualizationConfiguration .getInstance(MetaDataCache.getOperatingSystems(), machineDescription, machineDescription.length); // transform virtualization configuration for local editing byte[] configuration = null; try { final ConfigurationLogicDozModServerToDozModClient downloadLogic = new ConfigurationLogicDozModServerToDozModClient(); downloadLogic.apply( virtualizationConfig, new ConfigurationDataDozModServerToDozModClient( imageName, diskFile, guestOs, virtualizerId, getMainMemoryMb() ) ); configuration = virtualizationConfig.getConfigurationAsByteArray(); } catch ( TransformationException e ) { throw new VirtualizationConfigurationException( e.getLocalizedMessage() ); } // save BIOS if virtualizer is VMware if (virtualizationConfig instanceof VirtualizationConfigurationVmware) { try { FileOutputStream output = new FileOutputStream(new File(diskFile.getAbsoluteFile().getParentFile(), "nvram")); InputStream input = ResourceLoader.getStream("/data/nvram"); IOUtils.copy(input, output); input.close(); output.close(); } catch (Exception e) { Gui.asyncMessageBox("Konnte das BIOS für die VM nicht kopieren", MessageType.ERROR, LOGGER, e); } } else if ( virtualizationConfig instanceof VirtualizationConfigurationQemu ) { try { final VirtualizationConfigurationQemu virtualizationConfigQemu = VirtualizationConfigurationQemu.class .cast( virtualizationConfig ); virtualizationConfigQemu.transformOsLoader(); } catch ( VirtualizationConfigurationException | ClassCastException e ) { Gui.asyncMessageBox( "Konnte das BIOS für die VM nicht anpassen", MessageType.ERROR, LOGGER, e ); } } // save virtualization configuration as file to disk final String baseFileName = FilenameUtils.removeExtension( diskFile.getAbsolutePath() ); final String fileNameExtension = virtualizationConfig.getFileNameExtension(); final File vmFile = new File(baseFileName + "." + fileNameExtension); // delete original virtualization configuration file vmFile.delete(); // actually write virtualization configuration to disk FileUtils.writeByteArrayToFile(vmFile, configuration); } private static byte[] getFallbackVmx(DiskImageVmdk diskImageInfo) throws IOException, DiskImageException { final String vmx = ResourceLoader.getTextFile("/txt/vmx_template"); final short hwVersion = diskImageInfo.getHwVersion().getMajor(); return vmx.replace("%VM_HW_VERSION%", Short.toString(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; } 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; } } }