Handled exception
[appc.git] / appc-adapters / appc-ansible-adapter / appc-ansible-adapter-bundle / src / main / java / org / onap / appc / adapter / ansible / impl / AnsibleAdapterImpl.java
index 0b426bb..91125b0 100644 (file)
@@ -2,23 +2,24 @@
  * ============LICENSE_START=======================================================
  * ONAP : APPC
  * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights reserved.
  * ================================================================================
  * Copyright (C) 2017 Amdocs
  * =============================================================================
+ * Modifications Copyright (C) 2019 IBM
+ * =============================================================================
  * 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=========================================================
  */
 
@@ -26,56 +27,33 @@ package org.onap.appc.adapter.ansible.impl;
 
 import java.util.Map;
 import java.util.Properties;
-import java.lang.*;
-    
-
-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 org.json.JSONObject;
-import org.json.JSONArray;
+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;
 import org.onap.appc.adapter.ansible.AnsibleAdapter;
-
-import org.onap.appc.adapter.ansible.model.AnsibleResult;
 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.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 com.att.eelf.i18n.EELFResourceManager;
-import static com.att.eelf.configuration.Configuration.*;
-
+import org.onap.appc.encryption.EncryptionTool;
 
 /**
  * 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 adapter name in the mapped diagnostic
-     * context
-     */
-       
-
-    @SuppressWarnings("nls")
-    public static final String MDC_ADAPTER = "Ansible Adapter";
-
-    /**
-     * The constant used to define the service name in the mapped diagnostic
-     * context
+     * The constant used to define the service name in the mapped diagnostic context
      */
     @SuppressWarnings("nls")
     public static final String MDC_SERVICE = "service";
@@ -93,409 +71,481 @@ public class AnsibleAdapterImpl implements AnsibleAdapter {
     public static final String OUTCOME_SUCCESS = "success";
 
     /**
-      Adapter Name 
-    **/
+     * Adapter Name
+     */
     private static final String ADAPTER_NAME = "Ansible Adapter";
+    private static final String APPC_EXCEPTION_CAUGHT = "APPCException caught";
+
+    private static final String RESULT_CODE_ATTRIBUTE_NAME = "org.onap.appc.adapter.ansible.result.code";
+    private static final String MESSAGE_ATTRIBUTE_NAME = "org.onap.appc.adapter.ansible.message";
+    private static final String RESULTS_ATTRIBUTE_NAME = "org.onap.appc.adapter.ansible.results";
+    private static final String OUTPUT_ATTRIBUTE_NAME = "org.onap.appc.adapter.ansible.output";
+    private static final String ID_ATTRIBUTE_NAME = "org.onap.appc.adapter.ansible.Id";
+    private static final String LOG_ATTRIBUTE_NAME = "org.onap.appc.adapter.ansible.log";
+
+    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;;
-
-    /** can Specify a X509 certificate file for use if required ... 
-    Must be initialized with setCertFile 
-    **/
-    private String certFile = "";
-
+     * Connection object
+     **/
+    private ConnectionBuilder httpClient;
 
     /**
-     * Connection object 
-     **/
-    ConnectionBuilder  http_client ;
-    
-    /** 
      * Ansible API Message Handlers
      **/
     private AnsibleMessageParser messageProcessor;
 
     /**
-       indicator whether in test mode
-    **/
-    private boolean  testMode = false;
+     * indicator whether in test mode
+     **/
+    private boolean testMode = false;
 
     /**
-       server emulator object to be used if in test mode 
-    **/
+     * server emulator object to be used if in test mode
+     **/
     private AnsibleServerEmulator testServer;
-    
+
     /**
      * This default constructor is used as a work around because the activator
-     * wasnt getting called
+     * wasn't getting called
      */
     public AnsibleAdapterImpl() {
-       initialize();
+        initialize();
     }
 
-
     /**
-     * @param props
-     *            not used
+     * Used for jUnit test and testing interface
      */
-    public AnsibleAdapterImpl(Properties props) {
-       initialize();
+    public AnsibleAdapterImpl(boolean mode) {
+        testMode = mode;
+        testServer = new AnsibleServerEmulator();
+        messageProcessor = new AnsibleMessageParser();
     }
 
-
-
-    /** 
-       Used for jUnit test and testing interface 
-    **/
-    public AnsibleAdapterImpl(boolean Mode){
-       testMode = Mode;
-       testServer = new AnsibleServerEmulator();
-       messageProcessor = new AnsibleMessageParser();
-    }
-    
     /**
      * Returns the symbolic name of the adapter
-     * 
+     *
      * @return The adapter name
      * @see org.onap.appc.adapter.rest.AnsibleAdapter#getAdapterName()
      */
     @Override
     public String getAdapterName() {
-       return ADAPTER_NAME;
+        return ADAPTER_NAME;
     }
 
-
-    
     /**
      * @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
+     *            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 {
+    private void doFailure(SvcLogicContext svcLogic, int code, String message) throws SvcLogicException {
 
-       svcLogic.setStatus(OUTCOME_FAILURE);
-       svcLogic.setAttribute("org.onap.appc.adapter.ansible.result.code",Integer.toString(code));
-       svcLogic.setAttribute("org.onap.appc.adapter.ansible.message",message);
-       
-       throw new SvcLogicException("Ansible Adapter Error = " + message );
+        svcLogic.setStatus(OUTCOME_FAILURE);
+        svcLogic.setAttribute(RESULT_CODE_ATTRIBUTE_NAME, Integer.toString(code));
+        svcLogic.setAttribute(MESSAGE_ATTRIBUTE_NAME, message);
+
+        throw new SvcLogicException("Ansible Adapter Error = " + message);
     }
-       
 
     /**
-     * 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()  {
-
-       configuration = ConfigurationFactory.getConfiguration();
-       Properties props = configuration.getProperties();
-       
-       // Create the message processor instance 
-       messageProcessor = new AnsibleMessageParser();
+    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;
+
+        } catch (Exception e) {
+            defaultTimeout = 600 * 1000;
+            logger.error("Error while reading time out property" , e);
+        }
+        //continuing for checking timeout
+        try {
+            String timeoutStr = props.getProperty(SOCKET_TIMEOUT_PROPERTY_NAME);
+            defaultSocketTimeout = Integer.parseInt(timeoutStr) * 1000;
+
+        } catch (Exception e) {
+            defaultSocketTimeout = 60 * 1000;
+            logger.error("Error while reading socket time out property" , e);
+        }
+        //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.error("Error while reading poll interval property" , e);
+        }
+        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 behaviour to which it will
-        //     revert. To be used in PROD
-
-        try{
-            String clientType = props.getProperty("org.onap.appc.adapter.ansible.clientType");
-           logger.info("Ansible http client type set to " + clientType);
-
-            if (clientType.equals("TRUST_ALL")){
-                logger.info("Creating http client to trust ALL ssl certificates. WARNING. This should be done only in dev environments");
-                http_client = new ConnectionBuilder(1);
-            }
-            else if (clientType.equals("TRUST_CERT")){
+        // 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
+        // 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);
+
+            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, timeout);
+            } else if ("TRUST_CERT".equals(clientType)) {
                 // set path to keystore file
-                String trustStoreFile = props.getProperty("org.onap.appc.adapter.ansible.trustStore");
-                String key  = props.getProperty("org.onap.appc.adapter.ansible.trustStore.trustPasswd");
-                char [] trustStorePasswd = key.toCharArray();
-                String trustStoreType = "JKS";
+                String trustStoreFile = props.getProperty(TRUSTSTORE_PROPERTY_NAME);
+                String key = props.getProperty(TRUSTPASSWD_PROPERTY_NAME);
+                char[] trustStorePasswd = EncryptionTool.getInstance().decrypt(key).toCharArray();
                 logger.info("Creating http client with trustmanager from " + trustStoreFile);
-                http_client = new ConnectionBuilder(trustStoreFile, trustStorePasswd);
-            }
-            else{
+                httpClient = new ConnectionBuilder(trustStoreFile, trustStorePasswd, timeout, serverIP);
+            } else {
                 logger.info("Creating http client with default behaviour");
-                http_client = new ConnectionBuilder(0);
+                httpClient = new ConnectionBuilder(0, timeout);
             }
-        }
-        catch (Exception e){
-            logger.error("Error Initializing Ansible Adapter due to Unknown Exception: reason = " + e.getMessage());
+        } catch (Exception e) {
+            logger.error("Error Getting HTTP Connection Builder due to Unknown Exception", e);
         }
 
-       logger.info("Intitialized 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
+    @Override
+    public void reqExec(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
+
+        String playbookName = StringUtils.EMPTY;
+        String payload = StringUtils.EMPTY;
+        String agentUrl = StringUtils.EMPTY;
+        String user = StringUtils.EMPTY;
+        String password = StringUtils.EMPTY;
+        String id = StringUtils.EMPTY;
+        String timeout = StringUtils.EMPTY;
+        JSONObject jsonPayload;
+
+        try {
+            // create json object to send request
+            jsonPayload = messageProcessor.reqMessage(params);
+
+            agentUrl = (String) jsonPayload.remove("AgentUrl");
+            user = (String) jsonPayload.remove("User");
+            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();
+            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(),
+                    "Error constructing request for execution of playbook due to missing mandatory parameters. Reason = "
+                            + e.getMessage());
+        } catch (JSONException e) {
+            logger.error("JSONException caught", e);
+            doFailure(ctx, AnsibleResultCodes.INVALID_PAYLOAD.getValue(),
+                    "Error constructing request for execution of playbook due to invalid JSON block. Reason = "
+                            + e.getMessage());
+        } catch (NumberFormatException e) {
+            logger.error("NumberFormatException caught", e);
+            doFailure(ctx, AnsibleResultCodes.INVALID_PAYLOAD.getValue(),
+                    "Error constructing request for execution of playbook due to invalid parameter values. Reason = "
+                            + e.getMessage());
+        }
+
+        int code = -1;
+        String message = StringUtils.EMPTY;
+
+        try {
+            // post the test request
+            logger.info("Posting ansible request = " + payload + " to url = " + agentUrl);
+            AnsibleResult testResult = postExecRequest(agentUrl, payload, user, password,ctx);
+          if (testResult != null) {
+            logger.info("Received response on ansible post request " + testResult.getStatusMessage());
+            // Process if HTTP was successful
+            if (testResult.getStatusCode() == 200) {
+              testResult = messageProcessor.parsePostResponse(testResult.getStatusMessage());
+            } else {
+              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));
+              // test request accepted. We are in asynchronous case
+            } else {
+              doFailure(ctx, code, "Request for execution of playbook rejected. Reason = " + message);
+            }
+          } else {
+            doFailure(ctx, code, "Ansible Test result is null");
+          }
+        } catch (APPCException e) {
+            logger.error(APPC_EXCEPTION_CAUGHT, e);
+            doFailure(ctx, AnsibleResultCodes.UNKNOWN_EXCEPTION.getValue(),
+                    "Exception encountered when posting request for execution of playbook. Reason = " + e.getMessage());
+        }
 
-    /** set the certificate file if not a trusted/known CA **/
-    private void setCertFile(String CertFile){
-       this.certFile = CertFile;
+        ctx.setAttribute(RESULT_CODE_ATTRIBUTE_NAME, Integer.toString(code));
+        ctx.setAttribute(MESSAGE_ATTRIBUTE_NAME, message);
+        ctx.setAttribute(ID_ATTRIBUTE_NAME, id);
     }
-    
 
+    /**
+     * 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)
+     */
+    @Override
+    public void reqExecResult(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
 
-    // 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
-
-    public void reqExec(Map <String, String> params, SvcLogicContext ctx) throws SvcLogicException {
-
-       String PlaybookName = "";
-       String payload = "";
-       String AgentUrl = "";
-       String User = "";
-       String Password = "";
-       String Id = "";
-       
-       JSONObject JsonPayload;
-       
-       try{
-           // create json object to send request
-           JsonPayload = messageProcessor.ReqMessage(params);
-           
-           AgentUrl = (String) JsonPayload.remove("AgentUrl");
-                   User =  (String) JsonPayload.remove("User");
-           Password = (String) JsonPayload.remove("Password");
-           Id = (String)JsonPayload.getString("Id");
-           payload = JsonPayload.toString();
-           logger.info("Updated Payload  = "  + payload);
-       }
-       catch(APPCException e){
-           doFailure(ctx, AnsibleResultCodes.INVALID_PAYLOAD.getValue(), "Error constructing request for execution of playbook due to missing mandatory parameters. Reason = " + e.getMessage());
-       }
-       catch(JSONException e){
-           doFailure(ctx, AnsibleResultCodes.INVALID_PAYLOAD.getValue(), "Error constructing request for execution of playbook due to invalid JSON block. Reason = " + e.getMessage());
-       }
-       catch(NumberFormatException e){
-           doFailure(ctx, AnsibleResultCodes.INVALID_PAYLOAD.getValue(), "Error constructing request for execution of playbook due to invalid parameter values. Reason = " + e.getMessage());
-       }
-       
-    
-       int code = -1;
-       String message = "";
-       
-       try{
-           
-           // post the test request
-           //---------------------------------------
-           logger.info("Posting request = " + payload + " to url = " + AgentUrl );
-           AnsibleResult testresult = postExecRequest(AgentUrl, payload, User, Password);
-
-    
-           // Process if HTTP was successfull
-           if(testresult.getStatusCode() == 200){
-               testresult = messageProcessor.parsePostResponse(testresult.getStatusMessage());
-           }
-           else{
-               doFailure(ctx, testresult.getStatusCode(), "Error posting request. Reason = " + testresult.getStatusMessage());
-           }
-
-    
-           code = testresult.getStatusCode();
-           message = testresult.getStatusMessage();
-
-                   
-           // Check status of test request returned by Agent
-           //-----------------------------------------------
-           if (code == AnsibleResultCodes.PENDING.getValue()){
-               logger.info(String.format("Submission of Test %s successful.", PlaybookName));
-               // test request accepted. We are in asynchronous case
-           }
-           else{
-               doFailure(ctx, code, "Request for execution of playbook rejected. Reason = " + message);
-           }
-       }
-       
-       catch(APPCException e){
-           doFailure(ctx, AnsibleResultCodes.UNKNOWN_EXCEPTION.getValue(), "Exception encountered when posting request for execution of playbook. Reason = "  + e.getMessage());
-       }
-
-
-       ctx.setAttribute("org.onap.appc.adapter.ansible.result.code", Integer.toString(code));
-       ctx.setAttribute("org.onap.appc.adapter.ansible.message", message );
-       ctx.setAttribute("org.onap.appc.adapter.ansible.Id", Id);
-       
-    }
+        // Get URI
+        String reqUri = StringUtils.EMPTY;
+
+        try {
+            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(),
+                    "Error constructing request to retrieve result due to missing parameters. Reason = "
+                            + e.getMessage());
+            return;
+        } catch (NumberFormatException e) {
+            logger.error("NumberFormatException caught", e);
+            doFailure(ctx, AnsibleResultCodes.INVALID_PAYLOAD.getValue(),
+                    "Error constructing request to retrieve result due to invalid parameters value. Reason = "
+                            + e.getMessage());
+            return;
+        }
 
+        int code = -1;
+        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"),
+                    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 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(),
+                    "Exception encountered retrieving result : " + e.getMessage());
+            return;
+        }
 
-    // Public method to query status of a specific request
-    // It blocks till the Ansible Server responds or the session times out
-    
-    public void reqExecResult(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
+        // We were able to get and process the results. Determine if playbook succeeded
+
+        if (code == AnsibleResultCodes.FINAL_SUCCESS.getValue()) {
+            message = String.format("Ansible Request  %s finished with Result = %s, Message = %s", params.get("Id"),
+                    OUTCOME_SUCCESS, message);
+            logger.info(message);
+        } else {
+            logger.info(String.format("Ansible Request  %s finished with Result %s, Message = %s", params.get("Id"),
+                    OUTCOME_FAILURE, message));
+            ctx.setAttribute(RESULTS_ATTRIBUTE_NAME, results);
+            ctx.setAttribute(OUTPUT_ATTRIBUTE_NAME, output);
+            doFailure(ctx, code, message);
+            return;
+        }
 
-           
-       // Get uri
-       String ReqUri = "";
-       
-       try{
-           ReqUri = messageProcessor.ReqUri_Result(params);
-           System.out.println("Got uri = " + ReqUri);
-       }
-       catch(APPCException e){
-           doFailure(ctx, AnsibleResultCodes.INVALID_PAYLOAD.getValue(), "Error constructing request to retreive result due to missing parameters. Reason = " + e.getMessage());
-           return;
-       }
-       catch(NumberFormatException e){
-           doFailure(ctx, AnsibleResultCodes.INVALID_PAYLOAD.getValue(), "Error constructing request to retreive result due to invalid parameters value. Reason = " + e.getMessage());
-           return;
-       }
-
-       int code = -1;
-       String message = "";
-       String results = "";
-       
-       try{
-           // Try to  retreive the test results (modify the url for that)
-           AnsibleResult testresult = queryServer(ReqUri, params.get("User"), params.get("Password"));
-           code = testresult.getStatusCode();
-           message = testresult.getStatusMessage();
-
-           if(code == 200){
-               logger.info("Parsing response from Server = " + message);
-               // Valid HTTP. process the Ansible message
-               testresult = messageProcessor.parseGetResponse(message);
-               code = testresult.getStatusCode();
-               message = testresult.getStatusMessage();
-               results = testresult.getResults();
-               
-           }
-           
-           logger.info("Request response = " + message);
-
-       }
-       catch (APPCException e){
-           doFailure(ctx, AnsibleResultCodes.UNKNOWN_EXCEPTION.getValue(), "Exception encountered retreiving result : " + e.getMessage());
-           return;
-       }
-
-       // We were able to get and process the results. Determine if playbook succeeded
-       
-       if (code == AnsibleResultCodes.FINAL_SUCCESS.getValue()){
-           message = String.format("Ansible Request  %s finished with Result = %s, Message = %s", params.get("Id"), OUTCOME_SUCCESS, message);
-           logger.info(message);
-       }
-       else {
-           logger.info(String.format("Ansible Request  %s finished with Result %s, Message = %s", params.get("Id"), OUTCOME_FAILURE, message));
-           ctx.setAttribute("org.onap.appc.adapter.ansible.results", results);
-           doFailure(ctx, code, message );
-           return;         
-       }
-       
-      
-       ctx.setAttribute("org.onap.appc.adapter.ansible.result.code", Integer.toString(400));
-       ctx.setAttribute("org.onap.appc.adapter.ansible.message",message);
-       ctx.setAttribute("org.onap.appc.adapter.ansible.results", results);
-       ctx.setStatus(OUTCOME_SUCCESS);
-    }
-    
-
-    // Public method to get logs  from plyabook execution for a  specifcic 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
-    
-    public void reqExecLog(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException{
-
-
-       // Get uri
-       String ReqUri = "";
-       try{
-           ReqUri = messageProcessor.ReqUri_Log(params);
-           logger.info("Retreiving results from " + ReqUri); 
-       }
-       catch(Exception e){
-           doFailure(ctx, AnsibleResultCodes.INVALID_PAYLOAD.getValue(), e.getMessage());
-       }
-
-       int code = -1;
-       String message = "";
-       float Duration = -1;
-       
-       try{
-           // Try to  retreive the test results (modify the url for that)
-           AnsibleResult testresult = queryServer(ReqUri, params.get("User"), params.get("Password"));
-           code = testresult.getStatusCode();
-           message = testresult.getStatusMessage();
-
-           logger.info("Request output = " + message);
-
-       }
-       catch (Exception e){
-           doFailure(ctx, AnsibleResultCodes.UNKNOWN_EXCEPTION.getValue(), "Exception encountered retreiving output : " + e.getMessage());
-       }
-       
-       ctx.setAttribute("org.onap.appc.adapter.ansible.log",message);
-       ctx.setStatus(OUTCOME_SUCCESS);
+        // In case of 200,400,FINISHED return 400
+        ctx.setAttribute(RESULT_CODE_ATTRIBUTE_NAME, "400");
+        ctx.setAttribute(MESSAGE_ATTRIBUTE_NAME, message);
+        ctx.setAttribute(RESULTS_ATTRIBUTE_NAME, results);
+        ctx.setAttribute(OUTPUT_ATTRIBUTE_NAME, output);
+        ctx.setStatus(OUTCOME_SUCCESS);
     }
-    
 
-    
+    /**
+     * 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
+     */
+    @Override
+    public void reqExecLog(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
+
+        String reqUri = StringUtils.EMPTY;
+        try {
+            reqUri = messageProcessor.reqUriLog(params);
+            logger.info("Retrieving results from " + reqUri);
+        } catch (Exception e) {
+            logger.error("Exception caught", e);
+            doFailure(ctx, AnsibleResultCodes.INVALID_PAYLOAD.getValue(), e.getMessage());
+        }
+
+        String message = StringUtils.EMPTY;
+        try {
+            // Try to retrieve the test results (modify the url for that)
+            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);
+            ctx.setStatus(OUTCOME_SUCCESS);
+        } catch (Exception e) {
+            logger.error("Exception caught", e);
+            doFailure(ctx, AnsibleResultCodes.UNKNOWN_EXCEPTION.getValue(),
+                    "Exception encountered retreiving output : " + e.getMessage());
+        }
+    }
 
-       
     /**
      * Method that posts the request
-     **/
-    
-    private AnsibleResult  postExecRequest(String AgentUrl, String Payload, String User, String Password)  {
-       
-       String reqOutput = "UNKNOWN";
-       int    reqStatus = -1;
-
-       AnsibleResult testresult;
-       
-       if (!testMode){
-           http_client.setHttpContext(User, Password);
-           testresult  = http_client.Post(AgentUrl, Payload);
-       }
-       else{
-           testresult = testServer.Post(AgentUrl, Payload);
-       }
-          
-       return testresult;
-    }
-    
-
-    /* 
-       Method to query Ansible server
-
-    */
-    private AnsibleResult queryServer(String AgentUrl, String User, String Password) {
-
-       String testOutput = "UNKNOWN";
-       int    testStatus = -1;
-       AnsibleResult testresult;
-       
-       logger.info("Querying url = " + AgentUrl);
-
-       if (!testMode){
-           testresult = http_client.Get(AgentUrl);
-       }
-       else{
-           testresult = testServer.Get(AgentUrl);
-       }
-       
-       return testresult;
-       
+     */
+    private AnsibleResult postExecRequest(String agentUrl, String payload, String user, String password,
+            SvcLogicContext ctx) {
+
+        AnsibleResult testResult = null;
+        ConnectionBuilder httpClient = getHttpConn(defaultSocketTimeout, "");
+        if (!testMode) {
+          if(httpClient!=null) {
+            httpClient.setHttpContext(user, password);
+            testResult = httpClient.post(agentUrl, payload);
+            httpClient.close();
+          }
+        } else {
+            testResult = testServer.Post(agentUrl, payload);
+        }
+        return testResult;
     }
 
+    /**
+     * Method to query Ansible server
+     */
+    private AnsibleResult queryServer(String agentUrl, String user, String password, SvcLogicContext ctx) {
+
+        AnsibleResult testResult = new AnsibleResult();
+        int timeout = 600 * 1000;
+        try {
+            timeout = Integer.parseInt(ctx.getAttribute("AnsibleTimeout")) * 1000;
+
+        } catch (Exception e) {
+            timeout = defaultTimeout;
+        }
+        long endTime = System.currentTimeMillis() + timeout;
+
+        while (System.currentTimeMillis() < endTime) {
+            String serverIP = ctx.getAttribute("ServerIP");
+            ConnectionBuilder httpClient = getHttpConn(defaultSocketTimeout, serverIP);
+            logger.info("Querying ansible GetResult URL = " + agentUrl);
+
+            if (!testMode) {
+              if(httpClient!=null) {
+                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) {
+              logger.error("Thread Interrupted Exception", ex);
+              Thread.currentThread().interrupt();
+            }
 
+        }
+        if (testResult.getStatusCode() == AnsibleResultCodes.PENDING.getValue()) {
+            testResult.setStatusCode(AnsibleResultCodes.IO_EXCEPTION.getValue());
+            testResult.setStatusMessage("Request timed out");
+        }
 
+        return testResult;
+    }
 }