69b57f7ce0f9c220a6047b488c0e1db88568ea55
[appc.git] / appc-adapters / appc-chef-adapter / appc-chef-adapter-bundle / src / main / java / org / onap / appc / adapter / chef / impl / ChefAdapterImpl.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP : APPC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Copyright (C) 2017 Amdocs
8  * =============================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22  * ============LICENSE_END=========================================================
23  */
24 package org.onap.appc.adapter.chef.impl;
25
26 import java.io.File;
27 import java.util.Arrays;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Properties;
31 import org.apache.commons.lang.StringUtils;
32 import org.apache.http.HttpEntity;
33 import org.apache.http.HttpResponse;
34 import org.apache.http.client.methods.HttpGet;
35 import org.apache.http.impl.client.CloseableHttpClient;
36 import org.apache.http.impl.client.HttpClients;
37 import org.apache.http.util.EntityUtils;
38 import org.json.JSONException;
39 import org.json.JSONObject;
40 import org.onap.appc.adapter.chef.ChefAdapter;
41 import org.onap.appc.adapter.chef.chefclient.api.ChefApiClient;
42 import org.onap.appc.adapter.chef.chefclient.ChefApiClientFactory;
43 import org.onap.appc.adapter.chef.chefclient.api.ChefResponse;
44 import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
45 import org.onap.ccsdk.sli.core.sli.SvcLogicException;
46 import com.att.eelf.configuration.EELFLogger;
47 import com.att.eelf.configuration.EELFManager;
48
49 /**
50  * This class implements the {@link ChefAdapter} interface. This interface defines the behaviors that our service
51  * provides.
52  */
53 public class ChefAdapterImpl implements ChefAdapter {
54
55     // chef server Initialize variable
56     private String username = StringUtils.EMPTY;
57     private String clientPrivatekey = StringUtils.EMPTY;
58     private String chefserver = StringUtils.EMPTY;
59     private String serverAddress = StringUtils.EMPTY;
60     private String organizations = StringUtils.EMPTY;
61
62     @SuppressWarnings("nls")
63     public static final String MDC_ADAPTER = "adapter";
64
65     @SuppressWarnings("nls")
66     public static final String MDC_SERVICE = "service";
67
68     @SuppressWarnings("nls")
69     public static final String OUTCOME_FAILURE = "failure";
70
71     @SuppressWarnings("nls")
72     public static final String OUTCOME_SUCCESS = "success";
73
74     @SuppressWarnings("nls")
75     public static final String PROPERTY_PROVIDER = "provider";
76
77     @SuppressWarnings("nls")
78     public static final String PROPERTY_PROVIDER_IDENTITY = "identity";
79
80     @SuppressWarnings("nls")
81     public static final String PROPERTY_PROVIDER_NAME = "name";
82
83     @SuppressWarnings("nls")
84     public static final String PROPERTY_PROVIDER_TENANT = "tenant";
85
86     @SuppressWarnings("nls")
87     public static final String PROPERTY_PROVIDER_TENANT_NAME = "name";
88
89     @SuppressWarnings("nls")
90     public static final String PROPERTY_PROVIDER_TENANT_PASSWORD = "password"; // NOSONAR
91
92     @SuppressWarnings("nls")
93     public static final String PROPERTY_PROVIDER_TENANT_USERID = "userid";
94
95     @SuppressWarnings("nls")
96     public static final String PROPERTY_PROVIDER_TYPE = "type";
97
98
99     private static final EELFLogger logger = EELFManager.getInstance().getLogger(ChefAdapterImpl.class);
100
101     private static final String CANNOT_FIND_PRIVATE_KEY_STR =
102         "Cannot find the private key in the APPC file system, please load the private key to ";
103
104     private static final String POSTING_REQUEST_JSON_ERROR_STR = "Error posting request due to invalid JSON block: ";
105     private static final String POSTING_REQUEST_ERROR_STR = "Error posting request: ";
106     private static final String CHEF_CLIENT_RESULT_CODE_STR = "chefClientResult.code";
107     private static final String CHEF_SERVER_RESULT_CODE_STR = "chefServerResult.code";
108     private static final String CHEF_CLIENT_RESULT_MSG_STR = "chefClientResult.message";
109     private static final String CHEF_SERVER_RESULT_MSG_STR = "chefServerResult.message";
110     private static final String CHEF_ACTION_STR = "chefAction";
111     private static final String NODE_LIST_STR = "NodeList";
112     private ChefApiClientFactory chefApiClientFactory = new ChefApiClientFactory();
113
114     /**
115      * This default constructor is used as a work around because the activator wasnt getting called
116      */
117     public ChefAdapterImpl() {
118         logger.info("Initialize Chef Adapter");
119     }
120
121     @SuppressWarnings("nls")
122     @Override
123     public void vnfcEnvironment(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
124         int code;
125         try {
126             logger.info("environment of VNF-C");
127             chefInfo(params, ctx);
128             RequestContext rc = new RequestContext(ctx);
129             logger.info("Context" + ctx);
130             rc.isAlive();
131             String env = params.get("Environment");
132             logger.info("Environmnet" + env);
133             if (env.equals(StringUtils.EMPTY)) {
134                 chefServerResult(rc, 200, "Skip Environment block ");
135             } else {
136                 JSONObject envJ = new JSONObject(env);
137                 String envName = envJ.getString("name");
138                 String message;
139                 if (privateKeyCheck()) {
140                     // update the details of an environment on the Chef server.
141                     ChefApiClient chefApiClient = chefApiClientFactory.create(chefserver, organizations, username, clientPrivatekey);
142                     ChefResponse chefResponse = chefApiClient.put("/environments/" + envName, env);
143                     code = chefResponse.getStatusCode();
144                     message = chefResponse.getBody();
145                     if (code == 404) {
146                         // need create a new environment
147                         chefResponse = chefApiClient.post("/environments", env);
148                         code = chefResponse.getStatusCode();
149                         message = chefResponse.getBody();
150                         logger.info("requestbody {}", chefResponse.getBody());
151                     }
152
153                 } else {
154                     code = 500;
155                     message = CANNOT_FIND_PRIVATE_KEY_STR + clientPrivatekey;
156                     doFailure(ctx, code, message);
157                 }
158                 chefServerResult(rc, code, message);
159             }
160         } catch (JSONException e) {
161             code = 401;
162             logger.error(POSTING_REQUEST_JSON_ERROR_STR, e);
163             doFailure(ctx, code, POSTING_REQUEST_JSON_ERROR_STR + e.getMessage());
164         } catch (Exception e) {
165             code = 401;
166             logger.error(POSTING_REQUEST_ERROR_STR, e);
167             doFailure(ctx, code, POSTING_REQUEST_ERROR_STR + e.getMessage());
168         }
169     }
170
171     @SuppressWarnings("nls")
172     @Override
173     public void vnfcNodeobjects(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
174         logger.info("update the nodeObjects of VNF-C");
175         int code;
176         try {
177             chefInfo(params, ctx);
178             String nodeListS = params.get(NODE_LIST_STR);
179             String nodeS = params.get("Node");
180             if (StringUtils.isNotBlank(nodeListS) && StringUtils.isNotBlank(nodeS)) {
181                 nodeListS = nodeListS.replace("[", StringUtils.EMPTY);
182                 nodeListS = nodeListS.replace("]", StringUtils.EMPTY);
183                 nodeListS = nodeListS.replace("\"", StringUtils.EMPTY);
184                 nodeListS = nodeListS.replace(" ", StringUtils.EMPTY);
185                 List<String> nodes = Arrays.asList(nodeListS.split("\\s*,\\s*"));
186                 RequestContext rc = new RequestContext(ctx);
187                 rc.isAlive();
188                 code = 200;
189                 String message = null;
190                 if (privateKeyCheck()) {
191                     ChefApiClient cac = chefApiClientFactory.create(chefserver, organizations, username, clientPrivatekey);
192
193                     for (String nodeName: nodes) {
194                         JSONObject nodeJ = new JSONObject(nodeS);
195                         nodeJ.remove("name");
196                         nodeJ.put("name", nodeName);
197                         String nodeObject = nodeJ.toString();
198                         logger.info(nodeObject);
199                         ChefResponse chefResponse = cac.put("/nodes/" + nodeName, nodeObject);
200                         code = chefResponse.getStatusCode();
201                         message = chefResponse.getBody();
202                         if (code != 200) {
203                             break;
204                         }
205                     }
206                 } else {
207                     code = 500;
208                     message = CANNOT_FIND_PRIVATE_KEY_STR + clientPrivatekey;
209                     doFailure(ctx, code, message);
210                 }
211                 chefServerResult(rc, code, message);
212             } else {
213                 throw new SvcLogicException("Missing Mandatory param(s) Node , NodeList ");
214             }
215         } catch (JSONException e) {
216             code = 401;
217             logger.error(POSTING_REQUEST_JSON_ERROR_STR, e);
218             doFailure(ctx, code, POSTING_REQUEST_JSON_ERROR_STR + e.getMessage());
219         } catch (Exception e) {
220             code = 401;
221             logger.error(POSTING_REQUEST_ERROR_STR, e);
222             doFailure(ctx, code, POSTING_REQUEST_ERROR_STR + e.getMessage());
223         }
224     }
225
226     @Override
227     public void vnfcPushJob(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
228         int code;
229         try {
230             chefInfo(params, ctx);
231             String nodeList = params.get(NODE_LIST_STR);
232             if (StringUtils.isNotBlank(nodeList)) {
233                 String isCallback = params.get("CallbackCapable");
234                 String chefAction = "/pushy/jobs";
235                 // need work on this
236                 String pushRequest;
237                 if ("true".equals(isCallback)) {
238                     String requestId = params.get("RequestId");
239                     String callbackUrl = params.get("CallbackUrl");
240                     pushRequest = "{" + "\"command\": \"chef-client\"," + "\"run_timeout\": 300," + "\"nodes\":"
241                         + nodeList + "," + "\"env\": {\"RequestId\": \"" + requestId + "\", \"CallbackUrl\": \""
242                         + callbackUrl + "\"}," + "\"capture_output\": true" + "}";
243                 } else {
244                     pushRequest = "{" + "\"command\": \"chef-client\"," + "\"run_timeout\": 300," + "\"nodes\":"
245                         + nodeList + "," + "\"env\": {}," + "\"capture_output\": true" + "}";
246                 }
247                 RequestContext rc = new RequestContext(ctx);
248
249                 rc.isAlive();
250                 SvcLogicContext svcLogic = rc.getSvcLogicContext();
251                 ChefApiClient cac = chefApiClientFactory.create(chefserver, organizations, username, clientPrivatekey);
252                 ChefResponse chefResponse = cac.post(chefAction, pushRequest);
253                 code = chefResponse.getStatusCode();
254                 logger.info("pushRequest:" + pushRequest);
255                 logger.info("requestbody: {}", chefResponse.getBody());
256                 String message = chefResponse.getBody();
257                 if (code == 201) {
258                     int startIndex = message.indexOf("jobs") + 5;
259                     int endIndex = message.length() - 2;
260                     String jobID = message.substring(startIndex, endIndex);
261                     svcLogic.setAttribute("jobID", jobID);
262                     logger.info(jobID);
263                 }
264                 chefServerResult(rc, code, message);
265             } else {
266                 throw new SvcLogicException("Missing Mandatory param(s)  NodeList ");
267             }
268         } catch (JSONException e) {
269             code = 401;
270             logger.error(POSTING_REQUEST_JSON_ERROR_STR, e);
271             doFailure(ctx, code, POSTING_REQUEST_JSON_ERROR_STR + e.getMessage());
272         } catch (Exception e) {
273             code = 401;
274             logger.error(POSTING_REQUEST_ERROR_STR, e);
275             doFailure(ctx, code, POSTING_REQUEST_ERROR_STR + e.getMessage());
276         }
277     }
278
279     @SuppressWarnings("nls")
280     @Override
281     public void fetchResults(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
282         int code = 200;
283         try {
284             chefInfo(params, ctx);
285             String nodeListS = params.get(NODE_LIST_STR);
286             if (StringUtils.isNotBlank(nodeListS)) {
287                 nodeListS = nodeListS.replace("[", StringUtils.EMPTY);
288                 nodeListS = nodeListS.replace("]", StringUtils.EMPTY);
289                 nodeListS = nodeListS.replace("\"", StringUtils.EMPTY);
290                 nodeListS = nodeListS.replace(" ", StringUtils.EMPTY);
291                 List<String> nodes = Arrays.asList(nodeListS.split("\\s*,\\s*"));
292                 JSONObject result = new JSONObject();
293                 String returnMessage = StringUtils.EMPTY;
294
295                 for (String node : nodes) {
296                     String chefAction = "/nodes/" + node;
297                     String message;
298                     if (privateKeyCheck()) {
299                         ChefResponse chefResponse = getApiMethod(chefAction);
300                         code = chefResponse.getStatusCode();
301                         message = chefResponse.getBody();
302                     } else {
303                         code = 500;
304                         message = CANNOT_FIND_PRIVATE_KEY_STR + clientPrivatekey;
305                         doFailure(ctx, code, message);
306                     }
307                     if (code == 200) {
308                         JSONObject nodeResult = new JSONObject();
309                         JSONObject allNodeData = new JSONObject(message);
310                         allNodeData = allNodeData.getJSONObject("normal");
311                         String attribute = "PushJobOutput";
312
313                         String resultData = allNodeData.optString(attribute);
314                         if (resultData == null) {
315                             resultData = allNodeData.optJSONObject(attribute).toString();
316
317                             if (resultData == null) {
318                                 resultData = allNodeData.optJSONArray(attribute).toString();
319
320                                 if (resultData == null) {
321                                     code = 500;
322                                     returnMessage = "Cannot find " + attribute;
323                                     break;
324                                 }
325                             }
326                         }
327                         nodeResult.put(attribute, resultData);
328                         result.put(node, nodeResult);
329                         returnMessage = result.toString();
330                     } else {
331                         code = 500;
332                         returnMessage = message + " Cannot access: " + node;
333                         doFailure(ctx, code, message);
334                         break;
335                     }
336                 }
337
338                 RequestContext rc = new RequestContext(ctx);
339                 rc.isAlive();
340                 chefServerResult(rc, code, returnMessage);
341             } else {
342                 throw new SvcLogicException("Missing Mandatory param(s)  NodeList ");
343             }
344         } catch (JSONException e) {
345             code = 401;
346             logger.error(POSTING_REQUEST_JSON_ERROR_STR, e);
347             doFailure(ctx, code, POSTING_REQUEST_JSON_ERROR_STR + e.getMessage());
348         } catch (Exception e) {
349             code = 401;
350             logger.error(POSTING_REQUEST_ERROR_STR , e);
351             doFailure(ctx, code, POSTING_REQUEST_ERROR_STR + e.getMessage());
352         }
353     }
354
355     private ChefResponse getApiMethod(String chefAction) {
356         ChefApiClient cac = chefApiClientFactory.create(chefserver, organizations, username, clientPrivatekey);
357         return cac.get(chefAction);
358     }
359
360     /**
361      * build node object
362      */
363     @SuppressWarnings("nls")
364     @Override
365     public void nodeObejctBuilder(Map<String, String> params, SvcLogicContext ctx) {
366         logger.info("nodeObejctBuilder");
367         String name = params.get("nodeobject.name");
368         String normal = params.get("nodeobject.normal");
369         String overrides = params.get("nodeobject.overrides");
370         String defaults = params.get("nodeobject.defaults");
371         String runList = params.get("nodeobject.run_list");
372         String chefEnvironment = params.get("nodeobject.chef_environment");
373         String nodeObject = "{\"json_class\":\"Chef::Node\",\"default\":{" + defaults
374             + "},\"chef_type\":\"node\",\"run_list\":[" + runList + "],\"override\":{" + overrides
375             + "},\"normal\": {" + normal + "},\"automatic\":{},\"name\":\"" + name + "\",\"chef_environment\":\""
376             + chefEnvironment + "\",}";
377         logger.info(nodeObject);
378         ctx.setAttribute("chef.nodeObject", nodeObject);
379     }
380
381     /**
382      * send get request to chef server
383      */
384     private void chefInfo(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
385
386         username = params.get("username");
387         serverAddress = params.get("serverAddress");
388         organizations = params.get("organizations");
389         if (StringUtils.isNotBlank(username) && StringUtils.isNotBlank(serverAddress)
390             && StringUtils.isNotBlank(organizations)) {
391             chefserver = "https://" + serverAddress + "/organizations/" + organizations;
392             clientPrivatekey = "/opt/onap/appc/chef/" + serverAddress + "/" + organizations + "/" + username + ".pem";
393             logger.info(" clientPrivatekey  " + clientPrivatekey);
394         } else {
395             doFailure(ctx, 401, "Missing mandatory param(s) such as username, serverAddress, organizations");
396         }
397     }
398
399     private Boolean privateKeyCheck() {
400         File f = new File(clientPrivatekey);
401         if (f.exists()) {
402             logger.info("Key exists");
403             return true;
404         } else {
405             logger.info("Key doesn't exists");
406             return false;
407         }
408     }
409
410     @SuppressWarnings("nls")
411     @Override
412     public void retrieveData(Map<String, String> params, SvcLogicContext ctx) {
413         String allConfigData = params.get("allConfig");
414         String key = params.get("key");
415         String dgContext = params.get("dgContext");
416         JSONObject jsonConfig = new JSONObject(allConfigData);
417         String contextData = fetchContextData(key, jsonConfig);
418
419         RequestContext rc = new RequestContext(ctx);
420         rc.isAlive();
421         SvcLogicContext svcLogic = rc.getSvcLogicContext();
422         svcLogic.setAttribute(dgContext, contextData);
423     }
424
425     private String fetchContextData(String key, JSONObject jsonConfig) {
426         try {
427             return jsonConfig.getString(key);
428         } catch (Exception e) {
429             logger.error("Failed getting string value corresponding to " + key + ". Trying to fetch nested json object", e);
430             try {
431                 return jsonConfig.getJSONObject(key).toString();
432             } catch (Exception ex) {
433                 logger.error("Failed getting json object corresponding to " + key + ". Trying to fetch array", ex);
434                 return jsonConfig.getJSONArray(key).toString();
435             }
436         }
437     }
438
439     @SuppressWarnings("nls")
440     @Override
441     public void combineStrings(Map<String, String> params, SvcLogicContext ctx) {
442         String string1 = params.get("String1");
443         String string2 = params.get("String2");
444         String dgContext = params.get("dgContext");
445         String contextData = string1 + string2;
446         RequestContext rc = new RequestContext(ctx);
447         rc.isAlive();
448         SvcLogicContext svcLogic = rc.getSvcLogicContext();
449         svcLogic.setAttribute(dgContext, contextData);
450     }
451
452     /**
453      * Send GET request to chef server
454      */
455     @SuppressWarnings("nls")
456
457     @Override
458     public void chefGet(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
459         logger.info("chef get method");
460         chefInfo(params, ctx);
461         String chefAction = params.get(CHEF_ACTION_STR);
462         RequestContext rc = new RequestContext(ctx);
463         rc.isAlive();
464         int code;
465         String message;
466
467         if (privateKeyCheck()) {
468             ChefResponse chefResponse = getApiMethod(chefAction);
469             code = chefResponse.getStatusCode();
470             message = chefResponse.getBody();
471         } else {
472             code = 500;
473             message = CANNOT_FIND_PRIVATE_KEY_STR + clientPrivatekey;
474         }
475         chefServerResult(rc, code, message);
476     }
477
478     /**
479      * Send PUT request to chef server
480      */
481     @SuppressWarnings("nls")
482
483     @Override
484     public void chefPut(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
485         chefInfo(params, ctx);
486         String chefAction = params.get(CHEF_ACTION_STR);
487         String chefNodeStr = params.get("chefRequestBody");
488         RequestContext rc = new RequestContext(ctx);
489         rc.isAlive();
490         int code;
491         String message;
492         if (privateKeyCheck()) {
493             ChefApiClient chefApiClient = chefApiClientFactory.create(chefserver, organizations, username, clientPrivatekey);
494
495             ChefResponse chefResponse = chefApiClient.put(chefAction, chefNodeStr);
496             code = chefResponse.getStatusCode();
497             message = chefResponse.getBody();
498         } else {
499             code = 500;
500             message = CANNOT_FIND_PRIVATE_KEY_STR + clientPrivatekey;
501         }
502         logger.info(code + "   " + message);
503         chefServerResult(rc, code, message);
504     }
505
506     /**
507      * send Post request to chef server
508      */
509     @Override
510     public void chefPost(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
511         chefInfo(params, ctx);
512         logger.info("chef Post method");
513         logger.info(username + " " + clientPrivatekey + " " + chefserver + " " + organizations);
514         String chefNodeStr = params.get("chefRequestBody");
515         String chefAction = params.get(CHEF_ACTION_STR);
516
517         RequestContext rc = new RequestContext(ctx);
518         rc.isAlive();
519         int code;
520         String message;
521         // should load pem from somewhere else
522         if (privateKeyCheck()) {
523             ChefApiClient chefApiClient = chefApiClientFactory.create(chefserver, organizations, username, clientPrivatekey);
524
525             // need pass path into it
526             // "/nodes/testnode"
527             ChefResponse chefResponse = chefApiClient.post(chefAction, chefNodeStr);
528             code = chefResponse.getStatusCode();
529             message = chefResponse.getBody();
530         } else {
531             code = 500;
532             message = CANNOT_FIND_PRIVATE_KEY_STR + clientPrivatekey;
533         }
534         logger.info(code + "   " + message);
535         chefServerResult(rc, code, message);
536     }
537
538     /**
539      * send delete request to chef server
540      */
541     @Override
542     public void chefDelete(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
543         logger.info("chef delete method");
544         chefInfo(params, ctx);
545         String chefAction = params.get(CHEF_ACTION_STR);
546         RequestContext rc = new RequestContext(ctx);
547         rc.isAlive();
548         int code;
549         String message;
550         if (privateKeyCheck()) {
551             ChefApiClient chefApiClient = chefApiClientFactory.create(chefserver, organizations, username, clientPrivatekey);
552             ChefResponse chefResponse = chefApiClient.delete(chefAction);
553             code = chefResponse.getStatusCode();
554             message = chefResponse.getBody();
555         } else {
556             code = 500;
557             message = CANNOT_FIND_PRIVATE_KEY_STR + clientPrivatekey;
558         }
559         logger.info(code + "   " + message);
560         chefServerResult(rc, code, message);
561     }
562
563     /**
564      * Trigger target vm run chef
565      */
566     @Override
567     public void trigger(Map<String, String> params, SvcLogicContext ctx) {
568         logger.info("Run trigger method");
569         String tVmIp = params.get("ip");
570         RequestContext rc = new RequestContext(ctx);
571         rc.isAlive();
572
573         try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
574             HttpGet httpGet = new HttpGet(tVmIp);
575             HttpResponse response = httpClient.execute(httpGet);
576             int responseCode = response.getStatusLine().getStatusCode();
577             HttpEntity entity = response.getEntity();
578             String responseOutput = EntityUtils.toString(entity);
579             chefClientResult(rc, responseCode, responseOutput);
580             doSuccess(rc);
581         } catch (Exception e) {
582             logger.error("An error occurred when executing trigger method", e);
583             doFailure(rc, 500, e.toString());
584         }
585     }
586
587     @SuppressWarnings("nls")
588     @Override
589     public void checkPushJob(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
590         int code;
591         try {
592             chefInfo(params, ctx);
593             String jobID = params.get("jobid");
594             String retry = params.get("retryTimes");
595             String intrva = params.get("retryInterval");
596             if (StringUtils.isNotBlank(retry) && StringUtils.isNotBlank(intrva)) {
597
598                 int retryTimes = Integer.parseInt(params.get("retryTimes"));
599                 int retryInterval = Integer.parseInt(params.get("retryInterval"));
600
601                 String chefAction = "/pushy/jobs/" + jobID;
602
603                 RequestContext rc = new RequestContext(ctx);
604                 rc.isAlive();
605                 SvcLogicContext svcLogic = rc.getSvcLogicContext();
606                 String message = StringUtils.EMPTY;
607                 String status = StringUtils.EMPTY;
608                 for (int i = 0; i < retryTimes; i++) {
609                     sleepFor(retryInterval);
610                     ChefResponse chefResponse = getApiMethod(chefAction);
611                     code = chefResponse.getStatusCode();
612                     message = chefResponse.getBody();
613                     JSONObject obj = new JSONObject(message);
614                     status = obj.getString("status");
615                     if (!"running".equals(status)) {
616                         logger.info(i + " time " + code + "   " + status);
617                         break;
618                     }
619                 }
620                 resolveSvcLogicAttributes(svcLogic, message, status);
621             } else {
622                 throw new SvcLogicException("Missing Mandatory param(s) retryTimes , retryInterval ");
623             }
624         } catch (Exception e) {
625             code = 401;
626             logger.error("An error occurred when executing checkPushJob method", e);
627             doFailure(ctx, code, e.getMessage());
628         }
629     }
630
631     private void resolveSvcLogicAttributes(SvcLogicContext svcLogic, String message, String status) {
632         if ("complete".equals(status)) {
633             svcLogic.setAttribute(CHEF_SERVER_RESULT_CODE_STR, "200");
634             svcLogic.setAttribute(CHEF_SERVER_RESULT_MSG_STR, message);
635         } else {
636             if ("running".equals(status)) {
637                 svcLogic.setAttribute(CHEF_SERVER_RESULT_CODE_STR, "202");
638                 svcLogic.setAttribute(CHEF_SERVER_RESULT_MSG_STR, "chef client runtime out");
639             } else {
640                 svcLogic.setAttribute(CHEF_SERVER_RESULT_CODE_STR, "500");
641                 svcLogic.setAttribute(CHEF_SERVER_RESULT_MSG_STR, message);
642             }
643         }
644     }
645
646     private void sleepFor(int retryInterval) {
647         try {
648             Thread.sleep(retryInterval); // 1000 milliseconds is one second.
649         } catch (InterruptedException ex) {
650             Thread.currentThread().interrupt();
651         }
652     }
653
654     @SuppressWarnings("nls")
655     @Override
656     public void pushJob(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
657         int code;
658         try {
659             chefInfo(params, ctx);
660             String pushRequest = params.get("pushRequest");
661             String chefAction = "/pushy/jobs";
662             RequestContext rc = new RequestContext(ctx);
663             rc.isAlive();
664             SvcLogicContext svcLogic = rc.getSvcLogicContext();
665             ChefApiClient chefApiClient = chefApiClientFactory.create(chefserver, organizations, username, clientPrivatekey);
666             ChefResponse chefResponse = chefApiClient.post(chefAction, pushRequest);
667
668             code = chefResponse.getStatusCode();
669             String message = chefResponse.getBody();
670             if (code == 201) {
671                 int startIndex = message.indexOf("jobs") + 6;
672                 int endIndex = message.length() - 2;
673                 String jobID = message.substring(startIndex, endIndex);
674                 svcLogic.setAttribute("jobID", jobID);
675                 logger.info(jobID);
676             }
677             chefServerResult(rc, code, message);
678         } catch (Exception e) {
679             code = 401;
680             logger.error("An error occurred when executing pushJob method", e);
681             doFailure(ctx, code, e.getMessage());
682         }
683     }
684
685     @SuppressWarnings("static-method")
686     private void doFailure(RequestContext rc, int code, String message) {
687         SvcLogicContext svcLogic = rc.getSvcLogicContext();
688         String msg = (message == null) ? Integer.toString(code) : message;
689         if (msg.contains("\n")) {
690             msg = msg.substring(msg.indexOf('\n'));
691         }
692
693         String status;
694         try {
695             status = Integer.toString(code);
696         } catch (Exception e) {
697             status = "500";
698             logger.error("Parsing status code failed. Setting it to \"500\"", e);
699         }
700         svcLogic.setAttribute("chefAgent.code", status);
701         svcLogic.setAttribute("chefAgent.message", msg);
702     }
703
704     /**
705      * @param rc The request context that manages the state and recovery of the request for the life of its processing.
706      */
707     @SuppressWarnings("static-method")
708     private void doSuccess(RequestContext rc) {
709         SvcLogicContext svcLogic = rc.getSvcLogicContext();
710         svcLogic.setAttribute("chefAgent.code", "200");
711     }
712
713     @SuppressWarnings("static-method")
714     private void chefServerResult(RequestContext rc, int code, String message) {
715         initSvcLogic(rc, code, message, "server");
716     }
717
718     @SuppressWarnings("static-method")
719     private void chefClientResult(RequestContext rc, int code, String message) {
720         initSvcLogic(rc, code, message, "client");
721     }
722
723     private void initSvcLogic(RequestContext rc, int code, String message, String target) {
724
725         SvcLogicContext svcLogic = rc.getSvcLogicContext();
726         String codeStr = "server".equals(target) ? CHEF_SERVER_RESULT_CODE_STR : CHEF_CLIENT_RESULT_CODE_STR;
727         String messageStr = "client".equals(target) ? CHEF_SERVER_RESULT_MSG_STR : CHEF_CLIENT_RESULT_MSG_STR;
728
729         svcLogic.setStatus(OUTCOME_SUCCESS);
730         svcLogic.setAttribute(codeStr, Integer.toString(code));
731         svcLogic.setAttribute(messageStr, message);
732         logger.info(codeStr + ": " + svcLogic.getAttribute(codeStr));
733         logger.info(messageStr + ": " + svcLogic.getAttribute(messageStr));
734     }
735
736     @SuppressWarnings("static-method")
737     private void doFailure(SvcLogicContext svcLogic, int code, String message) throws SvcLogicException {
738
739         String cutMessage = message.contains("\n") ? message.substring(message.indexOf('\n')) : message;
740
741         svcLogic.setStatus(OUTCOME_FAILURE);
742         svcLogic.setAttribute(CHEF_SERVER_RESULT_CODE_STR, Integer.toString(code));
743         svcLogic.setAttribute(CHEF_SERVER_RESULT_MSG_STR, cutMessage);
744
745         throw new SvcLogicException("Chef Adapter error:" + cutMessage);
746     }
747 }