Issue 79: added ssh exec feature

git-svn-id: http://jclouds.googlecode.com/svn/trunk@1824 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
adrian.f.cole 2009-07-21 12:45:08 +00:00
parent d2985b5c4b
commit ea874483b0
4 changed files with 78 additions and 2 deletions

View File

@ -0,0 +1,23 @@
package org.jclouds.ssh;
/**
* @author Adrian Cole
*/
public class ExecResponse {
private final String error;
private final String output;
public ExecResponse(String output, String error) {
this.output = output;
this.error = error;
}
public String getError() {
return error;
}
public String getOutput() {
return output;
}
}

View File

@ -12,7 +12,7 @@ import com.google.inject.assistedinject.Assisted;
* @author Adrian Cole * @author Adrian Cole
*/ */
public interface SshConnection { public interface SshConnection {
public interface Factory { public interface Factory {
SshConnection create(InetAddress host, int port, @Assisted("username") String username, SshConnection create(InetAddress host, int port, @Assisted("username") String username,
@Assisted("password") String password); @Assisted("password") String password);
@ -20,6 +20,8 @@ public interface SshConnection {
InputStream get(String path); InputStream get(String path);
ExecResponse exec(String command);
@PostConstruct @PostConstruct
void connect(); void connect();

View File

@ -11,13 +11,17 @@ import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy; import javax.annotation.PreDestroy;
import javax.annotation.Resource; import javax.annotation.Resource;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.ssh.ExecResponse;
import org.jclouds.ssh.SshConnection; import org.jclouds.ssh.SshConnection;
import org.jclouds.ssh.SshException; import org.jclouds.ssh.SshException;
import org.jclouds.util.Utils;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.Assisted;
import com.jcraft.jsch.Channel; import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.ChannelSftp; import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch; import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException; import com.jcraft.jsch.JSchException;
@ -37,6 +41,7 @@ public class JschSshConnection implements SshConnection {
private ChannelSftp sftp; private ChannelSftp sftp;
@Resource @Resource
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
private Session session;
@Inject @Inject
public JschSshConnection(@Assisted InetAddress host, @Assisted int port, public JschSshConnection(@Assisted InetAddress host, @Assisted int port,
@ -69,7 +74,7 @@ public class JschSshConnection implements SshConnection {
if (sftp != null && sftp.isConnected()) if (sftp != null && sftp.isConnected())
return; return;
JSch jsch = new JSch(); JSch jsch = new JSch();
Session session = null; session = null;
Channel channel = null; Channel channel = null;
try { try {
session = jsch.getSession(username, host.getHostAddress(), port); session = jsch.getSession(username, host.getHostAddress(), port);
@ -106,4 +111,30 @@ public class JschSshConnection implements SshConnection {
sftp.quit(); sftp.quit();
} }
public ExecResponse exec(String command) {
ChannelExec executor = null;
try {
try {
executor = (ChannelExec) session.openChannel("exec");
} catch (JSchException e) {
throw new SshException(String.format("%s@%s:%d: Error connecting to exec.", username,
host.getHostAddress(), port), e);
}
executor.setCommand(command);
ByteArrayOutputStream error = new ByteArrayOutputStream();
executor.setErrStream(error);
try {
executor.connect();
return new ExecResponse(Utils.toStringAndClose(executor.getInputStream()), error
.toString());
} catch (Exception e) {
throw new SshException(String.format("%s@%s:%d: Error executing command: ", username,
host.getHostAddress(), port, command), e);
}
} finally {
if (executor != null)
executor.disconnect();
}
}
} }

View File

@ -1,11 +1,14 @@
package org.jclouds.ssh.jsch; package org.jclouds.ssh.jsch;
import static org.testng.Assert.assertEquals;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.jclouds.ssh.ExecResponse;
import org.jclouds.ssh.SshConnection; import org.jclouds.ssh.SshConnection;
import org.jclouds.ssh.jsch.config.JschSshConnectionModule; import org.jclouds.ssh.jsch.config.JschSshConnectionModule;
import org.jclouds.util.Utils; import org.jclouds.util.Utils;
@ -54,6 +57,17 @@ public class JschSshConnectionLiveTest {
throw new RuntimeException("path " + path + " not stubbed"); throw new RuntimeException("path " + path + " not stubbed");
} }
public ExecResponse exec(String command) {
if (command.equals("hostname")) {
try {
return new ExecResponse(InetAddress.getLocalHost().getHostName(), "");
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
}
throw new RuntimeException("command " + command + " not stubbed");
}
}; };
} else { } else {
Injector i = Guice.createInjector(new JschSshConnectionModule()); Injector i = Guice.createInjector(new JschSshConnectionModule());
@ -69,4 +83,10 @@ public class JschSshConnectionLiveTest {
assert contents.indexOf("root") >= 0 : "no root in " + contents; assert contents.indexOf("root") >= 0 : "no root in " + contents;
} }
public void testExecHostname() throws IOException {
ExecResponse response = connection.exec("hostname");
assertEquals(response.getError(), "");
assertEquals(response.getOutput().trim(), InetAddress.getLocalHost().getHostName());
}
} }