824a6af95e3ab3cf69223164929f448eb88af778
[appc.git] / appc-adapters / appc-chef-adapter / appc-chef-adapter-bundle / src / main / java / org / openecomp / 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
25 package org.onap.appc.adapter.chef.impl;
26
27 import java.io.File;
28 import java.util.Map;
29
30 import org.apache.http.HttpEntity;
31 import org.apache.http.HttpResponse;
32 import org.apache.http.client.methods.HttpGet;
33 import org.apache.http.impl.client.CloseableHttpClient;
34 import org.apache.http.impl.client.HttpClients;
35 import org.apache.http.util.EntityUtils;
36 import org.json.JSONObject;
37 import org.onap.appc.Constants;
38 import org.onap.appc.adapter.chef.ChefAdapter;
39 import org.onap.appc.adapter.chef.chefapi.ApiMethod;
40 import org.onap.appc.adapter.chef.chefclient.ChefApiClient;
41 import org.onap.appc.configuration.Configuration;
42 import org.onap.appc.configuration.ConfigurationFactory;
43 import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
44
45 import com.att.eelf.configuration.EELFLogger;
46 import com.att.eelf.configuration.EELFManager;
47
48 /**
49  * This class implements the {@link ChefAdapter} interface. This interface
50  * defines the behaviors that our service provides.
51  */
52 public class ChefAdapterImpl implements ChefAdapter {
53     // chef server Initialize variable
54     private String clientName = "";
55     private String clientPrivatekey = "";
56     private String chefserver = "";
57     private String serverAddress = "";
58     private String organizations = "";
59
60
61     /**
62      * The constant for the status code for a successful outcome
63      */
64     private static final String OUTCOME_SUCCESS = "success";
65
66     /**
67      * The logger to be used
68      */
69     private final EELFLogger logger = EELFManager.getInstance().getLogger(ChefAdapterImpl.class);
70
71     private final String CANNOT_FIND_PRIVATE_KEY_STR = "Cannot find the private key in the APPC file system, please load the private key to ";
72     private final String CHEF_ACTION_STR = "org.onap.appc.instance.chefAction";
73     private final String ORGANIZATIONS_STR = "/organizations/";
74     /**
75      * A reference to the adapter configuration object.
76      */
77     private Configuration configuration;
78
79     /**
80      * This default constructor is used as a work around because the activator wasnt
81      * getting called
82      */
83     public ChefAdapterImpl() {
84         initialize();
85     }
86
87     /**
88      * This constructor is used primarily in the test cases to bypass initialization
89      * of the adapter for isolated, disconnected testing
90      *
91      * @param initialize
92      *            True if the adapter is to be initialized, can false if not
93      */
94     public ChefAdapterImpl(boolean initialize) {
95         configuration = ConfigurationFactory.getConfiguration();
96         if (initialize) {
97             initialize();
98         }
99     }
100
101     public ChefAdapterImpl(String key) {
102         initialize(key);
103     }
104
105     /**
106      * Returns the symbolic name of the adapter
107      *
108      * @return The adapter name
109      * @see org.onap.appc.adapter.chef.ChefAdapter#getAdapterName()
110      */
111     @Override
112     public String getAdapterName() {
113         return configuration.getProperty(Constants.PROPERTY_ADAPTER_NAME);
114     }
115
116     /**
117      * build node object
118      */
119     @Override
120     public void nodeObejctBuilder(Map<String, String> params, SvcLogicContext ctx) {
121         logger.info("nodeObejctBuilder");
122         String name = params.get("org.onap.appc.instance.nodeobject.name");
123         String normal = params.get("org.onap.appc.instance.nodeobject.normal");
124         String overrides = params.get("org.onap.appc.instance.nodeobject.overrides");
125         String defaults = params.get("org.onap.appc.instance.nodeobject.defaults");
126         String runList = params.get("org.onap.appc.instance.nodeobject.run_list");
127         String chefEnvironment = params.get("org.onap.appc.instance.nodeobject.chef_environment");
128         String nodeObject = "{\"json_class\":\"Chef::Node\",\"default\":{" + defaults
129                 + "},\"chef_type\":\"node\",\"run_list\":[" + runList + "],\"override\":{" + overrides
130                 + "},\"normal\": {" + normal + "},\"automatic\":{},\"name\":\"" + name + "\",\"chef_environment\":\""
131                 + chefEnvironment + "\"}";
132         logger.info(nodeObject);
133
134         RequestContext rc = new RequestContext(ctx);
135         rc.isAlive();
136         SvcLogicContext svcLogic = rc.getSvcLogicContext();
137         svcLogic.setAttribute("org.onap.appc.chef.nodeObject", nodeObject);
138     }
139
140     /**
141      * send get request to chef server
142      */
143     public void chefInfo(Map<String, String> params) {
144         clientName = params.get("org.onap.appc.instance.username");
145         serverAddress = params.get("org.onap.appc.instance.serverAddress");
146         organizations = params.get("org.onap.appc.instance.organizations");
147         chefserver = "https://" + serverAddress + ORGANIZATIONS_STR + organizations;
148         if (params.containsKey("org.onap.appc.instance.pemPath")) {
149             clientPrivatekey = params.get("org.onap.appc.instance.pemPath");
150         } else {
151             clientPrivatekey = "/opt/app/bvc/chef/" + serverAddress + "/" + organizations + "/" + clientName + ".pem";
152         }
153     }
154
155     public Boolean privateKeyCheck() {
156         File f = new File(clientPrivatekey);
157         return f.exists();
158     }
159
160     @Override
161     public void retrieveData(Map<String, String> params, SvcLogicContext ctx) {
162         String allConfigData = params.get("org.onap.appc.instance.allConfig");
163         String key = params.get("org.onap.appc.instance.key");
164         String dgContext = params.get("org.onap.appc.instance.dgContext");
165         JSONObject josnConfig = new JSONObject(allConfigData);
166
167         String contextData;
168         try {
169             contextData = josnConfig.getString(key);
170         } catch (Exception ex) {
171             try {
172                 contextData = josnConfig.getJSONObject(key).toString();
173             } catch (Exception exc) {
174                 contextData = josnConfig.getJSONArray(key).toString();
175             }
176         }
177
178         RequestContext rc = new RequestContext(ctx);
179         rc.isAlive();
180         SvcLogicContext svcLogic = rc.getSvcLogicContext();
181         svcLogic.setAttribute(dgContext, contextData);
182     }
183
184     @Override
185     public void combineStrings(Map<String, String> params, SvcLogicContext ctx) {
186
187         String string1 = params.get("org.onap.appc.instance.String1");
188         String string2 = params.get("org.onap.appc.instance.String2");
189         String dgContext = params.get("org.onap.appc.instance.dgContext");
190         String contextData = string1 + string2;
191         RequestContext rc = new RequestContext(ctx);
192         rc.isAlive();
193         SvcLogicContext svcLogic = rc.getSvcLogicContext();
194         svcLogic.setAttribute(dgContext, contextData);
195     }
196
197     /**
198      * Send GET request to chef server
199      */
200     @Override
201     public void chefGet(Map<String, String> params, SvcLogicContext ctx) {
202         logger.info("chef get method");
203         chefInfo(params);
204         String chefAction = params.get(CHEF_ACTION_STR);
205         RequestContext rc = new RequestContext(ctx);
206         rc.isAlive();
207         int code;
208         String message;
209         if (privateKeyCheck()) {
210             ChefApiClient cac = new ChefApiClient(clientName, clientPrivatekey, chefserver, organizations);
211             ApiMethod am = cac.get(chefAction);
212             am.execute();
213             code = am.getReturnCode();
214             message = am.getResponseBodyAsString();
215         } else {
216             code = 500;
217             message = CANNOT_FIND_PRIVATE_KEY_STR + clientPrivatekey;
218         }
219         chefServerResult(rc, Integer.toString(code), message);
220     }
221
222     /**
223      * Send PUT request to chef server
224      */
225     @Override
226     public void chefPut(Map<String, String> params, SvcLogicContext ctx) {
227         chefInfo(params);
228         String chefAction = params.get(CHEF_ACTION_STR);
229         String chefNodeStr = params.get("org.onap.appc.instance.chefRequestBody");
230         RequestContext rc = new RequestContext(ctx);
231         rc.isAlive();
232         int code;
233         String message;
234         if (privateKeyCheck()) {
235             ChefApiClient cac = new ChefApiClient(clientName, clientPrivatekey, chefserver, organizations);
236
237             ApiMethod am = cac.put(chefAction).body(chefNodeStr);
238             am.execute();
239             code = am.getReturnCode();
240             message = am.getResponseBodyAsString();
241         } else {
242             code = 500;
243             message = CANNOT_FIND_PRIVATE_KEY_STR + clientPrivatekey;
244         }
245         logger.info(code + "   " + message);
246         chefServerResult(rc, Integer.toString(code), message);
247     }
248
249     /**
250      *  send Post request to chef server
251      */
252     @Override
253     public void chefPost(Map<String, String> params, SvcLogicContext ctx) {
254         chefInfo(params);
255         logger.info("chef Post method");
256         logger.info(clientName + " " + clientPrivatekey + " " + chefserver + " " + organizations);
257         String chefNodeStr = params.get("org.onap.appc.instance.chefRequestBody");
258         String chefAction = params.get(CHEF_ACTION_STR);
259
260         RequestContext rc = new RequestContext(ctx);
261         rc.isAlive();
262         int code;
263         String message;
264         // should load pem from somewhere else
265         if (privateKeyCheck()) {
266             ChefApiClient cac = new ChefApiClient(clientName, clientPrivatekey, chefserver, organizations);
267
268             // need pass path into it
269             // "/nodes/testnode"
270             ApiMethod am = cac.post(chefAction).body(chefNodeStr);
271             am.execute();
272             code = am.getReturnCode();
273             message = am.getResponseBodyAsString();
274         } else {
275             code = 500;
276             message = CANNOT_FIND_PRIVATE_KEY_STR + clientPrivatekey;
277         }
278         logger.info(code + "   " + message);
279         chefServerResult(rc, Integer.toString(code), message);
280     }
281
282     /**
283      * send delete request to chef server
284      */
285     @Override
286     public void chefDelete(Map<String, String> params, SvcLogicContext ctx) {
287         logger.info("chef delete method");
288         chefInfo(params);
289         String chefAction = params.get(CHEF_ACTION_STR);
290         RequestContext rc = new RequestContext(ctx);
291         rc.isAlive();
292         int code;
293         String message;
294         if (privateKeyCheck()) {
295             ChefApiClient cac = new ChefApiClient(clientName, clientPrivatekey, chefserver, organizations);
296             ApiMethod am = cac.delete(chefAction);
297             am.execute();
298             code = am.getReturnCode();
299             message = am.getResponseBodyAsString();
300         } else {
301             code = 500;
302             message = CANNOT_FIND_PRIVATE_KEY_STR + clientPrivatekey;
303         }
304         logger.info(code + "   " + message);
305         chefServerResult(rc, Integer.toString(code), message);
306     }
307
308     /**
309      * Trigger target vm run chef
310      */
311     @Override
312     public void trigger(Map<String, String> params, SvcLogicContext ctx) {
313         logger.info("Run trigger method");
314         String tVmIp = params.get("org.onap.appc.instance.ip");
315         RequestContext rc = new RequestContext(ctx);
316         rc.isAlive();
317
318         try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
319             HttpGet httpGet = new HttpGet(tVmIp);
320             HttpResponse response;
321             response = httpClient.execute(httpGet);
322             int responseCode = response.getStatusLine().getStatusCode();
323             HttpEntity entity = response.getEntity();
324             String responseOutput = EntityUtils.toString(entity);
325             chefClientResult(rc, Integer.toString(responseCode), responseOutput);
326             doSuccess(rc);
327         } catch (Exception ex) {
328             doFailure(rc, 500, ex.toString());
329         }
330     }
331
332     @Override
333     public void checkPushJob(Map<String, String> params, SvcLogicContext ctx) {
334         chefInfo(params);
335         String jobID = params.get("org.onap.appc.instance.jobid");
336         int retryTimes = Integer.parseInt(params.get("org.onap.appc.instance.retryTimes"));
337         int retryInterval = Integer.parseInt(params.get("org.onap.appc.instance.retryInterval"));
338         String chefAction = "/pushy/jobs/" + jobID;
339
340         RequestContext rc = new RequestContext(ctx);
341         rc.isAlive();
342         SvcLogicContext svcLogic = rc.getSvcLogicContext();
343         String message = "";
344         String status = "";
345         for (int i = 0; i < retryTimes; i++) {
346             try {
347                 Thread.sleep(retryInterval); // 1000 milliseconds is one second.
348             } catch (InterruptedException ex) {
349                 Thread.currentThread().interrupt();
350             }
351             ChefApiClient cac = new ChefApiClient(clientName, clientPrivatekey, chefserver, organizations);
352             ApiMethod am = cac.get(chefAction);
353             am.execute();
354             int code = am.getReturnCode();
355             message = am.getResponseBodyAsString();
356             JSONObject obj = new JSONObject(message);
357             status = obj.getString("status");
358             if (!"running".equals(status)) {
359                 logger.info(i + " time " + code + "   " + status);
360                 break;
361             }
362
363         }
364         if ("complete".equals(status)) {
365             svcLogic.setAttribute("org.onap.appc.chefServerResult.code", "200");
366             svcLogic.setAttribute("org.onap.appc.chefServerResult.message", message);
367         } else {
368             if ("running".equals(status)) {
369                 svcLogic.setAttribute("org.onap.appc.chefServerResult.code", "202");
370                 svcLogic.setAttribute("org.onap.appc.chefServerResult.message", "chef client runtime out");
371             } else {
372                 svcLogic.setAttribute("org.onap.appc.chefServerResult.code", "500");
373                 svcLogic.setAttribute("org.onap.appc.chefServerResult.message", message);
374             }
375         }
376     }
377
378     @Override
379     public void pushJob(Map<String, String> params, SvcLogicContext ctx) {
380         chefInfo(params);
381         String pushRequest = params.get("org.onap.appc.instance.pushRequest");
382         String chefAction = "/pushy/jobs";
383         RequestContext rc = new RequestContext(ctx);
384         rc.isAlive();
385         SvcLogicContext svcLogic = rc.getSvcLogicContext();
386         ChefApiClient cac = new ChefApiClient(clientName, clientPrivatekey, chefserver, organizations);
387         ApiMethod am = cac.post(chefAction).body(pushRequest);
388
389         am.execute();
390         int code = am.getReturnCode();
391         String message = am.getResponseBodyAsString();
392         if (code == 201) {
393             int startIndex = message.indexOf("jobs") + 6;
394             int endIndex = message.length() - 2;
395             String jobID = message.substring(startIndex, endIndex);
396             svcLogic.setAttribute("org.onap.appc.jobID", jobID);
397             logger.info(jobID);
398         }
399         chefServerResult(rc, Integer.toString(code), message);
400     }
401
402     private void doFailure(RequestContext rc, int code, String message) {
403         SvcLogicContext svcLogic = rc.getSvcLogicContext();
404         String msg = (message == null) ? Integer.toString(code) : message;
405         if (msg.contains("\n")) {
406             msg = msg.substring(msg.indexOf("\n"));
407         }
408
409         String status;
410         try {
411             status = Integer.toString(code);
412         } catch (Exception e) {
413             logger.info("Couldn't covert " + code + " to an Integer, defaulting status to 500", e);
414             status = "500";
415         }
416         svcLogic.setAttribute("org.onap.appc.chefAgent.code", status);
417         svcLogic.setAttribute("org.onap.appc.chefAgent.message", msg);
418     }
419
420     /**
421      * @param rc
422      *            The request context that manages the state and recovery of the
423      *            request for the life of its processing.
424      */
425     private void doSuccess(RequestContext rc) {
426         SvcLogicContext svcLogic = rc.getSvcLogicContext();
427         svcLogic.setAttribute("org.onap.appc.chefAgent.code", "200");
428     }
429
430     private void chefServerResult(RequestContext rc, String code, String message) {
431         SvcLogicContext svcLogic = rc.getSvcLogicContext();
432         svcLogic.setStatus(OUTCOME_SUCCESS);
433         svcLogic.setAttribute("org.onap.appc.chefServerResult.code", code);
434         svcLogic.setAttribute("org.onap.appc.chefServerResult.message", message);
435     }
436
437     private void chefClientResult(RequestContext rc, String code, String message) {
438         SvcLogicContext svcLogic = rc.getSvcLogicContext();
439         svcLogic.setStatus(OUTCOME_SUCCESS);
440         svcLogic.setAttribute("org.onap.appc.chefClientResult.code", code);
441         svcLogic.setAttribute("org.onap.appc.chefClientResult.message", message);
442     }
443
444     /**
445      * initialize the provider adapter by building the context cache
446      */
447     private void initialize() {
448         configuration = ConfigurationFactory.getConfiguration();
449         // need to fetch data from appc configurator or form some file in the appc vms
450         clientName = "testnode";
451         clientPrivatekey = System.getProperty("user.dir") + "/src/test/resources/testclient.pem";
452         serverAddress = "http://example.com";
453         organizations = "test";
454         chefserver = serverAddress + ORGANIZATIONS_STR + organizations;
455         logger.info("Initialize Chef Adapter");
456     }
457
458     private void initialize(String key) {
459         configuration = ConfigurationFactory.getConfiguration();
460         // need to fetch data from appc configurator or form some file in the appc vms
461         clientName = "testnode";
462         clientPrivatekey = key;
463         serverAddress = "http://example.com";
464         organizations = "test";
465         chefserver = serverAddress + ORGANIZATIONS_STR + organizations;
466         logger.info("Initialize Chef Adapter");
467     }
468
469 }