package com.yahoo.dtf.deploy;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.yahoo.dtf.actions.protocol.deploy.DTFNode;
import com.yahoo.dtf.exception.DTFException;
import com.yahoo.dtf.logger.DTFLogger;
public class SSHUtil {
private static DTFLogger _logger = DTFLogger.getLogger(SSHUtil.class);
public static Session connectToHost(String host,
String user,
String privkey,
String passphrase) throws JSchException {
JSch jsch = new JSch();
DeployUI ui = new DeployUI(host,user,passphrase);
String home = System.getProperty("user.home");
String known_hosts = home + "/.dtf/known_hosts";
String id_rsa = null;
if ( privkey != null ) {
id_rsa = privkey;
_logger.info("Using specified RSA key [" + id_rsa + "]");
} else {
id_rsa = home + "/.dtf/id_rsa";
_logger.info("Using default RSA key [" + id_rsa + "]");
}
if (new File(known_hosts).exists())
jsch.setKnownHosts(known_hosts);
if (new File(id_rsa).exists())
jsch.addIdentity(id_rsa);
Session session = jsch.getSession(user, host);
session.setUserInfo(ui);
session.connect();
return session;
}
public static int execute(Session session,
String command,
boolean showoutput)
throws JSchException, IOException {
ChannelExec exec = (ChannelExec) session.openChannel("exec");
exec.setCommand(command);
InputStream is = exec.getInputStream();
exec.connect();
BufferedReader br = null;
if ( _logger.isDebugEnabled())
_logger.debug("executing [" + command + "]");
try {
InputStreamReader esr = new InputStreamReader(exec.getErrStream());
InputStreamReader isr = new InputStreamReader(is);
br = new BufferedReader(isr);
String line = null;
while ( (line = br.readLine()) != null ) {
if ( showoutput)
System.out.println(line);
}
br = new BufferedReader(esr);
while ( (line = br.readLine()) != null ) {
if ( showoutput)
System.err.println(line);
}
return exec.getExitStatus();
} finally {
if ( br != null ) br.close();
exec.disconnect();
}
}
public static int execute(Session session,
String command,
InputStream in,
OutputStream out,
OutputStream err)
throws JSchException, IOException {
ChannelExec exec = (ChannelExec) session.openChannel("exec");
if (_logger.isDebugEnabled())
_logger.debug("executing [" + command + "]");
exec.setCommand(command);
exec.connect();
OutputStream os = exec.getOutputStream();
byte[] buffer = new byte[1024];
int read = 0;
while ( (read = in.read(buffer)) != -1 )
os.write(buffer,0,read);
os.close();
BufferedReader br = null;
try {
String line = null;
/*
* Have to do this because the JSSH library will sometimes not
* instantiate an output or error stream even though it has
* succeeded. So we'll ignore the null and then check the return
* code.
*/
InputStream ise = null;
try {
ise = exec.getErrStream();
} catch (NullPointerException e) { }
if ( ise != null ) {
InputStreamReader esr = new InputStreamReader(ise);
br = new BufferedReader(esr);
while ((line = br.readLine()) != null) {
err.write((line + "\n").getBytes());
}
}
/*
* Have to do this because the JSSH library will sometimes not
* instantiate an output or error stream even though it has
* succeeded. So we'll ignore the null and then check the return
* code.
*/
InputStream is = null;
try {
is = exec.getInputStream();
} catch (NullPointerException e) { }
if ( is != null ) {
InputStreamReader isr = new InputStreamReader(is);
br = new BufferedReader(isr);
while ((line = br.readLine()) != null) {
out.write((line + "\n").getBytes());
}
}
return exec.getExitStatus();
} finally {
if (br != null)
br.close();
exec.disconnect();
}
}
public static String getHomeDir(Session session, DTFNode node)
throws JSchException, IOException, DTFException {
String cmd = DeployDTF.wrap(node.getWrapcmd(), "pwd");
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayOutputStream err = new ByteArrayOutputStream();
int rc = SSHUtil.execute(session, cmd, new ByteArrayInputStream(
new byte[0]), out, err);
if (rc != 0) {
throw new DTFException("Unable to determine home, got rc " + rc);
}
return new String(out.toByteArray()).replaceAll("\n", "");
}
}