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.StringTokenizer; 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.JSONArray; import org.json.simple.JSONObject; import org.json.simple.JSONValue; public class Boot extends Thread { private String eventName; private Vector> clients; private String bootOS; private final int updateRate; private long waitTime; private Vector psWhitelist; private Vector psBlacklist; private final GearmanJobServerConnection gearmanConnection; private GearmanClient gearmanClient; private HashMap pingJobs; private HashMap wolJobs; private HashMap pingWoLJobs; private HashMap osJobs; private HashMap whoJobs; private HashMap psJobs; private HashMap restartJobs; private HashMap pingRestartShutdownJobs; private HashMap pingRestartBootJobs; private HashMap pingWolTime; private HashMap pingRestartShutdownTime; private HashMap pingRestartBootTime; private HashMap status; private HashMap errors; private HashMap finishedClients; private Boolean finished; private Boolean error; private String[] statusText; public Boot(String eventName, Vector> clients, String bootOS, int updateRate, long waitTime, Vector psWhitelist, Vector psBlacklist, String gearmanServerAddress, int gearmanServerPort) { this.eventName = eventName; this.clients = clients; this.bootOS = bootOS; this.waitTime = waitTime * 1000; this.updateRate = updateRate; // updates per second this.psWhitelist = psWhitelist; this.psBlacklist = psBlacklist; gearmanConnection = new GearmanNIOJobServerConnection( gearmanServerAddress, gearmanServerPort); gearmanClient = new GearmanClientImpl(); gearmanClient.addJobServer(this.gearmanConnection); pingJobs = new HashMap(); pingWoLJobs = new HashMap(); wolJobs = new HashMap(); osJobs = new HashMap(); whoJobs = new HashMap(); psJobs = new HashMap(); restartJobs = new HashMap(); pingRestartShutdownJobs = new HashMap(); pingRestartBootJobs = new HashMap(); pingWolTime = new HashMap(); pingRestartShutdownTime = new HashMap(); pingRestartBootTime = new HashMap(); status = new HashMap(); errors = new HashMap(); finishedClients = new HashMap(); finished = false; error = false; statusText = new String[31]; statusText[0] = "The booting process of the client has been started."; statusText[1] = "The ping has been started."; statusText[2] = "The client is alive."; statusText[3] = "The client is not alive."; statusText[4] = "The wake on LAN has been started."; statusText[5] = "The Magic packet has been sent."; statusText[6] = "The ping after wake on LAN has been started."; statusText[7] = "Doing ping after wake on LAN again and again, until client is alive or " + waitTime / 60 + " minutes has been elapsed"; statusText[8] = "The check for the correct operating system has been started."; statusText[9] = "The wrong operating system is running."; statusText[10] = "The check if a user is logged in has been started."; statusText[11] = "A user is logged in."; statusText[12] = "The check if the user is working has been started."; statusText[13] = "The user is not working."; statusText[14] = "A restart of the client has been triggered."; statusText[15] = "The restart command has been sent."; statusText[16] = "The ping after shutdown has been started."; statusText[17] = "Doing ping after shutdown again and again, until client is not alive or " + waitTime / 60 + " minutes has been elapsed"; statusText[18] = "The user is working."; statusText[19] = "The client has been shutted down."; statusText[20] = "The ping after reboot has been started."; statusText[21] = "Doing ping after reboot again and again, until client is not alive or " + waitTime / 60 + " minutes has been elapsed"; statusText[29] = "Booting of the client has not been finished, due to an error."; statusText[30] = "Booting of the client has been finished."; for (HashMap client : clients) { int clientID = Integer.parseInt(client.get("id")); status.put(clientID, 0); // no work finishedClients.put(clientID, false); } } public void run() { workerLoop(); } private void workerLoop() { long beginTime; long timeTaken; long timeLeft; long updatePeriod = 1000000000L / updateRate; // nanoseconds 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(); } } finished = true; if (error) { System.out.println("Booting of " + eventName + " failed"); } else { System.out.println("Booting of " + eventName + " finished"); } } private Boolean update() throws IllegalStateException, IOException, InterruptedException, ExecutionException { Date date; long timestamp; 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.isEmpty()) { JSONObject resultObj = (JSONObject) JSONValue .parse(result); if (!resultObj.containsKey("err")) { String alive = resultObj.get("alive") .toString(); if (alive.equals("true")) { System.out.println(ipAddress + " alive"); status.put(clientID, 2); // alive pingJobs.remove(clientID); } else if (alive.equals("false")) { System.out .println(ipAddress + " not alive"); status.put(clientID, 3); // not alive pingJobs.remove(clientID); } } else { System.out.println(ipAddress + " Cannot send the ping message."); errors .put(clientID, "Sending the ping message has been failed."); // sending the ping message has been failed status.put(clientID, 29); pingJobs.remove(clientID); } } } } break; case 2: checkOS(client); break; case 3: wakeOnLan(client); break; case 4: GearmanJob wolJob = wolJobs.get(clientID); if (wolJob != null) { GearmanJobStatus jobStatus = gearmanClient .getJobStatus(wolJob); if (!jobStatus.isKnown() && wolJob.isDone()) { GearmanJobResult wolJobRes = wolJob.get(); String result = ByteUtils.fromUTF8Bytes(wolJobRes .getResults()); if (result.equals("Magic packet send.")) { System.out.println(macAddress + " Magic packet send."); status.put(clientID, 5); // magic packet send wolJobs.remove(clientID); } else { System.out.println(ipAddress + " Cannot send magic packet."); errors .put(clientID, "Sending the magic packet has been failed."); // cannot send magic packet, go in errorState status.put(clientID, 29); wolJobs.remove(clientID); } } } break; case 5: date = new Date(); timestamp = date.getTime(); pingWolTime.put(clientID, timestamp); status.put(clientID, 6); // ping after wake on LAN break; case 6: pingWakeOnLan(client); break; case 7: GearmanJob pingJobWoL = pingWoLJobs.get(clientID); if (pingJobWoL != null) { Date currentDate = new Date(); Long currentTimestamp = currentDate.getTime(); // wait 2 min until WoL - Failed Long expectedTimestamp = pingWolTime.get(clientID) + waitTime; if (expectedTimestamp >= currentTimestamp) { GearmanJobStatus jobStatus = gearmanClient .getJobStatus(pingJobWoL); if (!jobStatus.isKnown() && pingJobWoL.isDone()) { GearmanJobResult pingJobRes = pingJobWoL.get(); String result = ByteUtils.fromUTF8Bytes(pingJobRes .getResults()); if (!result.isEmpty()) { JSONObject resultObj = (JSONObject) JSONValue .parse(result); if (!resultObj.containsKey("err")) { String alive = resultObj.get("alive") .toString(); if (alive.equals("true")) { System.out.println(ipAddress + " is alive after WoL"); // alive, go in successState status.put(clientID, 30); pingWoLJobs.remove(clientID); } else if (alive.equals("false")) { System.out.println("ping again " + ipAddress); status.put(clientID, 6); // again ping pingWoLJobs.remove(clientID); } } else { System.out .println(ipAddress + " Cannot send the ping after wake on LAN message."); errors .put(clientID, "Sending the ping after wake on LAN message has been failed."); /* * sending the ping after wake on LAN * message has been failed */ status.put(clientID, 29); pingWoLJobs.remove(clientID); } } } } else { System.out.println(ipAddress + " is not alive after WoL"); errors .put(clientID, "The wake on LAN has been failed."); status.put(clientID, 29); // not alive, go in errorState pingWoLJobs.remove(clientID); } } break; case 8: GearmanJob osJob = osJobs.get(clientID); if (osJob != null) { GearmanJobStatus jobStatus = gearmanClient .getJobStatus(osJob); if (!jobStatus.isKnown() && osJob.isDone()) { GearmanJobResult osJobRes = osJob.get(); String result = ByteUtils.fromUTF8Bytes(osJobRes .getResults()); if (!result.isEmpty()) { JSONObject resultObj = (JSONObject) JSONValue .parse(result); if (!resultObj.containsKey("err")) { /* * String release = * resultObj.get("Release").toString(); String * distriputorID = * resultObj.get("Distributor ID").toString(); */ String description = resultObj.get( "Description").toString(); if (description.equals(bootOS)) { System.out.println(ipAddress + " right OS"); status.put(clientID, 30); // right os osJobs.remove(clientID); } else { System.out.println(ipAddress + " wrong OS"); status.put(clientID, 9); // wrong os osJobs.remove(clientID); } } else { System.out.println(ipAddress + " Cannot check os"); errors .put(clientID, "The check for correct operating system has been failed."); // cannot check os, go in errorState status.put(clientID, 29); osJobs.remove(clientID); } } } } break; case 9: who(client); break; case 10: GearmanJob whoJob = whoJobs.get(clientID); if (whoJob != null) { GearmanJobStatus jobStatus = gearmanClient .getJobStatus(whoJob); if (!jobStatus.isKnown() && whoJob.isDone()) { GearmanJobResult whoJobRes = whoJob.get(); String result = ByteUtils.fromUTF8Bytes(whoJobRes .getResults()); if (!result.isEmpty()) { JSONObject resultObj = (JSONObject) JSONValue .parse(result); if (!resultObj.containsKey("err")) { String rawoutput = resultObj.get("rawoutput") .toString(); StringTokenizer str = new StringTokenizer( rawoutput, " "); String user = ""; if (str.hasMoreTokens()) { user = str.nextToken(); } if (user.isEmpty()) { System.out.println(ipAddress + " no user is logged in"); // no user is logged in status.put(clientID, 13); whoJobs.remove(clientID); } else { System.out.println(ipAddress + " a user is logged in"); // a user is logged in status.put(clientID, 11); whoJobs.remove(clientID); } } else { System.out .println(ipAddress + " Cannot check if a user is logged in."); errors .put(clientID, "The check if a user is logged in has been failed."); /* * cannot check if a user is logged in, go in * errorState */ status.put(clientID, 29); whoJobs.remove(clientID); } } } } break; case 11: ps(client); break; case 12: GearmanJob psJob = psJobs.get(clientID); if (psJob != null) { GearmanJobStatus jobStatus = gearmanClient .getJobStatus(psJob); if (!jobStatus.isKnown() && psJob.isDone()) { GearmanJobResult whoJobRes = psJob.get(); String result = ByteUtils.fromUTF8Bytes(whoJobRes .getResults()); if (!result.isEmpty()) { JSONObject resultObj = (JSONObject) JSONValue .parse(result); if (!resultObj.containsKey("err")) { JSONArray ps = (JSONArray) resultObj.get("ps"); boolean whitelistFound = false; boolean blacklistFound = false; for (String blackEntry : psBlacklist) { if (ps.toString().contains(blackEntry)) { blacklistFound = true; } } for (String whiteEntry : psWhitelist) { if (ps.toString().contains(whiteEntry)) { whitelistFound = true; } } if (blacklistFound) { if (whitelistFound) { /* * System.out.println(ipAddress + * " is not working"); // is not working * status.put(clientID, 13); * psJobs.remove(clientID); */ } else { System.out.println(ipAddress + " is working"); status.put(clientID, 18); // is working psJobs.remove(clientID); } } else { System.out.println(ipAddress + " is not working"); // is not working status.put(clientID, 13); psJobs.remove(clientID); } } else { System.out.println(ipAddress + " Cannot check if user is working."); errors .put(clientID, "The check if a user is working has been failed."); /* * cannot check if user is working, go in * errorState */ status.put(clientID, 29); psJobs.remove(clientID); } } } } break; case 13: restart(client); break; case 14: GearmanJob restartJob = restartJobs.get(clientID); if (restartJob != null) { GearmanJobStatus jobStatus = gearmanClient .getJobStatus(restartJob); if (!jobStatus.isKnown() && restartJob.isDone()) { GearmanJobResult wolJobRes = restartJob.get(); String result = ByteUtils.fromUTF8Bytes(wolJobRes .getResults()); if (!result.isEmpty()) { JSONObject resultObj = (JSONObject) JSONValue .parse(result); if (!resultObj.containsKey("err")) { System.out.println(ipAddress + " Restart command send"); status.put(clientID, 15); // restart command // send restartJobs.remove(clientID); } else { System.out.println(ipAddress + " Cannot send restart command"); errors .put(clientID, "Sending the restart command has been failed."); // cannot send restart command, go in errorState status.put(clientID, 29); restartJobs.remove(clientID); } } } } break; case 15: date = new Date(); timestamp = date.getTime(); pingRestartShutdownTime.put(clientID, timestamp); status.put(clientID, 16); // ping after restart shutdown break; case 16: pingRestartShutdown(client); break; case 17: GearmanJob pingJobRestartShutdown = pingRestartShutdownJobs .get(clientID); if (pingJobRestartShutdown != null) { Date currentDate = new Date(); Long currentTimestamp = currentDate.getTime(); // wait 2 min until Restart - Failed Long expectedTimestamp = pingRestartShutdownTime .get(clientID) + waitTime; if (expectedTimestamp >= currentTimestamp) { GearmanJobStatus jobStatus = gearmanClient .getJobStatus(pingJobRestartShutdown); if (!jobStatus.isKnown() && pingJobRestartShutdown.isDone()) { GearmanJobResult pingJobRestartRes = pingJobRestartShutdown .get(); String result = ByteUtils .fromUTF8Bytes(pingJobRestartRes .getResults()); if (!result.isEmpty()) { JSONObject resultObj = (JSONObject) JSONValue .parse(result); if (!resultObj.containsKey("err")) { String alive = resultObj.get("alive") .toString(); if (alive.equals("true")) { System.out.println(ipAddress + " is still alive"); // alive, ping again status.put(clientID, 16); pingRestartShutdownJobs .remove(clientID); } else if (alive.equals("false")) { System.out.println(ipAddress + " is down"); // not alive, ping again status.put(clientID, 19); // is down pingRestartShutdownJobs .remove(clientID); } } else { System.out .println(ipAddress + " Cannot send the ping after restart message."); errors .put(clientID, "Sending the ping after restart message has been failed."); /* * sending the ping after restart message * has been failed */ status.put(clientID, 29); pingRestartShutdownJobs.remove(clientID); } } } } else { System.out.println(ipAddress + " shutdown failed"); errors.put(clientID, "The shutdown has been failed."); // still alive, go in errorState status.put(clientID, 29); pingRestartShutdownJobs.remove(clientID); } } break; case 18: System.out.println(ipAddress + " User has been working"); errors.put(clientID, "The user has been working."); // user has been working, go in errorState status.put(clientID, 29); break; case 19: date = new Date(); timestamp = date.getTime(); pingRestartBootTime.put(clientID, timestamp); status.put(clientID, 20); // ping after restart boot break; case 20: pingRestartBoot(client); break; case 21: GearmanJob pingJobRestartBoot = pingRestartBootJobs .get(clientID); if (pingJobRestartBoot != null) { Date currentDate = new Date(); Long currentTimestamp = currentDate.getTime(); // wait 2 min until Restart - Failed Long expectedTimestamp = pingRestartBootTime.get(clientID) + waitTime; if (expectedTimestamp >= currentTimestamp) { GearmanJobStatus jobStatus = gearmanClient .getJobStatus(pingJobRestartBoot); if (!jobStatus.isKnown() && pingJobRestartBoot.isDone()) { GearmanJobResult pingJobRestartRes = pingJobRestartBoot .get(); String result = ByteUtils .fromUTF8Bytes(pingJobRestartRes .getResults()); if (!result.isEmpty()) { JSONObject resultObj = (JSONObject) JSONValue .parse(result); if (!resultObj.containsKey("err")) { String alive = resultObj.get("alive") .toString(); if (alive.equals("true")) { System.out.println(ipAddress + " is alive after restart"); // alive, go to success state status.put(clientID, 30); pingRestartBootJobs.remove(clientID); } else if (alive.equals("false")) { System.out.println("ping again " + ipAddress); // not alive, ping again status.put(clientID, 20); // again ping pingRestartBootJobs.remove(clientID); } } else { System.out .println(ipAddress + " Cannot send the ping after shutdown message."); errors .put(clientID, "Sending the ping after shutdown message has been failed."); /* * sending the ping after shutdown message * has been failed */ status.put(clientID, 29); pingRestartBootJobs.remove(clientID); } } } } else { System.out.println(ipAddress + " is not alive after reboot"); errors.put(clientID, "The reboot has been failed."); status.put(clientID, 29); // not alive, go in errorState pingRestartBootJobs.remove(clientID); } } break; case 29: if (!finishedClients.get(clientID)) { System.out.println(ipAddress + " Booting failed"); // errorState finishedClients.put(clientID, true); error = true; } break; case 30: if (!finishedClients.get(clientID)) { System.out.println(ipAddress + " Booting finished"); // successState finishedClients.put(clientID, true); } break; } } boolean allFinished = false; for (HashMap client : clients) { int clientID = Integer.parseInt(client.get("id")); boolean clientFinished = finishedClients.get(clientID); if (clientFinished) { allFinished = true; } else { allFinished = false; break; } } 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 pingWakeOnLan(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); // pingWol started pingWoLJobs.put(clientID, job); System.out.println("ping " + ipAddress); } private void pingRestartShutdown(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, 17); // pingRestartShutdown started pingRestartShutdownJobs.put(clientID, job); System.out.println("ping " + ipAddress); } private void pingRestartBoot(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, 21); // pingRestartBoot started pingRestartBootJobs.put(clientID, job); System.out.println("ping " + ipAddress); } private void wakeOnLan(HashMap client) { String macAddress = client.get("mac"); int clientID = Integer.parseInt(client.get("id")); GearmanJob job = GearmanJobImpl.createJob("wol", macAddress.getBytes(), "wol" + clientID); gearmanClient.submit(job); status.put(clientID, 4); // wake on lan started wolJobs.put(clientID, job); System.out.println("wake on lan"); } private void checkOS(HashMap client) { String ipAddress = client.get("ip"); int clientID = Integer.parseInt(client.get("id")); GearmanJob job = GearmanJobImpl.createJob("os", ipAddress.getBytes(), "os" + clientID); gearmanClient.submit(job); status.put(clientID, 8); // checkOS started osJobs.put(clientID, job); System.out.println("check OS " + ipAddress); } private void who(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, 10); // who started whoJobs.put(clientID, job); System.out.println("who " + ipAddress); } private void ps(HashMap client) { String ipAddress = client.get("ip"); int clientID = Integer.parseInt(client.get("id")); GearmanJob job = GearmanJobImpl.createJob("ps", ipAddress.getBytes(), "ps" + clientID); gearmanClient.submit(job); status.put(clientID, 12); // ps started psJobs.put(clientID, job); System.out.println("ps " + ipAddress); } private void restart(HashMap client) { String ipAddress = client.get("ip"); int clientID = Integer.parseInt(client.get("id")); GearmanJob job = GearmanJobImpl.createJob("restart", ipAddress .getBytes(), "restart" + clientID); gearmanClient.submit(job); status.put(clientID, 14); // restart started restartJobs.put(clientID, job); System.out.println("restart " + ipAddress); } public String getStatusText(HashMap client) { int clientID = Integer.parseInt(client.get("id")); int clientStatus = status.get(clientID); return statusText[clientStatus]; } public String getError(HashMap client) { int clientID = Integer.parseInt(client.get("id")); String clientError = errors.get(clientID); return clientError; } public Boolean isFinished() { return finished && !error; } public Boolean isFinishedWithErrors() { return finished && error; } public Vector> getClients() { return clients; } public String getEventName() { return eventName; } }