2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Copyright (C) 2017 Amdocs
8 * =============================================================================
9 * Modifications Copyright (C) 2019 IBM
10 * =============================================================================
11 * Modifications Copyright (C) 2019 Orange
12 * =============================================================================
13 * Licensed under the Apache License, Version 2.0 (the "License");
14 * you may not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
17 * http://www.apache.org/licenses/LICENSE-2.0
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS,
21 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
25 * ============LICENSE_END=========================================================
28 package org.onap.appc.adapter.ansible.impl;
32 import java.util.HashMap;
33 import java.util.Properties;
35 import org.apache.commons.lang.StringUtils;
36 import org.json.JSONException;
37 import org.json.JSONObject;
38 import org.json.JSONArray;
39 import org.onap.appc.adapter.ansible.AnsibleAdapter;
40 import org.onap.appc.adapter.ansible.model.AnsibleMessageParser;
41 import org.onap.appc.adapter.ansible.model.AnsibleResult;
42 import org.onap.appc.adapter.ansible.model.AnsibleResultCodes;
43 import org.onap.appc.adapter.ansible.model.AnsibleServerEmulator;
44 import org.onap.appc.exceptions.APPCException;
45 import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
46 import org.onap.ccsdk.sli.core.sli.SvcLogicException;
48 import com.att.eelf.configuration.EELFLogger;
49 import com.att.eelf.configuration.EELFManager;
50 import org.onap.appc.encryption.EncryptionTool;
53 * This class implements the {@link AnsibleAdapter} interface. This interface
54 * defines the behaviors that our service provides.
56 public class AnsibleAdapterImpl implements AnsibleAdapter {
59 * The constant used to define the service name in the mapped diagnostic context
61 @SuppressWarnings("nls")
62 public static final String MDC_SERVICE = "service";
65 * The constant for the status code for a failed outcome
67 @SuppressWarnings("nls")
68 public static final String OUTCOME_FAILURE = "failure";
71 * The constant for the status code for a successful outcome
73 @SuppressWarnings("nls")
74 public static final String OUTCOME_SUCCESS = "success";
79 private static final String ADAPTER_NAME = "Ansible Adapter";
80 private static final String APPC_EXCEPTION_CAUGHT = "APPCException caught";
82 private static final String RESULT_CODE_ATTRIBUTE_NAME = "org.onap.appc.adapter.ansible.result.code";
83 private static final String MESSAGE_ATTRIBUTE_NAME = "org.onap.appc.adapter.ansible.message";
84 private static final String RESULTS_ATTRIBUTE_NAME = "org.onap.appc.adapter.ansible.results";
85 private static final String OUTPUT_ATTRIBUTE_NAME = "org.onap.appc.adapter.ansible.output";
86 private static final String ID_ATTRIBUTE_NAME = "org.onap.appc.adapter.ansible.Id";
87 private static final String LOG_ATTRIBUTE_NAME = "org.onap.appc.adapter.ansible.log";
89 private static final String CLIENT_TYPE_PROPERTY_NAME = "org.onap.appc.adapter.ansible.clientType";
90 private static final String TRUSTSTORE_PROPERTY_NAME = "org.onap.appc.adapter.ansible.trustStore";
91 private static final String TRUSTPASSWD_PROPERTY_NAME = "org.onap.appc.adapter.ansible.trustStore.trustPasswd";
92 private static final String TIMEOUT_PROPERTY_NAME = "org.onap.appc.adapter.ansible.timeout";
93 private static final String POLL_INTERVAL_PROPERTY_NAME = "org.onap.appc.adapter.ansible.pollInterval";
94 private static final String SOCKET_TIMEOUT_PROPERTY_NAME = "org.onap.appc.adapter.ansible.socketTimeout";
95 private static final String PASSWORD = "Password";
96 private static final String APPC_PROPS = "/appc.properties";
97 private static final String SDNC_CONFIG_DIR = "SDNC_CONFIG_DIR";
98 private static final String propDir = System.getenv(SDNC_CONFIG_DIR);
99 private static final String SERVERIP = "ServerIP";
100 private Properties props;
101 private int defaultTimeout = 600 * 1000;
102 private int defaultSocketTimeout = 60 * 1000;
103 private int defaultPollInterval = 60 * 1000;
106 * The logger to be used
108 private static final EELFLogger logger = EELFManager.getInstance().getLogger(AnsibleAdapterImpl.class);
112 private ConnectionBuilder httpClient;
115 * Ansible API Message Handlers
117 private AnsibleMessageParser messageProcessor;
120 * indicator whether in test mode
122 private boolean testMode = false;
125 * server emulator object to be used if in test mode
127 private AnsibleServerEmulator testServer;
130 * This default constructor is used as a work around because the activator
131 * wasn't getting called
133 public AnsibleAdapterImpl() {
138 * Used for jUnit test and testing interface
140 public AnsibleAdapterImpl(boolean mode) {
142 testServer = new AnsibleServerEmulator();
143 messageProcessor = new AnsibleMessageParser();
147 * Returns the symbolic name of the adapter
149 * @return The adapter name
150 * @see org.onap.appc.adapter.rest.AnsibleAdapter#getAdapterName()
153 public String getAdapterName() {
159 * Method posts info to Context memory in case of an error and throws
160 * a SvcLogicException causing SLI to register this as a failure
162 @SuppressWarnings("static-method")
163 private void doFailure(SvcLogicContext svcLogic, int code, String message) throws SvcLogicException {
165 svcLogic.setStatus(OUTCOME_FAILURE);
166 svcLogic.setAttribute(RESULT_CODE_ATTRIBUTE_NAME, Integer.toString(code));
167 svcLogic.setAttribute(MESSAGE_ATTRIBUTE_NAME, message);
169 throw new SvcLogicException("Ansible Adapter Error = " + message);
173 * initialize the Ansible adapter based on default and over-ride configuration
176 private void initialize() {
177 String path = propDir + APPC_PROPS;
178 File propFile = new File(path);
179 props = new Properties();
181 InputStream input = new FileInputStream(propFile);
183 } catch (Exception ex) {
184 logger.error("Error while reading appc.properties file" + ex.getMessage());
186 // Create the message processor instance
187 messageProcessor = new AnsibleMessageParser();
188 //continuing for checking timeout
190 String timeoutStr = props.getProperty(TIMEOUT_PROPERTY_NAME);
191 defaultTimeout = Integer.parseInt(timeoutStr) * 1000;
193 } catch (Exception e) {
194 defaultTimeout = 600 * 1000;
195 logger.error("Error while reading time out property" , e);
197 //continuing for checking timeout
199 String timeoutStr = props.getProperty(SOCKET_TIMEOUT_PROPERTY_NAME);
200 defaultSocketTimeout = Integer.parseInt(timeoutStr) * 1000;
202 } catch (Exception e) {
203 defaultSocketTimeout = 60 * 1000;
204 logger.error("Error while reading socket time out property" , e);
206 //continuing for checking timeout
208 String timeoutStr = props.getProperty(POLL_INTERVAL_PROPERTY_NAME);
209 defaultPollInterval = Integer.parseInt(timeoutStr) * 1000;
211 } catch (Exception e) {
212 defaultPollInterval = 60 * 1000;
213 logger.error("Error while reading poll interval property" , e);
215 logger.info("Initialized Ansible Adapter");
218 private ConnectionBuilder getHttpConn(int timeout, String serverIP) {
220 String path = propDir + APPC_PROPS;
221 File propFile = new File(path);
222 props = new Properties();
225 input = new FileInputStream(propFile);
227 } catch (Exception ex) {
228 // TODO Auto-generated catch block
229 logger.error("Error while reading appc.properties file" + ex.getMessage());
231 // Create the http client instance
232 // type of client is extracted from the property file parameter
233 // org.onap.appc.adapter.ansible.clientType
235 // 1. TRUST_ALL (trust all SSL certs). To be used ONLY in dev
236 // 2. TRUST_CERT (trust only those whose certificates have been stored in the
238 // 3. DEFAULT (trust only well known certificates). This is standard behavior to
240 // revert. To be used in PROD
241 ConnectionBuilder httpClientLocal = null;
243 String clientType = props.getProperty(CLIENT_TYPE_PROPERTY_NAME);
244 logger.info("Ansible http client type set to " + clientType);
246 if ("TRUST_ALL".equals(clientType)) {
248 "Creating http client to trust ALL ssl certificates. WARNING. This should be done only in dev environments");
249 httpClientLocal = new ConnectionBuilder(1, timeout);
250 } else if ("TRUST_CERT".equals(clientType)) {
251 // set path to keystore file
252 String trustStoreFile = props.getProperty(TRUSTSTORE_PROPERTY_NAME);
253 String key = props.getProperty(TRUSTPASSWD_PROPERTY_NAME);
254 char[] trustStorePasswd = EncryptionTool.getInstance().decrypt(key).toCharArray();
255 logger.info("Creating http client with trustmanager from " + trustStoreFile);
256 httpClientLocal = new ConnectionBuilder(trustStoreFile, trustStorePasswd, timeout, serverIP);
258 logger.info("Creating http client with default behaviour");
259 httpClientLocal = new ConnectionBuilder(0, timeout);
261 } catch (Exception e) {
262 logger.error("Error Getting HTTP Connection Builder due to Unknown Exception", e);
265 logger.info("Got HTTP Connection Builder");
266 return httpClientLocal;
269 // Public Method to post request to execute playbook. Posts the following back
270 // to Svc context memory
271 // org.onap.appc.adapter.ansible.req.code : 100 if successful
272 // org.onap.appc.adapter.ansible.req.messge : any message
273 // org.onap.appc.adapter.ansible.req.Id : a unique uuid to reference the request
275 public void reqExec(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
277 String playbookName = StringUtils.EMPTY;
278 String payload = StringUtils.EMPTY;
279 String agentUrl = StringUtils.EMPTY;
280 String user = StringUtils.EMPTY;
281 String password = StringUtils.EMPTY;
282 String id = StringUtils.EMPTY;
283 String timeout = StringUtils.EMPTY;
284 JSONObject jsonPayload;
287 // create json object to send request
288 jsonPayload = messageProcessor.reqMessage(params);
290 logger.info("Initial Payload = " + jsonPayload.toString());
291 agentUrl = (String) jsonPayload.remove("AgentUrl");
292 user = (String) jsonPayload.remove("User");
293 password = (String)jsonPayload.remove(PASSWORD);
294 if(StringUtils.isNotBlank(password))
295 password = EncryptionTool.getInstance().decrypt(password);
296 id = jsonPayload.getString("Id");
297 timeout = jsonPayload.getString("Timeout");
298 if (StringUtils.isBlank(timeout))
301 String autoNodeList = (String) jsonPayload.remove("AutoNodeList");
302 if (autoNodeList != null && Boolean.parseBoolean(autoNodeList)) {
303 JSONArray generatedNodeList = generateNodeList(params, ctx);
304 if (generatedNodeList.length() > 0) {
305 jsonPayload.put("NodeList", generatedNodeList);
306 jsonPayload.put("InventoryNames", "VM");
308 doFailure(ctx, AnsibleResultCodes.INVALID_PAYLOAD.getValue(),
309 "Auto generation of Node List Failed - no elements on the list");
312 logger.debug("Auto Node List is DISABLED");
314 payload = jsonPayload.toString();
315 ctx.setAttribute("AnsibleTimeout", timeout);
316 logger.info("Updated Payload = " + payload + " timeout = " + timeout);
317 } catch (APPCException e) {
318 logger.error(APPC_EXCEPTION_CAUGHT, e);
319 doFailure(ctx, AnsibleResultCodes.INVALID_PAYLOAD.getValue(),
320 "Error constructing request for execution of playbook due to missing mandatory parameters. Reason = "
322 } catch (JSONException e) {
323 logger.error("JSONException caught", e);
324 doFailure(ctx, AnsibleResultCodes.INVALID_PAYLOAD.getValue(),
325 "Error constructing request for execution of playbook due to invalid JSON block. Reason = "
327 } catch (NumberFormatException e) {
328 logger.error("NumberFormatException caught", e);
329 doFailure(ctx, AnsibleResultCodes.INVALID_PAYLOAD.getValue(),
330 "Error constructing request for execution of playbook due to invalid parameter values. Reason = "
335 String message = StringUtils.EMPTY;
338 // post the test request
339 logger.info("Posting ansible request = " + payload + " to url = " + agentUrl);
340 AnsibleResult testResult = postExecRequest(agentUrl, payload, user, password,ctx);
341 if (testResult != null) {
342 logger.info("Received response on ansible post request " + testResult.getStatusMessage());
343 // Process if HTTP was successful
344 if (testResult.getStatusCode() == 200) {
345 testResult = messageProcessor.parsePostResponse(testResult.getStatusMessage());
347 doFailure(ctx, testResult.getStatusCode(),
348 "Error posting request. Reason = " + testResult.getStatusMessage());
350 String output = StringUtils.EMPTY;
351 code = testResult.getStatusCode();
352 message = testResult.getStatusMessage();
353 output = testResult.getOutput();
354 ctx.setAttribute(OUTPUT_ATTRIBUTE_NAME, output);
355 String serverIp = testResult.getServerIp();
356 if (StringUtils.isBlank(serverIp))
357 ctx.setAttribute(SERVERIP, serverIp);
359 ctx.setAttribute(SERVERIP, "");
360 // Check status of test request returned by Agent
361 if (code == AnsibleResultCodes.PENDING.getValue()) {
362 logger.info(String.format("Submission of Test %s successful.", playbookName));
363 // test request accepted. We are in asynchronous case
365 doFailure(ctx, code, "Request for execution of playbook rejected. Reason = " + message);
368 doFailure(ctx, code, "Ansible Test result is null");
370 } catch (APPCException e) {
371 logger.error(APPC_EXCEPTION_CAUGHT, e);
372 doFailure(ctx, AnsibleResultCodes.UNKNOWN_EXCEPTION.getValue(),
373 "Exception encountered when posting request for execution of playbook. Reason = " + e.getMessage());
376 ctx.setAttribute(RESULT_CODE_ATTRIBUTE_NAME, Integer.toString(code));
377 ctx.setAttribute(MESSAGE_ATTRIBUTE_NAME, message);
378 ctx.setAttribute(ID_ATTRIBUTE_NAME, id);
382 * Method is used to automatically generate NodeList section base on the svc context
384 * @see org.onap.appc.adapter.ansible.AnsibleAdapter#reqExecResult(java.util.Map,
385 * org.onap.ccsdk.sli.core.sli.SvcLogicContext)
387 private JSONArray generateNodeList(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
388 String vfModuleId = params.get("vf-module-id");
389 String vnfcName = params.get("vnfc-name");
390 String vServerId = params.get("vserver-id");
391 String vnfcType = params.get("vnfc-type");
392 logger.info("GENERATING NODE LIST");
393 JSONArray result = new JSONArray();
395 if (vServerId != null && !vServerId.equals(""))
396 logger.debug("Auto Node List filtering parameter vserver-id " + vServerId);
399 if (vnfcName != null && !vnfcName.equals(""))
400 logger.debug("Auto Node List filtering parameter vnfc-name " + vnfcName);
403 if (vnfcType != null && !vnfcType.equals(""))
404 logger.debug("Auto Node List filtering parameter vnfc-type " + vnfcType);
407 if (vfModuleId != null && !vfModuleId.equals(""))
408 logger.debug("Auto Node List filtering parameter vf-module-id " + vfModuleId);
412 Map<String, JSONObject> candidates = new HashMap<String, JSONObject>();
413 for (int i = 0; ; i++) {
414 String vmKey = "tmp.vnfInfo.vm[" + Integer.toString(i) + "]";
415 logger.info("Looking for attributes of: " + vmKey);
416 if (ctx.getAttribute(vmKey + ".vnfc-name") != null) {
417 String vmVnfcName = ctx.getAttribute(vmKey + ".vnfc-name");
418 String vmVnfcIpv4Address = ctx.getAttribute(vmKey + ".vnfc-ipaddress-v4-oam-vip");
419 String vmVnfcType = ctx.getAttribute(vmKey + ".vnfc-type");
421 if (vmVnfcName != null && vmVnfcIpv4Address != null && vmVnfcType != null
422 && !vmVnfcName.equals("") && !vmVnfcIpv4Address.equals("") && !vmVnfcType.equals("")) {
423 if (vServerId != null) {
424 String vmVserverId = ctx.getAttribute(vmKey + ".vserver-id");
425 if (vmVserverId == null || !vmVserverId.equals(vServerId)) {
426 logger.debug("Auto Node List candidate " + vmVnfcName + " dropped. vserver-id mismatch");
430 if (vfModuleId != null) {
431 String vmVfModuleId = ctx.getAttribute(vmKey + ".vf-module-id");
432 if (vmVfModuleId == null || !vmVfModuleId.equals(vfModuleId)) {
433 logger.debug("Auto Node List candidate " + vmVnfcName + " dropped. vf-module-id mismatch");
437 if (vnfcName != null) {
438 if (!vmVnfcName.equals(vnfcName)) {
439 logger.debug("Auto Node List candidate " + vmVnfcName + " dropped. vnfc-name mismatch");
443 if (vnfcType != null) {
444 if (!vmVnfcType.equals(vnfcType)) {
445 logger.debug("Auto Node List candidate " + vmVnfcType + " dropped. vnfc-type mismatch");
450 logger.info("Auto Node List candidate " + vmVnfcName + " [" + vmVnfcIpv4Address + "," + vmVnfcType + "]");
452 JSONObject vnfTypeCandidates = null;
453 JSONArray vmList = null;
454 if (!candidates.containsKey(vmVnfcType)) {
455 vnfTypeCandidates = new JSONObject();
456 vmList = new JSONArray();
457 vnfTypeCandidates.put("site", "site");
458 vnfTypeCandidates.put("vnfc-type", vmVnfcType);
459 vnfTypeCandidates.put("vm-info", vmList);
460 candidates.put(vmVnfcType, vnfTypeCandidates);
462 vnfTypeCandidates = candidates.get(vmVnfcType);
463 vmList = (JSONArray) vnfTypeCandidates.get("vm-info");
466 JSONObject candidate = new JSONObject();
467 candidate.put("ne_id", vmVnfcName);
468 candidate.put("fixed_ip_address", vmVnfcIpv4Address);
469 vmList.put(candidate);
471 logger.warn("Incomplete information for Auto Node List candidate " + vmKey);
477 for(JSONObject vnfcCandidates : candidates.values()) {
478 result.put(vnfcCandidates);
481 logger.info("GENERATING NODE LIST COMPLETED");
486 * Public method to query status of a specific request It blocks till the
487 * Ansible Server responds or the session times out (non-Javadoc)
489 * @see org.onap.appc.adapter.ansible.AnsibleAdapter#reqExecResult(java.util.Map,
490 * org.onap.ccsdk.sli.core.sli.SvcLogicContext)
493 public void reqExecResult(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
496 String reqUri = StringUtils.EMPTY;
499 String serverIp = ctx.getAttribute(SERVERIP);
500 if (StringUtils.isNotBlank(serverIp))
501 reqUri = messageProcessor.reqUriResultWithIP(params, serverIp);
503 reqUri = messageProcessor.reqUriResult(params);
504 logger.info("Got uri " + reqUri);
505 } catch (APPCException e) {
506 logger.error(APPC_EXCEPTION_CAUGHT, e);
507 doFailure(ctx, AnsibleResultCodes.INVALID_PAYLOAD.getValue(),
508 "Error constructing request to retrieve result due to missing parameters. Reason = "
511 } catch (NumberFormatException e) {
512 logger.error("NumberFormatException caught", e);
513 doFailure(ctx, AnsibleResultCodes.INVALID_PAYLOAD.getValue(),
514 "Error constructing request to retrieve result due to invalid parameters value. Reason = "
520 String message = StringUtils.EMPTY;
521 String results = StringUtils.EMPTY;
522 String output = StringUtils.EMPTY;
524 // Try to retrieve the test results (modify the URL for that)
525 AnsibleResult testResult = queryServer(reqUri, params.get("User"),
526 EncryptionTool.getInstance().decrypt(params.get(PASSWORD)), ctx);
527 code = testResult.getStatusCode();
528 message = testResult.getStatusMessage();
530 if (code == 200 || code == 400 || "FINISHED".equalsIgnoreCase(message)) {
531 logger.info("Parsing response from ansible Server = " + message);
532 // Valid HTTP. process the Ansible message
533 testResult = messageProcessor.parseGetResponse(message);
534 code = testResult.getStatusCode();
535 message = testResult.getStatusMessage();
536 results = testResult.getResults();
537 output = testResult.getOutput();
538 ctx.setAttribute(OUTPUT_ATTRIBUTE_NAME, output);
540 logger.info("Request response = " + message);
541 } catch (APPCException e) {
542 doFailure(ctx, AnsibleResultCodes.UNKNOWN_EXCEPTION.getValue(),
543 "Exception encountered retrieving result : " + e.getMessage());
547 // We were able to get and process the results. Determine if playbook succeeded
549 if (code == AnsibleResultCodes.FINAL_SUCCESS.getValue()) {
550 message = String.format("Ansible Request %s finished with Result = %s, Message = %s", params.get("Id"),
551 OUTCOME_SUCCESS, message);
552 logger.info(message);
554 logger.info(String.format("Ansible Request %s finished with Result %s, Message = %s", params.get("Id"),
555 OUTCOME_FAILURE, message));
556 ctx.setAttribute(RESULTS_ATTRIBUTE_NAME, results);
557 ctx.setAttribute(OUTPUT_ATTRIBUTE_NAME, output);
558 doFailure(ctx, code, message);
562 // In case of 200,400,FINISHED return 400
563 ctx.setAttribute(RESULT_CODE_ATTRIBUTE_NAME, "400");
564 ctx.setAttribute(MESSAGE_ATTRIBUTE_NAME, message);
565 ctx.setAttribute(RESULTS_ATTRIBUTE_NAME, results);
566 ctx.setAttribute(OUTPUT_ATTRIBUTE_NAME, output);
567 ctx.setStatus(OUTCOME_SUCCESS);
571 * Public method to get logs from playbook execution for a specific request
573 * It blocks till the Ansible Server responds or the session times out very
574 * similar to reqExecResult logs are returned in the DG context variable
575 * org.onap.appc.adapter.ansible.log
578 public void reqExecLog(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
580 String reqUri = StringUtils.EMPTY;
582 reqUri = messageProcessor.reqUriLog(params);
583 logger.info("Retrieving results from " + reqUri);
584 } catch (Exception e) {
585 logger.error("Exception caught", e);
586 doFailure(ctx, AnsibleResultCodes.INVALID_PAYLOAD.getValue(), e.getMessage());
589 String message = StringUtils.EMPTY;
591 // Try to retrieve the test results (modify the url for that)
592 AnsibleResult testResult = queryServer(reqUri, params.get("User"),
593 EncryptionTool.getInstance().decrypt(params.get(PASSWORD)), ctx);
594 message = testResult.getStatusMessage();
595 logger.info("Request output = " + message);
596 ctx.setAttribute(LOG_ATTRIBUTE_NAME, message);
597 ctx.setStatus(OUTCOME_SUCCESS);
598 } catch (Exception e) {
599 logger.error("Exception caught", e);
600 doFailure(ctx, AnsibleResultCodes.UNKNOWN_EXCEPTION.getValue(),
601 "Exception encountered retreiving output : " + e.getMessage());
606 * Method that posts the request
608 private AnsibleResult postExecRequest(String agentUrl, String payload, String user, String password,
609 SvcLogicContext ctx) {
611 AnsibleResult testResult = null;
612 ConnectionBuilder httpClientLocal = getHttpConn(defaultSocketTimeout, "");
614 if(httpClientLocal!=null) {
615 httpClientLocal.setHttpContext(user, password);
616 testResult = httpClientLocal.post(agentUrl, payload);
617 httpClientLocal.close();
620 testResult = testServer.post(agentUrl, payload);
626 * Method to query Ansible server
628 private AnsibleResult queryServer(String agentUrl, String user, String password, SvcLogicContext ctx) {
630 AnsibleResult testResult = new AnsibleResult();
631 int timeout = 600 * 1000;
633 timeout = Integer.parseInt(ctx.getAttribute("AnsibleTimeout")) * 1000;
635 } catch (Exception e) {
636 timeout = defaultTimeout;
638 long endTime = System.currentTimeMillis() + timeout;
640 while (System.currentTimeMillis() < endTime) {
641 String serverIP = ctx.getAttribute(SERVERIP);
642 ConnectionBuilder httpClientLocal = getHttpConn(defaultSocketTimeout, serverIP);
643 logger.info("Querying ansible GetResult URL = " + agentUrl);
646 if(httpClientLocal!=null) {
647 httpClientLocal.setHttpContext(user, password);
648 testResult = httpClientLocal.get(agentUrl);
649 httpClientLocal.close();
652 testResult = testServer.get(agentUrl);
654 if (testResult.getStatusCode() != AnsibleResultCodes.IO_EXCEPTION.getValue()
655 && testResult.getStatusCode() != AnsibleResultCodes.PENDING.getValue()) {
660 Thread.sleep(defaultPollInterval);
661 } catch (InterruptedException ex) {
662 logger.error("Thread Interrupted Exception", ex);
663 Thread.currentThread().interrupt();
667 if (testResult.getStatusCode() == AnsibleResultCodes.PENDING.getValue()) {
668 testResult.setStatusCode(AnsibleResultCodes.IO_EXCEPTION.getValue());
669 testResult.setStatusMessage("Request timed out");