diff options
Diffstat (limited to 'appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd')
5 files changed, 257 insertions, 198 deletions
diff --git a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/pom.xml b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/pom.xml index 35bb0cf92..76601450e 100644 --- a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/pom.xml +++ b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/pom.xml @@ -1,62 +1,64 @@ <?xml version="1.0" encoding="UTF-8"?> -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - <modelVersion>4.0.0</modelVersion> - <parent> - <groupId>org.openecomp.appc</groupId> - <artifactId>appc-ssh-adapter</artifactId> - <version>1.1.0-SNAPSHOT</version> - </parent> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.openecomp.appc</groupId> + <artifactId>appc-ssh-adapter</artifactId> + <version>1.1.0-SNAPSHOT</version> + </parent> - <artifactId>appc-ssh-adapter-sshd</artifactId> - <packaging>bundle</packaging> + <artifactId>appc-ssh-adapter-sshd</artifactId> + <packaging>bundle</packaging> - <dependencies> - <dependency> - <groupId>org.openecomp.appc</groupId> - <artifactId>appc-ssh-adapter-api</artifactId> - <version>${project.version}</version> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>org.apache.sshd</groupId> - <artifactId>sshd-core</artifactId> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>com.att.eelf</groupId> - <artifactId>eelf-core</artifactId> - </dependency> - <dependency> - <groupId>junit</groupId> - <artifactId>junit</artifactId> - </dependency> - <dependency> - <groupId>org.openecomp.appc</groupId> - <artifactId>appc-common</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>org.openecomp.sdnc.core</groupId> - <artifactId>dblib-provider</artifactId> - </dependency> - </dependencies> + <dependencies> + <dependency> + <groupId>org.openecomp.appc</groupId> + <artifactId>appc-ssh-adapter-api</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.sshd</groupId> + <artifactId>sshd-core</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.att.eelf</groupId> + <artifactId>eelf-core</artifactId> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.openecomp.appc</groupId> + <artifactId>appc-common</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>dblib-provider</artifactId> + </dependency> + </dependencies> - <build> - <plugins> - <plugin> - <groupId>org.apache.felix</groupId> - <artifactId>maven-bundle-plugin</artifactId> - <extensions>true</extensions> - <configuration> - <instructions> - <Export-Service>org.openecomp.appc.adapter.ssh.SshAdapter</Export-Service> - <Private-Package>org.openecomp.appc.adapter.ssh.impl.*</Private-Package> - <Import-Package>!org.apache.log,!org.apache.commons.logging,!groovy.lang,!javax.jms,!org.codehaus.commons.compiler,!org.codehaus.groovy.*,!org.codehaus.janino,!com.ibm.icu.*,!com.sun.faces.*,!org.jasypt.*,*;resolution:=optional</Import-Package> - <Embed-Dependency>!dblib-provider,appc-common,jasypt,eelf-core,logback-core,logback-classic;scope=compile|runtime;inline=false</Embed-Dependency> - <Embed-Transitive>true</Embed-Transitive> - </instructions> - </configuration> - </plugin> - </plugins> - </build> + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Export-Service>org.openecomp.appc.adapter.ssh.SshAdapter</Export-Service> + <Private-Package>org.openecomp.appc.adapter.ssh.impl.*</Private-Package> + <Import-Package>!org.apache.log,!org.apache.commons.logging,!groovy.lang,!javax.jms,!org.codehaus.commons.compiler,!org.codehaus.groovy.*,!org.codehaus.janino,!com.ibm.icu.*,!com.sun.faces.*,!org.jasypt.*,*</Import-Package> + <Embed-Dependency>!dblib-provider,jasypt,eelf-core,logback-core,logback-classic;scope=compile|runtime;inline=false</Embed-Dependency> + <Embed-Transitive>true</Embed-Transitive> + </instructions> + </configuration> + </plugin> + </plugins> + </build> </project> diff --git a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/openecomp/appc/adapter/ssh/sshd/SshConnectionSshd.java b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/openecomp/appc/adapter/ssh/sshd/SshConnectionSshd.java index 4d8b83b6f..e87bfa264 100644 --- a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/openecomp/appc/adapter/ssh/sshd/SshConnectionSshd.java +++ b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/openecomp/appc/adapter/ssh/sshd/SshConnectionSshd.java @@ -21,6 +21,12 @@ package org.openecomp.appc.adapter.ssh.sshd; +import org.openecomp.appc.adapter.ssh.Constants; +import org.openecomp.appc.adapter.ssh.SshConnection; +import org.openecomp.appc.adapter.ssh.SshException; +import org.openecomp.appc.encryption.EncryptionTool; +import org.openecomp.appc.configuration.Configuration; +import org.openecomp.appc.configuration.ConfigurationFactory; import org.apache.sshd.ClientChannel; import org.apache.sshd.ClientSession; import org.apache.sshd.SshClient; @@ -29,9 +35,7 @@ import org.apache.sshd.client.future.AuthFuture; import org.apache.sshd.client.future.OpenFuture; import org.apache.sshd.common.KeyPairProvider; import org.apache.sshd.common.keyprovider.FileKeyPairProvider; -import org.openecomp.appc.adapter.ssh.SshConnection; -import org.openecomp.appc.adapter.ssh.SshException; -import org.openecomp.appc.encryption.EncryptionTool; + import com.att.eelf.configuration.EELFLogger; import com.att.eelf.configuration.EELFManager; @@ -43,130 +47,187 @@ import java.security.KeyPair; */ class SshConnectionSshd implements SshConnection { - private static final EELFLogger logger = EELFManager.getInstance().getApplicationLogger(); - - private static final long AUTH_TIMEOUT = 60000; - private static final long EXEC_TIMEOUT = 120000; - - private String host; - private int port; - private String username; - private String password; - private long timeout = EXEC_TIMEOUT; - private String keyFile; - private SshClient sshClient; - private ClientSession clientSession; - - public SshConnectionSshd(String host, int port, String username, String password, String keyFile) { - this.host = host; - this.port = port; - this.username = username; - this.password = password; - this.keyFile = keyFile; - } - - public SshConnectionSshd(String host, int port, String username, String password) { - this(host, port, username, password, null); - } - - public SshConnectionSshd(String host, int port, String keyFile) { - this(host, port, null, null, keyFile); - } - - @Override - public void connect() { - sshClient = SshClient.setUpDefaultClient(); - sshClient.start(); - try { - clientSession = sshClient.connect(EncryptionTool.getInstance().decrypt(username), host, port).await().getSession(); - if(password != null) { - clientSession.addPasswordIdentity(EncryptionTool.getInstance().decrypt(password)); - } - if(keyFile != null) { - KeyPairProvider keyPairProvider = new FileKeyPairProvider(new String[]{keyFile}); - KeyPair keyPair = keyPairProvider.loadKeys().iterator().next(); - clientSession.addPublicKeyIdentity(keyPair); - } - AuthFuture authFuture = clientSession.auth(); - authFuture.await(AUTH_TIMEOUT); - if(!authFuture.isSuccess()) { - throw new SshException("Error establishing ssh connection to [" + username + "@" + host + ":" + port + "]. Authentication failed."); - } - } catch(RuntimeException e) { - throw e; - } catch(Exception e) { - throw new SshException("Error establishing ssh connection to [" + username + "@" + host + ":" + port + "].", e); - } - if(logger.isDebugEnabled()) { - logger.debug("SSH: connected to [" + toString() + "]"); - } - } - - @Override - public void disconnect() { - try { - if(logger.isDebugEnabled()) { - logger.debug("SSH: disconnecting from [" + toString() + "]"); - } - clientSession.close(false); - } finally { - if(sshClient != null) { - sshClient.stop(); - } - } - } - - @Override - public void setExecTimeout(long timeout) { - this.timeout = timeout; - } - - @Override - public int execCommand(String cmd, OutputStream out, OutputStream err) { - return execCommand(cmd, out, err, false); - } - - @Override - public int execCommandWithPty(String cmd, OutputStream out) { - return execCommand(cmd, out, out, true); - } - - private int execCommand(String cmd, OutputStream out, OutputStream err, boolean usePty) { - try { - if(logger.isDebugEnabled()) { - logger.debug("SSH: executing command"); - } - ChannelExec client = clientSession.createExecChannel(cmd); + private static final EELFLogger logger = EELFManager.getInstance().getApplicationLogger(); + + private static final long AUTH_TIMEOUT = 60000; + private static final long EXEC_TIMEOUT = 120000; + + private String host; + private int port; + private String username; + private String password; + private long timeout = EXEC_TIMEOUT; + private String keyFile; + private SshClient sshClient; + private ClientSession clientSession; + private static final Configuration configuration = ConfigurationFactory.getConfiguration(); + + public SshConnectionSshd(String host, int port, String username, String password, String keyFile) { + this.host = host; + this.port = port; + this.username = username; + this.password = password; + this.keyFile = keyFile; + } + + public SshConnectionSshd(String host, int port, String username, String password) { + this(host, port, username, password, null); + } + + public SshConnectionSshd(String host, int port, String keyFile) { + this(host, port, null, null, keyFile); + } + + @Override + public void connect() { + sshClient = SshClient.setUpDefaultClient(); + sshClient.start(); + try { + clientSession = + sshClient.connect(EncryptionTool.getInstance().decrypt(username), host, port).await().getSession(); + if (password != null) { + clientSession.addPasswordIdentity(EncryptionTool.getInstance().decrypt(password)); + } + if (keyFile != null) { + KeyPairProvider keyPairProvider = new FileKeyPairProvider(new String[] { + keyFile + }); + KeyPair keyPair = keyPairProvider.loadKeys().iterator().next(); + clientSession.addPublicKeyIdentity(keyPair); + } + AuthFuture authFuture = clientSession.auth(); + authFuture.await(AUTH_TIMEOUT); + if (!authFuture.isSuccess()) { + throw new SshException("Error establishing ssh connection to [" + username + "@" + host + ":" + port + + "]. Authentication failed."); + } + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new SshException("Error establishing ssh connection to [" + username + "@" + host + ":" + port + "].", + e); + } + if (logger.isDebugEnabled()) { + logger.debug("SSH: connected to [" + toString() + "]"); + } + } + + @Override + public void connectWithRetry() { + int retryCount = 0; + int retryDelay = 0; + int retriesLeft = 0; + retryCount = configuration.getIntegerProperty(Constants.CONNECTION_RETRY_COUNT, + Constants.DEFAULT_CONNECTION_RETRY_COUNT); + retryDelay = configuration.getIntegerProperty(Constants.CONNECTION_RETRY_DELAY, + Constants.DEFAULT_CONNECTION_RETRY_DELAY); + retriesLeft = retryCount + 1; + do { + try { + this.connect(); + break; + } catch (RuntimeException e) { + if (retriesLeft > 1) { + logger.debug("SSH Connection failed. Waiting for change in server's state."); + waitForConnection(retryDelay); + retriesLeft--; + logger.debug("Retrying SSH connection. Attempt [" + Integer.toString(retryCount - retriesLeft + 1) + + "] out of [" + retryCount + "]"); + } else { + throw e; + } + } catch (Exception e) { + throw e; + } + } while (retriesLeft > 0); + } + + @Override + public void disconnect() { + try { + if (logger.isDebugEnabled()) { + logger.debug("SSH: disconnecting from [" + toString() + "]"); + } + clientSession.close(false); + } finally { + if (sshClient != null) { + sshClient.stop(); + } + } + } + + @Override + public void setExecTimeout(long timeout) { + this.timeout = timeout; + } + + @Override + public int execCommand(String cmd, OutputStream out, OutputStream err) { + return execCommand(cmd, out, err, false); + } + + @Override + public int execCommandWithPty(String cmd, OutputStream out) { + return execCommand(cmd, out, out, true); + } + + private int execCommand(String cmd, OutputStream out, OutputStream err, boolean usePty) { + try { + if (logger.isDebugEnabled()) { + logger.debug("SSH: executing command"); + } + ChannelExec client = clientSession.createExecChannel(cmd); client.setUsePty(usePty); // use pseudo-tty? - client.setOut(out); - client.setErr(err); - OpenFuture openFuture = client.open(); - int exitStatus = 0; - try { - client.waitFor(ClientChannel.CLOSED, timeout); - openFuture.verify(); - Integer exitStatusI = client.getExitStatus(); - if(exitStatusI == null) { - throw new SshException("Error executing command [" + cmd + "] over SSH [" + username + "@" + host + ":" + port + "]. Operation timed out."); - } - exitStatus = exitStatusI; - } finally { - client.close(false); - } - return exitStatus; - } catch(RuntimeException e) { - throw e; - } catch(Exception t) { - throw new SshException("Error executing command [" + cmd + "] over SSH [" + username + "@" + host + ":" + port + "]", t); - } - } - - @Override - public String toString() { - String address = host; - if(username != null) { - address = username + '@' +address; - } - return address; - } + client.setOut(out); + client.setErr(err); + OpenFuture openFuture = client.open(); + int exitStatus = 0; + try { + client.waitFor(ClientChannel.CLOSED, timeout); + openFuture.verify(); + Integer exitStatusI = client.getExitStatus(); + if (exitStatusI == null) { + throw new SshException("Error executing command [" + cmd + "] over SSH [" + username + "@" + host + + ":" + port + "]. Operation timed out."); + } + exitStatus = exitStatusI; + } finally { + client.close(false); + } + return exitStatus; + } catch (RuntimeException e) { + throw e; + } catch (Exception t) { + throw new SshException( + "Error executing command [" + cmd + "] over SSH [" + username + "@" + host + ":" + port + "]", t); + } + } + + private void waitForConnection(int retryDelay) { + long time = retryDelay * 1000L; + long future = System.currentTimeMillis() + time; + if (time != 0) { + while (System.currentTimeMillis() < future && time > 0) { + try { + Thread.sleep(time); + } catch (InterruptedException e) { + /* + * This is rare, but it can happen if another thread interrupts us while we are sleeping. In that + * case, the thread is resumed before the delay time has actually expired, so re-calculate the + * amount of delay time needed and reenter the sleep until we get to the future time. + */ + time = future - System.currentTimeMillis(); + } + } + } + } + + @Override + public String toString() { + String address = host; + if (username != null) { + address = username + '@' + address; + } + return address; + } } diff --git a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/openecomp/appc/adapter/ssh/sshd/SshdDataAccessService.java b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/openecomp/appc/adapter/ssh/sshd/SshdDataAccessService.java index a12e2be93..4e7f8d2f5 100644 --- a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/openecomp/appc/adapter/ssh/sshd/SshdDataAccessService.java +++ b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/openecomp/appc/adapter/ssh/sshd/SshdDataAccessService.java @@ -27,14 +27,11 @@ import org.openecomp.appc.adapter.ssh.Constants; import org.openecomp.appc.adapter.ssh.SshConnectionDetails; import org.openecomp.appc.adapter.ssh.SshDataAccessException; import org.openecomp.appc.adapter.ssh.SshDataAccessService; -import org.openecomp.appc.exceptions.APPCException; import org.openecomp.sdnc.sli.resource.dblib.DbLibService; import java.sql.SQLException; import java.util.ArrayList; - - public class SshdDataAccessService implements SshDataAccessService { private String schema = Constants.NETCONF_SCHEMA; diff --git a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/resources/OSGI-INF/blueprint/blueprint.xml index f9d10868a..d6c0f686f 100644 --- a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/resources/OSGI-INF/blueprint/blueprint.xml +++ b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -22,17 +22,17 @@ <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd"> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd"> - <bean id="sshdBean" class="org.openecomp.appc.adapter.ssh.sshd.SshAdapterSshd" scope="singleton"/> - <service id="sshAdapter" interface="org.openecomp.appc.adapter.ssh.SshAdapter" ref="sshdBean"/> + <bean id="sshdBean" class="org.openecomp.appc.adapter.ssh.sshd.SshAdapterSshd" scope="singleton"/> + <service id="sshAdapter" interface="org.openecomp.appc.adapter.ssh.SshAdapter" ref="sshdBean"/> - <reference id="dbLibServiceRef" availability="mandatory" activation="eager" interface="org.openecomp.sdnc.sli.resource.dblib.DbLibService" /> - <bean id="sshdDAServiceBean" class="org.openecomp.appc.adapter.ssh.sshd.SshdDataAccessService" scope="singleton"> - <property name="dbLibService" ref="dbLibServiceRef" /> - </bean> + <reference id="dbLibServiceRef" availability="mandatory" activation="eager" interface="org.openecomp.sdnc.sli.resource.dblib.DbLibService" /> + <bean id="sshdDAServiceBean" class="org.openecomp.appc.adapter.ssh.sshd.SshdDataAccessService" scope="singleton"> + <property name="dbLibService" ref="dbLibServiceRef" /> + </bean> - <service id="sshDAService" interface="org.openecomp.appc.adapter.ssh.SshDataAccessService" ref="sshdDAServiceBean"/> + <service id="sshDAService" interface="org.openecomp.appc.adapter.ssh.SshDataAccessService" ref="sshdDAServiceBean"/> </blueprint> diff --git a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/test/java/org/openecomp/appc/adapter/ssh/sshd/SshAdapterTest.java b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/test/java/org/openecomp/appc/adapter/ssh/sshd/SshAdapterTest.java index 980395476..1d7d06df2 100644 --- a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/test/java/org/openecomp/appc/adapter/ssh/sshd/SshAdapterTest.java +++ b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/test/java/org/openecomp/appc/adapter/ssh/sshd/SshAdapterTest.java @@ -49,7 +49,6 @@ import java.security.PublicKey; import java.util.Collections; import java.util.EnumSet; -@Ignore public class SshAdapterTest { private static final boolean START_SERVER = true; |