mirror of https://github.com/apache/jclouds.git
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:
parent
d2985b5c4b
commit
ea874483b0
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue