package ControllerWorker; import java.io.IOException; import java.lang.Thread; import java.util.concurrent.ExecutionException; import java.util.Date; import java.util.HashMap; import java.util.Vector; import org.gearman.client.GearmanClient; import org.gearman.client.GearmanClientImpl; import org.gearman.client.GearmanJob; import org.gearman.client.GearmanJobImpl; import org.gearman.client.GearmanJobResult; import org.gearman.client.GearmanJobStatus; import org.gearman.common.GearmanJobServerConnection; import org.gearman.common.GearmanNIOJobServerConnection; import org.gearman.util.ByteUtils; import org.json.simple.JSONObject; import org.json.simple.JSONValue; public class Shutdown extends Thread { private long beginTime; private long timeTaken; private long timeLeft; private Boolean finished; private Boolean error; private final int updateRate; private final long updatePeriod; private HashMap pingJobs; private HashMap whoJobs; private HashMap shutdownJobs; private HashMap pingShutdownJobs; private HashMap sshJobs; private HashMap status; private HashMap errors; private HashMap pingShutdownTime; private Vector> clients; private final GearmanJobServerConnection gearmanConnection; private GearmanClient gearmanClient; public Shutdown(String serverAddress, int port, Vector> clients, int updateRate) { this.pingJobs = new HashMap(); this.whoJobs = new HashMap(); this.shutdownJobs = new HashMap(); this.sshJobs = new HashMap(); this.status = new HashMap(); this.errors = new HashMap(); this.updateRate = updateRate; // updates per second this.updatePeriod = 1000000000L / this.updateRate; // nanoseconds this.gearmanConnection = new GearmanNIOJobServerConnection( serverAddress, port); this.gearmanClient = new GearmanClientImpl(); gearmanClient.addJobServer(this.gearmanConnection); this.clients = clients; for (HashMap client : clients) { int clientID = Integer.parseInt(client.get("id")); status.put(clientID, 0); // no work } this.finished = false; this.error = false; } public void run() { workerLoop(); } private void workerLoop() { Boolean run = true; while (run) { try { beginTime = System.nanoTime(); run = update(); timeTaken = System.nanoTime() - beginTime; timeLeft = (updatePeriod - timeTaken) / 1000000; if (timeLeft < 10) timeLeft = 10; Thread.sleep(timeLeft); } catch (Exception e) { e.printStackTrace(); } } this.finished = true; System.out.println("Shutdown finished"); } private Boolean update() throws IllegalStateException, IOException, InterruptedException, ExecutionException { Boolean allFinished = false; for (HashMap client : clients) { String ipAddress = client.get("ip"); String macAddress = client.get("mac"); int clientID = Integer.parseInt(client.get("id")); int clientStatus = status.get(clientID); switch (clientStatus) { case 0: ping(client); break; case 1: GearmanJob pingJob = pingJobs.get(clientID); if (pingJob != null) { GearmanJobStatus jobStatus = gearmanClient .getJobStatus(pingJob); if (!jobStatus.isKnown() && pingJob.isDone()) { GearmanJobResult pingJobRes = pingJob.get(); String result = ByteUtils.fromUTF8Bytes(pingJobRes .getResults()); if (result != "") { JSONObject resultObj = (JSONObject) JSONValue .parse(result); String alive = resultObj.get("alive").toString(); if (alive.equals("true")) { System.out.println(ipAddress + " alive"); status.put(clientID, 3); // alive, check Users pingJobs.remove(clientID); } else { System.out.println(ipAddress + " not alive"); status.put(clientID, 7); // not alive, go in successState pingJobs.remove(clientID); } } } } break; case 2: woh(client); break; case 3: shutdown(client); break; case 4: pingShutdown(client); break; case 5: GearmanJob pingJobShutdown = pingShutdownJobs.get(clientID); if (pingJobShutdown != null) { Date currentDate = new Date(); Long currentTimestamp = currentDate.getTime(); Long expectedTimestamp = this.pingShutdownTime.get(clientID) + 120000L; //wait 2 min until WoL-Failed if (expectedTimestamp >= currentTimestamp) { GearmanJobStatus jobStatus = gearmanClient .getJobStatus(pingJobShutdown); if (!jobStatus.isKnown() && pingJobShutdown.isDone()) { GearmanJobResult pingJobRes = pingJobShutdown.get(); String result = ByteUtils.fromUTF8Bytes(pingJobRes .getResults()); if (result != "") { JSONObject resultObj = (JSONObject) JSONValue .parse(result); String alive = resultObj.get("alive") .toString(); if (alive.equals("false")) { System.out.println(ipAddress + " is alive after shutdown. Ping again..."); status.put(clientID, 4); // alive, ping again pingShutdownJobs.remove(clientID); } else { System.out.println("not alive after shutdown" +ipAddress); status.put(clientID, 7); // go in successState } } } } else { System.out.println(ipAddress + " is alive after shutdown"); status.put(clientID, 6); // not alive, go in errorState pingShutdownJobs.remove(clientID); } } break; case 6: System.out.println("Shutdown failed after 2min"); // errorState break; case 7: System.out.println("Shutdown successful"); // successState break; } if (clientStatus == 20) { allFinished = true; } else if (clientStatus == 19) { allFinished = true; this.error = true; } else { allFinished = false; } } if (allFinished) { return false; } else { return true; } } private void ping(HashMap client) { String ipAddress = client.get("ip"); int clientID = Integer.parseInt(client.get("id")); GearmanJob job = GearmanJobImpl.createJob("ping", ipAddress.getBytes(), "ping" + clientID); gearmanClient.submit(job); status.put(clientID, 1); // ping started pingJobs.put(clientID, job); System.out.println("ping " + ipAddress); } private void woh(HashMap client) { String ipAddress = client.get("ip"); int clientID = Integer.parseInt(client.get("id")); GearmanJob job = GearmanJobImpl.createJob("who", ipAddress.getBytes(), "who" + clientID); gearmanClient.submit(job); status.put(clientID, 1); // who started pingJobs.put(clientID, job); System.out.println("who " + ipAddress); } private void shutdown(HashMap client) { String ipAddress = client.get("ip"); int clientID = Integer.parseInt(client.get("id")); GearmanJob job = GearmanJobImpl.createJob("shutdown", ipAddress.getBytes(), "shutdown" + clientID); gearmanClient.submit(job); status.put(clientID, 5); // shutdown started pingJobs.put(clientID, job); System.out.println("shutdown " + ipAddress); } private void pingShutdown(HashMap client) { String ipAddress = client.get("ip"); int clientID = Integer.parseInt(client.get("id")); GearmanJob job = GearmanJobImpl.createJob("ping", ipAddress.getBytes(), "ping" + clientID); gearmanClient.submit(job); status.put(clientID, 7); // pingShutdown started pingShutdownJobs.put(clientID, job); System.out.println("ping " + ipAddress); } private void ssh(HashMap client) { String ipAddress = client.get("ip"); int clientID = Integer.parseInt(client.get("id")); GearmanJob job = GearmanJobImpl.createJob("ssh", ipAddress.getBytes(), "ssh" + clientID); gearmanClient.submit(job); status.put(clientID, 6); // ssh started sshJobs.put(clientID, job); System.out.println("ssh " + ipAddress); } public Vector> getClients() { return clients; } public GearmanClient getGearmanClient() { return gearmanClient; } public GearmanJobServerConnection getGearmanConnection() { return gearmanConnection; } public HashMap getPingJobs() { return pingJobs; } public HashMap getSshJobs() { return sshJobs; } public HashMap getWhoJobs() { return whoJobs; } public HashMap getShutdownJobs() { return shutdownJobs; } public HashMap getStatus() { return status; } public HashMap getErrors() { return errors; } public Boolean isFinished() { return finished; } public Boolean isFinishedWithErrors() { return finished && error; } }