blob: 7e1b228f358eb40d20aa855286d364dad7025c1e (
plain) (
tree)
|
|
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<String, String>[] 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<String, String> 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<String> rebootingClients = new ArrayList<String>();
for (Map.Entry<String, String> 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<String, String> 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<String, String> clientStatus = new ConcurrentHashMap<String, String>();
private HashMap<String, String>[] clients;
private String time;
private String locationId;
private String locationName;
}
}
|