summaryrefslogtreecommitdiffstats
path: root/sshapi-call-node/provider/src/main/java
diff options
context:
space:
mode:
authorDan Timoney <dt5972@att.com>2018-07-27 20:52:48 +0000
committerGerrit Code Review <gerrit@onap.org>2018-07-27 20:52:48 +0000
commitbace9b5f98bfef3168134a747c8795196ce9a723 (patch)
tree707bcf95399eb7f875581439b1b40e99f13f0655 /sshapi-call-node/provider/src/main/java
parentbe3d4606d9627e5dfb461b72140f7be52e1c7776 (diff)
parent8b39ca99c8a49197b05f8fea7de9a1606c810e63 (diff)
Merge "SSHApiCallNode sshExec API Impl"
Diffstat (limited to 'sshapi-call-node/provider/src/main/java')
-rw-r--r--sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/SshApiCallNode.java226
-rw-r--r--sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/impl/AuthType.java19
-rw-r--r--sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/impl/SshapiCallNodeImpl.java43
-rw-r--r--sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/AuthType.java (renamed from sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/RetryException.java)21
-rw-r--r--sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/Format.java (renamed from sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/impl/Format.java)2
-rw-r--r--sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/JsonParser.java6
-rw-r--r--sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/Parameters.java (renamed from sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/impl/Parameters.java)15
-rw-r--r--sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/ParseParam.java274
-rw-r--r--sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/RetryPolicy.java62
-rw-r--r--sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/RetryPolicyStore.java56
10 files changed, 494 insertions, 230 deletions
diff --git a/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/SshApiCallNode.java b/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/SshApiCallNode.java
index 4efddec80..e4b082cda 100644
--- a/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/SshApiCallNode.java
+++ b/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/SshApiCallNode.java
@@ -1,10 +1,11 @@
/*-
* ============LICENSE_START=======================================================
- * openECOMP : SDN-C
+ * ONAP : APPC
* ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights
- * reserved.
+ * Copyright (C) 2017-2018 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
@@ -16,36 +17,89 @@
* 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.plugins.sshapicall;
-import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+//import com.fasterxml.jackson.databind.ObjectMapper;
+
+import java.io.ByteArrayOutputStream;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import com.google.common.base.Strings;
+import org.json.JSONObject;
+import org.onap.appc.adapter.ssh.SshAdapter;
+import org.onap.appc.adapter.ssh.SshConnection;
import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
-import java.io.OutputStream;
-import java.util.Map;
+import org.onap.ccsdk.sli.plugins.sshapicall.model.AuthType;
+import org.onap.ccsdk.sli.plugins.sshapicall.model.Parameters;
+import org.onap.ccsdk.sli.plugins.sshapicall.model.ParseParam;
+
+
+public class SshApiCallNode implements SvcLogicJavaPlugin {
+
+ private static final EELFLogger logger = EELFManager.getInstance().getApplicationLogger();
+
+ /**
+ * Output parameter - SSH command execution status.
+ */
+ String PARAM_OUT_status = "status";
+
+ /**
+ * Output parameter - content of SSH command stdout.
+ */
+ String PARAM_OUT_stdout = "stdout";
+
+ /**
+ * Output parameter - content of SSH command stderr.
+ */
+ String PARAM_OUT_stderr = "stderr";
+
+ /**
+ * Default success status.
+ */
+ int DEF_SUCCESS_STATUS = 0;
+
+ private SshAdapter sshAdapter;
-public interface SshApiCallNode extends SvcLogicJavaPlugin {
+ public void setSshAdapter(SshAdapter sshAdapter) {
+ this.sshAdapter = sshAdapter;
+ }
/**
* Allows Directed Graphs the ability to interact with SSH APIs.
- * @param paramMap HashMap<String,String> of parameters passed by the DG to this function
+ * @param params HashMap<String,String> of parameters passed by the DG to this function
* <table border="1">
* <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th><th>example values</th></thead>
* <tbody>
* <tr><td>templateFileName</td><td>Optional</td><td>full path to template file that can be used to build a request</td><td>/sdncopt/bvc/sshapi/templates/vnf_service-configuration-operation_minimal.json</td></tr>
- * <tr><td>sshapiUrl</td><td>Mandatory</td><td>url to make the SSH connection request to.</td></tr>
- * <tr><td>sshapiUser</td><td>Optional</td><td>user name to use for ssh basic authentication</td><td>sdnc_ws</td></tr>
- * <tr><td>sshapiPassword</td><td>Optional</td><td>unencrypted password to use for ssh basic authentication</td><td>plain_password</td></tr>
- * <tr><td>sshKey</td><td>Optional</td><td>Consumer SSH key to use for ssh authentication</td><td>plain_key</td></tr>
- * <tr><td>cmd</td><td>Mandatory</td><td>ssh command to be executed on the server.</td><td>get post put delete patch</td></tr>
- * <tr><td>responsePrefix</td><td>Optional</td><td>location the response will be written to in context memory</td><td>tmp.sshapi.result</td></tr>
+ * <tr><td>Url</td><td>Mandatory</td><td>url to make the SSH connection request to.</td></tr>
+ * <tr><td>Port</td><td>Mandatory</td><td>port to make the SSH connection request to.</td></tr>
+ * <tr><td>User</td><td>Optional</td><td>user name to use for ssh basic authentication</td><td>sdnc_ws</td></tr>
+ * <tr><td>Password</td><td>Optional</td><td>unencrypted password to use for ssh basic authentication</td><td>plain_password</td></tr>
+ * <tr><td>SshKey</td><td>Optional</td><td>Consumer SSH key to use for ssh authentication</td><td>plain_key</td></tr>
+ * <tr><td>ExecTimeout</td><td>Optional</td><td>SSH command execution timeout</td><td>plain_key</td></tr>
+ * <tr><td>Retry</td><td>Optional</td><td>Make ssh connection with default retry policy</td><td>plain_key</td></tr>
+ * <tr><td>Cmd</td><td>Mandatory</td><td>ssh command to be executed on the server.</td><td>get post put delete patch</td></tr>
+ * <tr><td>ResponsePrefix</td><td>Optional</td><td>location the response will be written to in context memory</td><td>tmp.sshapi.result</td></tr>
+ * <tr><td>ResponseType</td><td>Optional</td><td>If we know the response is to be in a specific format (supported are JSON, XML and NONE) </td><td>tmp.sshapi.result</td></tr>
* <tr><td>listName[i]</td><td>Optional</td><td>Used for processing XML responses with repeating elements.</td>vpn-information.vrf-details<td></td></tr>
- * <tr><td>convertResponse </td><td>Optional</td><td>whether the response should be converted</td><td>true or false</td></tr>
- * <tr><td>dumpHeaders</td><td>Optional</td><td>when true writes ssh response content to context memory</td><td>true or false</td></tr>
- * <tr><td>returnRequestPayload</td><td>Optional</td><td>used to return payload built in the request</td><td>true or false</td></tr>
+ * <tr><td>ConvertResponse </td><td>Optional</td><td>whether the response should be converted</td><td>true or false</td></tr>
+ * <tr><td>AuthType</td><td>Optional</td><td>Type of authentiation to be used BASIC or sshKey based</td><td>true or false</td></tr>
+ * <tr><td>EnvParameters</td><td>Optional</td><td>A JSON dictionary which should list key value pairs to be passed to the command execution.
+ * These values would correspond to instance specific parameters that a command may need to execute an action.</td></tr>
+ * <tr><td>FileParameters</td><td>Optional</td><td>A JSON dictionary where keys are filenames and values are contents of files.
+ * The SSH Server will utilize this feature to generate files with keys as filenames and values as content.
+ * This attribute can be used to generate files that a command may require as part of execution.</td></tr>
* </tbody>
* </table>
* Exec remote command over SSH. Return command execution status.
@@ -53,32 +107,140 @@ public interface SshApiCallNode extends SvcLogicJavaPlugin {
*
* @param ctx Reference to context memory
*/
- void execCommand(Map<String, String> paramMap, SvcLogicContext ctx) throws SvcLogicException;
+
+ public void execCommand(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
+ ParseParam parser = new ParseParam();
+ Parameters p = parser.getParameters(params);
+ logger.debug("=> Connecting to SSH server...");
+ SshConnection sshConnection = getSshConnection(p);
+ sshConnection.connect();
+ try {
+ logger.debug("=> Connected to SSH server...");
+ logger.debug("=> Running SSH command...");
+ sshConnection.setExecTimeout(p.sshExecTimeout);
+ ByteArrayOutputStream stdout = new ByteArrayOutputStream();
+ ByteArrayOutputStream stderr = new ByteArrayOutputStream();
+ int status = sshConnection.execCommand(parser.makeCommand(params), stdout, stderr);
+ String stdoutRes = stdout.toString();
+ String stderrRes = stderr.toString();
+ logger.debug("=> executed SSH command");
+
+ if(status == DEF_SUCCESS_STATUS) {
+ parser.parseOutput(ctx, stdoutRes);
+ }
+ ctx.setAttribute(PARAM_OUT_status, String.format("%01d", status));
+ ctx.setAttribute(PARAM_OUT_stdout, stdoutRes);
+ ctx.setAttribute(PARAM_OUT_stderr, stderrRes);
+ } finally {
+ sshConnection.disconnect();
+ }
+ }
+
+ private SshConnection getSshConnection(Parameters p) throws SvcLogicException{
+ if (p.authtype == AuthType.BASIC)
+ return sshAdapter.getConnection(p.sshapiUrl, p.sshapiPort, p.sshapiUser, p.sshapiPassword);
+ // This is not supported yet in the API, patch has already been added to APPC
+ else if (p.authtype == AuthType.KEY){
+ //return sshAdapter.getConnection(p.sshapiUrl, p.sshapiPort, p.sshKey);
+ throw new SvcLogicException("SSH Key based Auth method not supported");
+ }
+ else if (p.authtype == AuthType.NONE){
+ //return sshAdapter.getConnection(p.sshapiUrl, p.sshapiPort, p.sshKey);
+ throw new SvcLogicException("SSH Auth type required, BASIC auth in support");
+ }
+ else if (p.authtype == AuthType.UNSPECIFIED){
+ if (p.sshapiUser != null && p.sshapiPassword != null)
+ return sshAdapter.getConnection(p.sshapiUrl, p.sshapiPort, p.sshapiUser, p.sshapiPassword);
+ else if (p.sshKey != null)
+ throw new SvcLogicException("SSH Key based Auth method not supported");
+ }
+ throw new SvcLogicException("SSH Auth type required, BASIC auth in support");
+ }
+
/**
* Allows Directed Graphs the ability to interact with SSH APIs.
- * @param paramMap HashMap<String,String> of parameters passed by the DG to this function
+ * @param params HashMap<String,String> of parameters passed by the DG to this function
* <table border="1">
* <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th><th>example values</th></thead>
* <tbody>
* <tr><td>templateFileName</td><td>Optional</td><td>full path to template file that can be used to build a request</td><td>/sdncopt/bvc/sshapi/templates/vnf_service-configuration-operation_minimal.json</td></tr>
- * <tr><td>sshapiUrl</td><td>Mandatory</td><td>url to make the SSH connection request to.</td></tr>
- * <tr><td>sshapiUser</td><td>Optional</td><td>user name to use for ssh basic authentication</td><td>sdnc_ws</td></tr>
- * <tr><td>sshapiPassword</td><td>Optional</td><td>unencrypted password to use for ssh basic authentication</td><td>plain_password</td></tr>
- * <tr><td>sshKey</td><td>Optional</td><td>Consumer SSH key to use for ssh authentication</td><td>plain_key</td></tr>
- * <tr><td>cmd</td><td>Mandatory</td><td>ssh command to be executed on the server.</td><td>get post put delete patch</td></tr>
- * <tr><td>responsePrefix</td><td>Optional</td><td>location the response will be written to in context memory</td><td>tmp.sshapi.result</td></tr>
+ * <tr><td>Url</td><td>Mandatory</td><td>url to make the SSH connection request to.</td></tr>
+ * <tr><td>Port</td><td>Mandatory</td><td>port to make the SSH connection request to.</td></tr>
+ * <tr><td>User</td><td>Optional</td><td>user name to use for ssh basic authentication</td><td>sdnc_ws</td></tr>
+ * <tr><td>Password</td><td>Optional</td><td>unencrypted password to use for ssh basic authentication</td><td>plain_password</td></tr>
+ * <tr><td>SshKey</td><td>Optional</td><td>Consumer SSH key to use for ssh authentication</td><td>plain_key</td></tr>
+ * <tr><td>ExecTimeout</td><td>Optional</td><td>SSH command execution timeout</td><td>plain_key</td></tr>
+ * <tr><td>Retry</td><td>Optional</td><td>Make ssh connection with default retry policy</td><td>plain_key</td></tr>
+ * <tr><td>Cmd</td><td>Mandatory</td><td>ssh command to be executed on the server.</td><td>get post put delete patch</td></tr>
+ * <tr><td>ResponsePrefix</td><td>Optional</td><td>location the response will be written to in context memory</td><td>tmp.sshapi.result</td></tr>
+ * <tr><td>ResponseType</td><td>Optional</td><td>If we know the response is to be in a specific format (supported are JSON, XML and NONE) </td><td>tmp.sshapi.result</td></tr>
* <tr><td>listName[i]</td><td>Optional</td><td>Used for processing XML responses with repeating elements.</td>vpn-information.vrf-details<td></td></tr>
- * <tr><td>convertResponse </td><td>Optional</td><td>whether the response should be converted</td><td>true or false</td></tr>
- * <tr><td>dumpHeaders</td><td>Optional</td><td>when true writes ssh response content to context memory</td><td>true or false</td></tr>
- * <tr><td>returnRequestPayload</td><td>Optional</td><td>used to return payload built in the request</td><td>true or false</td></tr>
+ * <tr><td>ConvertResponse </td><td>Optional</td><td>whether the response should be converted</td><td>true or false</td></tr>
+ * <tr><td>AuthType</td><td>Optional</td><td>Type of authentiation to be used BASIC or sshKey based</td><td>true or false</td></tr>
+ * <tr><td>EnvParameters</td><td>Optional</td><td>A JSON dictionary which should list key value pairs to be passed to the command execution.
+ * These values would correspond to instance specific parameters that a command may need to execute an action.</td></tr>
+ * <tr><td>FileParameters</td><td>Optional</td><td>A JSON dictionary where keys are filenames and values are contents of files.
+ * The SSH Server will utilize this feature to generate files with keys as filenames and values as content.
+ * This attribute can be used to generate files that a command may require as part of execution.</td></tr>
* </tbody>
* </table>
- * 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.
+ * Exec remote command over SSH. Return command execution status.
+ * Command output is written to out or err stream.
*
- * @param ctx Reference to context memory
+ * @param ctx Reference to context memory
+ */
+
+ public void execWithStatusCheck(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
+ execCommand(params, ctx);
+ int status = Integer.parseInt(ctx.getAttribute(PARAM_OUT_status));
+ if(status != DEF_SUCCESS_STATUS) {
+ StringBuilder errmsg = new StringBuilder();
+ errmsg.append("SSH command returned error status [").append(status).append(']');
+ String stderrRes = ctx.getAttribute(PARAM_OUT_stderr);
+ String stdoutRes = ctx.getAttribute(PARAM_OUT_stdout);
+ if((stderrRes != null) && !stderrRes.isEmpty()) {
+ errmsg.append(". Error: [").append(stderrRes).append(']');
+ } else if ((stdoutRes != null) && !stdoutRes.isEmpty()) {
+ errmsg.append(". Error: [").append(stdoutRes).append(']');
+ }
+ throw new SvcLogicException(errmsg.toString());
+ }
+ }
+
+ /**
+ * Allows Directed Graphs the ability to interact with SSH APIs.
+ * @param params HashMap<String,String> of parameters passed by the DG to this function
+ * <table border="1">
+ * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th><th>example values</th></thead>
+ * <tbody>
+ * <tr><td>templateFileName</td><td>Optional</td><td>full path to template file that can be used to build a request</td><td>/sdncopt/bvc/sshapi/templates/vnf_service-configuration-operation_minimal.json</td></tr>
+ * <tr><td>Url</td><td>Mandatory</td><td>url to make the SSH connection request to.</td></tr>
+ * <tr><td>Port</td><td>Mandatory</td><td>port to make the SSH connection request to.</td></tr>
+ * <tr><td>User</td><td>Optional</td><td>user name to use for ssh basic authentication</td><td>sdnc_ws</td></tr>
+ * <tr><td>Password</td><td>Optional</td><td>unencrypted password to use for ssh basic authentication</td><td>plain_password</td></tr>
+ * <tr><td>SshKey</td><td>Optional</td><td>Consumer SSH key to use for ssh authentication</td><td>plain_key</td></tr>
+ * <tr><td>ExecTimeout</td><td>Optional</td><td>SSH command execution timeout</td><td>plain_key</td></tr>
+ * <tr><td>Retry</td><td>Optional</td><td>Make ssh connection with default retry policy</td><td>plain_key</td></tr>
+ * <tr><td>Cmd</td><td>Mandatory</td><td>ssh command to be executed on the server.</td><td>get post put delete patch</td></tr>
+ * <tr><td>ResponsePrefix</td><td>Optional</td><td>location the response will be written to in context memory</td><td>tmp.sshapi.result</td></tr>
+ * <tr><td>ResponseType</td><td>Optional</td><td>If we know the response is to be in a specific format (supported are JSON, XML and NONE) </td><td>tmp.sshapi.result</td></tr>
+ * <tr><td>listName[i]</td><td>Optional</td><td>Used for processing XML responses with repeating elements.</td>vpn-information.vrf-details<td></td></tr>
+ * <tr><td>ConvertResponse </td><td>Optional</td><td>whether the response should be converted</td><td>true or false</td></tr>
+ * <tr><td>AuthType</td><td>Optional</td><td>Type of authentiation to be used BASIC or sshKey based</td><td>true or false</td></tr>
+ * <tr><td>EnvParameters</td><td>Optional</td><td>A JSON dictionary which should list key value pairs to be passed to the command execution.
+ * These values would correspond to instance specific parameters that a command may need to execute an action.</td></tr>
+ * <tr><td>FileParameters</td><td>Optional</td><td>A JSON dictionary where keys are filenames and values are contents of files.
+ * The SSH Server will utilize this feature to generate files with keys as filenames and values as content.
+ * This attribute can be used to generate files that a command may require as part of execution.</td></tr>
+ * </tbody>
+ * </table>
+ * Exec remote command over SSH. Return command execution status.
+ * Command output is written to out or err stream.
+ *
+ * @param ctx Reference to context memory
*/
- void execCommandWithPty(Map<String, String> paramMap, SvcLogicContext ctx) throws SvcLogicException ;
+ public void execCommandWithPty(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
+ }
}
diff --git a/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/impl/AuthType.java b/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/impl/AuthType.java
deleted file mode 100644
index 308162271..000000000
--- a/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/impl/AuthType.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.onap.ccsdk.sli.plugins.sshapicall.impl;
-
-public enum AuthType {
- NONE, BASIC, DIGEST, OAUTH, Unspecified;
-
- public static AuthType fromString(String s) {
- if ("basic".equalsIgnoreCase(s))
- return BASIC;
- if ("digest".equalsIgnoreCase(s))
- return DIGEST;
- if ("oauth".equalsIgnoreCase(s))
- return OAUTH;
- if ("none".equalsIgnoreCase(s))
- return NONE;
- if ("unspecified".equalsIgnoreCase(s))
- return Unspecified;
- throw new IllegalArgumentException("Invalid value for format: " + s);
- }
-}
diff --git a/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/impl/SshapiCallNodeImpl.java b/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/impl/SshapiCallNodeImpl.java
deleted file mode 100644
index 9283b8b5f..000000000
--- a/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/impl/SshapiCallNodeImpl.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * openECOMP : SDN-C
- * ================================================================================
- * * Copyright (C) 2017 AT&T Intellectual Property.
- * ================================================================================
- * Copyright (C) 2018 Samsung Electronics. 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.plugins.sshapicall.impl;
-
-import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
-import org.onap.ccsdk.sli.core.sli.SvcLogicException;
-import org.onap.ccsdk.sli.plugins.sshapicall.SshApiCallNode;
-
-import java.io.OutputStream;
-import java.util.Map;
-
-public class SshapiCallNodeImpl implements SshApiCallNode {
- @Override
- public void execCommand(Map<String, String> paramMap, SvcLogicContext ctx) throws SvcLogicException {
- //TODO: Implementation
- }
-
- @Override
- public void execCommandWithPty(Map<String, String> paramMap, SvcLogicContext ctx) throws SvcLogicException {
- //TODO: Implementation
- }
-}
diff --git a/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/RetryException.java b/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/AuthType.java
index 9a1d3a312..2ec48c70c 100644
--- a/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/RetryException.java
+++ b/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/AuthType.java
@@ -7,12 +7,13 @@
* Copyright (C) 2018 Samsung Electronics. 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.
@@ -23,10 +24,18 @@
package org.onap.ccsdk.sli.plugins.sshapicall.model;
-public class RetryException extends Exception {
+public enum AuthType {
+ NONE, BASIC, KEY, UNSPECIFIED;
- public RetryException(String message) {
- super(message);
+ public static AuthType fromString(String s) {
+ if ("basic".equalsIgnoreCase(s))
+ return BASIC;
+ if ("key".equalsIgnoreCase(s))
+ return KEY;
+ if ("unspecified".equalsIgnoreCase(s))
+ return UNSPECIFIED;
+ if ("none".equalsIgnoreCase(s))
+ return NONE;
+ throw new IllegalArgumentException("Invalid value for format: " + s);
}
-
}
diff --git a/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/impl/Format.java b/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/Format.java
index 75604de66..e50a96c6c 100644
--- a/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/impl/Format.java
+++ b/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/Format.java
@@ -22,7 +22,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.ccsdk.sli.plugins.sshapicall.impl;
+package org.onap.ccsdk.sli.plugins.sshapicall.model;
public enum Format {
JSON, XML, NONE;
diff --git a/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/JsonParser.java b/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/JsonParser.java
index e840053f8..f40f1ad71 100644
--- a/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/JsonParser.java
+++ b/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/JsonParser.java
@@ -47,11 +47,10 @@ public final class JsonParser {
@SuppressWarnings("unchecked")
public static Map<String, String> convertToProperties(String s)
- throws SvcLogicException {
+ throws JSONException {
checkNotNull(s, "Input should not be null.");
- try {
JSONObject json = new JSONObject(s);
Map<String, Object> wm = new HashMap<>();
Iterator<String> ii = json.keys();
@@ -89,8 +88,5 @@ public final class JsonParser {
}
}
return mm;
- } catch (JSONException e) {
- throw new SvcLogicException("Unable to convert JSON to properties" + e.getLocalizedMessage(), e);
- }
}
}
diff --git a/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/impl/Parameters.java b/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/Parameters.java
index a392cc73c..a22da5bcb 100644
--- a/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/impl/Parameters.java
+++ b/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/Parameters.java
@@ -21,22 +21,25 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.ccsdk.sli.plugins.sshapicall.impl;
+package org.onap.ccsdk.sli.plugins.sshapicall.model;
import java.util.Set;
public class Parameters {
- public String templateFileName;
public String sshapiUrl;
+ public int sshapiPort;
public String sshapiUser;
public String sshapiPassword;
- public Format sshKey;
+ public String sshKey;
+ public long sshExecTimeout;
+ public String sshFileParameters;
+ public String sshEnvParameters;
+ public boolean sshWithRetry;
public String cmd;
public String responsePrefix;
+ public Format responseType;
+
public Set<String> listNameList;
public boolean convertResponse;
- public Boolean dumpHeaders;
- public String requestBody;
public AuthType authtype;
- public Boolean returnRequestPayload;
}
diff --git a/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/ParseParam.java b/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/ParseParam.java
new file mode 100644
index 000000000..caf49ef91
--- /dev/null
+++ b/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/ParseParam.java
@@ -0,0 +1,274 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * * Copyright (C) 2017 AT&T Intellectual Property.
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. 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.plugins.sshapicall.model;
+
+import com.google.common.base.Strings;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+public class ParseParam {
+ private static final Logger log = LoggerFactory.getLogger(ParseParam.class);
+ /**
+ * Default SSH command timeout
+ */
+ private long dEF_timeout = 12000;
+ /**
+ * Default SSH connection port.
+ */
+ private int dEF_port = 22;
+ /**
+ * Default SSH command timeout
+ */
+ private final String FILE_PARAMETERS_OPT_KEY = "FileParameters";
+ /**
+ * Default SSH connection port.
+ */
+ private final String ENV_PARAMETERS_OPT_KEY = "EnvParameters";
+ private Parameters p = new Parameters();
+
+ public Parameters getParameters(Map<String, String> paramMap) throws SvcLogicException {
+ p.sshapiUrl = parseParam(paramMap, "Url", true, null);
+ p.sshapiPort = Integer.parseInt(parseParam(paramMap, "Port", true, Integer.toString(dEF_port)));
+ p.sshapiUser = parseParam(paramMap, "User", false, null);
+ p.sshapiPassword = parseParam(paramMap, "Password", false, null);
+ p.sshKey = parseParam(paramMap, "SshKey", false, null);
+ p.sshExecTimeout = Long.parseLong(parseParam(paramMap, "ExecTimeout", false, Long.toString(dEF_timeout)));
+ p.sshWithRetry = Boolean.valueOf(parseParam(paramMap, "Retry", false, "false"));
+ p.cmd = parseParam(paramMap, "Cmd", true, null);
+ p.responsePrefix = parseParam(paramMap, "ResponsePrefix", false, null);
+ p.responseType = Format.fromString(parseParam(paramMap, "ResponseType", false, "none"));
+ p.listNameList = getListNameList(paramMap);
+ p.convertResponse = Boolean.valueOf(parseParam(paramMap, "ConvertResponse", false, "true"));
+ p.authtype = AuthType.fromString(parseParam(paramMap, "AuthType", false, "unspecified"));
+
+ return p;
+ }
+
+ public void parseOutput (SvcLogicContext ctx, String outMessage) throws SvcLogicException {
+ if (p.convertResponse) {
+ if (p.responseType == Format.NONE) {
+ classifyOutput(ctx, outMessage);
+ } else if (p.responseType == Format.JSON) {
+ classifyOutput(ctx, outMessage);
+ } else if (p.responseType == Format.XML) {
+ classifyOutput(ctx, outMessage, p.listNameList);
+ }
+ }
+ }
+
+ private void classifyOutput(SvcLogicContext ctx, String outMessage, Set<String> listNameList) throws SvcLogicException {
+ Map<String, String> mm = XmlParser.convertToProperties(outMessage, p.listNameList);
+ toCtx (ctx, mm);
+ }
+
+ private void toCtx (SvcLogicContext ctx, Map<String, String> mm) {
+ if (mm != null) {
+ for (Map.Entry<String, String> entry : mm.entrySet()) {
+ if (p.responsePrefix != null) {
+ ctx.setAttribute(p.responsePrefix + "." + entry.getKey(), entry.getValue());
+ log.info("+++ " + p.responsePrefix + "." + entry.getKey() + ": [" + entry.getValue() + "]");
+ } else {
+ ctx.setAttribute(entry.getKey(), entry.getValue());
+ log.info("+++ " + entry.getKey() + ": [" + entry.getValue() + "]");
+ }
+ }
+ }
+ }
+
+ private void classifyOutput(SvcLogicContext ctx, String outMessage) throws SvcLogicException {
+ try {
+ Map<String, String> mm = JsonParser.convertToProperties(outMessage);
+ toCtx (ctx, mm);
+ } catch (org.codehaus.jettison.json.JSONException e) {
+ log.info("Output not in JSON format");
+ putToProperties(ctx, p.responsePrefix);
+ } catch (Exception e) {
+ throw new SvcLogicException("error parsing response file");
+ }
+ }
+
+ private void putToProperties(SvcLogicContext ctx, String outMessage) throws SvcLogicException {
+
+ try {
+ Properties prop = new Properties();
+ prop.load(new ByteArrayInputStream(outMessage.getBytes(StandardCharsets.UTF_8)));
+ for (Object key : prop.keySet()) {
+ String name = (String) key;
+ String value = prop.getProperty(name);
+ if (value != null && value.trim().length() > 0) {
+ if (p.responsePrefix != null) {
+ ctx.setAttribute(p.responsePrefix + "." + name, value.trim());
+ log.info("+++ " + p.responsePrefix + "." + name + ": [" + value + "]");
+ } else {
+ ctx.setAttribute(name, value.trim());
+ log.info("+++ " + name + ": [" + value + "]");
+ }
+ }
+ }
+ } catch (Exception e) {
+ throw new SvcLogicException( "Error parsing response file.");
+ }
+ }
+
+ public String makeCommand (Map<String, String> params) {
+ JSONObject jsonPayload = new JSONObject();
+ final String[] optionalTestParams = {ENV_PARAMETERS_OPT_KEY, FILE_PARAMETERS_OPT_KEY};
+ parseParam(params, optionalTestParams, jsonPayload);
+ JSONObject envParams = (JSONObject) jsonPayload.remove(ENV_PARAMETERS_OPT_KEY);
+ JSONObject fileParams = (JSONObject) jsonPayload.remove(FILE_PARAMETERS_OPT_KEY);
+
+ StringBuilder constructedCommand = new StringBuilder();
+ constructedCommand.append(parseFileParam(fileParams)).append(p.cmd).append(" ").append(parseEnvParam(envParams));
+
+ return constructedCommand.toString();
+ }
+
+ private String parseEnvParam(JSONObject envParams) {
+ StringBuilder envParamBuilder = new StringBuilder();
+ if (envParams != null) {
+ for (Object key : envParams.keySet()) {
+ if (envParamBuilder.length() > 0) {
+ envParamBuilder.append(", ");
+ }
+ envParamBuilder.append(key + "=" + envParams.get((String) key));
+ }
+ }
+ return envParamBuilder.toString();
+ }
+
+ private String parseFileParam(JSONObject fileParams) {
+ StringBuilder fileParamBuilder = new StringBuilder();
+ if (fileParams != null) {
+ for (Object key : fileParams.keySet()) {
+ fileParamBuilder.append("echo -e \"" + fileParams.get((String) key) + "\" > /srv/salt/" + key).append("; ");
+ }
+ }
+ return fileParamBuilder.toString();
+ }
+
+ private void parseParam(Map<String, String> params, String[] optionalTestParams, JSONObject jsonPayload)
+ throws JSONException {
+
+ Set<String> optionalParamsSet = new HashSet<>();
+ Collections.addAll(optionalParamsSet, optionalTestParams);
+
+ //@formatter:off
+ params.entrySet()
+ .stream()
+ .filter(entry -> optionalParamsSet.contains(entry.getKey()))
+ .filter(entry -> !Strings.isNullOrEmpty(entry.getValue()))
+ .forEach(entry -> parseParam(entry, jsonPayload));
+ //@formatter:on
+ }
+
+ private void parseParam(Map.Entry<String, String> params, JSONObject jsonPayload)
+ throws JSONException {
+ String key = params.getKey();
+ String payload = params.getValue();
+
+ switch (key) {
+ case ENV_PARAMETERS_OPT_KEY:
+ JSONObject paramsJson = new JSONObject(payload);
+ jsonPayload.put(key, paramsJson);
+ break;
+
+ case FILE_PARAMETERS_OPT_KEY:
+ jsonPayload.put(key, getFilePayload(payload));
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /**
+ * Return payload with escaped newlines
+ */
+ private JSONObject getFilePayload(String payload) {
+ String formattedPayload = payload.replace("\n", "\\n").replace("\r", "\\r");
+ return new JSONObject(formattedPayload);
+ }
+
+ private Set<String> getListNameList(Map<String, String> paramMap) {
+ Set<String> ll = new HashSet<>();
+ for (Map.Entry<String,String> entry : paramMap.entrySet())
+ if (entry.getKey().startsWith("listName"))
+ ll.add(entry.getValue());
+ return ll;
+ }
+
+ private String parseParam(Map<String, String> paramMap, String name, boolean required, String def)
+ throws SvcLogicException {
+ String s = paramMap.get(name);
+
+ if (s == null || s.trim().length() == 0) {
+ if (!required)
+ return def;
+ throw new SvcLogicException("Parameter " + name + " is required in sshapiCallNode");
+ }
+
+ s = s.trim();
+ StringBuilder value = new StringBuilder();
+ int i = 0;
+ int i1 = s.indexOf('%');
+ while (i1 >= 0) {
+ int i2 = s.indexOf('%', i1 + 1);
+ if (i2 < 0)
+ break;
+
+ String varName = s.substring(i1 + 1, i2);
+ String varValue = System.getenv(varName);
+ if (varValue == null)
+ varValue = "%" + varName + "%";
+
+ value.append(s.substring(i, i1));
+ value.append(varValue);
+
+ i = i2 + 1;
+ i1 = s.indexOf('%', i);
+ }
+ value.append(s.substring(i));
+
+ log.info("Parameter {}: [{}]", name, value);
+ return value.toString();
+ }
+}
diff --git a/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/RetryPolicy.java b/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/RetryPolicy.java
deleted file mode 100644
index fef0f81af..000000000
--- a/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/RetryPolicy.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * openECOMP : SDN-C
- * ================================================================================
- * * Copyright (C) 2017 AT&T Intellectual Property.
- * ================================================================================
- * Copyright (C) 2018 Samsung Electronics. 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.plugins.sshapicall.model;
-
-public class RetryPolicy {
- private String[] hostnames;
- private Integer maximumRetries;
-
- public Integer getMaximumRetries() {
- return maximumRetries;
- }
-
- public String getNextHostName(String uri) throws RetryException {
- Integer position = null;
-
- for (int i = 0; i < hostnames.length; i++) {
- if (uri.contains(hostnames[i])) {
- position = i;
- break;
- }
- }
-
- if(position == null){
- throw new RetryException("No match found for the provided uri[" + uri + "] " +
- "so the next host name could not be retreived");
- }
- position++;
-
- if (position > hostnames.length - 1) {
- position = 0;
- }
- return hostnames[position];
- }
-
- public RetryPolicy(String[] hostnames, Integer maximumRetries){
- this.hostnames = hostnames;
- this.maximumRetries = maximumRetries;
- }
-
-
-}
diff --git a/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/RetryPolicyStore.java b/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/RetryPolicyStore.java
deleted file mode 100644
index 65575b8ce..000000000
--- a/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/RetryPolicyStore.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * openECOMP : SDN-C
- * ================================================================================
- * * Copyright (C) 2017 AT&T Intellectual Property.
- * ================================================================================
- * Copyright (C) 2018 Samsung Electronics. 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.plugins.sshapicall.model;
-
-import java.util.HashMap;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class RetryPolicyStore {
- private static final Logger log = LoggerFactory.getLogger(RetryPolicyStore.class);
-
- HashMap<String, RetryPolicy> retryPolicies;
- public String proxyServers;
-
- public String getProxyServers() {
- return proxyServers;
- }
-
- public void setProxyServers(String admServers) {
- this.proxyServers = admServers;
- String[] adminServersArray = admServers.split(",");
- RetryPolicy adminPortalRetry = new RetryPolicy(adminServersArray, adminServersArray.length);
- retryPolicies.put("dme2proxy", adminPortalRetry);
- }
-
- public RetryPolicyStore() {
- retryPolicies = new HashMap<>();
- }
-
- public RetryPolicy getRetryPolicy(String policyName) {
- return (this.retryPolicies.get(policyName));
- }
-
-}