package org.openslx.util.vm;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.UUID;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.log4j.Logger;
import org.openslx.bwlp.thrift.iface.OperatingSystem;
import org.openslx.bwlp.thrift.iface.Virtualizer;
public class VboxMetaData extends VmMetaData {
private static final Logger LOGGER = Logger.getLogger(VboxMetaData.class);
private static final Virtualizer virtualizer = new Virtualizer("virtualbox", "VirtualBox");
private final VboxConfig config;
public VboxMetaData(List<OperatingSystem> osList, File file)
throws IOException, UnsupportedVirtualizerFormatException {
super(osList);
this.config = new VboxConfig(file);
init();
}
public VboxMetaData(List<OperatingSystem> osList, byte[] vmContent, int length)
throws IOException, UnsupportedVirtualizerFormatException {
super(osList);
this.config = new VboxConfig(vmContent, length);
init();
}
private void init() {
this.config.init();
displayName = config.getDisplayName();
setOs("virtualbox", config.getOsName());
for (HardDisk hardDisk : config.getHdds()) {
hdds.add(hardDisk);
}
// DEBUG Code???? mark such code please!
try {
addFloppy(0, null, true);
WriteToFile();
} catch (TransformerFactoryConfigurationError | TransformerException e) {
// WriteToFile exceptions here...not important for the the LOGGER
e.printStackTrace();
}
}
// --TODO will be needed later again
private void WriteToFile() throws TransformerFactoryConfigurationError, TransformerException {
Transformer transformer = TransformerFactory.newInstance().newTransformer();
StreamResult output = new StreamResult(new File("output.xml"));
Source input = new DOMSource(config.getConfigDoc());
transformer.transform(input, output);
}
@Override
public Virtualizer getVirtualizer() {
return virtualizer;
}
@Override
public void enableUsb(boolean enabled) {
// TODO Auto-generated method stub
}
@Override
public void applySettingsForLocalEdit() {
// TODO Auto-generated method stub
}
@Override
public byte[] getFilteredDefinitionArray() {
return config.toString().getBytes(StandardCharsets.UTF_8);
}
@Override
public boolean addHddTemplate(String diskImage, String hddMode, String redoDir) {
config.changeAttribute("HardDisk", "location", diskImage);
return true;
}
@Override
public boolean addHddTemplate(File diskImage, String hddMode, String redoDir) {
String diskImagePath = diskImage.getName();
config.changeAttribute("HardDisk", "location", diskImagePath);
UUID newhdduuid = UUID.randomUUID();
LOGGER.debug(newhdduuid);
// patching the new uuid in the vbox config file here
String vboxUUid = "{" + newhdduuid.toString() + "}";
config.changeAttribute("HardDisk", "uuid", vboxUUid);
config.changeAttribute("Image", "uuid", vboxUUid);
// write the new hdd uuid in the vdi file
byte[] bytesToWrite = new byte[16];
int[] bytesOffset = { 32, 40, 48, 56, 16, 24, 0, 8, 56, 48, 40, 32, 24, 16, 8, 0 };
int offset = 0;
for (int i = 0; i < 2; i++) {
Long uuidlong = null;
if (i == 0) {
uuidlong = newhdduuid.getMostSignificantBits();
} else {
uuidlong = newhdduuid.getLeastSignificantBits();
}
for (int j = 0; j < 8; j++) {
int index = j + offset;
bytesToWrite[index] = (byte) (uuidlong >>> bytesOffset[index]);
}
offset = 8;
}
try (RandomAccessFile file = new RandomAccessFile(diskImage, "rw")) {
file.seek(392);
file.write(bytesToWrite, 0, 16);
} catch (Exception e) {
LOGGER.warn("could not patch new uuid in the vdi", e);
}
// we need a new machine uuid
UUID newMachineUuid = UUID.randomUUID();
if (newMachineUuid.equals(newhdduuid)) {
LOGGER.warn("The new Machine UUID is the same as the new HDD UUID; tying again...this vm might not start");
newMachineUuid = UUID.randomUUID();
}
String machineUUid = "{" + newMachineUuid.toString() + "}";
config.changeAttribute("Machine", "uuid", machineUUid);
return true;
}
@Override
public boolean addDefaultNat() {
config.addNewNode("Adapter", "NAT", false);
return true;
}
public void reWrite() {
try {
WriteToFile();
} catch (TransformerFactoryConfigurationError | TransformerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void setOs(String vendorOsId) {
// TODO Auto-generated method stub
}
@Override
public boolean addDisplayName(String name) {
config.changeAttribute("Machine", "name", name);
return true;
}
@Override
public boolean addRam(int mem) {
config.changeAttribute("Memory", "RAMSize", Integer.toString(mem));
return true;
}
@Override
public void addFloppy(int index, String image, boolean readOnly) {
if (image == null) {
} else {
}
}
@Override
public boolean addCdrom(String image) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean addCpuCoreCount(int nrOfCores) {
config.changeAttribute("CPU", "count", "1");
return true;
}
}