/* Copyright 2011 Massimo Gengarelli <gengarel@cs.unibo.it>
* This file is part of Floz Configurator.
* Floz Configurator is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Floz Configurator is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Floz Configurator. If not, see http://www.gnu.org/licenses/.
*/
package it.unibo.cs.v2.server;
import it.unibo.cs.v2.servlets.StartMachine;
import it.unibo.cs.v2.shared.MachineInfo;
import it.unibo.cs.v2.shared.MachineProcessInfo;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.LinkedList;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
@SuppressWarnings("serial")
public class StartMachineImpl extends RemoteServiceServlet implements StartMachine {
@Override
public MachineProcessInfo startViewMachine(MachineInfo machineInfo) throws Exception {
MachineProcessInfo mp = new MachineProcessInfo();
mp.setMachineName(machineInfo.getName());
mp.setOwned(true);
String home = (String) getThreadLocalRequest().getSession().getAttribute("home");
String user = (String) getThreadLocalRequest().getSession().getAttribute("login");
// TODO: check if the machine is owned by the user that invoked the applet
String realOwner = machineInfo.getRealOwner();
if (!realOwner.equals(user)) {
File otherUserDir = new File(getServletContext().getRealPath("/users/" + realOwner));
if (!otherUserDir.exists())
throw new Exception("You don't own this machine, and appearently, the user that owns it doesn't exist.");
File otherUserActiveFile = new File(getServletContext().getRealPath("users/" + realOwner + "/ACTIVEMACHINES.txt"));
if (!otherUserActiveFile.exists())
throw new Exception("You don't own this machine and " + realOwner + " hasn't started any machine yet.");
else {
BufferedReader br = new BufferedReader(new FileReader(otherUserActiveFile));
String line;
while ((line = br.readLine()) != null) {
if (line.length() < 7)
continue;
String[] values = line.split("::");
if (values == null)
continue;
if (values[0].equals(machineInfo.getName())) {
mp.setPid(new Integer(values[1]));
mp.setVncServer(new Integer(values[2]));
br.close();
mp.setOwned(false);
return mp;
}
}
}
throw new Exception("You don't own this machine and " + realOwner + " hasn't started it yet.");
}
// The owner of the machine is the user that invoked the applet
VirtuaLogger logger = new VirtuaLogger(home, this.getClass().toString());
if (home.equals("") || user.equals(""))
throw new Exception("Session expired.");
File activeMachines = new File(home + "/ACTIVEMACHINES.txt");
File freeServers = new File(getServletContext().getRealPath("/.freeServers"));
File startup = new File(home + "/startup.sh");
if (!freeServers.exists())
throw new Exception("No free servers file found.");
if (!activeMachines.exists())
activeMachines.createNewFile();
else {
BufferedReader br = new BufferedReader(new FileReader(activeMachines));
String line;
while ((line = br.readLine()) != null) {
if (line.length() < 7)
continue;
String[] values = line.split("::");
if (values == null)
continue;
if (values[0].equals(machineInfo.getName())) {
mp.setPid(new Integer(values[1]));
mp.setVncServer(new Integer(values[2]));
br.close();
return mp;
}
}
}
String freeVnc = "";
// Guarantee a synchronized access to the resources
synchronized (this) {
final BufferedReader freeServersReader = new BufferedReader(new FileReader(freeServers));
while (freeVnc.equals("")) {
freeVnc = freeServersReader.readLine();
if (freeVnc == null)
throw new Exception("No free servers found. Wait your turn!");
}
final LinkedList<String> freeList = new LinkedList<String>();
String read;
while ((read = freeServersReader.readLine()) != null) {
if (!read.equals(""))
freeList.add(read);
}
freeServersReader.close();
BufferedWriter freeServersWriter = new BufferedWriter(new FileWriter(freeServers));
for (String server : freeList) {
freeServersWriter.write(server);
freeServersWriter.newLine();
}
freeServersWriter.close();
};
mp.setVncServer(new Integer(freeVnc));
mp.setPid(0);
String kvmCommand = "kvm -cdrom " + getServletContext().getRealPath(machineInfo.getIso());
kvmCommand += " -hda " + machineInfo.getHda();
if (machineInfo.isHdbEnabled())
kvmCommand += " -hdb " + machineInfo.getHdb();
if (machineInfo.isVirtuacluster()) {
String mac = "";
if ((mac = machineInfo.getMacAddress()) != null)
kvmCommand += " -net nic,vlan=0,macaddr=" + mac;
else
kvmCommand += " -net nic,vlan=0,macaddr=52:54:00:AA:BB:" + freeVnc;
kvmCommand += " -net vde,vlan=0,sock=/tmp/virtua_switch";
}
if (!machineInfo.isVirtuacluster() && !machineInfo.isSecondNetwork())
kvmCommand += " -net none";
kvmCommand += " -boot " + (machineInfo.isBootCdrom()? "d" : "c");
kvmCommand += " -nographic -vnc :" + freeVnc;
kvmCommand += " -m 1024 -enable-kvm";
if (machineInfo.isTabletDevice())
kvmCommand += " -usbdevice tablet";
String pgrepCommand = "pgrep -nu tomcat6 -fx \"" + kvmCommand + "\" > .temp\n\n";
FileWriter startupWriter = new FileWriter(startup);
startupWriter.write("#!/bin/sh\n\n");
startupWriter.write(kvmCommand + "&\n");
startupWriter.write("sleep 3\n");
startupWriter.write(pgrepCommand);
startupWriter.flush();
startupWriter.close();
if (!startup.canExecute())
startup.setExecutable(true, true);
int pid = -1;
try {
ProcessBuilder execScript = new ProcessBuilder("/bin/sh", startup.getAbsolutePath());
execScript.directory(new File(home));
Process exec = execScript.start();
exec.waitFor();
File pidFile = new File(home + "/.temp");
if (pidFile.exists()) {
BufferedReader tempReader = new BufferedReader(new FileReader(pidFile));
pid = new Integer(tempReader.readLine());
tempReader.close();
pidFile.delete();
}
BufferedWriter activeMachinesWriter = new BufferedWriter(new FileWriter(activeMachines, true));
activeMachinesWriter.write(machineInfo.getName() + "::" + pid + "::" + freeVnc);
activeMachinesWriter.newLine();
activeMachinesWriter.close();
mp.setPid(pid);
}
catch (IOException e) {
logger.log(e.getMessage());
throw e;
}
return mp;
}
}