package org.opendedup.util;
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.ByteBuffer;
import java.util.logging.Logger;
import org.opendedup.sdfs.Main;
import org.opendedup.sdfs.filestore.MetaFileStore;
import org.opendedup.sdfs.io.BufferClosedException;
import org.opendedup.sdfs.io.DedupFileChannel;
import org.opendedup.sdfs.io.MetaDataDedupFile;
import org.opendedup.sdfs.io.VMDKData;
public class VMDKParser {
static long gb = 1024 * 1024 * 1024;
static long twogb = 2 * 1024 * 1024 * 1024;
private transient static Logger log = Logger.getLogger("sdfs");
public static MetaDataDedupFile writeFile(String path, String fileName,
long size) throws IOException, BufferClosedException {
path = path + File.separator + fileName;
File f = new File(path);
if (!f.exists())
f.mkdirs();
else {
throw new IOException("Cannot create vmdk at path " + path
+ "because path aleady exists");
}
long blockL = size / 512;
int heads = 255;
int sectors = 63;
if (size < gb) {
heads = 64;
sectors = 32;
} else if (size < twogb) {
heads = 128;
sectors = 32;
}
long cylanders = (size - 512) / (heads * sectors * 512);
if (cylanders < 0)
cylanders = 1;
StringBuffer sb = new StringBuffer(Main.CHUNK_LENGTH);
sb.append("# Disk DescriptorFile \n");
sb.append("version=1 \n");
sb.append("encoding=\"UTF-8\"\n");
sb.append("CID=" + RandomGUID.getVMDKCID() + "\n");
sb.append("parentCID=ffffffff\n");
sb.append("createType=\"vmfs\"\n");
sb.append("# Extent description\n");
sb.append("RW " + blockL + " VMFS \"" + fileName + "-flat.vmdk\" 0\n");
sb.append("# The Disk Data Base\n");
sb.append("ddb.virtualHWVersion = \"6\"\n");
sb.append("ddb.uuid = \"" + RandomGUID.getVMDKGUID() + "\"\n");
sb.append("ddb.geometry.cylinders = \"" + cylanders + "\"\n");
sb.append("ddb.geometry.heads = \"" + heads + "\"\n");
sb.append("ddb.geometry.sectors = \"" + sectors + "\"\n");
sb.append("ddb.adapterType = \"buslogic\"\n");
MetaDataDedupFile vmd = MetaFileStore.getMF(path + File.separator
+ fileName + ".vmdk");
DedupFileChannel ch = vmd.getDedupFile().getChannel();
ByteBuffer b = ByteBuffer.wrap(new byte[Main.CHUNK_LENGTH]);
byte[] strB = sb.toString().getBytes();
b.put(strB);
vmd.setLength(strB.length, true);
vmd.getDedupFile().getWriteBuffer(0).write(b.array(), 0);
vmd.getDedupFile().writeCache();
vmd.sync();
vmd.getDedupFile().writeCache();
MetaDataDedupFile vmdk = MetaFileStore.getMF(path + File.separator
+ fileName + "-flat.vmdk");
vmdk.setLength(size, true);
vmdk.getIOMonitor().setActualBytesWritten(0);
vmdk.getIOMonitor().setBytesRead(0);
vmdk.getIOMonitor().setDuplicateBlocks(0);
vmdk.sync();
ch.close();
log.info("Created vmdk of size " + vmdk.length() + " at " + path
+ File.separator + fileName);
return vmdk;
}
public static VMDKData parserVMDKFile(byte[] b)
throws NumberFormatException, IOException {
ByteArrayInputStream bis = new ByteArrayInputStream(b);
BufferedReader br = new BufferedReader(new InputStreamReader(bis));
String line;
int linesRead = 0;
VMDKData data = new VMDKData();
while ((line = br.readLine()) != null) {
String[] vals = line.split("=");
if (vals[0].trim().equalsIgnoreCase("version"))
data.setVersion(vals[1].trim().replaceAll("\"", ""));
if (vals[0].trim().equalsIgnoreCase("encoding"))
data.setEncoding(vals[1].trim().replaceAll("\"", ""));
if (vals[0].trim().equalsIgnoreCase("CID"))
data.setCid(vals[1].trim().replaceAll("\"", ""));
if (vals[0].trim().equalsIgnoreCase("parentCID"))
data.setParentCID(vals[1].trim().replaceAll("\"", ""));
if (vals[0].trim().equalsIgnoreCase("createType"))
data.setCreateType(vals[1].trim().replaceAll("\"", ""));
if (vals[0].trim().toUpperCase().startsWith("RW")) {
String sVals[] = vals[0].split(" ");
data.setAccess(sVals[0]);
data.setBlocks(Long.parseLong(sVals[1].replaceAll("\"", "")));
data.setVmfsType(sVals[2].replaceAll("\"", ""));
data.setDiskFile(sVals[3].replaceAll("\"", ""));
}
if (vals[0].trim().equalsIgnoreCase("ddb.virtualHWVersion")) {
data.setVirtualHWVersion(vals[1].trim().replaceAll("\"", ""));
}
if (vals[0].trim().equalsIgnoreCase("ddb.uuid")) {
data.setUuid(vals[1].trim().replaceAll("\"", ""));
}
if (vals[0].trim().equalsIgnoreCase("ddb.geometry.cylinders")) {
data.setCylinders(Long.parseLong(vals[1].trim().replaceAll(
"\"", "")));
}
if (vals[0].trim().equalsIgnoreCase("ddb.geometry.heads")) {
data.setHeads(Integer.parseInt(vals[1].trim().replaceAll("\"",
"")));
}
if (vals[0].trim().equalsIgnoreCase("ddb.geometry.sectors")) {
data.setSectors(Integer.parseInt(vals[1].trim().replaceAll(
"\"", "")));
}
if (vals[0].trim().equalsIgnoreCase("ddb.adapterType")) {
data.setAdapterType(vals[1].trim().replaceAll("\"", ""));
}
linesRead++;
}
if (data.getUuid() == null)
return null;
else
return data;
}
public static VMDKData parseVMDKFile(String path) throws IOException {
FileInputStream fileinputstream = new FileInputStream(path);
int numberBytes = fileinputstream.available();
byte bytearray[] = new byte[numberBytes];
fileinputstream.read(bytearray);
return parserVMDKFile(bytearray);
}
public static void main(String[] args) throws IOException {
System.out
.println(parseVMDKFile("/media/vmware/vmfs/Win2k8-3/Win2k8-3.vmdk"));
}
}