final ExecutionListener listener = context.getExecutionListener();
final Project project = new Project();
AntSupport.addAntBuildListener(listener, project);
boolean success = false;
final ExtSSHExec sshexec;
//perform jsch sssh command
final NodeSSHConnectionInfo nodeAuthentication = new NodeSSHConnectionInfo(node, framework,
context);
final int timeout = nodeAuthentication.getSSHTimeout();
try {
sshexec = SSHTaskBuilder.build(node, command, project, context.getDataContext(),
nodeAuthentication, context.getLoglevel(),listener);
} catch (SSHTaskBuilder.BuilderException e) {
return NodeExecutorResultImpl.createFailure(StepFailureReason.ConfigurationFailure,
e.getMessage(), node);
}
//Sudo support
final ExecutorService executor = Executors.newSingleThreadExecutor(
new ThreadFactory() {
public Thread newThread(Runnable r) {
return new Thread(null, r, "SudoResponder " + node.getNodename() + ": "
+ System.currentTimeMillis());
}
}
);
final Future<ResponderTask.ResponderResult> responderFuture;
final SudoResponder sudoResponder = SudoResponder.create(node, framework, context);
Runnable responderCleanup=null;
if (sudoResponder.isSudoEnabled() && sudoResponder.matchesCommandPattern(command[0])) {
final DisconnectResultHandler resultHandler = new DisconnectResultHandler();
//configure two piped i/o stream pairs, to connect to the input/output of the SSH connection
final PipedInputStream responderInput = new PipedInputStream();
final PipedOutputStream responderOutput = new PipedOutputStream();
final PipedInputStream jschInput = new PipedInputStream();
//lead pipe allows connected inputstream to close and not hang the writer to this stream
final PipedOutputStream jschOutput = new LeadPipeOutputStream();
try {
responderInput.connect(jschOutput);
jschInput.connect(responderOutput);
} catch (IOException e) {
return NodeExecutorResultImpl.createFailure(StepFailureReason.IOFailure, e.getMessage(), node);
}
//first sudo prompt responder
ResponderTask responder = new ResponderTask(sudoResponder, responderInput, responderOutput, resultHandler);
/**
* Callable will be executed by the ExecutorService
*/
final Callable<ResponderTask.ResponderResult> responderResultCallable;
//if 2nd responder
final SudoResponder sudoResponder2 = SudoResponder.create(node, framework, context, SUDO2_OPT_PREFIX,
DEFAULT_SUDO2_PASSWORD_OPTION,
DEFAULT_SUDO2_COMMAND_PATTERN);
if (sudoResponder2.isSudoEnabled()
&& sudoResponder2.matchesCommandPattern(CLIUtils.generateArgline(null, command, false))) {
logger.debug("Enable second sudo responder");
sudoResponder2.setDescription("Second " + SudoResponder.DEFAULT_DESCRIPTION);
sudoResponder.setDescription("First " + SudoResponder.DEFAULT_DESCRIPTION);
//sequence of the first then the second sudo responder
responderResultCallable = responder.createSequence(sudoResponder2);
} else {
responderResultCallable = responder;
}
//set up SSH execution
sshexec.setAllocatePty(true);
sshexec.setInputStream(jschInput);
sshexec.setSecondaryStream(jschOutput);
sshexec.setDisconnectHolder(resultHandler);
responderFuture = executor.submit(responderResultCallable);
//close streams after responder is finished
responderCleanup = new Runnable() {
public void run() {
logger.debug("SudoResponder shutting down...");
try {
responderInput.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
responderOutput.flush();
responderOutput.close();
} catch (IOException e) {
e.printStackTrace();
}
//executor pool shutdown
executor.shutdownNow();
}
};
executor.submit(responderCleanup);
}else {
responderFuture = null;
}
if (null != context.getExecutionListener()) {
context.getExecutionListener().log(3,
"Starting SSH Connection: " + nodeAuthentication.getUsername() + "@"
+ node.getHostname() + " ("
+ node.getNodename() + ")");
}
String errormsg = null;
FailureReason failureReason=null;
try {
sshexec.execute();
success = true;
} catch (BuildException e) {
final ExtractFailure extractJschFailure = extractFailure(e,node, timeout, framework);
errormsg = extractJschFailure.getErrormsg();
failureReason = extractJschFailure.getReason();
context.getExecutionListener().log(0, errormsg);
}
if (null != responderCleanup) {
responderCleanup.run();
}
shutdownAndAwaitTermination(executor);
if (null != responderFuture) {
try {
logger.debug("Waiting 5 seconds for responder future result");
final ResponderTask.ResponderResult result = responderFuture.get(5, TimeUnit.SECONDS);
logger.debug("Responder result: " + result);
if (!result.isSuccess() && !result.isInterrupted()) {
context.getExecutionListener().log(0,
result.getResponder().toString() + " failed: "
+ result.getFailureReason());
}
} catch (InterruptedException e) {
//ignore
} catch (java.util.concurrent.ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
//ignore
}
}
final int resultCode = sshexec.getExitStatus();
if (success) {
return NodeExecutorResultImpl.createSuccess(node);
} else {
return NodeExecutorResultImpl.createFailure(failureReason, errormsg, node, resultCode);