package org.opendedup.mtools;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.opendedup.sdfs.Main;
import org.opendedup.sdfs.io.VMDKData;
import org.opendedup.util.VMDKParser;
public class DiskUtils {
private static Logger log = Logger.getLogger("sdfs");
public static HashMap<String, VMDKMountPoint> mountedVMDKs = new HashMap<String, VMDKMountPoint>();
public static ArrayList<Partition> getPartitions(String fileName,
long cylinders) throws IOException {
ArrayList<Partition> al = new ArrayList<Partition>();
Process p = Runtime.getRuntime().exec(
"fdisk -l -u -C " + cylinders + " " + fileName);
BufferedReader reader = new BufferedReader(new InputStreamReader(p
.getInputStream()));
String line = null;
boolean initialized = false;
while ((line = reader.readLine()) != null) {
if (initialized) {
String[] tokens = line.split("\\s+");
Partition par = new Partition();
par.setDevice(tokens[0].trim());
if (tokens[1].trim().equals("*")) {
par.setBoot(true);
par.setStart(Integer.parseInt(tokens[2]));
par.setEnd(Long.parseLong(tokens[3]));
par.setBlocks(Long.parseLong(tokens[4]));
par.setSystem(Integer.parseInt(tokens[5]));
par.setType(tokens[6].trim());
} else {
par.setBoot(false);
par.setStart(Integer.parseInt(tokens[1]));
par.setEnd(Long.parseLong(tokens[2]));
par.setBlocks(Long.parseLong(tokens[3]));
par.setSystem(Integer.parseInt(tokens[4]));
par.setType(tokens[5].trim());
}
al.add(par);
} else
System.out.println(line);
if (line.trim().toLowerCase().startsWith("device"))
initialized = true;
}
return al;
}
public static synchronized String mountLoopBack(String fileName, long offset)
throws IOException {
offset = offset * 512;
Process p = Runtime.getRuntime().exec(
"losetup -v -f -o " + offset + " " + fileName);
BufferedReader reader = new BufferedReader(new InputStreamReader(p
.getInputStream()));
String line = reader.readLine();
String[] tokens = line.split(" /");
if (tokens.length != 2)
throw new IOException("unable to mount loopback for device "
+ fileName + " output is " + line);
String dev = "/" + tokens[1];
log.info("mounted volume to " + dev);
return dev;
}
public static synchronized boolean mountVMDK(String fileName,
String mountPath, long offset) {
mountPath = new File(mountPath).getPath();
log.info("mounting " + fileName + " to " + mountPath
+ " with offset : " + offset);
boolean mounted = true;
String loopBack = null;
if (!mountedVMDKs.containsKey(mountPath)) {
try {
loopBack = mountLoopBack(fileName, offset);
VMDKMountPoint mp = new VMDKMountPoint(loopBack, mountPath);
File f = new File(mountPath);
if (!f.exists())
f.mkdirs();
String mountCmd = "mount -t ntfs " + loopBack + " "
+ mp.getMountPoint();
log.info("mounting cmd " + mountCmd);
Process p = Runtime.getRuntime().exec(mountCmd);
BufferedReader reader = new BufferedReader(
new InputStreamReader(p.getErrorStream()));
String line;
while ((line = reader.readLine()) != null) {
log.info(" error mounting " + fileName + " mount output "
+ line);
mounted = false;
}
try {
p.waitFor();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
mounted = false;
}
if (!mounted) {
f.delete();
p = Runtime.getRuntime().exec("losetup -d " + loopBack);
log.info(" unable to mount filesystem ");
try {
p.waitFor();
} catch (InterruptedException e) {
log.log(Level.SEVERE, e.toString(), e);
}
}
mountedVMDKs.put(mountPath, mp);
log.info("mount of " + fileName + " successful");
} catch (IOException e) {
if (loopBack != null) {
try {
Process p = Runtime.getRuntime().exec(
"losetup -d " + loopBack);
p.waitFor();
} catch (Exception e1) {
}
}
log.log(Level.SEVERE, "unable to mount volume " + fileName
+ " to " + mountPath, e);
mounted = false;
}
return mounted;
} else {
return false;
}
}
public static boolean isMountedVMDK(String mountPath) {
return mountedVMDKs.containsKey(mountPath);
}
public static void unmountVMDK(String mountPath) {
if (mountedVMDKs.containsKey(mountPath)) {
VMDKMountPoint mp = mountedVMDKs.get(mountPath);
try {
Process p = Runtime.getRuntime().exec(
"umount -f -l " + mp.getMountPoint());
p.waitFor();
p = Runtime.getRuntime().exec("losetup -d " + mp.getLoopBack());
p.waitFor();
mountedVMDKs.remove(mountPath);
File f = new File(mountPath);
f.delete();
} catch (Exception e) {
log.log(Level.SEVERE, "unable to unmount volume " + mountPath,
e);
}
}
}
public static String mountVMDK(String vmdkPath, String mountPath)
throws IOException {
log.info("mounting " + vmdkPath + " to " + mountPath);
File internalFile = new File(vmdkPath);
VMDKData data = VMDKParser.parseVMDKFile(internalFile.getPath());
File diskFile = new File(internalFile.getParentFile().getPath()
+ File.separator + data.getDiskFile());
long cylanders = data.getCylinders();
ArrayList<Partition> partitions = getPartitions(diskFile.getPath(),
cylanders);
File mountPoint = new File(mountPath);
if (partitions.size() == 0)
return null;
if (partitions.size() == 1) {
Partition part = partitions.get(0);
mountVMDK(diskFile.getPath(), mountPoint.getPath(), part.getStart());
} else {
for (int i = 0; i < partitions.size(); i++) {
Partition part = partitions.get(i);
mountVMDK(diskFile.getPath(), mountPoint.getPath()
+ File.separator + i, part.getStart());
}
}
return mountPoint.getPath();
}
/*
* public static File getInternalFile(String fileName) throws IOException {
* Volume vol = JLanConfig.getVolume(fileName); File localVolumePath = new
* File(vol.getLocalPath()); log.info("file name is " + fileName +
* " volume is " + vol.getName() + " local path is " + vol.getLocalPath());
* File baseFilePath = new File(fileName); fileName =
* baseFilePath.getPath(); File internalFile = new
* File(vol.getInternalMountPoint() + File.separator +
* fileName.substring(localVolumePath.getPath().length())); return
* internalFile; }
*/
public static void prepareVMDK(String fileName) throws IOException {
File internalFile = new File(fileName);
VMDKData data = VMDKParser.parseVMDKFile(internalFile.getPath());
File diskFile = new File(internalFile.getParentFile().getPath()
+ File.separator + data.getDiskFile());
prepareVMDK(diskFile.getPath(), data.getCylinders());
}
public static void prepareVMDK(String fileName, long cylinders)
throws IOException {
log.info("Preparing vmdk " + fileName + " " + cylinders);
String cmd = Main.scriptsDir + File.separator + "prepdisk.sh" + " "
+ fileName + " " + cylinders + " " + Main.scriptsDir;
log.info("executing " + cmd);
Process p = Runtime.getRuntime().exec(cmd);
BufferedReader reader = new BufferedReader(new InputStreamReader(p
.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
log.info("Making " + fileName + " fdisk output " + line);
}
try {
p.waitFor();
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
String loopDevice = mountLoopBack(fileName, Main.defaultOffset);
p = Runtime.getRuntime()
.exec("mkfs.ntfs -f -c 32768 -v " + loopDevice);
reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = reader.readLine()) != null) {
log.info("NTFS Format " + fileName + " ntfs output " + line);
}
p = Runtime.getRuntime().exec("losetup -d " + loopDevice);
try {
p.waitFor();
} catch (InterruptedException e) {
log.log(Level.SEVERE, e.toString(), e);
}
}
protected static void unmountAll() {
synchronized (mountedVMDKs) {
Iterator<VMDKMountPoint> vIter = mountedVMDKs.values().iterator();
while (vIter.hasNext()) {
unmountVMDK(vIter.next());
}
mountedVMDKs.clear();
log.info("Unmounted all VMDKs");
}
}
private static void unmountVMDK(VMDKMountPoint mp) {
try {
Process p = Runtime.getRuntime().exec(
"umount -f -l " + mp.getMountPoint());
p.waitFor();
p = Runtime.getRuntime().exec("losetup -d " + mp.getLoopBack());
p.waitFor();
File f = new File(mp.getMountPoint());
f.delete();
log.info("unmounted " + mp.getMountPoint());
} catch (Exception e) {
log.log(Level.SEVERE, "unable to unmount volume "
+ mp.getMountPoint(), e);
}
}
public static void close() {
unmountAll();
}
public static void main(String[] args) {
String cmd = args[0];
if (cmd.equalsIgnoreCase("format")) {
if (args.length < 2)
System.out
.println("Partition and format(ntfs) a virtual volume.");
System.out
.println("Note : Only FAT ESX vmdks are supported and the taget \n "
+ "should be the description file");
System.out
.println("e.g. format /mount/vmware/vmfs/win2k8/win2k8.vmdk");
try {
DiskUtils.prepareVMDK(args[1]);
System.out.println("Success");
} catch (Exception e) {
System.err.println("format failed");
e.printStackTrace();
}
}
}
}