diff options
Diffstat (limited to 'adaptors/ssh-adaptor/ssh-adaptor-bundle')
22 files changed, 2023 insertions, 0 deletions
diff --git a/adaptors/ssh-adaptor/ssh-adaptor-bundle/pom.xml b/adaptors/ssh-adaptor/ssh-adaptor-bundle/pom.xml new file mode 100644 index 000000000..359ecade6 --- /dev/null +++ b/adaptors/ssh-adaptor/ssh-adaptor-bundle/pom.xml @@ -0,0 +1,121 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + ONAP : APPC + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Copyright (C) 2017 Amdocs + ============================================================================= + Licensed 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. + + ECOMP is a trademark and service mark of AT&T Intellectual Property. + ============LICENSE_END========================================================= + --> +<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.onap.ccsdk.parent</groupId> + <artifactId>binding-parent</artifactId> + <version>2.2.0-SNAPSHOT</version> + <relativePath/> + </parent> + + <groupId>org.onap.ccsdk.sli.adaptors</groupId> + <artifactId>ssh-adaptor-bundle</artifactId> + <version>1.3.0-SNAPSHOT</version> + <packaging>bundle</packaging> + + <name>ccsdk-sli-adaptors :: ${project.artifactId}</name> + + <dependencyManagement> + <dependencies> + <dependency> + <groupId>org.onap.ccsdk.sli.core</groupId> + <artifactId>sli-core-artifacts</artifactId> + <version>${project.version}</version> + <type>pom</type> + <scope>import</scope> + </dependency> + </dependencies> + </dependencyManagement> + <dependencies> + <dependency> + <groupId>org.apache.sshd</groupId> + <artifactId>sshd-core</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.onap.ccsdk.sli.core</groupId> + <artifactId>dblib-provider</artifactId> + </dependency> + <dependency> + <groupId>com.att.eelf</groupId> + <artifactId>eelf-core</artifactId> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Export-Service>org.onap.ccsdk.sli.adaptors.ssh.SshAdaptor</Export-Service> + <Export-Package>org.onap.ccsdk.sli.adaptors.ssh</Export-Package> + <Import-Package> + !org.slf4j.impl, + !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> + jasypt, + eelf-core, + logback-core, + logback-classic;scope=compile|runtime;inline=false + </Embed-Dependency> + <Embed-Transitive>true</Embed-Transitive> + </instructions> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-javadoc-plugin</artifactId> + <executions> + <execution> + <id>attach-javadocs</id> + <goals> + <goal>jar</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> diff --git a/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ssh/Constants.java b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ssh/Constants.java new file mode 100644 index 000000000..513b86e4a --- /dev/null +++ b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ssh/Constants.java @@ -0,0 +1,120 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed 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. + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * ============LICENSE_END========================================================= + */ + +package org.onap.ccsdk.sli.adaptors.ssh; + +public class Constants { + + private Constants(){} + + // tables and fields + public static final String NETCONF_SCHEMA = "sdnctl"; + public static final String SDNCTL_SCHEMA = "sdnctl"; + public static final String DEVICE_AUTHENTICATION_TABLE_NAME = "DEVICE_AUTHENTICATION"; + public static final String CONFIGFILES_TABLE_NAME = "CONFIGFILES"; + public static final String DEVICE_INTERFACE_LOG_TABLE_NAME = "DEVICE_INTERFACE_LOG"; + public static final String FILE_CONTENT_TABLE_FIELD_NAME = "FILE_CONTENT"; + public static final String FILE_NAME_TABLE_FIELD_NAME = "FILE_NAME"; + public static final String USER_NAME_TABLE_FIELD_NAME = "USER_NAME"; + public static final String PASSWORD_TABLE_FIELD_NAME = "PASSWORD"; + public static final String PORT_NUMBER_TABLE_FIELD_NAME = "PORT_NUMBER"; + public static final String VNF_TYPE_TABLE_FIELD_NAME = "VNF_TYPE"; + public static final String SERVICE_INSTANCE_ID_FIELD_NAME = "SERVICE_INSTANCE_ID"; + public static final String REQUEST_ID_FIELD_NAME = "REQUEST_ID"; + public static final String CREATION_DATE_FIELD_NAME = "CREATION_DATE"; + public static final String LOG_FIELD_NAME = "LOG"; + public static final String SDC_ARTIFACTS_TABLE_NAME = "ASDC_ARTIFACTS"; + + // input fields names + public static final String PAYLOAD = "payload"; + + public static final String CONNECTION_RETRY_DELAY = "org.onap.appc.ssh.connection.retry.delay"; + public static final String CONNECTION_RETRY_COUNT = "org.onap.appc.ssh.connection.retry.count"; + public static final int DEFAULT_CONNECTION_RETRY_DELAY = 60; + public static final int DEFAULT_CONNECTION_RETRY_COUNT = 5; + + public static final int DEFAULT_SSH_COMMAND_RETRY_COUNT = 3; + + public static final int DEFAULT_CHECKACTIVE_RETRY_COUNT = 3; + public static final int DEFAULT_CHECKACTIVE_RETRY_DELAY = 30; + + public static final int DEFAULT_STOP_RETRY_COUNT = 3; + public static final int DEFAULT_STOP_RETRY_DELAY = 30; //seconds + + public static final String PARAM_IN_CONNECTION_DETAILS = "connection-details"; + public static final String PARAM_IN_NODE_NAME = "node-name"; + public static final String PARAM_IN_NODE_STATUS = "node-status"; + public static final String PARAM_IN_VM_URL = "vm-url"; + public static final String SKIP_EXECUTION_INSTALLER_BIN_FILE = "Skip-execution-installer-bin-file"; + public static final String SKIP_DEPLOY = "Skip-deploy"; + public static final String UPGRADE_VERSION = "upgrade-version"; + + //command to get number of UP hosts + public static final String STATE_COMMAND = "/opt/jnetx/skyfall-scp/asp-state.sh | grep -o UP | wc -l"; + //command to get each VNFC status + public static final String VNFC_STATE_COMMAND = "/opt/jnetx/skyfall-scp/asp-state.sh"; + //command to restart node + public static final String RESTART_NODE_COMMAND = "/opt/jnetx/skyfall-scp/asp-stop.sh --restart -f --nodes"; + //command to start node + public static final String START_NODE_COMMAND = "/opt/jnetx/skyfall-scp/asp-start.sh -f --nodes"; + //command to stop node + public static final String STOP_NODE_COMMAND = "/opt/jnetx/skyfall-scp/asp-stop.sh -f --nodes"; + public static final int STATE_COMMAND_RESULT = 18; + //commands to check FE hosts + public static final String FE_STATE_TRUE_TEST_COMMAND = "ssh -t -q fe1 /opt/omni/bin/swmml -e display-platform-status | grep -o TRUE | wc -l"; + public static final int FE_STATE_TRUE_TEST_RESULT = 22; + public static final String FE_STATE_FALSE_TEST_COMMAND = "ssh -t -q fe1 /opt/omni/bin/swmml -e display-platform-status | grep -o FALSE | wc -l"; + public static final int FE_STATE_FALSE_TEST_RESULT = 2; + public static final String FE_OPERATIONAL_TEST_COMMAND = "ssh -t -q fe1 /opt/omni/bin/swmml -e display-platform-status | grep -o 'NOT FULLY OPERATIONAL' | wc -l"; + public static final int FE_OPERATIONAL_TEST_RESULT = 2; + + //smp commands + public static final String SMP_CHECK_ACTIVE_STATE_COMMAND = "cat skyfall-scp/runtime/SCP_SMP_*/smp/log/system.log| grep SSS | tail -1"; + public static final String SMP_STATE_ACTIVE="SMP is active"; + public static final String SMP_STATE_INACTIVE="SMP is not active"; + + //rsync command + public static final String RSYNC_COMMAND = "yes n | /opt/jnetx/skyfall-scp/asp-rsync.sh --check | grep -o 'is active' | wc -l"; + public static final int RSYNC_COMMAND_RESULT = 9; + + public static final String PARAM_IN_TIMEOUT = "timeout"; + public static final String PARAM_IN_FILE_URL = "source-file-url"; + public static final String DOWNLOAD_COMMAND = "wget -N %s"; + + // pre-define VM names + public static final String[] VM_NAMES = {"fe1", "fe2", "be1", "be2", "be3", "be4", "be5", "smp1", "smp2"}; + + public static final String DEFAULT_DISK_SPACE = "10240000"; + public static final String DF_COMMAND_TEMPLATE = "ssh %s df | grep vda1 | grep -v grep | tr -s ' '|cut -d ' ' -f4"; + + public static final String DG_OUTPUT_STATUS_MESSAGE = "output.status.message"; + public static final String ATTRIBUTE_ERROR_MESSAGE = "error-message"; + + + // constants for DG + public static final String CONNECTION_DETAILS_FIELD_NAME = PARAM_IN_CONNECTION_DETAILS; + public static final String VNF_HOST_IP_ADDRESS_FIELD_NAME = "vnf-host-ip-address"; + public static final String VNF_HOST_IP2_ADDRESS_FIELD_NAME = "vnf-host-ip2-address"; + public static final String DG_ERROR_FIELD_NAME = "org.openecom.appc.dg.error"; +} diff --git a/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ssh/SshAdaptor.java b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ssh/SshAdaptor.java new file mode 100644 index 000000000..eed7f4e3b --- /dev/null +++ b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ssh/SshAdaptor.java @@ -0,0 +1,53 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed 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. + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * ============LICENSE_END========================================================= + */ + +package org.onap.ccsdk.sli.adaptors.ssh; + +/** + * Factory class for creating SshConnection instances. + */ +public interface SshAdaptor { + + /** + * Creates instance of SshConnection. + * + * @param host remote host to open SSH connection to + * @param port remote SSH port + * @param username SSH connection user name + * @param password SSH connection password + * @return instance of SshConnection + */ + SshConnection getConnection(String host, int port, String username, String password); + + /** + * Creates instance of SshConnection. + * + * @param host remote host to open SSH connection to + * @param port remote SSH port + * @param keyFile SSH connection key file location + * @return instance of SshConnection + */ + SshConnection getConnection(String host, int port, String keyFile); + +} diff --git a/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ssh/SshConnection.java b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ssh/SshConnection.java new file mode 100644 index 000000000..9fc8216b1 --- /dev/null +++ b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ssh/SshConnection.java @@ -0,0 +1,75 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed 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. + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * ============LICENSE_END========================================================= + */ + +package org.onap.ccsdk.sli.adaptors.ssh; + +import java.io.OutputStream; + +/** + * Provides utility method(s) to call commands on remote host via SSH. + */ +public interface SshConnection { + + /** + * Connect to SSH server. + */ + void connect(); + + /** + * Connect to SSH Server using a retry mechanism + */ + void connectWithRetry(); + + /** + * Disconnect from SSH server. + */ + void disconnect(); + + /** + * Exec remote command over SSH. Return command execution status. + * Command output is written to out or err stream. + * + * @param cmd command to execute + * @param out content of sysout will go to this stream + * @param err content of syserr will go to this stream + * @return command execution status + */ + int execCommand(String cmd, OutputStream out, OutputStream err); + + /** + * Exec remote command over SSH with pseudo-tty. Return command execution status. + * Command output is written to out stream only as pseudo-tty writes to one stream only. + * + * @param cmd command to execute + * @param out content of sysout will go to this stream + * @return command execution status + */ + int execCommandWithPty(String cmd, OutputStream out); + + /** + * Set the command execution timeout + * @param timeout time in milliseconds + */ + void setExecTimeout(long timeout); +} diff --git a/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ssh/SshConnectionDetails.java b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ssh/SshConnectionDetails.java new file mode 100644 index 000000000..318287cd7 --- /dev/null +++ b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ssh/SshConnectionDetails.java @@ -0,0 +1,75 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed 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. + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * ============LICENSE_END========================================================= + */ + +package org.onap.ccsdk.sli.adaptors.ssh; + +/** + * Provides details required for connecting to device. + */ +public class SshConnectionDetails { + + private static int DEFAULT_PORT = 22; + + private String host; + private int port = DEFAULT_PORT; + private String username; + private String password; + + public SshConnectionDetails() { + } + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + +} diff --git a/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ssh/SshDataAccessException.java b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ssh/SshDataAccessException.java new file mode 100644 index 000000000..a04a043c2 --- /dev/null +++ b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ssh/SshDataAccessException.java @@ -0,0 +1,48 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed 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. + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * ============LICENSE_END========================================================= + */ + +package org.onap.ccsdk.sli.adaptors.ssh; + + + +public class SshDataAccessException extends RuntimeException { + + private static final long serialVersionUID = -155423437162622414L; + + public SshDataAccessException(){ + } + + public SshDataAccessException(String message){ + super(message); + } + + public SshDataAccessException(Throwable cause){ + super(cause); + } + + public SshDataAccessException(String message , Throwable cause){ + super(message , cause); + } + +} diff --git a/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ssh/SshDataAccessService.java b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ssh/SshDataAccessService.java new file mode 100644 index 000000000..48165e823 --- /dev/null +++ b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ssh/SshDataAccessService.java @@ -0,0 +1,61 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed 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. + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * ============LICENSE_END========================================================= + */ + +package org.onap.ccsdk.sli.adaptors.ssh; + +import org.onap.ccsdk.sli.core.dblib.DbLibService; + + +@SuppressWarnings("JavaDoc") +public interface SshDataAccessService { + + /** + * + * @param schema + */ + void setSchema(String schema); + + /** + *@param dbLibService + */ + void setDbLibService(DbLibService dbLibService); + + /** + * + * @param xmlID + * @return + * @throws SshDataAccessException + */ + String retrieveConfigFileName(String xmlID) throws SshDataAccessException; + + /** + * + * @param vnfType + * @param connectionDetails + * @return + * @throws SshException + */ + boolean retrieveConnectionDetails(String vnfType, SshConnectionDetails connectionDetails) throws SshDataAccessException; + +} diff --git a/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ssh/SshException.java b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ssh/SshException.java new file mode 100644 index 000000000..52f102620 --- /dev/null +++ b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ssh/SshException.java @@ -0,0 +1,49 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed 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. + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * ============LICENSE_END========================================================= + */ + +package org.onap.ccsdk.sli.adaptors.ssh; + +public class SshException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + /** + * Constructor with message. + * + * @param message exception message + */ + public SshException(String message) { + super(message); + } + + /** + * Constructor with message and cause exception. + * + * @param message exception message + * @param cause exception cause + */ + public SshException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ssh/sshd/SshAdaptorSshd.java b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ssh/sshd/SshAdaptorSshd.java new file mode 100644 index 000000000..e7a2c9a38 --- /dev/null +++ b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ssh/sshd/SshAdaptorSshd.java @@ -0,0 +1,42 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed 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. + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * ============LICENSE_END========================================================= + */ + +package org.onap.ccsdk.sli.adaptors.ssh.sshd; + +import org.onap.ccsdk.sli.adaptors.ssh.SshAdaptor; +import org.onap.ccsdk.sli.adaptors.ssh.SshConnection; + +public class SshAdaptorSshd implements SshAdaptor { + + //@Override + public SshConnection getConnection(String host, int port, String username, String password) { + return new SshConnectionSshd(host, port, username, password); + } + + // @Override + public SshConnection getConnection(String host, int port, String keyFile) { + return new SshConnectionSshd(host, port, keyFile); + } + +} diff --git a/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ssh/sshd/SshConnectionSshd.java b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ssh/sshd/SshConnectionSshd.java new file mode 100644 index 000000000..4194159fe --- /dev/null +++ b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ssh/sshd/SshConnectionSshd.java @@ -0,0 +1,233 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed 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. + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * ============LICENSE_END========================================================= + */ + +package org.onap.ccsdk.sli.adaptors.ssh.sshd; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import java.io.OutputStream; +import java.nio.file.Paths; +import java.security.KeyPair; +import java.util.Collections; +import org.apache.sshd.client.SshClient; +import org.apache.sshd.client.channel.ChannelExec; +import org.apache.sshd.client.channel.ClientChannelEvent; +import org.apache.sshd.client.future.AuthFuture; +import org.apache.sshd.client.future.OpenFuture; +import org.apache.sshd.client.session.ClientSession; +import org.apache.sshd.common.keyprovider.FileKeyPairProvider; +import org.apache.sshd.common.keyprovider.KeyPairProvider; +import org.onap.ccsdk.sli.adaptors.ssh.Constants; +import org.onap.ccsdk.sli.adaptors.ssh.SshConnection; +import org.onap.ccsdk.sli.adaptors.ssh.SshException; +import org.onap.ccsdk.sli.core.utils.configuration.Configuration; +import org.onap.ccsdk.sli.core.utils.configuration.ConfigurationFactory; +import org.onap.ccsdk.sli.core.utils.encryption.EncryptionTool; + +/** + * Implementation of SshConnection interface based on Apache MINA SSHD library. + */ +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 final String host; + private final int port; + private final String username; + private final String password; + private long timeout = EXEC_TIMEOUT; + private final 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).verify().getSession(); + if (password != null) { + clientSession.addPasswordIdentity(EncryptionTool.getInstance().decrypt(password)); + } + if (keyFile != null) { + KeyPairProvider keyPairProvider = new FileKeyPairProvider(Paths.get(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 ; + int retryDelay ; + int retriesLeft; + + 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; + } + } + } 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; + try { + client.waitFor(Collections.singleton(ClientChannelEvent.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 e1) { + throw new SshException( + "Error executing command [" + cmd + "] over SSH [" + username + "@" + host + ":" + port + "]", e1); + } + } + + 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/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ssh/sshd/SshdDataAccessService.java b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ssh/sshd/SshdDataAccessService.java new file mode 100644 index 000000000..af8cb8b03 --- /dev/null +++ b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ssh/sshd/SshdDataAccessService.java @@ -0,0 +1,113 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed 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. + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * ============LICENSE_END========================================================= + */ + +package org.onap.ccsdk.sli.adaptors.ssh.sshd; + +import java.sql.SQLException; +import java.util.ArrayList; +import javax.sql.rowset.CachedRowSet; +import org.onap.ccsdk.sli.adaptors.ssh.Constants; +import org.onap.ccsdk.sli.adaptors.ssh.SshConnectionDetails; +import org.onap.ccsdk.sli.adaptors.ssh.SshDataAccessException; +import org.onap.ccsdk.sli.adaptors.ssh.SshDataAccessService; +import org.onap.ccsdk.sli.core.dblib.DbLibService; + +public class SshdDataAccessService implements SshDataAccessService { + + private String schema = Constants.NETCONF_SCHEMA; + private DbLibService dbLibService; + + @Override + public void setSchema(String schema) { + this.schema = schema; + } + + public String getSchema() { + return this.schema; + } + + @Override + public void setDbLibService(DbLibService dbLibService) { + this.dbLibService = dbLibService; + } + + public DbLibService getDbLibService() { + return this.dbLibService; + } + + + @Override + public boolean retrieveConnectionDetails(String vnfType, SshConnectionDetails connectionDetails) throws SshDataAccessException { + + boolean recordFound = false; + + String queryString = "select " + Constants.USER_NAME_TABLE_FIELD_NAME + "," + Constants.PASSWORD_TABLE_FIELD_NAME + "," + Constants.PORT_NUMBER_TABLE_FIELD_NAME + " " + + "from " + Constants.DEVICE_AUTHENTICATION_TABLE_NAME + " " + + "where " + Constants.VNF_TYPE_TABLE_FIELD_NAME + " = ?"; + + ArrayList<String> argList = new ArrayList<>(); + argList.add(vnfType); + + try { + + final CachedRowSet data = dbLibService.getData(queryString, argList, schema); + if (data.first()) { + recordFound = true; + connectionDetails.setUsername(data.getString(Constants.USER_NAME_TABLE_FIELD_NAME)); + connectionDetails.setPassword(data.getString(Constants.PASSWORD_TABLE_FIELD_NAME)); + connectionDetails.setPort(data.getInt(Constants.PORT_NUMBER_TABLE_FIELD_NAME)); + } + + } catch (SQLException e) { + throw new SshDataAccessException(e); + } + + return recordFound; + } + + @Override + public String retrieveConfigFileName(String xmlID) throws SshDataAccessException { + String fileContent; + + String queryString = "select " + Constants.FILE_CONTENT_TABLE_FIELD_NAME + " " + + "from " + Constants.CONFIGFILES_TABLE_NAME + " " + + "where " + Constants.FILE_NAME_TABLE_FIELD_NAME + " = ?"; + + ArrayList<String> argList = new ArrayList<>(); + argList.add(xmlID); + + try { + + final CachedRowSet data = dbLibService.getData(queryString, argList, schema); + fileContent = data.getString(Constants.FILE_CONTENT_TABLE_FIELD_NAME); + + } catch (SQLException e) { + throw new SshDataAccessException(e); + } + + return fileContent; + } + + +} diff --git a/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 000000000..e24bbb386 --- /dev/null +++ b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + ONAP : APPC + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Copyright (C) 2017 Amdocs + ============================================================================= + Licensed 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. + + ECOMP is a trademark and service mark of AT&T Intellectual Property. + ============LICENSE_END========================================================= + --> + + +<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"> + + <bean id="sshdBean" class="org.onap.ccsdk.sli.adaptors.ssh.sshd.SshAdaptorSshd" scope="singleton"/> + <service id="sshAdaptor" interface="org.onap.ccsdk.sli.adaptors.ssh.SshAdaptor" ref="sshdBean"/> + + <reference id="dbLibServiceRef" availability="mandatory" activation="eager" interface="org.onap.ccsdk.sli.core.dblib.DbLibService" /> + <bean id="sshdDAServiceBean" class="org.onap.ccsdk.sli.adaptors.ssh.sshd.SshdDataAccessService" scope="singleton"> + <property name="dbLibService" ref="dbLibServiceRef" /> + </bean> + + <service id="sshDAService" interface="org.onap.ccsdk.sli.adaptors.ssh.SshDataAccessService" ref="sshdDAServiceBean"/> + +</blueprint> diff --git a/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/test/java/org/onap/ccsdk/sli/adaptors/ssh/ConstantsTest.java b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/test/java/org/onap/ccsdk/sli/adaptors/ssh/ConstantsTest.java new file mode 100644 index 000000000..dddf33878 --- /dev/null +++ b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/test/java/org/onap/ccsdk/sli/adaptors/ssh/ConstantsTest.java @@ -0,0 +1,62 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * ============================================================================= + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.ccsdk.sli.adaptors.ssh; + +import java.lang.reflect.Constructor; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class ConstantsTest { + + @Test + public void test() { + String payLoad = Constants.PAYLOAD; + assertEquals(payLoad, "payload"); + + assertEquals(Constants.NETCONF_SCHEMA, "sdnctl"); + assertEquals(Constants.SDNCTL_SCHEMA, "sdnctl" ); + assertEquals(Constants.DEVICE_AUTHENTICATION_TABLE_NAME, "DEVICE_AUTHENTICATION" ); + assertEquals(Constants.CONFIGFILES_TABLE_NAME, "CONFIGFILES" ); + assertEquals(Constants.DEVICE_INTERFACE_LOG_TABLE_NAME, "DEVICE_INTERFACE_LOG" ); + assertEquals(Constants.FILE_CONTENT_TABLE_FIELD_NAME, "FILE_CONTENT" ); + assertEquals(Constants.FILE_NAME_TABLE_FIELD_NAME, "FILE_NAME" ); + + assertEquals(Constants.VM_NAMES[0], "fe1"); + assertEquals(Constants.VM_NAMES[1], "fe2"); + assertEquals(Constants.VM_NAMES[2], "be1"); + assertEquals(Constants.VM_NAMES[3], "be2"); + assertEquals(Constants.VM_NAMES[4], "be3"); + assertEquals(Constants.VM_NAMES[5], "be4"); + assertEquals(Constants.VM_NAMES[6], "be5"); + assertEquals(Constants.VM_NAMES[7], "smp1"); + assertEquals(Constants.VM_NAMES[8], "smp2"); + + assertEquals(Constants.DG_ERROR_FIELD_NAME, "org.openecom.appc.dg.error"); + + } + @Test + public void testValidatesThatClassConstantsIsNotInstantiable() throws Exception { + Constructor<Constants> c = Constants.class.getDeclaredConstructor(); + c.setAccessible(true); + c.newInstance(); + } +} diff --git a/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/test/java/org/onap/ccsdk/sli/adaptors/ssh/SshAdaptorMock.java b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/test/java/org/onap/ccsdk/sli/adaptors/ssh/SshAdaptorMock.java new file mode 100644 index 000000000..d04f22e17 --- /dev/null +++ b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/test/java/org/onap/ccsdk/sli/adaptors/ssh/SshAdaptorMock.java @@ -0,0 +1,85 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed 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. + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * ============LICENSE_END========================================================= + */ + +package org.onap.ccsdk.sli.adaptors.ssh; + +import java.util.ArrayList; +import java.util.List; + +public class SshAdaptorMock implements SshAdaptor { + + private final List<SshConnectionMock> connectionMocks = new ArrayList<>(); + + private int returnStatus; + private String returnStdout; + private String returnStderr; + +@Override + public SshConnection getConnection(String host, int port, String username, String password) { + SshConnectionMock sshConnectionMock = new SshConnectionMock(host, port, username, password, null); + sshConnectionMock.setReturnStatus(returnStatus); + sshConnectionMock.setReturnStdout(returnStdout); + sshConnectionMock.setReturnStderr(returnStderr); + connectionMocks.add(sshConnectionMock); + return sshConnectionMock; + } + + @Override + public SshConnection getConnection(String host, int port, String keyFile) { + SshConnectionMock sshConnectionMock = new SshConnectionMock(host, port, null, null, keyFile); + sshConnectionMock.setReturnStatus(returnStatus); + sshConnectionMock.setReturnStdout(returnStdout); + sshConnectionMock.setReturnStderr(returnStderr); + connectionMocks.add(sshConnectionMock); + return sshConnectionMock; + } + + public List<SshConnectionMock> getConnectionMocks() { + return connectionMocks; + } + + public int getReturnStatus() { + return returnStatus; + } + + public void setReturnStatus(int returnStatus) { + this.returnStatus = returnStatus; + } + + public String getReturnStdout() { + return returnStdout; + } + + public void setReturnStdout(String returnStdout) { + this.returnStdout = returnStdout; + } + + public String getReturnStderr() { + return returnStderr; + } + + public void setReturnStderr(String returnStderr) { + this.returnStderr = returnStderr; + } +} diff --git a/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/test/java/org/onap/ccsdk/sli/adaptors/ssh/SshConnectionMock.java b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/test/java/org/onap/ccsdk/sli/adaptors/ssh/SshConnectionMock.java new file mode 100644 index 000000000..db35ddbec --- /dev/null +++ b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/test/java/org/onap/ccsdk/sli/adaptors/ssh/SshConnectionMock.java @@ -0,0 +1,169 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed 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. + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * ============LICENSE_END========================================================= + */ + +package org.onap.ccsdk.sli.adaptors.ssh; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +public class SshConnectionMock implements SshConnection { + + private static final int DEF_SUCCESS_STATUS = 0; + + private final String host; + private final int port; + private final String username; + private final String password; + private final String keyFile; + private long timeout; + + private int returnStatus = DEF_SUCCESS_STATUS; + private String returnStdout; + private String returnStderr; + + private int connectCallCount = 0; + private int disconnectCallCount = 0; + private final List<String> executedCommands = new ArrayList<>(); + + public SshConnectionMock(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; + } + + + + @Override + public void connect() { + connectCallCount++; + } + + @Override + public void connectWithRetry() { + connectCallCount++; + } + + @Override + public void disconnect() { + disconnectCallCount++; + } + + @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) { + executedCommands.add(cmd); + try { + if((out != null) && (returnStdout != null)) { + out.write(returnStdout.getBytes()); + } + } catch(IOException e) { + throw new RuntimeException("Error writing to stdout output stream", e); + } + try { + if((err != null) && (returnStderr != null)) { + err.write(returnStderr.getBytes()); + } + } catch(IOException e) { + throw new RuntimeException("Error writing to stderr output stream", e); + } + return returnStatus; + } + + @Override + public void setExecTimeout(long timeout) { + this.timeout = timeout; + } + + public long getExecTimeout() { + return timeout; + } + + public String getHost() { + return host; + } + + public int getPort() { + return port; + } + + public String getUsername() { + return username; + } + + public String getPassword() { + return password; + } + + public String getKeyFile() { + return keyFile; + } + + public int getConnectCallCount() { + return connectCallCount; + } + + public int getDisconnectCallCount() { + return disconnectCallCount; + } + + public List<String> getExecutedCommands() { + return executedCommands; + } + + public int getReturnStatus() { + return returnStatus; + } + + public void setReturnStatus(int returnStatus) { + this.returnStatus = returnStatus; + } + + public String getReturnStdout() { + return returnStdout; + } + + public void setReturnStdout(String returnStdout) { + this.returnStdout = returnStdout; + } + + public String getReturnStderr() { + return returnStderr; + } + + public void setReturnStderr(String returnStderr) { + this.returnStderr = returnStderr; + } +} diff --git a/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/test/java/org/onap/ccsdk/sli/adaptors/ssh/TestSshAdaptorMock.java b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/test/java/org/onap/ccsdk/sli/adaptors/ssh/TestSshAdaptorMock.java new file mode 100644 index 000000000..53048986a --- /dev/null +++ b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/test/java/org/onap/ccsdk/sli/adaptors/ssh/TestSshAdaptorMock.java @@ -0,0 +1,77 @@ +/* +* ============LICENSE_START======================================================= +* ONAP : APPC +* ================================================================================ +* Copyright 2018 TechMahindra +*================================================================================= +* Licensed 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. +* ============LICENSE_END========================================================= +*/ +package org.onap.ccsdk.sli.adaptors.ssh; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; + +public class TestSshAdaptorMock { + private SshAdaptorMock sshAdaptorMock; + + @Before + public void setUp() { + sshAdaptorMock = new SshAdaptorMock(); + } + + @Test + public void testGetReturnStatus() { + sshAdaptorMock.setReturnStatus(200); + assertEquals(sshAdaptorMock.getReturnStatus(), 200); + } + + @Test + public void testGetReturnStdout() { + sshAdaptorMock.setReturnStdout("success"); + assertNotNull(sshAdaptorMock.getReturnStdout()); + assertEquals(sshAdaptorMock.getReturnStdout(), "success"); + } + + @Test + public void testGetReturnStderr() { + sshAdaptorMock.setReturnStderr("error"); + assertNotNull(sshAdaptorMock.getReturnStderr()); + assertEquals(sshAdaptorMock.getReturnStderr(), "error"); + } + + @Test + public void testGetConnectionMocks() { + sshAdaptorMock.setReturnStatus(200); + sshAdaptorMock.setReturnStdout("success"); + sshAdaptorMock.setReturnStderr("error"); + sshAdaptorMock.getConnection("localhost", 8080, "myUser", "myPassword"); + assertFalse(sshAdaptorMock.getConnectionMocks().isEmpty()); + assertNotNull(sshAdaptorMock.getConnectionMocks()); + } + + @Test + public void testGetConnection() { + SshAdaptorMock sshAdaptorMock = new SshAdaptorMock(); + sshAdaptorMock.setReturnStatus(200); + sshAdaptorMock.setReturnStdout("success"); + sshAdaptorMock.setReturnStderr("error"); + sshAdaptorMock.getConnection("localhost", 8080, "keyFile"); + assertFalse(sshAdaptorMock.getConnectionMocks().isEmpty()); + } + +} diff --git a/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/test/java/org/onap/ccsdk/sli/adaptors/ssh/TestSshConnectionDetails.java b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/test/java/org/onap/ccsdk/sli/adaptors/ssh/TestSshConnectionDetails.java new file mode 100644 index 000000000..044d952f8 --- /dev/null +++ b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/test/java/org/onap/ccsdk/sli/adaptors/ssh/TestSshConnectionDetails.java @@ -0,0 +1,63 @@ +/* +* ============LICENSE_START======================================================= +* ONAP : APPC +* ================================================================================ +* Copyright 2018 TechMahindra +*================================================================================= +* Licensed 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. +* ============LICENSE_END========================================================= +*/ +package org.onap.ccsdk.sli.adaptors.ssh; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +public class TestSshConnectionDetails { + + private SshConnectionDetails sshConnectionDetails; + + @Before + public void setUp() { + sshConnectionDetails = new SshConnectionDetails(); + } + + @Test + public void testGetHost() { + sshConnectionDetails.setHost("localhost"); + assertNotNull(sshConnectionDetails.getHost()); + assertEquals(sshConnectionDetails.getHost(), "localhost"); + } + + @Test + public void testGetPort() { + sshConnectionDetails.setPort(8080); + assertEquals(sshConnectionDetails.getPort(), 8080); + } + + @Test + public void testGetUsername() { + sshConnectionDetails.setUsername("username"); + assertNotNull(sshConnectionDetails.getUsername()); + assertEquals(sshConnectionDetails.getUsername(), "username"); + } + + @Test + public void testGetPassword() { + sshConnectionDetails.setPassword("password"); + assertNotNull(sshConnectionDetails.getPassword()); + assertEquals(sshConnectionDetails.getPassword(), "password"); + } +} diff --git a/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/test/java/org/onap/ccsdk/sli/adaptors/ssh/TestSshConnectionMock.java b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/test/java/org/onap/ccsdk/sli/adaptors/ssh/TestSshConnectionMock.java new file mode 100644 index 000000000..70665a555 --- /dev/null +++ b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/test/java/org/onap/ccsdk/sli/adaptors/ssh/TestSshConnectionMock.java @@ -0,0 +1,104 @@ +/* +* ============LICENSE_START======================================================= +* ONAP : APPC +* ================================================================================ +* Copyright 2018 TechMahindra +*================================================================================= +* Licensed 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. +* ============LICENSE_END========================================================= +*/ +package org.onap.ccsdk.sli.adaptors.ssh; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; + +public class TestSshConnectionMock { + + private SshConnectionMock sshConnectionMock; + @Before + public void setUp() { + sshConnectionMock=new SshConnectionMock("localhost", 8080, "myUser", "myPassword", "sampleKeyFile"); + } + + @Test + public void testGetHost() { + assertEquals("localhost", sshConnectionMock.getHost()); + } + + @Test + public void testGetPort() { + assertEquals(8080, sshConnectionMock.getPort()); + } + + @Test + public void testGetUsername() { + assertEquals("myUser", sshConnectionMock.getUsername()); + } + + @Test + public void testGetPassword() { + assertEquals("myPassword", sshConnectionMock.getPassword()); + } + + @Test + public void testKeyFile() { + assertEquals("sampleKeyFile", sshConnectionMock.getKeyFile()); + } + + @Test + public void testGetReturnStderr() { + sshConnectionMock.setReturnStderr("returnStderr"); + assertEquals("returnStderr", sshConnectionMock.getReturnStderr()); + } + @Test + public void testGetReturnStdout() { + sshConnectionMock.setReturnStdout("returnStdout"); + assertEquals("returnStdout", sshConnectionMock.getReturnStdout()); + } + @Test + public void testGetReturnStatus() { + sshConnectionMock.setReturnStatus(200); + assertEquals(200, sshConnectionMock.getReturnStatus()); + } + @Test + public void testGetExecutedCommands() { + sshConnectionMock.getExecutedCommands().add("cls"); + sshConnectionMock.getExecutedCommands().add("pwd"); + assertNotNull(sshConnectionMock.getExecutedCommands()); + assertFalse(sshConnectionMock.getExecutedCommands().isEmpty()); + } + + @Test + public void testExecTimeout() + { + sshConnectionMock.setExecTimeout(20); + assertEquals(20,sshConnectionMock.getExecTimeout()); + } + + @Test + public void testConnectCallCount() + { + assertEquals(0, sshConnectionMock.getConnectCallCount()); + } + + @Test + public void testDisconnectCallCount() + { + assertEquals(0, sshConnectionMock.getDisconnectCallCount()); + } + +} diff --git a/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/test/java/org/onap/ccsdk/sli/adaptors/ssh/TestSshDataAccessException.java b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/test/java/org/onap/ccsdk/sli/adaptors/ssh/TestSshDataAccessException.java new file mode 100644 index 000000000..f0fbd4d3f --- /dev/null +++ b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/test/java/org/onap/ccsdk/sli/adaptors/ssh/TestSshDataAccessException.java @@ -0,0 +1,64 @@ +/* +* ============LICENSE_START======================================================= +* ONAP : APPC +* ================================================================================ +* Copyright 2018 TechMahindra +*================================================================================= +* Licensed 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. +* ============LICENSE_END========================================================= +*/ +package org.onap.ccsdk.sli.adaptors.ssh; + +import org.junit.Assert; +import org.junit.Test; + +public class TestSshDataAccessException { + + @Test + public void testConstructorNoArgument() throws Exception { + SshDataAccessException sshDataAccessException = new SshDataAccessException(); + Assert.assertNull(sshDataAccessException.getCause()); + Assert.assertNull(sshDataAccessException.getLocalizedMessage()); + Assert.assertNull(sshDataAccessException.getMessage()); + } + + @Test + public void testConstructorWithMessaqge() throws Exception { + String message = "testing message"; + SshDataAccessException sshDataAccessException = new SshDataAccessException(message); + Assert.assertNull(sshDataAccessException.getCause()); + Assert.assertEquals(message, sshDataAccessException.getLocalizedMessage()); + Assert.assertEquals(message, sshDataAccessException.getMessage()); + } + + @Test + public void testConstructorWithThrowable() throws Exception { + String message = "testing message"; + Throwable throwable = new Throwable(message); + SshDataAccessException sshDataAccessException = new SshDataAccessException(throwable); + Assert.assertEquals(throwable, sshDataAccessException.getCause()); + Assert.assertTrue(sshDataAccessException.getLocalizedMessage().contains(message)); + Assert.assertTrue(sshDataAccessException.getMessage().contains(message)); + } + + @Test + public void testConstructorWithMessageAndThrowable() throws Exception { + String message = "testing message"; + String tMessage = "throwable message"; + Throwable throwable = new Throwable(tMessage); + SshDataAccessException sshDataAccessException =new SshDataAccessException(message, throwable); + Assert.assertEquals(throwable, sshDataAccessException.getCause()); + Assert.assertTrue(sshDataAccessException.getLocalizedMessage().contains(message)); + Assert.assertTrue(sshDataAccessException.getMessage().contains(message)); + } +} diff --git a/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/test/java/org/onap/ccsdk/sli/adaptors/ssh/TestSshException.java b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/test/java/org/onap/ccsdk/sli/adaptors/ssh/TestSshException.java new file mode 100644 index 000000000..5abc90d38 --- /dev/null +++ b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/test/java/org/onap/ccsdk/sli/adaptors/ssh/TestSshException.java @@ -0,0 +1,46 @@ +/* +* ============LICENSE_START======================================================= +* ONAP : APPC +* ================================================================================ +* Copyright 2018 TechMahindra +*================================================================================= +* Licensed 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. +* ============LICENSE_END========================================================= +*/ +package org.onap.ccsdk.sli.adaptors.ssh; + +import org.junit.Assert; +import org.junit.Test; + +public class TestSshException { + + @Test + public void testConstructorWithMessaqge() throws Exception { + String message = "testing message"; + SshException sshException = new SshException(message); + Assert.assertNull(sshException.getCause()); + Assert.assertEquals(message, sshException.getLocalizedMessage()); + Assert.assertEquals(message, sshException.getMessage()); + } + + @Test + public void testConstructorWithMessageAndThrowable() throws Exception { + String message = "testing message"; + String tMessage = "throwable message"; + Throwable throwable = new Throwable(tMessage); + SshException sshException = new SshException(message, throwable); + Assert.assertEquals(throwable, sshException.getCause()); + Assert.assertTrue(sshException.getLocalizedMessage().contains(message)); + Assert.assertTrue(sshException.getMessage().contains(message)); + } +} diff --git a/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/test/java/org/onap/ccsdk/sli/adaptors/ssh/sshd/SshAdaptorSample.java b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/test/java/org/onap/ccsdk/sli/adaptors/ssh/sshd/SshAdaptorSample.java new file mode 100644 index 000000000..e82d12fb9 --- /dev/null +++ b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/test/java/org/onap/ccsdk/sli/adaptors/ssh/sshd/SshAdaptorSample.java @@ -0,0 +1,57 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed 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. + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * ============LICENSE_END========================================================= + */ + +package org.onap.ccsdk.sli.adaptors.ssh.sshd; + +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; +import org.onap.ccsdk.sli.adaptors.ssh.SshAdaptor; +import org.onap.ccsdk.sli.adaptors.ssh.SshConnection; + +public class SshAdaptorSample { + + public static void main(String[] args) { + String host = "hostname"; + int port = 22; + String username = "user"; + String password = "secret"; + String command = "ls"; + + SshAdaptor sshAdaptor = new SshAdaptorSshd(); + SshConnection sshConnection = sshAdaptor.getConnection(host, port, username, password); + sshConnection.connect(); + try { + OutputStream stdout = new ByteArrayOutputStream(); + OutputStream stderr = new ByteArrayOutputStream(); + int status = sshConnection.execCommand(command, stdout, stderr); + if(status == 0) { + System.out.println("Command executed successfully. Output:\n" + stdout.toString()); + } else { + System.err.println("Command returned status " + status + ". Error:\n" + stderr.toString()); + } + } finally { + sshConnection.disconnect(); + } + } +} diff --git a/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/test/java/org/onap/ccsdk/sli/adaptors/ssh/sshd/SshAdaptorTest.java b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/test/java/org/onap/ccsdk/sli/adaptors/ssh/sshd/SshAdaptorTest.java new file mode 100644 index 000000000..5067debd5 --- /dev/null +++ b/adaptors/ssh-adaptor/ssh-adaptor-bundle/src/test/java/org/onap/ccsdk/sli/adaptors/ssh/sshd/SshAdaptorTest.java @@ -0,0 +1,265 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ================================================================================ + * Modifications Copyright (C) 2019 Ericsson + * ============================================================================= + * Licensed 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. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.ccsdk.sli.adaptors.ssh.sshd; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.net.BindException; +import java.nio.file.Paths; +import java.util.Collections; +import org.apache.sshd.common.util.OsUtils; +import org.apache.sshd.server.SshServer; +import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider; +import org.apache.sshd.server.scp.ScpCommandFactory; +import org.apache.sshd.server.subsystem.sftp.SftpSubsystemFactory; +import org.hamcrest.CoreMatchers; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.onap.ccsdk.sli.adaptors.ssh.SshAdaptor; +import org.onap.ccsdk.sli.adaptors.ssh.SshConnection; +import org.onap.ccsdk.sli.adaptors.ssh.SshException; + +import static org.junit.Assert.assertTrue; + +@Ignore +public class SshAdaptorTest { + + private static final boolean START_SERVER = true; + private static final String SSH_HOST = "localhost"; + private static final int SSH_PORT = 2222; + private static final String SSH_USERNAME = "test"; + private static final String SSH_PASSWORD = "test"; + private static final String F_TEST_CMD = "ping -%c 4 %s"; + + private int sshPort = SSH_PORT; + private SshServer sshd; + private final SshAdaptor sshAdaptor = new SshAdaptorSshd(); + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void testExecute() { + String cmd = String.format(F_TEST_CMD, OsUtils.isUNIX() ? 'c' : 'n', "localhost"); + SshConnection sshConnection = connect(); + if (sshConnection == null) return; + try { + System.out.println("SSH client connected. Server port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]"); + ByteArrayOutputStream stdout = new ByteArrayOutputStream(); + ByteArrayOutputStream stderr = new ByteArrayOutputStream(); + int status = execCmd(sshConnection, cmd, stdout, stderr, false); + Assert.assertEquals(stdout + ". " + stderr, 0, status); + } finally { + disconnect(sshConnection); + } + } + + @Test + public void testExecuteWithPty() { + String cmd = String.format(F_TEST_CMD, OsUtils.isUNIX() ? 'c' : 'n', "localhost"); + SshConnection sshConnection = connect(); + if (sshConnection == null) return; + try { + System.out.println("SSH client connected. Server port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]"); + ByteArrayOutputStream stdout = new ByteArrayOutputStream(); + int status = execCmd(sshConnection, cmd, stdout, null, true); + Assert.assertEquals(stdout + ". " + stdout, 0, status); + } finally { + disconnect(sshConnection); + } + } + + @Test + public void testExecuteInvalidCommand() { + String cmd = String.format(F_TEST_CMD, OsUtils.isUNIX() ? 'c' : 'n', "nosuchhost"); + SshConnection sshConnection = connect(); + if (sshConnection == null) return; + try { + ByteArrayOutputStream stdout = new ByteArrayOutputStream(); + ByteArrayOutputStream stderr = new ByteArrayOutputStream(); + int status = execCmd(sshConnection, cmd, stdout, stderr, false); + Assert.assertNotEquals(stdout + ". " + stderr, 0, status); + } finally { + disconnect(sshConnection); + } + } + + @Test + public void testWrongUsername() { + thrown.expect(SshException.class); + thrown.expectMessage(CoreMatchers.containsString("Authentication failed")); + disconnect(invalidConnect("WrongUsername", SSH_PASSWORD)); + } + + @Test + public void testWrongPassword() { + thrown.expect(SshException.class); + thrown.expectMessage(CoreMatchers.containsString("Authentication failed")); + disconnect(invalidConnect(SSH_USERNAME, "WrongPassword")); + } + + + + @Test + public void testInstantiateWithKeyFile() { + SshConnection connection = sshAdaptor.getConnection(null, 0, null); + assertTrue(connection instanceof SshConnection); + } + + /* + @Test + public void testConnectWithRetry() { + SshConnection connection = Mockito.spy(sshAdaptor.getConnection( + SSH_HOST, SSH_PORT, SSH_USERNAME, SSH_PASSWORD)); + connection.setExecTimeout(1); + connection.connectWithRetry(); + Mockito.verify(connection).connect(); + } + + @Test + public void testToString() { + SshConnection connection = Mockito.spy(sshAdaptor.getConnection( + SSH_HOST, SSH_PORT, SSH_USERNAME, SSH_PASSWORD)); + assertEquals(SSH_USERNAME + "@" + SSH_HOST, connection.toString()); + String s = null; + Whitebox.setInternalState(connection, "username", s); + assertEquals(SSH_HOST, connection.toString()); + } + */ + + @Before + public void beforeTest() throws IOException { + if (START_SERVER) { + startServer(); + } + } + + @After + public void afterTest() { + stopServer(); + } + + private SshConnection connect() { + SshConnection sshConnection = sshAdaptor.getConnection(SSH_HOST, sshPort, SshAdaptorTest.SSH_USERNAME, SshAdaptorTest.SSH_PASSWORD); + try { + /* move connect to inside try block, in case ssh connection to localhost is + * blocked by localhost ssh policy */ + sshConnection.connect(); + System.out.println("SSH client connected. Server port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]"); + } catch (Exception e) { + sshConnection = null; + System.out.println("SSH client connect failed. Server port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]"); + } + return sshConnection; + } + + private SshConnection invalidConnect(String username, String password) { + SshConnection sshConnection = sshAdaptor.getConnection(SSH_HOST, sshPort, username, password); + sshConnection.connect(); + System.out.println("SSH client connected. Server port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]"); + return sshConnection; + } + + private void disconnect(SshConnection sshConnection) { + if (sshConnection != null) { + sshConnection.disconnect(); + System.out.println("SSH client disconnected. Server port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]"); + } +} + + private int execCmd(SshConnection sshConnection, String cmd, OutputStream stdout, OutputStream stderr, boolean usePty) { + System.out.println("=> Running command [" + cmd + "] over SSH"); + int status; + if (usePty) { + status = sshConnection.execCommandWithPty(cmd, stdout); + } else { + status = sshConnection.execCommand(cmd, stdout, stderr); + } + System.out.println("=> Command [" + cmd + "] status is [" + status + "], stdout is [" + stdout + "], stderr is [" + stderr + "]"); + return status; + } + + private void startServer() throws IOException { + sshd = SshServer.setUpDefaultServer(); + sshd.setSubsystemFactories(Collections.singletonList(new SftpSubsystemFactory())); + sshd.setCommandFactory(new ScpCommandFactory()); + + sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(Paths.get(System.getProperty("java.io.tmpdir") + "/key.ser"))); + sshd.setPasswordAuthenticator((username, password, session) -> (SSH_USERNAME.equals(username) && SSH_PASSWORD.equals(password))); + sshd.setPublickeyAuthenticator((username, key, session) -> false); + sshd.getProperties().put(SshServer.WELCOME_BANNER, "Welcome to SSHD\n"); + startServer0(); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + // ignore + } + } + + private void startServer0() throws IOException { + boolean serverStarted = false; + IOException exception = null; + while (!serverStarted && (sshPort < Integer.MAX_VALUE)) { + try { + System.out.println("Starting SSH server on port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]"); + sshd.setPort(sshPort); + sshd.start(); + serverStarted = true; + } catch (BindException e) { + System.err.println("Cannot start SSH server on port [" + sshPort + "]. " + e.getMessage()); + if (exception == null) { + // store first thrown exception - will be thrown if cannot start the server + exception = e; + } + sshPort++; + } + } + if (!serverStarted && exception != null) { + throw exception; + } + System.out.println("SSH server started on port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]"); + } + + private void stopServer() { + try { + if (sshd != null) { + sshd.stop(); + System.out.println("SSH server stopped on port [" + sshPort + "]. [" + getClass().getName() + "#" + System.identityHashCode(this) + "]"); + } + } catch (IOException e) { + System.err.println("=> IO Error stopping SSH server."); + e.printStackTrace(); + } finally { + sshd = null; + } + } +} |