From 20350a2b7e5cfa13263b9ce41f48d9e988682909 Mon Sep 17 00:00:00 2001
From: Udo Walter
Date: Tue, 14 Feb 2017 15:52:30 +0100
Subject: Add RemoteReboot task
---
pom.xml | 5 +
.../openslx/taskmanager/tasks/RemoteReboot.java | 162 +++++++++++++++++++++
2 files changed, 167 insertions(+)
create mode 100644 src/main/java/org/openslx/taskmanager/tasks/RemoteReboot.java
diff --git a/pom.xml b/pom.xml
index 324c2a3..ce899cc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -110,5 +110,10 @@
1.0-SNAPSHOT
compile
+
+ com.jcabi
+ jcabi-ssh
+ 1.5.2
+
diff --git a/src/main/java/org/openslx/taskmanager/tasks/RemoteReboot.java b/src/main/java/org/openslx/taskmanager/tasks/RemoteReboot.java
new file mode 100644
index 0000000..7e1b228
--- /dev/null
+++ b/src/main/java/org/openslx/taskmanager/tasks/RemoteReboot.java
@@ -0,0 +1,162 @@
+package org.openslx.taskmanager.tasks;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import org.openslx.taskmanager.api.AbstractTask;
+
+import com.jcabi.ssh.Shell;
+import com.google.gson.annotations.Expose;
+import com.jcabi.ssh.SSH;
+
+public class RemoteReboot extends AbstractTask
+{
+ @Expose
+ private HashMap[] clients;
+
+ @Expose
+ private boolean shutdown = false;
+
+ @Expose
+ private int minutes = 0;
+
+ @Expose
+ private String locationId;
+
+ @Expose
+ private String locationName;
+
+ @Expose
+ private String sshkey;
+
+ @Expose
+ private int port = 22;
+
+ private Output status = new Output();
+
+ @Override
+ protected boolean initTask()
+ {
+ this.setStatusObject( this.status );
+
+ status.clients = clients;
+ Date shutdownTime = new Date(System.currentTimeMillis()+minutes*60*1000);
+ SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
+ status.time = sdf.format(shutdownTime);
+ status.locationId = locationId;
+ status.locationName = locationName;
+ return true;
+ }
+
+ @Override
+ protected boolean execute()
+ {
+ // try to connect to every client and start the reboot/shutdown process
+ ExecutorService tp = Executors.newFixedThreadPool( clients.length > 4 ? 4 : clients.length );
+ for (HashMap client : clients) {
+ final String ip = client.get("ip");
+ status.clientStatus.put(ip, "connecting");
+ tp.submit(new Runnable() {
+ public void run() {
+ try {
+ Shell shell = new SSH(ip, port, "root", sshkey);
+ if (shutdown) {
+ new Shell.Empty(shell).exec("/sbin/shutdown +" + minutes);
+ status.clientStatus.put(ip, minutes == 0 ? "shutdown" : "shutdownat");
+ } else {
+ new Shell.Empty(shell).exec("/sbin/reboot");
+ status.clientStatus.put(ip, "rebooting");
+ }
+ } catch (IOException e) {
+ status.clientStatus.put(ip, "error");
+ }
+ }
+ });
+ }
+ tp.shutdown();
+
+ try {
+ tp.awaitTermination( clients.length * 5, TimeUnit.SECONDS );
+ } catch ( InterruptedException e ) {
+ // ...
+ }
+
+ // wait for rebooting clients to finish rebooting
+ ArrayList rebootingClients = new ArrayList();
+ for (Map.Entry entry : status.clientStatus.entrySet()) {
+ if (entry.getValue() == "rebooting") {
+ rebootingClients.add(entry.getKey());
+ }
+ }
+
+ if (rebootingClients.size() > 0) {
+ ExecutorService statusTP = Executors.newFixedThreadPool( rebootingClients.size() > 4 ? 4 : rebootingClients.size() );
+ for (final String ip : rebootingClients) {
+ statusTP.submit(new Runnable() {
+ public void run() {
+ while (!isOnline(ip)) {
+ try {
+ Thread.sleep(3000);
+ } catch (InterruptedException e) {
+ }
+ }
+ status.clientStatus.put(ip, "online");
+ }
+ });
+ }
+ statusTP.shutdown();
+
+ try {
+ statusTP.awaitTermination( 180, TimeUnit.SECONDS );
+ } catch ( InterruptedException e ) {
+ // ...
+ }
+ }
+
+ // change status of clients that got stuck because of timeouts
+ for (Map.Entry entry : status.clientStatus.entrySet()) {
+ String value = entry.getValue();
+ if (value == "connecting" || value == "rebooting") {
+ entry.setValue("error");
+ }
+ }
+
+ return true;
+ }
+
+
+ private boolean isOnline(String address)
+ {
+ try (Socket s = new Socket(address, port)) {
+ return true;
+ } catch (IOException ex) {
+ }
+ return false;
+ }
+
+
+ /**
+ * Output - contains additional status data of this task
+ */
+ class Output
+ {
+ private ConcurrentHashMap clientStatus = new ConcurrentHashMap();
+ private HashMap[] clients;
+ private String time;
+ private String locationId;
+ private String locationName;
+ }
+}
--
cgit v1.2.3-55-g7522