mirror of https://github.com/apache/jclouds.git
Issue 79: improved session handling
git-svn-id: http://jclouds.googlecode.com/svn/trunk@1825 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
parent
ea874483b0
commit
c63e532271
|
@ -1,9 +1,33 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.ssh;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class ExecResponse {
|
||||
|
||||
private final String error;
|
||||
private final String output;
|
||||
|
||||
|
@ -20,4 +44,40 @@ public class ExecResponse {
|
|||
return output;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ExecResponse [error=" + error + ", output=" + output + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((error == null) ? 0 : error.hashCode());
|
||||
result = prime * result + ((output == null) ? 0 : output.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
ExecResponse other = (ExecResponse) obj;
|
||||
if (error == null) {
|
||||
if (other.error != null)
|
||||
return false;
|
||||
} else if (!error.equals(other.error))
|
||||
return false;
|
||||
if (output == null) {
|
||||
if (other.output != null)
|
||||
return false;
|
||||
} else if (!output.equals(other.output))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,3 +1,26 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.ssh;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
|
|
@ -1,3 +1,26 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.ssh;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,9 +1,33 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.ssh.jsch;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.InetAddress;
|
||||
|
||||
|
@ -11,6 +35,7 @@ import javax.annotation.PostConstruct;
|
|||
import javax.annotation.PreDestroy;
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.apache.commons.io.input.ProxyInputStream;
|
||||
import org.apache.commons.io.output.ByteArrayOutputStream;
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.ssh.ExecResponse;
|
||||
|
@ -20,7 +45,6 @@ import org.jclouds.util.Utils;
|
|||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
import com.jcraft.jsch.Channel;
|
||||
import com.jcraft.jsch.ChannelExec;
|
||||
import com.jcraft.jsch.ChannelSftp;
|
||||
import com.jcraft.jsch.JSch;
|
||||
|
@ -34,11 +58,27 @@ import com.jcraft.jsch.SftpException;
|
|||
*/
|
||||
public class JschSshConnection implements SshConnection {
|
||||
|
||||
private final class CloseFtpChannelOnCloseInputStream extends ProxyInputStream {
|
||||
|
||||
private final ChannelSftp sftp;
|
||||
|
||||
private CloseFtpChannelOnCloseInputStream(InputStream proxy, ChannelSftp sftp) {
|
||||
super(proxy);
|
||||
this.sftp = sftp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
super.close();
|
||||
if (sftp != null)
|
||||
sftp.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
private final InetAddress host;
|
||||
private final int port;
|
||||
private final String username;
|
||||
private final String password;
|
||||
private ChannelSftp sftp;
|
||||
@Resource
|
||||
protected Logger logger = Logger.NULL;
|
||||
private Session session;
|
||||
|
@ -54,10 +94,20 @@ public class JschSshConnection implements SshConnection {
|
|||
}
|
||||
|
||||
public InputStream get(String path) {
|
||||
checkConnected();
|
||||
checkNotNull(path, "path");
|
||||
|
||||
checkConnected();
|
||||
logger.debug("%s@%s:%d: Opening sftp Channel.", username, host.getHostAddress(), port);
|
||||
ChannelSftp sftp = null;
|
||||
try {
|
||||
return sftp.get(path);
|
||||
sftp = (ChannelSftp) session.openChannel("sftp");
|
||||
sftp.connect();
|
||||
} catch (JSchException e) {
|
||||
throw new SshException(String.format("%s@%s:%d: Error connecting to sftp.", username, host
|
||||
.getHostAddress(), port), e);
|
||||
}
|
||||
try {
|
||||
return new CloseFtpChannelOnCloseInputStream(sftp.get(path), sftp);
|
||||
} catch (SftpException e) {
|
||||
throw new SshException(String.format("%s@%s:%d: Error getting path: %s", username, host
|
||||
.getHostAddress(), port, path), e);
|
||||
|
@ -65,17 +115,15 @@ public class JschSshConnection implements SshConnection {
|
|||
}
|
||||
|
||||
private void checkConnected() {
|
||||
checkState(sftp != null && sftp.isConnected(), String.format("%s@%s:%d: SFTP not connected!",
|
||||
username, host.getHostAddress(), port));
|
||||
checkState(session != null && session.isConnected(), String.format(
|
||||
"%s@%s:%d: SFTP not connected!", username, host.getHostAddress(), port));
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void connect() {
|
||||
if (sftp != null && sftp.isConnected())
|
||||
return;
|
||||
disconnect();
|
||||
JSch jsch = new JSch();
|
||||
session = null;
|
||||
Channel channel = null;
|
||||
try {
|
||||
session = jsch.getSession(username, host.getHostAddress(), port);
|
||||
} catch (JSchException e) {
|
||||
|
@ -94,24 +142,16 @@ public class JschSshConnection implements SshConnection {
|
|||
host.getHostAddress(), port), e);
|
||||
}
|
||||
logger.debug("%s@%s:%d: Session connected.", username, host.getHostAddress(), port);
|
||||
logger.debug("%s@%s:%d: Opening sftp Channel.", username, host.getHostAddress(), port);
|
||||
try {
|
||||
channel = session.openChannel("sftp");
|
||||
channel.connect();
|
||||
} catch (JSchException e) {
|
||||
throw new SshException(String.format("%s@%s:%d: Error connecting to sftp.", username, host
|
||||
.getHostAddress(), port), e);
|
||||
}
|
||||
sftp = (ChannelSftp) channel;
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void disconnect() {
|
||||
if (sftp != null && sftp.isConnected())
|
||||
sftp.quit();
|
||||
if (session != null && session.isConnected())
|
||||
session.disconnect();
|
||||
}
|
||||
|
||||
public ExecResponse exec(String command) {
|
||||
checkConnected();
|
||||
ChannelExec executor = null;
|
||||
try {
|
||||
try {
|
||||
|
|
|
@ -1,3 +1,26 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.ssh.jsch;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
@ -12,7 +35,6 @@ import org.jclouds.ssh.ExecResponse;
|
|||
import org.jclouds.ssh.SshConnection;
|
||||
import org.jclouds.ssh.jsch.config.JschSshConnectionModule;
|
||||
import org.jclouds.util.Utils;
|
||||
import org.testng.ITestContext;
|
||||
import org.testng.annotations.BeforeGroups;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
|
@ -31,18 +53,15 @@ public class JschSshConnectionLiveTest {
|
|||
protected static final String sshUser = System.getProperty("jclouds.test.ssh.username");
|
||||
protected static final String sshPass = System.getProperty("jclouds.test.ssh.password");
|
||||
|
||||
protected SshConnection connection;
|
||||
|
||||
@BeforeGroups(groups = { "live" })
|
||||
public void setupConnection(ITestContext context) throws NumberFormatException,
|
||||
UnknownHostException {
|
||||
public SshConnection setupConnection() throws NumberFormatException, UnknownHostException {
|
||||
int port = (sshPort != null) ? Integer.parseInt(sshPort) : 22;
|
||||
InetAddress host = (sshHost != null) ? InetAddress.getByName(sshHost) : InetAddress
|
||||
.getLocalHost();
|
||||
if (sshUser == null || sshPass == null || sshUser.trim().equals("")
|
||||
|| sshPass.trim().equals("")) {
|
||||
System.err.println("ssh credentials not present. Tests will be lame");
|
||||
connection = new SshConnection() {
|
||||
return new SshConnection() {
|
||||
|
||||
public void connect() {
|
||||
}
|
||||
|
@ -72,19 +91,20 @@ public class JschSshConnectionLiveTest {
|
|||
} else {
|
||||
Injector i = Guice.createInjector(new JschSshConnectionModule());
|
||||
SshConnection.Factory factory = i.getInstance(SshConnection.Factory.class);
|
||||
connection = factory.create(host, port, sshUser, sshPass);
|
||||
SshConnection connection = factory.create(host, port, sshUser, sshPass);
|
||||
connection.connect();
|
||||
return connection;
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetEtcPassword() throws IOException {
|
||||
InputStream input = connection.get("/etc/passwd");
|
||||
InputStream input = setupConnection().get("/etc/passwd");
|
||||
String contents = Utils.toStringAndClose(input);
|
||||
assert contents.indexOf("root") >= 0 : "no root in " + contents;
|
||||
}
|
||||
|
||||
public void testExecHostname() throws IOException {
|
||||
ExecResponse response = connection.exec("hostname");
|
||||
ExecResponse response = setupConnection().exec("hostname");
|
||||
assertEquals(response.getError(), "");
|
||||
assertEquals(response.getOutput().trim(), InetAddress.getLocalHost().getHostName());
|
||||
}
|
||||
|
|
|
@ -1,3 +1,26 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.ssh.jsch.config;
|
||||
|
||||
import java.net.InetAddress;
|
||||
|
|
Loading…
Reference in New Issue