summaryrefslogtreecommitdiffstats
path: root/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main
diff options
context:
space:
mode:
authorModaboina, Kusumakumari (km583p) <km583p@us.att.com>2019-01-30 20:23:22 -0500
committerTakamune Cho <takamune.cho@att.com>2019-02-08 16:18:32 +0000
commit3c1eae3c0a0b3f1214eccf46c2b92591389f9090 (patch)
treeabb800726a2cdcc17bc3b121fa1cfbfadbc9395a /appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main
parent8501f18c560534018a839b0bbccccf071e51fa4f (diff)
ansible adapter changes for multiple ansible servs
Issue-ID: APPC-1365 Change-Id: Ie3d102d9efcef7ba98b1fb5920a73a6c64b01897 Signed-off-by: Modaboina, Kusumakumari (km583p) <km583p@us.att.com>
Diffstat (limited to 'appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main')
-rw-r--r--appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/onap/appc/adapter/ansible/impl/AnsibleAdapterImpl.java226
-rw-r--r--appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/onap/appc/adapter/ansible/impl/ConnectionBuilder.java96
-rw-r--r--appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/onap/appc/adapter/ansible/model/AnsibleMessageParser.java168
-rw-r--r--appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/onap/appc/adapter/ansible/model/AnsibleResult.java13
4 files changed, 341 insertions, 162 deletions
diff --git a/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/onap/appc/adapter/ansible/impl/AnsibleAdapterImpl.java b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/onap/appc/adapter/ansible/impl/AnsibleAdapterImpl.java
index ae0b8594f..fafe3deb1 100644
--- a/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/onap/appc/adapter/ansible/impl/AnsibleAdapterImpl.java
+++ b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/onap/appc/adapter/ansible/impl/AnsibleAdapterImpl.java
@@ -2,7 +2,7 @@
* ============LICENSE_START=======================================================
* ONAP : APPC
* ================================================================================
- * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights reserved.
* ================================================================================
* Copyright (C) 2017 Amdocs
* =============================================================================
@@ -25,7 +25,9 @@ package org.onap.appc.adapter.ansible.impl;
import java.util.Map;
import java.util.Properties;
-
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
import org.apache.commons.lang.StringUtils;
import org.json.JSONException;
import org.json.JSONObject;
@@ -34,22 +36,20 @@ import org.onap.appc.adapter.ansible.model.AnsibleMessageParser;
import org.onap.appc.adapter.ansible.model.AnsibleResult;
import org.onap.appc.adapter.ansible.model.AnsibleResultCodes;
import org.onap.appc.adapter.ansible.model.AnsibleServerEmulator;
-import org.onap.appc.configuration.Configuration;
-import org.onap.appc.configuration.ConfigurationFactory;
import org.onap.appc.exceptions.APPCException;
import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
import org.onap.ccsdk.sli.core.sli.SvcLogicException;
import com.att.eelf.configuration.EELFLogger;
import com.att.eelf.configuration.EELFManager;
+import org.onap.appc.encryption.EncryptionTool;
/**
- * This class implements the {@link AnsibleAdapter} interface. This interface defines the behaviors
- * that our service provides.
+ * This class implements the {@link AnsibleAdapter} interface. This interface
+ * defines the behaviors that our service provides.
*/
public class AnsibleAdapterImpl implements AnsibleAdapter {
-
/**
* The constant used to define the service name in the mapped diagnostic context
*/
@@ -84,19 +84,22 @@ public class AnsibleAdapterImpl implements AnsibleAdapter {
private static final String CLIENT_TYPE_PROPERTY_NAME = "org.onap.appc.adapter.ansible.clientType";
private static final String TRUSTSTORE_PROPERTY_NAME = "org.onap.appc.adapter.ansible.trustStore";
private static final String TRUSTPASSWD_PROPERTY_NAME = "org.onap.appc.adapter.ansible.trustStore.trustPasswd";
-
+ private static final String TIMEOUT_PROPERTY_NAME = "org.onap.appc.adapter.ansible.timeout";
+ private static final String POLL_INTERVAL_PROPERTY_NAME = "org.onap.appc.adapter.ansible.pollInterval";
+ private static final String SOCKET_TIMEOUT_PROPERTY_NAME = "org.onap.appc.adapter.ansible.socketTimeout";
private static final String PASSWORD = "Password";
+ private static final String APPC_PROPS = "/appc.properties";
+ private static final String SDNC_CONFIG_DIR = "SDNC_CONFIG_DIR";
+ private static final String propDir = System.getenv(SDNC_CONFIG_DIR);
+ private Properties props;
+ private int defaultTimeout = 600 * 1000;
+ private int defaultSocketTimeout = 60 * 1000;
+ private int defaultPollInterval = 60 * 1000;
/**
* The logger to be used
*/
private static final EELFLogger logger = EELFManager.getInstance().getLogger(AnsibleAdapterImpl.class);
-
- /**
- * A reference to the adapter configuration object.
- */
- private Configuration configuration;
-
/**
* Connection object
**/
@@ -118,7 +121,8 @@ public class AnsibleAdapterImpl implements AnsibleAdapter {
private AnsibleServerEmulator testServer;
/**
- * This default constructor is used as a work around because the activator wasn't getting called
+ * This default constructor is used as a work around because the activator
+ * wasn't getting called
*/
public AnsibleAdapterImpl() {
initialize();
@@ -145,8 +149,9 @@ public class AnsibleAdapterImpl implements AnsibleAdapter {
}
/**
- * @param rc Method posts info to Context memory in case of an error and throws a
- * SvcLogicException causing SLI to register this as a failure
+ * @param rc
+ * Method posts info to Context memory in case of an error and throws
+ * a SvcLogicException causing SLI to register this as a failure
*/
@SuppressWarnings("static-method")
private void doFailure(SvcLogicContext svcLogic, int code, String message) throws SvcLogicException {
@@ -159,25 +164,72 @@ public class AnsibleAdapterImpl implements AnsibleAdapter {
}
/**
- * initialize the Ansible adapter based on default and over-ride configuration data
+ * initialize the Ansible adapter based on default and over-ride configuration
+ * data
*/
private void initialize() {
+ String path = propDir + APPC_PROPS;
+ File propFile = new File(path);
+ props = new Properties();
+ try {
+ InputStream input = new FileInputStream(propFile);
+ props.load(input);
+ } catch (Exception ex) {
+ logger.error("Error while reading appc.properties file" + ex.getMessage());
+ }
+ // Create the message processor instance
+ messageProcessor = new AnsibleMessageParser();
+ //continuing for checking timeout
+ try {
+ String timeoutStr = props.getProperty(TIMEOUT_PROPERTY_NAME);
+ defaultTimeout = Integer.parseInt(timeoutStr) * 1000;
- configuration = ConfigurationFactory.getConfiguration();
- Properties props = configuration.getProperties();
+ } catch (Exception e) {
+ defaultTimeout = 600 * 1000;
+ }
+ //continuing for checking timeout
+ try {
+ String timeoutStr = props.getProperty(SOCKET_TIMEOUT_PROPERTY_NAME);
+ defaultSocketTimeout = Integer.parseInt(timeoutStr) * 1000;
- // Create the message processor instance
- messageProcessor = new AnsibleMessageParser();
+ } catch (Exception e) {
+ defaultSocketTimeout = 60 * 1000;
+ }
+ //continuing for checking timeout
+ try {
+ String timeoutStr = props.getProperty(POLL_INTERVAL_PROPERTY_NAME);
+ defaultPollInterval = Integer.parseInt(timeoutStr) * 1000;
+
+ } catch (Exception e) {
+ defaultPollInterval = 60 * 1000;
+ }
+ logger.info("Initialized Ansible Adapter");
+ }
+
+ private ConnectionBuilder getHttpConn(int timeout, String serverIP) {
+ String path = propDir + APPC_PROPS;
+ File propFile = new File(path);
+ props = new Properties();
+ InputStream input;
+ try {
+ input = new FileInputStream(propFile);
+ props.load(input);
+ } catch (Exception ex) {
+ // TODO Auto-generated catch block
+ logger.error("Error while reading appc.properties file" + ex.getMessage());
+ }
// Create the http client instance
// type of client is extracted from the property file parameter
// org.onap.appc.adapter.ansible.clientType
// It can be :
// 1. TRUST_ALL (trust all SSL certs). To be used ONLY in dev
- // 2. TRUST_CERT (trust only those whose certificates have been stored in the trustStore file)
- // 3. DEFAULT (trust only well known certificates). This is standard behavior to which it will
+ // 2. TRUST_CERT (trust only those whose certificates have been stored in the
+ // trustStore file)
+ // 3. DEFAULT (trust only well known certificates). This is standard behavior to
+ // which it will
// revert. To be used in PROD
-
+ ConnectionBuilder httpClient = null;
try {
String clientType = props.getProperty(CLIENT_TYPE_PROPERTY_NAME);
logger.info("Ansible http client type set to " + clientType);
@@ -185,30 +237,31 @@ public class AnsibleAdapterImpl implements AnsibleAdapter {
if ("TRUST_ALL".equals(clientType)) {
logger.info(
"Creating http client to trust ALL ssl certificates. WARNING. This should be done only in dev environments");
- httpClient = new ConnectionBuilder(1);
+ httpClient = new ConnectionBuilder(1, timeout);
} else if ("TRUST_CERT".equals(clientType)) {
// set path to keystore file
String trustStoreFile = props.getProperty(TRUSTSTORE_PROPERTY_NAME);
String key = props.getProperty(TRUSTPASSWD_PROPERTY_NAME);
- char[] trustStorePasswd = key.toCharArray();
+ char[] trustStorePasswd = EncryptionTool.getInstance().decrypt(key).toCharArray();
logger.info("Creating http client with trustmanager from " + trustStoreFile);
- httpClient = new ConnectionBuilder(trustStoreFile, trustStorePasswd);
+ httpClient = new ConnectionBuilder(trustStoreFile, trustStorePasswd, timeout, serverIP);
} else {
logger.info("Creating http client with default behaviour");
- httpClient = new ConnectionBuilder(0);
+ httpClient = new ConnectionBuilder(0, timeout);
}
} catch (Exception e) {
- logger.error("Error Initializing Ansible Adapter due to Unknown Exception", e);
+ logger.error("Error Getting HTTP Connection Builder due to Unknown Exception", e);
}
- logger.info("Initialized Ansible Adapter");
+ logger.info("Got HTTP Connection Builder");
+ return httpClient;
}
// Public Method to post request to execute playbook. Posts the following back
// to Svc context memory
- // org.onap.appc.adapter.ansible.req.code : 100 if successful
- // org.onap.appc.adapter.ansible.req.messge : any message
- // org.onap.appc.adapter.ansible.req.Id : a unique uuid to reference the request
+ // org.onap.appc.adapter.ansible.req.code : 100 if successful
+ // org.onap.appc.adapter.ansible.req.messge : any message
+ // org.onap.appc.adapter.ansible.req.Id : a unique uuid to reference the request
@Override
public void reqExec(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
@@ -218,7 +271,7 @@ public class AnsibleAdapterImpl implements AnsibleAdapter {
String user = StringUtils.EMPTY;
String password = StringUtils.EMPTY;
String id = StringUtils.EMPTY;
-
+ String timeout = StringUtils.EMPTY;
JSONObject jsonPayload;
try {
@@ -227,10 +280,16 @@ public class AnsibleAdapterImpl implements AnsibleAdapter {
agentUrl = (String) jsonPayload.remove("AgentUrl");
user = (String) jsonPayload.remove("User");
- password = (String) jsonPayload.remove(PASSWORD);
+ password = (String)jsonPayload.remove(PASSWORD);
+ if(StringUtils.isNotBlank(password))
+ password = EncryptionTool.getInstance().decrypt(password);
id = jsonPayload.getString("Id");
+ timeout = jsonPayload.getString("Timeout");
+ if (StringUtils.isBlank(timeout))
+ timeout = "600";
payload = jsonPayload.toString();
- logger.info("Updated Payload = " + payload);
+ ctx.setAttribute("AnsibleTimeout", timeout);
+ logger.info("Updated Payload = " + payload + " timeout = " + timeout);
} catch (APPCException e) {
logger.error(APPC_EXCEPTION_CAUGHT, e);
doFailure(ctx, AnsibleResultCodes.INVALID_PAYLOAD.getValue(),
@@ -253,9 +312,9 @@ public class AnsibleAdapterImpl implements AnsibleAdapter {
try {
// post the test request
- logger.info("Posting request = " + payload + " to url = " + agentUrl);
- AnsibleResult testResult = postExecRequest(agentUrl, payload, user, password);
-
+ logger.info("Posting ansible request = " + payload + " to url = " + agentUrl);
+ AnsibleResult testResult = postExecRequest(agentUrl, payload, user, password,ctx);
+ logger.info("Received response on ansible post request " + testResult.getStatusMessage());
// Process if HTTP was successful
if (testResult.getStatusCode() == 200) {
testResult = messageProcessor.parsePostResponse(testResult.getStatusMessage());
@@ -263,10 +322,16 @@ public class AnsibleAdapterImpl implements AnsibleAdapter {
doFailure(ctx, testResult.getStatusCode(),
"Error posting request. Reason = " + testResult.getStatusMessage());
}
-
+ String output = StringUtils.EMPTY;
code = testResult.getStatusCode();
message = testResult.getStatusMessage();
-
+ output = testResult.getOutput();
+ ctx.setAttribute(OUTPUT_ATTRIBUTE_NAME, output);
+ String serverIp = testResult.getServerIp();
+ if (StringUtils.isBlank(serverIp))
+ ctx.setAttribute("ServerIP", serverIp);
+ else
+ ctx.setAttribute("ServerIP", "");
// Check status of test request returned by Agent
if (code == AnsibleResultCodes.PENDING.getValue()) {
logger.info(String.format("Submission of Test %s successful.", playbookName));
@@ -286,8 +351,8 @@ public class AnsibleAdapterImpl implements AnsibleAdapter {
}
/**
- * Public method to query status of a specific request It blocks till the Ansible Server
- * responds or the session times out (non-Javadoc)
+ * Public method to query status of a specific request It blocks till the
+ * Ansible Server responds or the session times out (non-Javadoc)
*
* @see org.onap.appc.adapter.ansible.AnsibleAdapter#reqExecResult(java.util.Map,
* org.onap.ccsdk.sli.core.sli.SvcLogicContext)
@@ -299,8 +364,12 @@ public class AnsibleAdapterImpl implements AnsibleAdapter {
String reqUri = StringUtils.EMPTY;
try {
- reqUri = messageProcessor.reqUriResult(params);
- logger.info("Got uri ", reqUri );
+ String serverIp = ctx.getAttribute("ServerIP");
+ if (StringUtils.isNotBlank(serverIp))
+ reqUri = messageProcessor.reqUriResultWithIP(params, serverIp);
+ else
+ reqUri = messageProcessor.reqUriResult(params);
+ logger.info("Got uri " + reqUri);
} catch (APPCException e) {
logger.error(APPC_EXCEPTION_CAUGHT, e);
doFailure(ctx, AnsibleResultCodes.INVALID_PAYLOAD.getValue(),
@@ -319,23 +388,23 @@ public class AnsibleAdapterImpl implements AnsibleAdapter {
String message = StringUtils.EMPTY;
String results = StringUtils.EMPTY;
String output = StringUtils.EMPTY;
-
try {
// Try to retrieve the test results (modify the URL for that)
- AnsibleResult testResult = queryServer(reqUri, params.get("User"), params.get(PASSWORD));
+ AnsibleResult testResult = queryServer(reqUri, params.get("User"),
+ EncryptionTool.getInstance().decrypt(params.get(PASSWORD)), ctx);
code = testResult.getStatusCode();
message = testResult.getStatusMessage();
if (code == 200 || code == 400 || "FINISHED".equalsIgnoreCase(message)) {
- logger.info("Parsing response from Server = " + message);
+ logger.info("Parsing response from ansible Server = " + message);
// Valid HTTP. process the Ansible message
testResult = messageProcessor.parseGetResponse(message);
code = testResult.getStatusCode();
message = testResult.getStatusMessage();
results = testResult.getResults();
output = testResult.getOutput();
+ ctx.setAttribute(OUTPUT_ATTRIBUTE_NAME, output);
}
-
logger.info("Request response = " + message);
} catch (APPCException e) {
doFailure(ctx, AnsibleResultCodes.UNKNOWN_EXCEPTION.getValue(),
@@ -369,8 +438,9 @@ public class AnsibleAdapterImpl implements AnsibleAdapter {
/**
* Public method to get logs from playbook execution for a specific request
*
- * It blocks till the Ansible Server responds or the session times out very similar to
- * reqExecResult logs are returned in the DG context variable org.onap.appc.adapter.ansible.log
+ * It blocks till the Ansible Server responds or the session times out very
+ * similar to reqExecResult logs are returned in the DG context variable
+ * org.onap.appc.adapter.ansible.log
*/
@Override
public void reqExecLog(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
@@ -387,7 +457,8 @@ public class AnsibleAdapterImpl implements AnsibleAdapter {
String message = StringUtils.EMPTY;
try {
// Try to retrieve the test results (modify the url for that)
- AnsibleResult testResult = queryServer(reqUri, params.get("User"), params.get(PASSWORD));
+ AnsibleResult testResult = queryServer(reqUri, params.get("User"),
+ EncryptionTool.getInstance().decrypt(params.get(PASSWORD)), ctx);
message = testResult.getStatusMessage();
logger.info("Request output = " + message);
ctx.setAttribute(LOG_ATTRIBUTE_NAME, message);
@@ -402,13 +473,15 @@ public class AnsibleAdapterImpl implements AnsibleAdapter {
/**
* Method that posts the request
*/
- private AnsibleResult postExecRequest(String agentUrl, String payload, String user, String password) {
+ private AnsibleResult postExecRequest(String agentUrl, String payload, String user, String password,
+ SvcLogicContext ctx) {
AnsibleResult testResult;
-
+ ConnectionBuilder httpClient = getHttpConn(defaultSocketTimeout, "");
if (!testMode) {
httpClient.setHttpContext(user, password);
testResult = httpClient.post(agentUrl, payload);
+ httpClient.close();
} else {
testResult = testServer.Post(agentUrl, payload);
}
@@ -418,16 +491,45 @@ public class AnsibleAdapterImpl implements AnsibleAdapter {
/**
* Method to query Ansible server
*/
- private AnsibleResult queryServer(String agentUrl, String user, String password) {
+ private AnsibleResult queryServer(String agentUrl, String user, String password, SvcLogicContext ctx) {
- AnsibleResult testResult;
+ AnsibleResult testResult = new AnsibleResult();
+ int timeout = 600 * 1000;
+ try {
+ timeout = Integer.parseInt(ctx.getAttribute("AnsibleTimeout")) * 1000;
- logger.info("Querying url = " + agentUrl);
+ } catch (Exception e) {
+ timeout = defaultTimeout;
+ }
+ long endTime = System.currentTimeMillis() + timeout;
- if (!testMode) {
- testResult = httpClient.get(agentUrl);
- } else {
- testResult = testServer.Get(agentUrl);
+ while (System.currentTimeMillis() < endTime) {
+ String serverIP = ctx.getAttribute("ServerIP");
+ ConnectionBuilder httpClient = getHttpConn(defaultSocketTimeout, serverIP);
+ logger.info("Querying ansible GetResult URL = " + agentUrl);
+
+ if (!testMode) {
+ httpClient.setHttpContext(user, password);
+ testResult = httpClient.get(agentUrl);
+ httpClient.close();
+ } else {
+ testResult = testServer.Get(agentUrl);
+ }
+ if (testResult.getStatusCode() != AnsibleResultCodes.IO_EXCEPTION.getValue()
+ && testResult.getStatusCode() != AnsibleResultCodes.PENDING.getValue()) {
+ break;
+ }
+
+ try {
+ Thread.sleep(defaultPollInterval);
+ } catch (InterruptedException ex) {
+
+ }
+
+ }
+ if (testResult.getStatusCode() == AnsibleResultCodes.PENDING.getValue()) {
+ testResult.setStatusCode(AnsibleResultCodes.IO_EXCEPTION.getValue());
+ testResult.setStatusMessage("Request timed out");
}
return testResult;
diff --git a/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/onap/appc/adapter/ansible/impl/ConnectionBuilder.java b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/onap/appc/adapter/ansible/impl/ConnectionBuilder.java
index 902ae59b4..77c9af680 100644
--- a/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/onap/appc/adapter/ansible/impl/ConnectionBuilder.java
+++ b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/onap/appc/adapter/ansible/impl/ConnectionBuilder.java
@@ -2,7 +2,7 @@
* ============LICENSE_START=======================================================
* ONAP : APPC
* ================================================================================
- * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights reserved.
* ================================================================================
* Copyright (C) 2017 Amdocs
* ================================================================================
@@ -25,6 +25,7 @@
package org.onap.appc.adapter.ansible.impl;
+import java.io.Closeable;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyManagementException;
@@ -34,14 +35,16 @@ import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
-import javax.net.ssl.SSLContext;;
+import javax.net.ssl.SSLContext;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
@@ -54,18 +57,20 @@ import org.onap.appc.adapter.ansible.model.AnsibleResult;
import org.onap.appc.adapter.ansible.model.AnsibleResultCodes;
import com.att.eelf.configuration.EELFLogger;
import com.att.eelf.configuration.EELFManager;
+import org.json.JSONObject;
+import javax.net.ssl.SSLException;
+import org.onap.appc.exceptions.APPCException;
+import org.apache.commons.lang.StringUtils;
/**
- * Returns a custom http client
- * - based on options
- * - can create one with ssl using an X509 certificate that does NOT have a known CA
- * - create one which trusts ALL SSL certificates
- * - return default httpclient (which only trusts known CAs from default cacerts file for process) this is the default
- * option
+ * Returns a custom http client - based on options - can create one with ssl
+ * using an X509 certificate that does NOT have a known CA - create one which
+ * trusts ALL SSL certificates - return default httpclient (which only trusts
+ * known CAs from default cacerts file for process) this is the default option
**/
-public class ConnectionBuilder {
-
+public class ConnectionBuilder implements Closeable {
+ private static final String STATUS_CODE_KEY = "StatusCode";
private static final EELFLogger logger = EELFManager.getInstance().getLogger(ConnectionBuilder.class);
private CloseableHttpClient httpClient = null;
@@ -74,8 +79,10 @@ public class ConnectionBuilder {
/**
* Constructor that initializes an http client based on certificate
**/
- public ConnectionBuilder(String certFile) throws KeyStoreException, CertificateException, IOException,
- KeyManagementException, NoSuchAlgorithmException {
+
+
+ public ConnectionBuilder(String certFile, int timeout) throws KeyStoreException, CertificateException, IOException,
+ KeyManagementException, NoSuchAlgorithmException{
/* Point to the certificate */
try(FileInputStream fs = new FileInputStream(certFile)) {
@@ -93,43 +100,55 @@ public class ConnectionBuilder {
SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(sslcontext,
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
- httpClient = HttpClients.custom().setSSLSocketFactory(factory).build();
+ RequestConfig config = RequestConfig.custom().setSocketTimeout(timeout).build();
+ httpClient = HttpClients.custom().setDefaultRequestConfig(config).setSSLSocketFactory(factory).build();
}
}
/**
- * Constructor which trusts all certificates in a specific java keystore file (assumes a JKS
- * file)
+ * Constructor which trusts all certificates in a specific java keystore file
+ * (assumes a JKS file)
**/
- public ConnectionBuilder(String trustStoreFile, char[] trustStorePasswd) throws KeyStoreException, IOException,
- KeyManagementException, NoSuchAlgorithmException, CertificateException {
+ public ConnectionBuilder(String trustStoreFile, char[] trustStorePasswd, int timeout, String serverIP)
+ throws KeyStoreException, IOException, KeyManagementException, NoSuchAlgorithmException,
+ CertificateException ,APPCException{
/* Load the specified trustStore */
KeyStore keystore = KeyStore.getInstance("JKS");
FileInputStream readStream = new FileInputStream(trustStoreFile);
keystore.load(readStream, trustStorePasswd);
+ if (StringUtils.isNotBlank(serverIP)) {
+ SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build();
+ SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(sslcontext, new NoopHostnameVerifier());
- SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(keystore).build();
- SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(sslcontext,
- SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
+ RequestConfig config = RequestConfig.custom().setSocketTimeout(timeout).build();
+ httpClient = HttpClients.custom().setDefaultRequestConfig(config).setSSLSocketFactory(factory).build();
+ } else {
+ SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(keystore).build();
+ SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(sslcontext,
+ SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
+ RequestConfig config = RequestConfig.custom().setSocketTimeout(timeout).build();
+ httpClient = HttpClients.custom().setDefaultRequestConfig(config).setSSLSocketFactory(factory).build();
+ }
- httpClient = HttpClients.custom().setSSLSocketFactory(factory).build();
}
/**
- * Constructor that trusts ALL SSl certificates (NOTE : ONLY FOR DEV TESTING) if Mode == 1 or
- * Default if Mode == 0
+ * Constructor that trusts ALL SSl certificates (NOTE : ONLY FOR DEV TESTING) if
+ * Mode == 1 or Default if Mode == 0
*/
- public ConnectionBuilder(int mode)
- throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
+
+ public ConnectionBuilder(int mode, int timeout)
+ throws SSLException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException,APPCException{
+ RequestConfig config = RequestConfig.custom().setSocketTimeout(timeout).build();
if (mode == 1) {
SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build();
SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(sslcontext,
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
- httpClient = HttpClients.custom().setSSLSocketFactory(factory).build();
+ httpClient = HttpClients.custom().setDefaultRequestConfig(config).setSSLSocketFactory(factory).build();
} else {
- httpClient = HttpClients.createDefault();
+ httpClient = HttpClients.custom().setDefaultRequestConfig(config).build();
}
}
@@ -187,7 +206,16 @@ public class ConnectionBuilder {
HttpEntity entity = response.getEntity();
String responseOutput = entity != null ? EntityUtils.toString(entity) : null;
int responseCode = response.getStatusLine().getStatusCode();
- result.setStatusCode(responseCode);
+ logger.info("GetResult response for ansible GET URL" + agentUrl + " returned " + responseOutput);
+ JSONObject postResponse = new JSONObject(responseOutput);
+ if (postResponse.has(STATUS_CODE_KEY)) {
+ int codeStatus = postResponse.getInt(STATUS_CODE_KEY);
+ if (codeStatus == AnsibleResultCodes.PENDING.getValue())
+ result.setStatusCode(codeStatus);
+ else
+ result.setStatusCode(responseCode);
+ } else
+ result.setStatusCode(responseCode);
result.setStatusMessage(responseOutput);
} catch (IOException io) {
result.setStatusCode(AnsibleResultCodes.IO_EXCEPTION.getValue());
@@ -196,4 +224,16 @@ public class ConnectionBuilder {
}
return result;
}
+
+ @Override
+ public void close() {
+ if (httpClient != null) {
+ try {
+ httpClient.close();
+ } catch (IOException e) {
+ logger.error("Caught IOException during httpClient close", e);
+ }
+ }
+ }
+
}
diff --git a/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/onap/appc/adapter/ansible/model/AnsibleMessageParser.java b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/onap/appc/adapter/ansible/model/AnsibleMessageParser.java
index 5f6259c03..77738d7dd 100644
--- a/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/onap/appc/adapter/ansible/model/AnsibleMessageParser.java
+++ b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/onap/appc/adapter/ansible/model/AnsibleMessageParser.java
@@ -40,22 +40,22 @@ import org.onap.appc.exceptions.APPCException;
import com.google.common.base.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.apache.commons.lang.StringUtils;
/**
- * Class that validates and constructs requests sent/received from
- * Ansible Server
+ * Class that validates and constructs requests sent/received from Ansible
+ * Server
*/
public class AnsibleMessageParser {
private static final String STATUS_MESSAGE_KEY = "StatusMessage";
private static final String STATUS_CODE_KEY = "StatusCode";
-
+ private static final String SERVER_IP_KEY = "AnsibleServer";
private static final String PLAYBOOK_NAME_KEY = "PlaybookName";
private static final String AGENT_URL_KEY = "AgentUrl";
private static final String PASS_KEY = "Password";
private static final String USER_KEY = "User";
private static final String ID_KEY = "Id";
-
private static final String LOCAL_PARAMETERS_OPT_KEY = "LocalParameters";
private static final String FILE_PARAMETERS_OPT_KEY = "FileParameters";
private static final String ENV_PARAMETERS_OPT_KEY = "EnvParameters";
@@ -67,20 +67,19 @@ public class AnsibleMessageParser {
private static final Logger LOGGER = LoggerFactory.getLogger(AnsibleMessageParser.class);
/**
- * Accepts a map of strings and
- * a) validates if all parameters are appropriate (else, throws an exception) and
- * b) if correct returns a JSON object with appropriate key-value pairs to send to the server.
+ * Accepts a map of strings and a) validates if all parameters are appropriate
+ * (else, throws an exception) and b) if correct returns a JSON object with
+ * appropriate key-value pairs to send to the server.
*
- * Mandatory parameters, that must be in the supplied information to the Ansible Adapter
- * 1. URL to connect to
- * 2. credentials for URL (assume username password for now)
- * 3. Playbook name
+ * Mandatory parameters, that must be in the supplied information to the Ansible
+ * Adapter 1. URL to connect to 2. credentials for URL (assume username password
+ * for now) 3. Playbook name
*
*/
public JSONObject reqMessage(Map<String, String> params) throws APPCException {
- final String[] mandatoryTestParams = {AGENT_URL_KEY, PLAYBOOK_NAME_KEY, USER_KEY, PASS_KEY};
- final String[] optionalTestParams = {ENV_PARAMETERS_OPT_KEY, NODE_LIST_OPT_KEY, LOCAL_PARAMETERS_OPT_KEY,
- TIMEOUT_OPT_KEY, VERSION_OPT_KEY, FILE_PARAMETERS_OPT_KEY, ACTION_OPT_KEY};
+ final String[] mandatoryTestParams = { AGENT_URL_KEY, PLAYBOOK_NAME_KEY, USER_KEY, PASS_KEY };
+ final String[] optionalTestParams = { ENV_PARAMETERS_OPT_KEY, NODE_LIST_OPT_KEY, LOCAL_PARAMETERS_OPT_KEY,
+ TIMEOUT_OPT_KEY, VERSION_OPT_KEY, FILE_PARAMETERS_OPT_KEY, ACTION_OPT_KEY };
JSONObject jsonPayload = new JSONObject();
@@ -99,13 +98,13 @@ public class AnsibleMessageParser {
}
/**
- * Method that validates that the Map has enough information
- * to query Ansible server for a result. If so, it returns
- * the appropriate url, else an empty string.
+ * Method that validates that the Map has enough information to query Ansible
+ * server for a result. If so, it returns the appropriate url, else an empty
+ * string.
*/
public String reqUriResult(Map<String, String> params) throws APPCException {
- final String[] mandatoryTestParams = {AGENT_URL_KEY, ID_KEY, USER_KEY, PASS_KEY};
+ final String[] mandatoryTestParams = { AGENT_URL_KEY, ID_KEY, USER_KEY, PASS_KEY };
for (String key : mandatoryTestParams) {
throwIfMissingMandatoryParam(params, key);
@@ -114,13 +113,30 @@ public class AnsibleMessageParser {
}
/**
- * Method that validates that the Map has enough information
- * to query Ansible server for logs. If so, it populates the appropriate
- * returns the appropriate url, else an empty string.
+ * Method that validates that the Map has enough information to query Ansible
+ * server for a result. If so, it returns the appropriate url, else an empty
+ * string.
+ */
+ public String reqUriResultWithIP(Map<String, String> params, String serverIP) throws APPCException {
+
+ final String[] mandatoryTestParams = { AGENT_URL_KEY, ID_KEY, USER_KEY, PASS_KEY };
+
+ for (String key : mandatoryTestParams) {
+ throwIfMissingMandatoryParam(params, key);
+ }
+ String[] arr1 = params.get(AGENT_URL_KEY).split("//", 2);
+ String[] arr2 = arr1[1].split(":", 2);
+ return arr1[0] + "//" + serverIP + ":" + arr2[1] + "?Id=" + params.get(ID_KEY) + "&Type=GetResult";
+ }
+
+ /**
+ * Method that validates that the Map has enough information to query Ansible
+ * server for logs. If so, it populates the appropriate returns the appropriate
+ * url, else an empty string.
*/
public String reqUriLog(Map<String, String> params) throws APPCException {
- final String[] mandatoryTestParams = {AGENT_URL_KEY, ID_KEY, USER_KEY, PASS_KEY};
+ final String[] mandatoryTestParams = { AGENT_URL_KEY, ID_KEY, USER_KEY, PASS_KEY };
for (String mandatoryParam : mandatoryTestParams) {
throwIfMissingMandatoryParam(params, mandatoryParam);
@@ -129,8 +145,8 @@ public class AnsibleMessageParser {
}
/**
- * This method parses response from the Ansible Server when we do a post
- * and returns an AnsibleResult object.
+ * This method parses response from the Ansible Server when we do a post and
+ * returns an AnsibleResult object.
*/
public AnsibleResult parsePostResponse(String input) throws APPCException {
AnsibleResult ansibleResult;
@@ -139,7 +155,11 @@ public class AnsibleMessageParser {
int code = postResponse.getInt(STATUS_CODE_KEY);
String msg = postResponse.getString(STATUS_MESSAGE_KEY);
-
+ String serverIP = "";
+ if (postResponse.has(SERVER_IP_KEY))
+ serverIP = postResponse.getString(SERVER_IP_KEY);
+ else
+ serverIP = "";
int initResponseValue = AnsibleResultCodes.INITRESPONSE.getValue();
boolean validCode = AnsibleResultCodes.CODE.checkValidCode(initResponseValue, code);
if (!validCode) {
@@ -148,6 +168,14 @@ public class AnsibleMessageParser {
}
ansibleResult = new AnsibleResult(code, msg);
+ if (StringUtils.isNotBlank(serverIP))
+ ansibleResult.setServerIp(serverIP);
+
+ if (!postResponse.isNull("Output")) {
+ LOGGER.info("Processing results-output in post response");
+ JSONObject output = postResponse.getJSONObject("Output");
+ ansibleResult.setOutput(output.toString());
+ }
} catch (JSONException e) {
LOGGER.error("JSONException: Error parsing response", e);
@@ -157,8 +185,8 @@ public class AnsibleMessageParser {
}
/**
- * This method parses response from an Ansible server when we do a GET for a result
- * and returns an AnsibleResult object.
+ * This method parses response from an Ansible server when we do a GET for a
+ * result and returns an AnsibleResult object.
**/
public AnsibleResult parseGetResponse(String input) throws APPCException {
@@ -175,14 +203,14 @@ public class AnsibleMessageParser {
return ansibleResult;
}
- private AnsibleResult parseGetResponseNested(AnsibleResult ansibleResult, JSONObject postRsp) throws APPCException {
+ private AnsibleResult parseGetResponseNested(AnsibleResult ansibleResult, JSONObject postRsp) throws APPCException {
int codeStatus = postRsp.getInt(STATUS_CODE_KEY);
String messageStatus = postRsp.getString(STATUS_MESSAGE_KEY);
int finalCode = AnsibleResultCodes.FINAL_SUCCESS.getValue();
- boolean valCode =
- AnsibleResultCodes.CODE.checkValidCode(AnsibleResultCodes.FINALRESPONSE.getValue(), codeStatus);
+ boolean valCode = AnsibleResultCodes.CODE.checkValidCode(AnsibleResultCodes.FINALRESPONSE.getValue(),
+ codeStatus);
if (!valCode) {
throw new APPCException("Invalid FinalResponse code = " + codeStatus + " received. MUST be one of "
@@ -206,8 +234,8 @@ public class AnsibleMessageParser {
while (hosts.hasNext()) {
String host = hosts.next();
- LOGGER.info("Processing host = {}", host);
-
+ LOGGER.info("Processing host = {}",
+ (host.matches("^[\\w\\-.]+$")) ? host : "[unexpected value, logging suppressed]");
try {
JSONObject hostResponse = results.getJSONObject(host);
int subCode = hostResponse.getInt(STATUS_CODE_KEY);
@@ -221,8 +249,8 @@ public class AnsibleMessageParser {
} catch (JSONException e) {
LOGGER.error("JSONException: Error parsing response", e);
ansibleResult.setStatusCode(AnsibleResultCodes.INVALID_RESPONSE.getValue());
- ansibleResult.setStatusMessage(String.format(
- "Error processing response message = %s from host %s", results.getString(host), host));
+ ansibleResult.setStatusMessage(String.format("Error processing response message = %s from host %s",
+ results.getString(host), host));
break;
}
}
@@ -236,7 +264,7 @@ public class AnsibleMessageParser {
ansibleResult.setStatusCode(AnsibleResultCodes.INVALID_RESPONSE.getValue());
ansibleResult.setStatusMessage("Results not found in GET for response");
}
- if(!postRsp.isNull("Output")) {
+ if (!postRsp.isNull("Output")) {
LOGGER.info("Processing results-output in response");
JSONObject output = postRsp.getJSONObject("Output");
ansibleResult.setOutput(output.toString());
@@ -250,13 +278,11 @@ public class AnsibleMessageParser {
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 -> parseOptionalParam(entry, jsonPayload));
- //@formatter:on
+ // @formatter:off
+ params.entrySet().stream().filter(entry -> optionalParamsSet.contains(entry.getKey()))
+ .filter(entry -> !Strings.isNullOrEmpty(entry.getValue()))
+ .forEach(entry -> parseOptionalParam(entry, jsonPayload));
+ // @formatter:on
}
private void parseOptionalParam(Map.Entry<String, String> params, JSONObject jsonPayload) {
@@ -264,35 +290,35 @@ public class AnsibleMessageParser {
String payload = params.getValue();
switch (key) {
- case TIMEOUT_OPT_KEY:
- int timeout = Integer.parseInt(payload);
- if (timeout < 0) {
- throw new NumberFormatException(" : specified negative integer for timeout = " + payload);
- }
- jsonPayload.put(key, payload);
- break;
-
- case VERSION_OPT_KEY:
- jsonPayload.put(key, payload);
- break;
-
- case LOCAL_PARAMETERS_OPT_KEY:
- case ENV_PARAMETERS_OPT_KEY:
- JSONObject paramsJson = new JSONObject(payload);
- jsonPayload.put(key, paramsJson);
- break;
-
- case NODE_LIST_OPT_KEY:
- JSONArray paramsArray = new JSONArray(payload);
- jsonPayload.put(key, paramsArray);
- break;
-
- case FILE_PARAMETERS_OPT_KEY:
- jsonPayload.put(key, getFilePayload(payload));
- break;
-
- default:
- break;
+ case TIMEOUT_OPT_KEY:
+ int timeout = Integer.parseInt(payload);
+ if (timeout < 0) {
+ throw new NumberFormatException(" : specified negative integer for timeout = " + payload);
+ }
+ jsonPayload.put(key, payload);
+ break;
+
+ case VERSION_OPT_KEY:
+ jsonPayload.put(key, payload);
+ break;
+
+ case LOCAL_PARAMETERS_OPT_KEY:
+ case ENV_PARAMETERS_OPT_KEY:
+ JSONObject paramsJson = new JSONObject(payload);
+ jsonPayload.put(key, paramsJson);
+ break;
+
+ case NODE_LIST_OPT_KEY:
+ JSONArray paramsArray = new JSONArray(payload);
+ jsonPayload.put(key, paramsArray);
+ break;
+
+ case FILE_PARAMETERS_OPT_KEY:
+ jsonPayload.put(key, getFilePayload(payload));
+ break;
+
+ default:
+ break;
}
}
diff --git a/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/onap/appc/adapter/ansible/model/AnsibleResult.java b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/onap/appc/adapter/ansible/model/AnsibleResult.java
index de6b180ef..b67f3c74b 100644
--- a/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/onap/appc/adapter/ansible/model/AnsibleResult.java
+++ b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/onap/appc/adapter/ansible/model/AnsibleResult.java
@@ -2,7 +2,7 @@
* ============LICENSE_START=======================================================
* ONAP : APPC
* ================================================================================
- * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights reserved.
* ================================================================================
* Copyright (C) 2017 Amdocs
* =============================================================================
@@ -34,6 +34,7 @@ public class AnsibleResult {
private String statusMessage;
private String results;
private String output;
+ private String serverIp;
public AnsibleResult() {
this(-1, EMPTY_VALUE, EMPTY_VALUE);
@@ -75,6 +76,10 @@ public class AnsibleResult {
public void setResults(String results) {
this.results = results;
}
+
+ public void setServerIp(String serverIp) {
+ this.serverIp = serverIp;
+ }
void set(int code, String message, String results, String output) {
this.statusCode = code;
@@ -95,4 +100,10 @@ public class AnsibleResult {
public String getResults() {
return this.results;
}
+
+ public String getServerIp() {
+ return this.serverIp;
+ }
+
+
}