/*
* JBoss, Home of Professional Open Source
* Copyright 2008, Red Hat, Inc., and others contributors as indicated
* by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.jboss.narayana.blacktie.btadmin.commands;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.jboss.narayana.blacktie.administration.BlacktieAdministration;
import org.jboss.narayana.blacktie.btadmin.Command;
import org.jboss.narayana.blacktie.btadmin.CommandFailedException;
import org.jboss.narayana.blacktie.btadmin.IncompatibleArgsException;
import org.jboss.narayana.blacktie.jatmibroker.core.conf.Machine;
import org.jboss.narayana.blacktie.jatmibroker.core.conf.Server;
/**
* The shutdown command will shutdown the server specified. This method is non-blocking, i.e. the server is requested to
* shutdown, it will still be alive possibly
*/
public class Shutdown implements Command {
/**
* The logger to use for output
*/
private static Logger log = LogManager.getLogger(Shutdown.class);
/**
* The name of the server.
*/
private String serverName;
/**
* The ID of the server, will be 0 (all) if not provided
*/
private int id = 0;
/**
* The Operation System type which used to check server alive
*/
private static String OS = System.getProperty("os.name").toLowerCase();
private int checkPeriodMillis = 2 * 1000;
private int numChecks = 10;
/**
* Show the usage of the command
*/
public String getQuickstartUsage() {
return "[<serverName> [<serverId>]]";
}
public void initializeArgs(String[] args) throws IncompatibleArgsException {
if (args.length > 0) {
serverName = args[0];
if (args.length == 2) {
try {
id = Integer.parseInt(args[1]);
log.trace("Successfully parsed: " + args[1]);
} catch (NumberFormatException nfe) {
throw new IncompatibleArgsException(
"The third argument was expected to be the (integer) instance id to shutdown");
}
}
}
}
public void invoke(BlacktieAdministration connection, Properties configuration) throws CommandFailedException {
List<ServerToStop> serversToStop = new ArrayList<ServerToStop>();
List<Server> serverLaunchers = (List<Server>) configuration.get("blacktie.domain.serverLaunchers");
if (serverName == null) {
Iterator<Server> launchers = serverLaunchers.iterator();
while (launchers.hasNext()) {
Server server = launchers.next();
Iterator<Machine> iterator2;
try {
iterator2 = server.getLocalMachine().iterator();
} catch (UnknownHostException e) {
log.error("Could not get the local machine");
throw new CommandFailedException(-1);
}
while (iterator2.hasNext()) {
Machine machine = iterator2.next();
ServerToStop serverToStop = new ServerToStop();
serverToStop.setName(server.getName());
serverToStop.setId(machine.getServerId());
serversToStop.add(serverToStop);
}
}
} else {
ServerToStop serverToStop = new ServerToStop();
serverToStop.setName(serverName);
serverToStop.setId(id);
serversToStop.add(serverToStop);
}
if (serversToStop.size() != 0) {
Iterator<ServerToStop> iterator = serversToStop.iterator();
while (iterator.hasNext()) {
ServerToStop next = iterator.next();
String name = next.getName();
int id = next.getId();
Boolean result = connection.shutdown(name, id);
boolean shutdown = false;
if (result) {
log.info("Server shutdown successfully: " + name + " with id: " + id);
log.info("waiting for " + name + ":" + id + " shutdown complete");
for (int i = 0; i < numChecks; i++) {
if(checkServerAlive(name, id)) {
try{
Thread.sleep(checkPeriodMillis);
} catch (Exception e) {}
log.info(name + ":" + id + " is still alive, sleeping for a further " + checkPeriodMillis + "ms");
} else {
log.info(name + ":" + id + " shutdown complete");
shutdown = true;
break;
}
}
if(shutdown == false) {
log.error(name + ":" + id + " has not shutdown complete");
throw new CommandFailedException(-1);
}
} else {
log.error("Server could not be shutdown (may already be stopped)");
throw new CommandFailedException(-1);
}
}
} else {
log.error("No servers were configured for shutdown");
throw new CommandFailedException(-1);
}
}
private boolean checkServerAlive(String name, int id) {
String cmd = null;
ProcessBuilder pb = null;
boolean toReturn = false;
if(OS.indexOf("linux") >= 0){
log.debug(OS + " check for linux");
if(id != 0) {
cmd = "ps -ef | grep \"\\\\-i " + id + " \\\\-s " + name + "\" | grep -v grep";
} else {
cmd = "ps -ef | grep \"\\\\-s " + name + "\" | grep -v grep";
}
log.debug(cmd);
pb = new ProcessBuilder("/bin/sh", "-c", cmd);
} else if(OS.indexOf("win") >= 0) {
log.debug(OS + " check for windows ");
if(id != 0) {
cmd = "wmic process get commandline | findstr /c:\"\\-i " + id + " \\-s " + name + "\" | findstr /v findstr";
} else {
cmd = "wmic process get commandline | findstr /c:\"\\-s " + name + "\" | findstr /v findstr";
}
log.debug(cmd);
pb = new ProcessBuilder("cmd", "/c", cmd);
} else {
log.warn(OS + " no check");
return false;
}
try {
Process p = pb.start();
if(OS.indexOf("win") >= 0) {
//wmic is blocking for stdin. so we need to close it.
p.getOutputStream().close();
}
p.waitFor();
if(p.exitValue() == 0) {
log.debug("check cmd " + cmd + " output");
InputStream is = p.getInputStream();
BufferedReader ein = new BufferedReader(new InputStreamReader(is));
String res = ein.readLine();
if(res != null) {
log.debug("cmd " + cmd + " output: " + res);
toReturn = true;
}
is.close();
}
} catch (Exception e) {
log.error("run " + cmd + " failed with " + e);
}
return toReturn;
}
private class ServerToStop {
private String name;
private int id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
}